]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/dt3155/dt3155_drv.c
Staging: dt3155: fix different address spaces noise in dt3155_drv.c
[karo-tx-linux.git] / drivers / staging / dt3155 / dt3155_drv.c
1 /*
2
3 Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
4                          Jason Lapenta, Scott Smedley, Greg Sharp
5
6 This file is part of the DT3155 Device Driver.
7
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.
12
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.
17
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
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
58 extern void printques(int);
59
60 #include <linux/module.h>
61 #include <linux/interrupt.h>
62 #include <linux/pci.h>
63 #include <linux/types.h>
64 #include <linux/poll.h>
65 #include <linux/sched.h>
66 #include <linux/smp_lock.h>
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
77
78 MODULE_LICENSE("GPL");
79
80 /* Error variable.  Zero means no error. */
81 int 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 */
98 wait_queue_head_t dt3155_read_wait_queue[MAXBOARDS];
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 */
105 int 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 */
115 struct dt3155_status dt3155_status[MAXBOARDS];
116
117 /* kernel logical address of the board */
118 u8 *dt3155_lbase[MAXBOARDS] = { NULL
119 #if MAXBOARDS == 2
120                                       , NULL
121 #endif
122 };
123 /* DT3155 registers              */
124 u8 *dt3155_bbase = NULL;                  /* kernel logical address of the *
125                                            * buffer region                 */
126 u32  dt3155_dev_open[MAXBOARDS] = {0
127 #if MAXBOARDS == 2
128                                        , 0
129 #endif
130 };
131
132 u32  ndevices = 0;
133 u32 unique_tag = 0;;
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  */
141 static void quick_stop (int minor)
142 {
143   // TODO: scott was here
144 #if 1
145   ReadMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
146   /* disable interrupts */
147   int_csr_r.fld.FLD_END_EVE_EN = 0;
148   int_csr_r.fld.FLD_END_ODD_EN = 0;
149   WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
150
151   dt3155_status[minor].state &= ~(DT3155_STATE_STOP|0xff);
152   /* mark the system stopped: */
153   dt3155_status[minor].state |= DT3155_STATE_IDLE;
154   dt3155_fbuffer[minor]->stop_acquire = 0;
155   dt3155_fbuffer[minor]->even_stopped = 0;
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  *****************************************************/
171 static void dt3155_isr(int irq, void *dev_id, struct pt_regs *regs)
172 {
173   int    minor = -1;
174   int    index;
175   unsigned long flags;
176   u32 buffer_addr;
177
178   /* find out who issued the interrupt */
179   for (index = 0; index < ndevices; index++) {
180     if(dev_id == (void*) &dt3155_status[index])
181       {
182         minor = index;
183         break;
184       }
185   }
186
187   /* hopefully we should not get here */
188   if (minor < 0 || minor >= MAXBOARDS) {
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 */
194   ReadMReg((dt3155_lbase[minor] + CSR1), csr1_r.reg);
195
196   if ((csr1_r.fld.FLD_CRPT_EVE) || (csr1_r.fld.FLD_CRPT_ODD))
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
206   ReadMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
207
208   /* Handle the even field ... */
209   if (int_csr_r.fld.FLD_END_EVE)
210     {
211       if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
212            DT3155_STATE_FLD)
213         {
214           dt3155_fbuffer[minor]->frame_count++;
215         }
216
217       ReadI2C(dt3155_lbase[minor], EVEN_CSR, &i2c_even_csr.reg);
218
219       /* Clear the interrupt? */
220       int_csr_r.fld.FLD_END_EVE = 1;
221
222       /* disable the interrupt if last field */
223       if (dt3155_fbuffer[minor]->stop_acquire)
224         {
225           printk("dt3155:  even stopped.\n");
226           dt3155_fbuffer[minor]->even_stopped = 1;
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
237       WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
238
239       /* Set up next DMA if we are doing FIELDS */
240       if ((dt3155_status[minor].state & DT3155_STATE_MODE) ==
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 */
245           const u32 stride =  dt3155_status[minor].config.cols;
246           buffer_addr = dt3155_fbuffer[minor]->
247             frame_info[dt3155_fbuffer[minor]->active_buf].addr
248             + (DT3155_MAX_ROWS / 2) * stride;
249           local_save_flags(flags);
250           local_irq_disable();
251           wake_up_interruptible(&dt3155_read_wait_queue[minor]);
252
253           /* Set up the DMA address for the next field */
254           local_irq_restore(flags);
255           WriteMReg((dt3155_lbase[minor] + ODD_DMA_START), buffer_addr);
256         }
257
258       /* Check for errors. */
259       i2c_even_csr.fld.DONE_EVE = 1;
260       if (i2c_even_csr.fld.ERROR_EVE)
261         dt3155_errno = DT_ERR_OVERRUN;
262
263       WriteI2C(dt3155_lbase[minor], EVEN_CSR, i2c_even_csr.reg);
264
265       /* Note that we actually saw an even field meaning  */
266       /* that subsequent odd field complete the frame     */
267       dt3155_fbuffer[minor]->even_happened = 1;
268
269       /* recording the time that the even field finished, this should be */
270       /* about time in the middle of the frame */
271       do_gettimeofday(&(dt3155_fbuffer[minor]->
272                          frame_info[dt3155_fbuffer[minor]->
273                                      active_buf].time));
274       return;
275     }
276
277   /* ... now handle the odd field */
278   if (int_csr_r.fld.FLD_END_ODD)
279     {
280       ReadI2C(dt3155_lbase[minor], ODD_CSR, &i2c_odd_csr.reg);
281
282       /* Clear the interrupt? */
283       int_csr_r.fld.FLD_END_ODD = 1;
284
285       if (dt3155_fbuffer[minor]->even_happened ||
286           (dt3155_status[minor].state & DT3155_STATE_MODE) ==
287           DT3155_STATE_FLD)
288         {
289           dt3155_fbuffer[minor]->frame_count++;
290         }
291
292       if (dt3155_fbuffer[minor]->stop_acquire &&
293            dt3155_fbuffer[minor]->even_stopped)
294         {
295           printk(KERN_DEBUG "dt3155:  stopping odd..\n");
296           if (i2c_odd_csr.fld.SNGL_ODD)
297             {
298               /* disable interrupts */
299               int_csr_r.fld.FLD_END_ODD_EN = 0;
300               dt3155_status[minor].state &= ~(DT3155_STATE_STOP|0xff);
301
302               /* mark the system stopped: */
303               dt3155_status[minor].state |= DT3155_STATE_IDLE;
304               dt3155_fbuffer[minor]->stop_acquire = 0;
305               dt3155_fbuffer[minor]->even_stopped = 0;
306
307               printk(KERN_DEBUG "dt3155:  state is now %x\n",
308                      dt3155_status[minor].state);
309             }
310           else
311             {
312               i2c_odd_csr.fld.SNGL_ODD  = 1;
313             }
314         }
315
316       WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
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          */
321       if (dt3155_fbuffer[minor]->even_happened ||
322            (dt3155_status[minor].state & DT3155_STATE_MODE) ==
323            DT3155_STATE_FLD)
324         {
325
326           local_save_flags(flags);
327           local_irq_disable();
328
329 #ifdef DEBUG_QUES_B
330           printques(minor);
331 #endif
332           if (dt3155_fbuffer[minor]->nbuffers > 2)
333             {
334               if (!are_empty_buffers(minor))
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. */
340                   push_empty(pop_ready(minor),  minor);
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. */
346               push_ready(minor, dt3155_fbuffer[minor]->active_buf);
347               /* There's at least 1 empty -- make it active */
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;
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                */
358               if (dt3155_fbuffer[minor]->locked_buf < 0)
359                 {
360                   push_ready(minor,
361                               dt3155_fbuffer[minor]->active_buf);
362                   if (are_empty_buffers(minor))
363                     {
364                       dt3155_fbuffer[minor]->active_buf =
365                         pop_empty(minor);
366                     }
367                   else
368                     { /* no empty or locked buffers, so use a readybuf */
369                       dt3155_fbuffer[minor]->active_buf =
370                         pop_ready(minor);
371                     }
372                 }
373             }
374
375 #ifdef DEBUG_QUES_B
376           printques(minor);
377 #endif
378
379           dt3155_fbuffer[minor]->even_happened = 0;
380
381           wake_up_interruptible(&dt3155_read_wait_queue[minor]);
382
383           local_irq_restore(flags);
384         }
385
386
387       /* Set up the DMA address for the next frame/field */
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)
392         {
393           WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START), buffer_addr);
394         }
395       else
396         {
397           WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START), buffer_addr);
398
399           WriteMReg((dt3155_lbase[minor] + ODD_DMA_START), buffer_addr
400                     + dt3155_status[minor].config.cols);
401         }
402
403       /* Do error checking */
404       i2c_odd_csr.fld.DONE_ODD = 1;
405       if (i2c_odd_csr.fld.ERROR_ODD)
406         dt3155_errno = DT_ERR_OVERRUN;
407
408       WriteI2C(dt3155_lbase[minor], ODD_CSR, i2c_odd_csr.reg);
409
410       return;
411     }
412   /* If we get here, the Odd Field wasn't it either... */
413   printk("neither even nor odd.  shared perhaps?\n");
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  *****************************************************/
422 static void dt3155_init_isr(int minor)
423 {
424   const u32 stride =  dt3155_status[minor].config.cols;
425
426   switch (dt3155_status[minor].state & DT3155_STATE_MODE)
427     {
428     case DT3155_STATE_FLD:
429       {
430         even_dma_start_r  = dt3155_status[minor].
431           fbuffer.frame_info[dt3155_status[minor].fbuffer.active_buf].addr;
432         even_dma_stride_r = 0;
433         odd_dma_stride_r  = 0;
434
435         WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START),
436                   even_dma_start_r);
437         WriteMReg((dt3155_lbase[minor] + EVEN_DMA_STRIDE),
438                   even_dma_stride_r);
439         WriteMReg((dt3155_lbase[minor] + ODD_DMA_STRIDE),
440                   odd_dma_stride_r);
441         break;
442       }
443
444     case DT3155_STATE_FRAME:
445     default:
446       {
447         even_dma_start_r  = dt3155_status[minor].
448           fbuffer.frame_info[dt3155_status[minor].fbuffer.active_buf].addr;
449         odd_dma_start_r   =  even_dma_start_r + stride;
450         even_dma_stride_r =  stride;
451         odd_dma_stride_r  =  stride;
452
453         WriteMReg((dt3155_lbase[minor] + EVEN_DMA_START),
454                   even_dma_start_r);
455         WriteMReg((dt3155_lbase[minor] + ODD_DMA_START),
456                   odd_dma_start_r);
457         WriteMReg((dt3155_lbase[minor] + EVEN_DMA_STRIDE),
458                   even_dma_stride_r);
459         WriteMReg((dt3155_lbase[minor] + ODD_DMA_STRIDE),
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
468   ReadI2C(dt3155_lbase[minor], CSR2, &i2c_csr2.reg);
469   i2c_csr2.fld.HZ50 = FORMAT50HZ;
470   WriteI2C(dt3155_lbase[minor], CSR2, i2c_csr2.reg);
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
490   WriteMReg((dt3155_lbase[minor] + CSR1),csr1_r.reg);
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
499   WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
500
501   /* start internal BUSY bits */
502
503   ReadI2C(dt3155_lbase[minor], CSR2, &i2c_csr2.reg);
504   i2c_csr2.fld.BUSY_ODD  = 1;
505   i2c_csr2.fld.BUSY_EVE  = 1;
506   WriteI2C(dt3155_lbase[minor], CSR2, i2c_csr2.reg);
507
508   /* Now its up to the interrupt routine!! */
509
510   return;
511 }
512
513
514 /*****************************************************
515  * ioctl()
516  *
517  *****************************************************/
518 static int dt3155_ioctl(struct inode *inode,
519                         struct file *file,
520                         unsigned int cmd,
521                         unsigned long arg)
522 {
523   int minor = MINOR(inode->i_rdev); /* What device are we ioctl()'ing? */
524   void __user *up = (void __user *)arg;
525
526   if (minor >= MAXBOARDS || minor < 0)
527     return -ENODEV;
528
529   /* make sure it is valid command */
530   if (_IOC_NR(cmd) > DT3155_IOC_MAXNR)
531     {
532       printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
533       printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
534              (unsigned int)DT3155_GET_CONFIG,
535              (unsigned int)DT3155_SET_CONFIG,
536              (unsigned int)DT3155_START,
537              (unsigned int)DT3155_STOP,
538              (unsigned int)DT3155_FLUSH);
539       return -EINVAL;
540     }
541
542   switch (cmd)
543     {
544     case DT3155_SET_CONFIG:
545       {
546         if (dt3155_status[minor].state != DT3155_STATE_IDLE)
547           return -EBUSY;
548
549         {
550           struct dt3155_config tmp;
551           if (copy_from_user(&tmp, up, sizeof(tmp)))
552               return -EFAULT;
553           /* check for valid settings */
554           if (tmp.rows > DT3155_MAX_ROWS ||
555               tmp.cols > DT3155_MAX_COLS ||
556               (tmp.acq_mode != DT3155_MODE_FRAME &&
557                tmp.acq_mode != DT3155_MODE_FIELD) ||
558               (tmp.continuous != DT3155_SNAP &&
559                tmp.continuous != DT3155_ACQ))
560             {
561               return -EINVAL;
562             }
563           dt3155_status[minor].config = tmp;
564         }
565         return 0;
566       }
567     case DT3155_GET_CONFIG:
568       {
569         if (copy_to_user(up, &dt3155_status[minor],
570                      sizeof(struct dt3155_status)))
571             return -EFAULT;
572         return 0;
573       }
574     case DT3155_FLUSH: /* Flushes the buffers -- ensures fresh data */
575       {
576         if (dt3155_status[minor].state != DT3155_STATE_IDLE)
577           return -EBUSY;
578         return dt3155_flush(minor);
579       }
580     case DT3155_STOP:
581       {
582         if (dt3155_status[minor].state & DT3155_STATE_STOP ||
583             dt3155_status[minor].fbuffer.stop_acquire)
584           return -EBUSY;
585
586         if (dt3155_status[minor].state == DT3155_STATE_IDLE)
587           return 0;
588
589         quick_stop(minor);
590         if (copy_to_user(up, &dt3155_status[minor],
591                      sizeof(struct dt3155_status)))
592             return -EFAULT;
593         return 0;
594       }
595     case DT3155_START:
596       {
597         if (dt3155_status[minor].state != DT3155_STATE_IDLE)
598           return -EBUSY;
599
600         dt3155_status[minor].fbuffer.stop_acquire = 0;
601         dt3155_status[minor].fbuffer.frame_count = 0;
602
603         /* Set the MODE in the status -- we default to FRAME */
604         if (dt3155_status[minor].config.acq_mode == DT3155_MODE_FIELD)
605           {
606             dt3155_status[minor].state = DT3155_STATE_FLD;
607           }
608         else
609           {
610             dt3155_status[minor].state = DT3155_STATE_FRAME;
611           }
612
613         dt3155_init_isr(minor);
614         if (copy_to_user(up, &dt3155_status[minor],
615                       sizeof(struct dt3155_status)))
616             return -EFAULT;
617         return 0;
618       }
619     default:
620       {
621         printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
622       printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
623              (unsigned int)DT3155_GET_CONFIG,
624              (unsigned int)DT3155_SET_CONFIG,
625              DT3155_START, DT3155_STOP, DT3155_FLUSH);
626         return -ENOSYS;
627       }
628     }
629   return -ENOSYS;
630 }
631
632 /*****************************************************
633  * mmap()
634  *
635  * only allow the user to mmap the registers and buffer
636  * It is quite possible that this is broken, since the
637  * addition of of the capacity for two cards!!!!!!!!
638  * It *looks* like it should work but since I'm not
639  * sure how to use it, I'm not actually sure. (NJC? ditto by SS)
640  *****************************************************/
641 static int dt3155_mmap (struct file * file, struct vm_area_struct * vma)
642 {
643   /* which device are we mmapping? */
644   int                           minor = MINOR(file->f_dentry->d_inode->i_rdev);
645   unsigned long offset;
646   offset = vma->vm_pgoff << PAGE_SHIFT;
647
648   if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
649     vma->vm_flags |= VM_IO;
650
651   /* Don't try to swap out physical pages.. */
652   vma->vm_flags |= VM_RESERVED;
653
654   /* they are mapping the registers or the buffer */
655   if ((offset == dt3155_status[minor].reg_addr &&
656        vma->vm_end - vma->vm_start == PCI_PAGE_SIZE) ||
657       (offset == dt3155_status[minor].mem_addr &&
658        vma->vm_end - vma->vm_start == dt3155_status[minor].mem_size))
659     {
660       if (remap_pfn_range(vma,
661                         vma->vm_start,
662                         offset >> PAGE_SHIFT,
663                         vma->vm_end - vma->vm_start,
664                         vma->vm_page_prot)) {
665           printk("DT3155: remap_page_range() failed.\n");
666           return -EAGAIN;
667         }
668     }
669   else
670     {
671       printk("DT3155: dt3155_mmap() bad call.\n");
672       return -ENXIO;
673     }
674
675   return 0;
676 }
677
678
679 /*****************************************************
680  * open()
681  *
682  * Our special open code.
683  * MOD_INC_USE_COUNT make sure that the driver memory is not freed
684  * while the device is in use.
685  *****************************************************/
686 static int dt3155_open(struct inode* inode, struct file* filep)
687 {
688   int minor = MINOR(inode->i_rdev); /* what device are we opening? */
689   if (dt3155_dev_open[minor]) {
690     printk ("DT3155:  Already opened by another process.\n");
691     return -EBUSY;
692   }
693
694   if (dt3155_status[minor].device_installed==0)
695     {
696       printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
697              minor);
698       return -EIO;
699     }
700
701   if (dt3155_status[minor].state != DT3155_STATE_IDLE) {
702     printk ("DT3155:  Not in idle state (state = %x)\n",
703             dt3155_status[minor].state);
704     return -EBUSY;
705   }
706
707   printk("DT3155: Device opened.\n");
708
709   dt3155_dev_open[minor] = 1 ;
710
711   dt3155_flush(minor);
712
713   /* Disable ALL interrupts */
714   int_csr_r.reg = 0;
715   WriteMReg((dt3155_lbase[minor] + INT_CSR), int_csr_r.reg);
716
717   init_waitqueue_head(&(dt3155_read_wait_queue[minor]));
718
719   return 0;
720 }
721
722
723 /*****************************************************
724  * close()
725  *
726  * Now decrement the use count.
727  *
728  *****************************************************/
729 static int dt3155_close(struct inode *inode, struct file *filep)
730 {
731   int minor;
732
733   minor = MINOR(inode->i_rdev); /* which device are we closing */
734   if (!dt3155_dev_open[minor])
735     {
736       printk("DT3155: attempt to CLOSE a not OPEN device\n");
737     }
738   else
739     {
740       dt3155_dev_open[minor] = 0;
741
742       if (dt3155_status[minor].state != DT3155_STATE_IDLE)
743         {
744           quick_stop(minor);
745         }
746     }
747   return 0;
748 }
749
750 /*****************************************************
751  * read()
752  *
753  *****************************************************/
754 static ssize_t dt3155_read(struct file *filep, char __user *buf,
755                            size_t count, loff_t *ppos)
756 {
757   /* which device are we reading from? */
758   int           minor = MINOR(filep->f_dentry->d_inode->i_rdev);
759   u32           offset;
760   int           frame_index;
761   struct frame_info     *frame_info;
762
763   /* TODO: this should check the error flag and */
764   /*   return an error on hardware failures */
765   if (count != sizeof(struct dt3155_read))
766     {
767       printk("DT3155 ERROR (NJC): count is not right\n");
768       return -EINVAL;
769     }
770
771
772   /* Hack here -- I'm going to allow reading even when idle.
773    * this is so that the frames can be read after STOP has
774    * been called.  Leaving it here, commented out, as a reminder
775    * for a short while to make sure there are no problems.
776    * Note that if the driver is not opened in non_blocking mode,
777    * and the device is idle, then it could sit here forever! */
778
779   /*  if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
780   /*    return -EBUSY;*/
781
782   /* non-blocking reads should return if no data */
783   if (filep->f_flags & O_NDELAY)
784     {
785       if ((frame_index = dt3155_get_ready_buffer(minor)) < 0) {
786         /*printk("dt3155:  no buffers available (?)\n");*/
787         /*              printques(minor); */
788         return -EAGAIN;
789       }
790     }
791   else
792     {
793       /*
794        * sleep till data arrives , or we get interrupted.
795        * Note that wait_event_interruptible() does not actually
796        * sleep/wait if it's condition evaluates to true upon entry.
797        */
798       wait_event_interruptible(dt3155_read_wait_queue[minor],
799                                (frame_index = dt3155_get_ready_buffer(minor))
800                                >= 0);
801
802       if (frame_index < 0)
803         {
804           printk ("DT3155: read: interrupted\n");
805           quick_stop (minor);
806           printques(minor);
807           return -EINTR;
808         }
809     }
810
811   frame_info = &dt3155_status[minor].fbuffer.frame_info[frame_index];
812
813   /* make this an offset */
814   offset = frame_info->addr - dt3155_status[minor].mem_addr;
815
816   put_user(offset, (unsigned int __user *)buf);
817   buf += sizeof(u32);
818   put_user(dt3155_status[minor].fbuffer.frame_count, (unsigned int __user *)buf);
819   buf += sizeof(u32);
820   put_user(dt3155_status[minor].state, (unsigned int __user *)buf);
821   buf += sizeof(u32);
822   if (copy_to_user(buf, frame_info, sizeof(*frame_info)))
823       return -EFAULT;
824
825   return sizeof(struct dt3155_read);
826 }
827
828 static unsigned int dt3155_poll (struct file * filp, poll_table *wait)
829 {
830   int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
831
832   if (!is_ready_buf_empty(minor))
833     return POLLIN | POLLRDNORM;
834
835   poll_wait (filp, &dt3155_read_wait_queue[minor], wait);
836
837   return 0;
838 }
839
840 static long
841 dt3155_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
842 {
843         int ret;
844
845         lock_kernel();
846         ret = dt3155_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
847         unlock_kernel();
848
849         return ret;
850 }
851
852 /*****************************************************
853  * file operations supported by DT3155 driver
854  *  needed by init_module
855  *  register_chrdev
856  *****************************************************/
857 static struct file_operations dt3155_fops = {
858         .read           = dt3155_read,
859         .unlocked_ioctl = dt3155_unlocked_ioctl,
860         .mmap           = dt3155_mmap,
861         .poll           = dt3155_poll,
862         .open           = dt3155_open,
863         .release        = dt3155_close
864 };
865
866
867 /*****************************************************
868  * find_PCI();
869  *
870  * PCI has been totally reworked in 2.1..
871  *****************************************************/
872 static int find_PCI (void)
873 {
874   struct pci_dev *pci_dev = NULL;
875   int error, pci_index = 0;
876   unsigned short rev_device;
877   unsigned long base;
878   unsigned char irq;
879
880   while ((pci_dev = pci_get_device
881           (DT3155_VENDORID, DT3155_DEVICEID, pci_dev)) != NULL)
882     {
883       pci_index ++;
884
885       /* Is it really there? */
886       if ((error =
887            pci_read_config_word(pci_dev, PCI_CLASS_DEVICE, &rev_device)))
888         continue;
889
890       /* Found a board */
891       DT_3155_DEBUG_MSG("DT3155: Device number %d \n", pci_index);
892
893       /* Make sure the driver was compiled with enough buffers to handle
894          this many boards */
895       if (pci_index > MAXBOARDS) {
896         printk("DT3155: ERROR - found %d devices, but driver only configured "
897                "for %d devices\n"
898                "DT3155: Please change MAXBOARDS in dt3155.h\n",
899                pci_index, MAXBOARDS);
900         goto err;
901       }
902
903       /* Now, just go out and make sure that this/these device(s) is/are
904          actually mapped into the kernel address space */
905       if ((error = pci_read_config_dword(pci_dev, PCI_BASE_ADDRESS_0,
906                                           (u32 *) &base)))
907         {
908           printk("DT3155: Was not able to find device \n");
909           goto err;
910         }
911
912       DT_3155_DEBUG_MSG("DT3155: Base address 0 for device is %lx \n", base);
913       dt3155_status[pci_index-1].reg_addr = base;
914
915       /* Remap the base address to a logical address through which we
916        * can access it. */
917       dt3155_lbase[pci_index - 1] = ioremap(base,PCI_PAGE_SIZE);
918       dt3155_status[pci_index - 1].reg_addr = base;
919       DT_3155_DEBUG_MSG("DT3155: New logical address is %p \n",
920                         dt3155_lbase[pci_index-1]);
921       if (!dt3155_lbase[pci_index-1])
922         {
923           printk("DT3155: Unable to remap control registers\n");
924           goto err;
925         }
926
927       if ((error = pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &irq)))
928         {
929           printk("DT3155: Was not able to find device \n");
930           goto err;
931         }
932
933       DT_3155_DEBUG_MSG("DT3155: IRQ is %d \n",irq);
934       dt3155_status[pci_index-1].irq = irq;
935       /* Set flag: kth device found! */
936       dt3155_status[pci_index-1].device_installed = 1;
937       printk("DT3155: Installing device %d w/irq %d and address %p\n",
938              pci_index,
939              dt3155_status[pci_index-1].irq,
940              dt3155_lbase[pci_index-1]);
941
942     }
943   ndevices = pci_index;
944
945   return DT_3155_SUCCESS;
946
947 err:
948   pci_dev_put(pci_dev);
949   return DT_3155_FAILURE;
950 }
951
952 u32 allocatorAddr = 0;
953
954 /*****************************************************
955  * init_module()
956  *****************************************************/
957 int init_module(void)
958 {
959   int index;
960   int rcode = 0;
961   char *devname[MAXBOARDS];
962
963   devname[0] = "dt3155a";
964 #if MAXBOARDS == 2
965   devname[1] = "dt3155b";
966 #endif
967
968   printk("DT3155: Loading module...\n");
969
970   /* Register the device driver */
971   rcode = register_chrdev(dt3155_major, "dt3155", &dt3155_fops);
972   if(rcode < 0)
973     {
974       printk(KERN_INFO "DT3155: register_chrdev failed \n");
975       return rcode;
976     }
977
978   if(dt3155_major == 0)
979     dt3155_major = rcode; /* dynamic */
980
981
982   /* init the status variables.                     */
983   /* DMA memory is taken care of in setup_buffers() */
984   for (index = 0; index < MAXBOARDS; index++)
985     {
986       dt3155_status[index].config.acq_mode   = DT3155_MODE_FRAME;
987       dt3155_status[index].config.continuous = DT3155_ACQ;
988       dt3155_status[index].config.cols       = DT3155_MAX_COLS;
989       dt3155_status[index].config.rows       = DT3155_MAX_ROWS;
990       dt3155_status[index].state = DT3155_STATE_IDLE;
991
992       /* find_PCI() will check if devices are installed; */
993       /* first assume they're not:                       */
994       dt3155_status[index].mem_addr          = 0;
995       dt3155_status[index].mem_size          = 0;
996       dt3155_status[index].state             = DT3155_STATE_IDLE;
997       dt3155_status[index].device_installed  = 0;
998     }
999
1000   /* Now let's find the hardware.  find_PCI() will set ndevices to the
1001    * number of cards found in this machine. */
1002     {
1003       if ((rcode = find_PCI()) !=  DT_3155_SUCCESS)
1004         {
1005           printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n");
1006           unregister_chrdev(dt3155_major, "dt3155");
1007           return rcode;
1008         }
1009     }
1010
1011   /* Ok, time to setup the frame buffers */
1012   if((rcode = dt3155_setup_buffers(&allocatorAddr)) < 0)
1013     {
1014       printk("DT3155: Error: setting up buffer not large enough.");
1015       unregister_chrdev(dt3155_major, "dt3155");
1016       return rcode;
1017     }
1018
1019   /* If we are this far, then there is enough RAM */
1020   /* for the buffers: Print the configuration.    */
1021   for( index = 0;  index < ndevices;  index++)
1022     {
1023       printk("DT3155: Device = %d; acq_mode = %d; "
1024              "continuous = %d; cols = %d; rows = %d;\n",
1025              index ,
1026              dt3155_status[index].config.acq_mode,
1027              dt3155_status[index].config.continuous,
1028              dt3155_status[index].config.cols,
1029              dt3155_status[index].config.rows);
1030       printk("DT3155: m_addr = 0x%x; m_size = %ld; "
1031              "state = %d; device_installed = %d\n",
1032              dt3155_status[index].mem_addr,
1033              (long int)dt3155_status[index].mem_size,
1034              dt3155_status[index].state,
1035              dt3155_status[index].device_installed);
1036     }
1037
1038   /* Disable ALL interrupts */
1039   int_csr_r.reg = 0;
1040   for( index = 0;  index < ndevices;  index++)
1041     {
1042       WriteMReg((dt3155_lbase[index] + INT_CSR), int_csr_r.reg);
1043       if(dt3155_status[index].device_installed)
1044         {
1045           /*
1046            * This driver *looks* like it can handle sharing interrupts,
1047            * but I can't actually test myself. I've had reports that it
1048            * DOES work so I'll enable it for now. This comment will remain
1049            * as a reminder in case any problems arise. (SS)
1050            */
1051           /* in older kernels flags are: SA_SHIRQ | SA_INTERRUPT */
1052           rcode = request_irq(dt3155_status[index].irq, (void *)dt3155_isr,
1053                                IRQF_SHARED | IRQF_DISABLED, devname[index],
1054                                (void*) &dt3155_status[index]);
1055           if(rcode < 0)
1056             {
1057               printk("DT3155: minor %d request_irq failed for IRQ %d\n",
1058                      index, dt3155_status[index].irq);
1059               unregister_chrdev(dt3155_major, "dt3155");
1060               return rcode;
1061             }
1062         }
1063     }
1064
1065   printk("DT3155: finished loading\n");
1066
1067   return 0;
1068 }
1069
1070 /*****************************************************
1071  * cleanup_module(void)
1072  *
1073  *****************************************************/
1074 void cleanup_module(void)
1075 {
1076   int index;
1077
1078   printk("DT3155:  cleanup_module called\n");
1079
1080   /* removed DMA allocated with the allocator */
1081 #ifdef STANDALONE_ALLOCATOR
1082   if (allocatorAddr != 0)
1083     allocator_free_dma(allocatorAddr);
1084 #else
1085   allocator_cleanup();
1086 #endif
1087
1088   unregister_chrdev(dt3155_major, "dt3155");
1089
1090   for(index = 0; index < ndevices; index++)
1091     {
1092       if(dt3155_status[index].device_installed == 1)
1093         {
1094           printk("DT3155: Freeing irq %d for device %d\n",
1095                   dt3155_status[index].irq, index);
1096           free_irq(dt3155_status[index].irq, (void*)&dt3155_status[index]);
1097         }
1098     }
1099 }
1100