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