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