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