staging: remove the b3dfg driver
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 23 Dec 2009 00:29:26 +0000 (16:29 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 4 Mar 2010 00:42:33 +0000 (16:42 -0800)
It has no users, and no developers to maintain it to get
it merged into mainline.

So sad.

Cc: Daniel Drake <ddrake@brontes3d.com>
Cc: Justin Bronder <jsbronder@brontes3d.com>
Cc: Duane Griffin <duaneg@dghda.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/b3dfg/Kconfig [deleted file]
drivers/staging/b3dfg/Makefile [deleted file]
drivers/staging/b3dfg/TODO [deleted file]
drivers/staging/b3dfg/b3dfg.c [deleted file]

index 02cde3989c5ce481ef0b797b4295eba4f4df13e0..a1dee5c59775b4f0e6a58e15022f4f328dd01316 100644 (file)
@@ -89,8 +89,6 @@ source "drivers/staging/dream/Kconfig"
 
 source "drivers/staging/pohmelfs/Kconfig"
 
-source "drivers/staging/b3dfg/Kconfig"
-
 source "drivers/staging/phison/Kconfig"
 
 source "drivers/staging/p9auth/Kconfig"
index 9d47d42e73cef66ba1eedae8e96cbde19ed93499..f7d34eec67404796666a958dff1c2d3d6ad7c0e2 100644 (file)
@@ -27,7 +27,6 @@ obj-$(CONFIG_INPUT_MIMIO)     += mimio/
 obj-$(CONFIG_TRANZPORT)                += frontier/
 obj-$(CONFIG_DREAM)            += dream/
 obj-$(CONFIG_POHMELFS)         += pohmelfs/
-obj-$(CONFIG_B3DFG)            += b3dfg/
 obj-$(CONFIG_IDE_PHISON)       += phison/
 obj-$(CONFIG_PLAN9AUTH)                += p9auth/
 obj-$(CONFIG_LINE6_USB)                += line6/
diff --git a/drivers/staging/b3dfg/Kconfig b/drivers/staging/b3dfg/Kconfig
deleted file mode 100644 (file)
index 9e6573c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-config B3DFG
-       tristate "Brontes 3d Frame Framegrabber"
-       depends on PCI
-       default n
-       ---help---
-         This driver provides support for the Brontes 3d Framegrabber
-         PCI card.
-
-         To compile this driver as a module, choose M here. The module
-         will be called b3dfg.
diff --git a/drivers/staging/b3dfg/Makefile b/drivers/staging/b3dfg/Makefile
deleted file mode 100644 (file)
index 91f439f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_B3DFG) += b3dfg.o
diff --git a/drivers/staging/b3dfg/TODO b/drivers/staging/b3dfg/TODO
deleted file mode 100644 (file)
index f5a9298..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-
- - queue/wait buffer presents filltime results for each frame?
- - counting of dropped frames
- - review endianness
diff --git a/drivers/staging/b3dfg/b3dfg.c b/drivers/staging/b3dfg/b3dfg.c
deleted file mode 100644 (file)
index 4a43c51..0000000
+++ /dev/null
@@ -1,1100 +0,0 @@
- /*
- * Brontes PCI frame grabber driver
- *
- * Copyright (C) 2008 3M Company
- * Contact: Justin Bronder <jsbronder@brontes3d.com>
- * Original Authors: Daniel Drake <ddrake@brontes3d.com>
- *                   Duane Griffin <duaneg@dghda.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/ioctl.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <linux/cdev.h>
-#include <linux/list.h>
-#include <linux/poll.h>
-#include <linux/wait.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-#include <linux/sched.h>
-
-static unsigned int b3dfg_nbuf = 2;
-
-module_param_named(buffer_count, b3dfg_nbuf, uint, 0444);
-
-MODULE_PARM_DESC(buffer_count, "Number of buffers (min 2, default 2)");
-
-MODULE_AUTHOR("Daniel Drake <ddrake@brontes3d.com>");
-MODULE_DESCRIPTION("Brontes frame grabber driver");
-MODULE_LICENSE("GPL");
-
-#define DRIVER_NAME "b3dfg"
-#define B3DFG_MAX_DEVS 4
-#define B3DFG_FRAMES_PER_BUFFER 3
-
-#define B3DFG_BAR_REGS 0
-#define B3DFG_REGS_LENGTH 0x10000
-
-#define B3DFG_IOC_MAGIC                0xb3 /* dfg :-) */
-#define B3DFG_IOCGFRMSZ                _IOR(B3DFG_IOC_MAGIC, 1, int)
-#define B3DFG_IOCTNUMBUFS      _IO(B3DFG_IOC_MAGIC, 2)
-#define B3DFG_IOCTTRANS                _IO(B3DFG_IOC_MAGIC, 3)
-#define B3DFG_IOCTQUEUEBUF     _IO(B3DFG_IOC_MAGIC, 4)
-#define B3DFG_IOCTPOLLBUF      _IOWR(B3DFG_IOC_MAGIC, 5, struct b3dfg_poll)
-#define B3DFG_IOCTWAITBUF      _IOWR(B3DFG_IOC_MAGIC, 6, struct b3dfg_wait)
-#define B3DFG_IOCGWANDSTAT     _IOR(B3DFG_IOC_MAGIC, 7, int)
-
-enum {
-       /* number of 4kb pages per frame */
-       B3D_REG_FRM_SIZE = 0x0,
-
-       /* bit 0: set to enable interrupts
-        * bit 1: set to enable cable status change interrupts */
-       B3D_REG_HW_CTRL = 0x4,
-
-       /* bit 0-1 - 1-based ID of next pending frame transfer (0 = none)
-        * bit 2 indicates the previous DMA transfer has completed
-        * bit 3 indicates wand cable status change
-        * bit 8:15 - counter of number of discarded triplets */
-       B3D_REG_DMA_STS = 0x8,
-
-       /* bit 0: wand status (1 = present, 0 = disconnected) */
-       B3D_REG_WAND_STS = 0xc,
-
-       /* bus address for DMA transfers. lower 2 bits must be zero because DMA
-        * works with 32 bit word size. */
-       B3D_REG_EC220_DMA_ADDR = 0x8000,
-
-       /* bit 20:0 - number of 32 bit words to be transferred
-        * bit 21:31 - reserved */
-       B3D_REG_EC220_TRF_SIZE = 0x8004,
-
-       /* bit 0 - error bit
-        * bit 1 - interrupt bit (set to generate interrupt at end of transfer)
-        * bit 2 - start bit (set to start transfer)
-        * bit 3 - direction (0 = DMA_TO_DEVICE, 1 = DMA_FROM_DEVICE
-        * bit 4:31 - reserved */
-       B3D_REG_EC220_DMA_STS = 0x8008,
-};
-
-enum b3dfg_buffer_state {
-       B3DFG_BUFFER_POLLED = 0,
-       B3DFG_BUFFER_PENDING,
-       B3DFG_BUFFER_POPULATED,
-};
-
-struct b3dfg_buffer {
-       unsigned char *frame[B3DFG_FRAMES_PER_BUFFER];
-       struct list_head list;
-       u8 state;
-};
-
-struct b3dfg_dev {
-
-       /* no protection needed: all finalized at initialization time */
-       struct pci_dev *pdev;
-       struct cdev chardev;
-       struct device *dev;
-       void __iomem *regs;
-       unsigned int frame_size;
-
-       /*
-        * Protects buffer state, including buffer_queue, triplet_ready,
-        * cur_dma_frame_idx & cur_dma_frame_addr.
-        */
-       spinlock_t buffer_lock;
-       struct b3dfg_buffer *buffers;
-       struct list_head buffer_queue;
-
-       /* Last frame in triplet transferred (-1 if none). */
-       int cur_dma_frame_idx;
-
-       /* Current frame's address for DMA. */
-       dma_addr_t cur_dma_frame_addr;
-
-       /*
-        * Protects cstate_tstamp.
-        * Nests inside buffer_lock.
-        */
-       spinlock_t cstate_lock;
-       unsigned long cstate_tstamp;
-
-       /*
-        * Protects triplets_dropped.
-        * Nests inside buffers_lock.
-        */
-       spinlock_t triplets_dropped_lock;
-       unsigned int triplets_dropped;
-
-       wait_queue_head_t buffer_waitqueue;
-
-       unsigned int transmission_enabled:1;
-       unsigned int triplet_ready:1;
-};
-
-static u8 b3dfg_devices[B3DFG_MAX_DEVS];
-
-static struct class *b3dfg_class;
-static dev_t b3dfg_devt;
-
-static const struct pci_device_id b3dfg_ids[] __devinitdata = {
-       { PCI_DEVICE(0x0b3d, 0x0001) },
-       { },
-};
-
-MODULE_DEVICE_TABLE(pci, b3dfg_ids);
-
-/***** user-visible types *****/
-
-struct b3dfg_poll {
-       int buffer_idx;
-       unsigned int triplets_dropped;
-};
-
-struct b3dfg_wait {
-       int buffer_idx;
-       unsigned int timeout;
-       unsigned int triplets_dropped;
-};
-
-/**** register I/O ****/
-
-static u32 b3dfg_read32(struct b3dfg_dev *fgdev, u16 reg)
-{
-       return ioread32(fgdev->regs + reg);
-}
-
-static void b3dfg_write32(struct b3dfg_dev *fgdev, u16 reg, u32 value)
-{
-       iowrite32(value, fgdev->regs + reg);
-}
-
-/**** buffer management ****/
-
-/*
- * Program EC220 for transfer of a specific frame.
- * Called with buffer_lock held.
- */
-static int setup_frame_transfer(struct b3dfg_dev *fgdev,
-       struct b3dfg_buffer *buf, int frame)
-{
-       unsigned char *frm_addr;
-       dma_addr_t frm_addr_dma;
-       unsigned int frm_size = fgdev->frame_size;
-
-       frm_addr = buf->frame[frame];
-       frm_addr_dma = pci_map_single(fgdev->pdev, frm_addr,
-                                         frm_size, PCI_DMA_FROMDEVICE);
-       if (pci_dma_mapping_error(fgdev->pdev, frm_addr_dma))
-               return -ENOMEM;
-
-       fgdev->cur_dma_frame_addr = frm_addr_dma;
-       fgdev->cur_dma_frame_idx = frame;
-
-       b3dfg_write32(fgdev, B3D_REG_EC220_DMA_ADDR,
-                                       cpu_to_le32(frm_addr_dma));
-       b3dfg_write32(fgdev, B3D_REG_EC220_TRF_SIZE,
-                                       cpu_to_le32(frm_size >> 2));
-       b3dfg_write32(fgdev, B3D_REG_EC220_DMA_STS, 0xf);
-
-       return 0;
-}
-
-/* Caller should hold buffer lock */
-static void dequeue_all_buffers(struct b3dfg_dev *fgdev)
-{
-       int i;
-       for (i = 0; i < b3dfg_nbuf; i++) {
-               struct b3dfg_buffer *buf = &fgdev->buffers[i];
-               buf->state = B3DFG_BUFFER_POLLED;
-               list_del_init(&buf->list);
-       }
-}
-
-/* queue a buffer to receive data */
-static int queue_buffer(struct b3dfg_dev *fgdev, int bufidx)
-{
-       struct device *dev = &fgdev->pdev->dev;
-       struct b3dfg_buffer *buf;
-       unsigned long flags;
-       int r = 0;
-
-       spin_lock_irqsave(&fgdev->buffer_lock, flags);
-       if (bufidx < 0 || bufidx >= b3dfg_nbuf) {
-               dev_dbg(dev, "Invalid buffer index, %d\n", bufidx);
-               r = -ENOENT;
-               goto out;
-       }
-       buf = &fgdev->buffers[bufidx];
-
-       if (unlikely(buf->state == B3DFG_BUFFER_PENDING)) {
-               dev_dbg(dev, "buffer %d is already queued\n", bufidx);
-               r = -EINVAL;
-               goto out;
-       }
-
-       buf->state = B3DFG_BUFFER_PENDING;
-       list_add_tail(&buf->list, &fgdev->buffer_queue);
-
-       if (fgdev->transmission_enabled && fgdev->triplet_ready) {
-               dev_dbg(dev, "triplet is ready, pushing immediately\n");
-               fgdev->triplet_ready = 0;
-               r = setup_frame_transfer(fgdev, buf, 0);
-               if (r)
-                       dev_err(dev, "unable to map DMA buffer\n");
-       }
-
-out:
-       spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-       return r;
-}
-
-/* non-blocking buffer poll. returns 1 if data is present in the buffer,
- * 0 otherwise */
-static int poll_buffer(struct b3dfg_dev *fgdev, void __user *arg)
-{
-       struct device *dev = &fgdev->pdev->dev;
-       struct b3dfg_poll p;
-       struct b3dfg_buffer *buf;
-       unsigned long flags;
-       int r = 1;
-       int arg_out = 0;
-
-       if (copy_from_user(&p, arg, sizeof(p)))
-               return -EFAULT;
-
-       if (unlikely(!fgdev->transmission_enabled)) {
-               dev_dbg(dev, "cannot poll, transmission disabled\n");
-               return -EINVAL;
-       }
-
-       if (p.buffer_idx < 0 || p.buffer_idx >= b3dfg_nbuf)
-               return -ENOENT;
-
-       buf = &fgdev->buffers[p.buffer_idx];
-
-       spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
-       if (likely(buf->state == B3DFG_BUFFER_POPULATED)) {
-               arg_out = 1;
-               buf->state = B3DFG_BUFFER_POLLED;
-
-               /* IRQs already disabled by spin_lock_irqsave above. */
-               spin_lock(&fgdev->triplets_dropped_lock);
-               p.triplets_dropped = fgdev->triplets_dropped;
-               fgdev->triplets_dropped = 0;
-               spin_unlock(&fgdev->triplets_dropped_lock);
-       } else {
-               r = 0;
-       }
-
-       spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-       if (arg_out && copy_to_user(arg, &p, sizeof(p)))
-               r = -EFAULT;
-
-       return r;
-}
-
-static unsigned long get_cstate_change(struct b3dfg_dev *fgdev)
-{
-       unsigned long flags, when;
-
-       spin_lock_irqsave(&fgdev->cstate_lock, flags);
-       when = fgdev->cstate_tstamp;
-       spin_unlock_irqrestore(&fgdev->cstate_lock, flags);
-       return when;
-}
-
-static int is_event_ready(struct b3dfg_dev *fgdev, struct b3dfg_buffer *buf,
-                         unsigned long when)
-{
-       int result;
-       unsigned long flags;
-
-       spin_lock_irqsave(&fgdev->buffer_lock, flags);
-       spin_lock(&fgdev->cstate_lock);
-       result = (!fgdev->transmission_enabled ||
-                 buf->state == B3DFG_BUFFER_POPULATED ||
-                 when != fgdev->cstate_tstamp);
-       spin_unlock(&fgdev->cstate_lock);
-       spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-       return result;
-}
-
-/* sleep until a specific buffer becomes populated */
-static int wait_buffer(struct b3dfg_dev *fgdev, void __user *arg)
-{
-       struct device *dev = &fgdev->pdev->dev;
-       struct b3dfg_wait w;
-       struct b3dfg_buffer *buf;
-       unsigned long flags, when;
-       int r;
-
-       if (copy_from_user(&w, arg, sizeof(w)))
-               return -EFAULT;
-
-       if (!fgdev->transmission_enabled) {
-               dev_dbg(dev, "cannot wait, transmission disabled\n");
-               return -EINVAL;
-       }
-
-       if (w.buffer_idx < 0 || w.buffer_idx >= b3dfg_nbuf)
-               return -ENOENT;
-
-       buf = &fgdev->buffers[w.buffer_idx];
-
-       spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
-       if (buf->state == B3DFG_BUFFER_POPULATED) {
-               r = w.timeout;
-               goto out_triplets_dropped;
-       }
-
-       spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-       when = get_cstate_change(fgdev);
-       if (w.timeout > 0) {
-               r = wait_event_interruptible_timeout(fgdev->buffer_waitqueue,
-                       is_event_ready(fgdev, buf, when),
-                       (w.timeout * HZ) / 1000);
-
-               if (unlikely(r < 0))
-                       goto out;
-
-               w.timeout = r * 1000 / HZ;
-       } else {
-               r = wait_event_interruptible(fgdev->buffer_waitqueue,
-                       is_event_ready(fgdev, buf, when));
-
-               if (unlikely(r)) {
-                       r = -ERESTARTSYS;
-                       goto out;
-               }
-       }
-
-       /* TODO: Inform the user via field(s) in w? */
-       if (!fgdev->transmission_enabled || when != get_cstate_change(fgdev)) {
-               r = -EINVAL;
-               goto out;
-       }
-
-       spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
-       if (buf->state != B3DFG_BUFFER_POPULATED) {
-               r = -ETIMEDOUT;
-               goto out_unlock;
-       }
-
-       buf->state = B3DFG_BUFFER_POLLED;
-
-out_triplets_dropped:
-
-       /* IRQs already disabled by spin_lock_irqsave above. */
-       spin_lock(&fgdev->triplets_dropped_lock);
-       w.triplets_dropped = fgdev->triplets_dropped;
-       fgdev->triplets_dropped = 0;
-       spin_unlock(&fgdev->triplets_dropped_lock);
-
-out_unlock:
-       spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-       if (copy_to_user(arg, &w, sizeof(w)))
-               r = -EFAULT;
-out:
-       return r;
-}
-
-/* mmap page fault handler */
-static int b3dfg_vma_fault(struct vm_area_struct *vma,
-       struct vm_fault *vmf)
-{
-       struct b3dfg_dev *fgdev = vma->vm_file->private_data;
-       unsigned long off = vmf->pgoff << PAGE_SHIFT;
-       unsigned int frame_size = fgdev->frame_size;
-       unsigned int buf_size = frame_size * B3DFG_FRAMES_PER_BUFFER;
-       unsigned char *addr;
-
-       /* determine which buffer the offset lies within */
-       unsigned int buf_idx = off / buf_size;
-       /* and the offset into the buffer */
-       unsigned int buf_off = off % buf_size;
-
-       /* determine which frame inside the buffer the offset lies in */
-       unsigned int frm_idx = buf_off / frame_size;
-       /* and the offset into the frame */
-       unsigned int frm_off = buf_off % frame_size;
-
-       if (unlikely(buf_idx >= b3dfg_nbuf))
-               return VM_FAULT_SIGBUS;
-
-       addr = fgdev->buffers[buf_idx].frame[frm_idx] + frm_off;
-       vm_insert_pfn(vma, (unsigned long)vmf->virtual_address,
-                         virt_to_phys(addr) >> PAGE_SHIFT);
-
-       return VM_FAULT_NOPAGE;
-}
-
-static struct vm_operations_struct b3dfg_vm_ops = {
-       .fault = b3dfg_vma_fault,
-};
-
-static int get_wand_status(struct b3dfg_dev *fgdev, int __user *arg)
-{
-       u32 wndstat = b3dfg_read32(fgdev, B3D_REG_WAND_STS);
-       dev_dbg(&fgdev->pdev->dev, "wand status %x\n", wndstat);
-       return __put_user(wndstat & 0x1, arg);
-}
-
-static int enable_transmission(struct b3dfg_dev *fgdev)
-{
-       unsigned long flags;
-       struct device *dev = &fgdev->pdev->dev;
-
-       dev_dbg(dev, "enable transmission\n");
-
-       /* check the cable is plugged in. */
-       if (!b3dfg_read32(fgdev, B3D_REG_WAND_STS)) {
-               dev_dbg(dev, "cannot start transmission without wand\n");
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
-       /* Handle racing enable_transmission calls. */
-       if (fgdev->transmission_enabled) {
-               spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-               goto out;
-       }
-
-       spin_lock(&fgdev->triplets_dropped_lock);
-       fgdev->triplets_dropped = 0;
-       spin_unlock(&fgdev->triplets_dropped_lock);
-
-       fgdev->triplet_ready = 0;
-       fgdev->cur_dma_frame_idx = -1;
-       fgdev->transmission_enabled = 1;
-
-       spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-       /* Enable DMA and cable status interrupts. */
-       b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0x03);
-
-out:
-       return 0;
-}
-
-static void disable_transmission(struct b3dfg_dev *fgdev)
-{
-       struct device *dev = &fgdev->pdev->dev;
-       unsigned long flags;
-       u32 tmp;
-
-       dev_dbg(dev, "disable transmission\n");
-
-       /* guarantee that no more interrupts will be serviced */
-       spin_lock_irqsave(&fgdev->buffer_lock, flags);
-       fgdev->transmission_enabled = 0;
-
-       b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0);
-
-       /* FIXME: temporary debugging only. if the board stops transmitting,
-        * hitting ctrl+c and seeing this message is useful for determining
-        * the state of the board. */
-       tmp = b3dfg_read32(fgdev, B3D_REG_DMA_STS);
-       dev_dbg(dev, "DMA_STS reads %x after TX stopped\n", tmp);
-
-       dequeue_all_buffers(fgdev);
-       spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-       wake_up_interruptible(&fgdev->buffer_waitqueue);
-}
-
-static int set_transmission(struct b3dfg_dev *fgdev, int enabled)
-{
-       int res = 0;
-
-       if (enabled && !fgdev->transmission_enabled)
-               res = enable_transmission(fgdev);
-       else if (!enabled && fgdev->transmission_enabled)
-               disable_transmission(fgdev);
-
-       return res;
-}
-
-/* Called in interrupt context. */
-static void handle_cstate_unplug(struct b3dfg_dev *fgdev)
-{
-       /* Disable all interrupts. */
-       b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0);
-
-       /* Stop transmission. */
-       spin_lock(&fgdev->buffer_lock);
-       fgdev->transmission_enabled = 0;
-
-       fgdev->cur_dma_frame_idx = -1;
-       fgdev->triplet_ready = 0;
-       if (fgdev->cur_dma_frame_addr) {
-               pci_unmap_single(fgdev->pdev, fgdev->cur_dma_frame_addr,
-                                fgdev->frame_size, PCI_DMA_FROMDEVICE);
-               fgdev->cur_dma_frame_addr = 0;
-       }
-       dequeue_all_buffers(fgdev);
-       spin_unlock(&fgdev->buffer_lock);
-}
-
-/* Called in interrupt context. */
-static void handle_cstate_change(struct b3dfg_dev *fgdev)
-{
-       u32 cstate = b3dfg_read32(fgdev, B3D_REG_WAND_STS);
-       unsigned long when;
-       struct device *dev = &fgdev->pdev->dev;
-
-       dev_dbg(dev, "cable state change: %u\n", cstate);
-
-       /*
-        * When the wand is unplugged we reset our state. The hardware will
-        * have done the same internally.
-        *
-        * Note we should never see a cable *plugged* event, as interrupts
-        * should only be enabled when transmitting, which requires the cable
-        * to be plugged. If we do see one it probably means the cable has been
-        * unplugged and re-plugged very rapidly. Possibly because it has a
-        * broken wire and is momentarily losing contact.
-        *
-        * TODO: At the moment if you plug in the cable then enable transmission
-        * the hardware will raise a couple of spurious interrupts, so
-        * just ignore them for now.
-        *
-        * Once the hardware is fixed we should complain and treat it as an
-        * unplug. Or at least track how frequently it is happening and do
-        * so if too many come in.
-        */
-       if (cstate) {
-               dev_warn(dev, "ignoring unexpected plug event\n");
-               return;
-       }
-       handle_cstate_unplug(fgdev);
-
-       /*
-        * Record cable state change timestamp & wake anyone waiting
-        * on a cable state change. Be paranoid about ensuring events
-        * are not missed if we somehow get two interrupts in a jiffy.
-        */
-       spin_lock(&fgdev->cstate_lock);
-       when = jiffies_64;
-       if (when <= fgdev->cstate_tstamp)
-               when = fgdev->cstate_tstamp + 1;
-       fgdev->cstate_tstamp = when;
-       wake_up_interruptible(&fgdev->buffer_waitqueue);
-       spin_unlock(&fgdev->cstate_lock);
-}
-
-/* Called with buffer_lock held. */
-static void transfer_complete(struct b3dfg_dev *fgdev)
-{
-       struct b3dfg_buffer *buf;
-       struct device *dev = &fgdev->pdev->dev;
-
-       pci_unmap_single(fgdev->pdev, fgdev->cur_dma_frame_addr,
-                        fgdev->frame_size, PCI_DMA_FROMDEVICE);
-       fgdev->cur_dma_frame_addr = 0;
-
-       buf = list_entry(fgdev->buffer_queue.next, struct b3dfg_buffer, list);
-
-       dev_dbg(dev, "handle frame completion\n");
-       if (fgdev->cur_dma_frame_idx == B3DFG_FRAMES_PER_BUFFER - 1) {
-
-               /* last frame of that triplet completed */
-               dev_dbg(dev, "triplet completed\n");
-               buf->state = B3DFG_BUFFER_POPULATED;
-               list_del_init(&buf->list);
-               wake_up_interruptible(&fgdev->buffer_waitqueue);
-       }
-}
-
-/*
- * Called with buffer_lock held.
- *
- * Note that idx is the (1-based) *next* frame to be transferred, while
- * cur_dma_frame_idx is the (0-based) *last* frame to have been transferred (or
- * -1 if none). Thus there should be a difference of 2 between them.
- */
-static bool setup_next_frame_transfer(struct b3dfg_dev *fgdev, int idx)
-{
-       struct b3dfg_buffer *buf;
-       struct device *dev = &fgdev->pdev->dev;
-       bool need_ack = 1;
-
-       dev_dbg(dev, "program DMA transfer for next frame: %d\n", idx);
-
-       buf = list_entry(fgdev->buffer_queue.next, struct b3dfg_buffer, list);
-       if (idx == fgdev->cur_dma_frame_idx + 2) {
-               if (setup_frame_transfer(fgdev, buf, idx - 1))
-                       dev_err(dev, "unable to map DMA buffer\n");
-               need_ack = 0;
-       } else {
-               dev_err(dev, "frame mismatch, got %d, expected %d\n",
-                       idx, fgdev->cur_dma_frame_idx + 2);
-
-               /* FIXME: handle dropped triplets here */
-       }
-
-       return need_ack;
-}
-
-static irqreturn_t b3dfg_intr(int irq, void *dev_id)
-{
-       struct b3dfg_dev *fgdev = dev_id;
-       struct device *dev = &fgdev->pdev->dev;
-       u32 sts;
-       u8 dropped;
-       bool need_ack = 1;
-       irqreturn_t res = IRQ_HANDLED;
-
-       sts = b3dfg_read32(fgdev, B3D_REG_DMA_STS);
-       if (unlikely(sts == 0)) {
-               dev_warn(dev, "ignore interrupt, DMA status is 0\n");
-               res = IRQ_NONE;
-               goto out;
-       }
-
-       if (unlikely(!fgdev->transmission_enabled)) {
-               dev_warn(dev, "ignore interrupt, TX disabled\n");
-               res = IRQ_HANDLED;
-               goto out;
-       }
-
-       /* Handle dropped frames, as reported by the hardware. */
-       dropped = (sts >> 8) & 0xff;
-       dev_dbg(dev, "intr: DMA_STS=%08x (drop=%d comp=%d next=%d)\n",
-               sts, dropped, !!(sts & 0x4), sts & 0x3);
-       if (unlikely(dropped > 0)) {
-               spin_lock(&fgdev->triplets_dropped_lock);
-               fgdev->triplets_dropped += dropped;
-               spin_unlock(&fgdev->triplets_dropped_lock);
-       }
-
-       /* Handle a cable state change (i.e. the wand being unplugged). */
-       if (sts & 0x08) {
-               handle_cstate_change(fgdev);
-               goto out;
-       }
-
-       spin_lock(&fgdev->buffer_lock);
-       if (unlikely(list_empty(&fgdev->buffer_queue))) {
-
-               /* FIXME need more sanity checking here */
-               dev_info(dev, "buffer not ready for next transfer\n");
-               fgdev->triplet_ready = 1;
-               goto out_unlock;
-       }
-
-       /* Has a frame transfer been completed? */
-       if (sts & 0x4) {
-               u32 dma_status = b3dfg_read32(fgdev, B3D_REG_EC220_DMA_STS);
-
-               /* Check for DMA errors reported by the hardware. */
-               if (unlikely(dma_status & 0x1)) {
-                       dev_err(dev, "EC220 error: %08x\n", dma_status);
-
-                       /* FIXME flesh out error handling */
-                       goto out_unlock;
-               }
-
-               /* Sanity check, we should have a frame index at this point. */
-               if (unlikely(fgdev->cur_dma_frame_idx == -1)) {
-                       dev_err(dev, "completed but no last idx?\n");
-
-                       /* FIXME flesh out error handling */
-                       goto out_unlock;
-               }
-
-               transfer_complete(fgdev);
-       }
-
-       /* Is there another frame transfer pending? */
-       if (sts & 0x3)
-               need_ack = setup_next_frame_transfer(fgdev, sts & 0x3);
-       else
-               fgdev->cur_dma_frame_idx = -1;
-
-out_unlock:
-       spin_unlock(&fgdev->buffer_lock);
-out:
-       if (need_ack) {
-               dev_dbg(dev, "acknowledging interrupt\n");
-               b3dfg_write32(fgdev, B3D_REG_EC220_DMA_STS, 0x0b);
-       }
-       return res;
-}
-
-static int b3dfg_open(struct inode *inode, struct file *filp)
-{
-       struct b3dfg_dev *fgdev =
-               container_of(inode->i_cdev, struct b3dfg_dev, chardev);
-
-       dev_dbg(&fgdev->pdev->dev, "open\n");
-       filp->private_data = fgdev;
-       return 0;
-}
-
-static int b3dfg_release(struct inode *inode, struct file *filp)
-{
-       struct b3dfg_dev *fgdev = filp->private_data;
-       dev_dbg(&fgdev->pdev->dev, "release\n");
-       disable_transmission(fgdev);
-       return 0;
-}
-
-static long b3dfg_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       struct b3dfg_dev *fgdev = filp->private_data;
-
-       switch (cmd) {
-       case B3DFG_IOCGFRMSZ:
-               return __put_user(fgdev->frame_size, (int __user *) arg);
-       case B3DFG_IOCGWANDSTAT:
-               return get_wand_status(fgdev, (int __user *) arg);
-       case B3DFG_IOCTTRANS:
-               return set_transmission(fgdev, (int) arg);
-       case B3DFG_IOCTQUEUEBUF:
-               return queue_buffer(fgdev, (int) arg);
-       case B3DFG_IOCTPOLLBUF:
-               return poll_buffer(fgdev, (void __user *) arg);
-       case B3DFG_IOCTWAITBUF:
-               return wait_buffer(fgdev, (void __user *) arg);
-       default:
-               dev_dbg(&fgdev->pdev->dev, "unrecognised ioctl %x\n", cmd);
-               return -EINVAL;
-       }
-}
-
-static unsigned int b3dfg_poll(struct file *filp, poll_table *poll_table)
-{
-       struct b3dfg_dev *fgdev = filp->private_data;
-       unsigned long flags, when;
-       int i;
-       int r = 0;
-
-       when = get_cstate_change(fgdev);
-       poll_wait(filp, &fgdev->buffer_waitqueue, poll_table);
-
-       spin_lock_irqsave(&fgdev->buffer_lock, flags);
-       for (i = 0; i < b3dfg_nbuf; i++) {
-               if (fgdev->buffers[i].state == B3DFG_BUFFER_POPULATED) {
-                       r = POLLIN | POLLRDNORM;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-       /* TODO: Confirm this is how we want to communicate the change. */
-       if (!fgdev->transmission_enabled || when != get_cstate_change(fgdev))
-               r = POLLERR;
-
-       return r;
-}
-
-static int b3dfg_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       struct b3dfg_dev *fgdev = filp->private_data;
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       unsigned long vsize = vma->vm_end - vma->vm_start;
-       unsigned long bufdatalen = b3dfg_nbuf * fgdev->frame_size * 3;
-       unsigned long psize = bufdatalen - offset;
-       int r = 0;
-
-       if (vsize <= psize) {
-               vma->vm_flags |= VM_IO | VM_RESERVED | VM_CAN_NONLINEAR |
-                                VM_PFNMAP;
-               vma->vm_ops = &b3dfg_vm_ops;
-       } else {
-               r = -EINVAL;
-       }
-
-       return r;
-}
-
-static struct file_operations b3dfg_fops = {
-       .owner = THIS_MODULE,
-       .open = b3dfg_open,
-       .release = b3dfg_release,
-       .unlocked_ioctl = b3dfg_ioctl,
-       .poll = b3dfg_poll,
-       .mmap = b3dfg_mmap,
-};
-
-static void free_all_frame_buffers(struct b3dfg_dev *fgdev)
-{
-       int i, j;
-       for (i = 0; i < b3dfg_nbuf; i++)
-               for (j = 0; j < B3DFG_FRAMES_PER_BUFFER; j++)
-                       kfree(fgdev->buffers[i].frame[j]);
-       kfree(fgdev->buffers);
-}
-
-/* initialize device and any data structures. called before any interrupts
- * are enabled. */
-static int b3dfg_init_dev(struct b3dfg_dev *fgdev)
-{
-       int i, j;
-       u32 frm_size = b3dfg_read32(fgdev, B3D_REG_FRM_SIZE);
-
-       /* Disable interrupts. In abnormal circumstances (e.g. after a crash)
-        * the board may still be transmitting from the previous session. If we
-        * ensure that interrupts are disabled before we later enable them, we
-        * are sure to capture a triplet from the start, rather than starting
-        * from frame 2 or 3. Disabling interrupts causes the FG to throw away
-        * all buffered data and stop buffering more until interrupts are
-        * enabled again.
-        */
-       b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0);
-
-       fgdev->frame_size = frm_size * 4096;
-       fgdev->buffers = kzalloc(sizeof(struct b3dfg_buffer) * b3dfg_nbuf,
-                                GFP_KERNEL);
-       if (!fgdev->buffers)
-               goto err_no_buf;
-       for (i = 0; i < b3dfg_nbuf; i++) {
-               struct b3dfg_buffer *buf = &fgdev->buffers[i];
-               for (j = 0; j < B3DFG_FRAMES_PER_BUFFER; j++) {
-                       buf->frame[j] = kmalloc(fgdev->frame_size, GFP_KERNEL);
-                       if (!buf->frame[j])
-                               goto err_no_mem;
-               }
-               INIT_LIST_HEAD(&buf->list);
-       }
-
-       INIT_LIST_HEAD(&fgdev->buffer_queue);
-       init_waitqueue_head(&fgdev->buffer_waitqueue);
-       spin_lock_init(&fgdev->buffer_lock);
-       spin_lock_init(&fgdev->cstate_lock);
-       spin_lock_init(&fgdev->triplets_dropped_lock);
-       return 0;
-
-err_no_mem:
-       free_all_frame_buffers(fgdev);
-err_no_buf:
-       return -ENOMEM;
-}
-
-/* find next free minor number, returns -1 if none are availabile */
-static int get_free_minor(void)
-{
-       int i;
-       for (i = 0; i < B3DFG_MAX_DEVS; i++) {
-               if (b3dfg_devices[i] == 0)
-                       return i;
-       }
-       return -1;
-}
-
-static int __devinit b3dfg_probe(struct pci_dev *pdev,
-       const struct pci_device_id *id)
-{
-       struct b3dfg_dev *fgdev = kzalloc(sizeof(*fgdev), GFP_KERNEL);
-       int r = 0;
-       int minor = get_free_minor();
-       dev_t devno = MKDEV(MAJOR(b3dfg_devt), minor);
-       unsigned long res_len;
-       resource_size_t res_base;
-
-       if (fgdev == NULL)
-               return -ENOMEM;
-
-       if (minor < 0) {
-               dev_err(&pdev->dev, "too many devices found!\n");
-               r = -EIO;
-               goto err_free;
-       }
-
-       b3dfg_devices[minor] = 1;
-       dev_info(&pdev->dev, "probe device with IRQ %d\n", pdev->irq);
-
-       cdev_init(&fgdev->chardev, &b3dfg_fops);
-       fgdev->chardev.owner = THIS_MODULE;
-
-       r = cdev_add(&fgdev->chardev, devno, 1);
-       if (r) {
-               dev_err(&pdev->dev, "cannot add char device\n");
-               goto err_release_minor;
-       }
-
-       fgdev->dev = device_create(
-               b3dfg_class,
-               &pdev->dev,
-               devno,
-               dev_get_drvdata(&pdev->dev),
-               DRIVER_NAME "%d", minor);
-
-       if (IS_ERR(fgdev->dev)) {
-               dev_err(&pdev->dev, "cannot create device\n");
-               r = PTR_ERR(fgdev->dev);
-               goto err_del_cdev;
-       }
-
-       r = pci_enable_device(pdev);
-       if (r) {
-               dev_err(&pdev->dev, "cannot enable PCI device\n");
-               goto err_dev_unreg;
-       }
-
-       res_len = pci_resource_len(pdev, B3DFG_BAR_REGS);
-       if (res_len != B3DFG_REGS_LENGTH) {
-               dev_err(&pdev->dev, "invalid register resource size\n");
-               r = -EIO;
-               goto err_disable;
-       }
-
-       if (pci_resource_flags(pdev, B3DFG_BAR_REGS)
-                               != (IORESOURCE_MEM | IORESOURCE_SIZEALIGN)) {
-               dev_err(&pdev->dev, "invalid resource flags\n");
-               r = -EIO;
-               goto err_disable;
-       }
-       r = pci_request_regions(pdev, DRIVER_NAME);
-       if (r) {
-               dev_err(&pdev->dev, "cannot obtain PCI resources\n");
-               goto err_disable;
-       }
-
-       pci_set_master(pdev);
-
-       r = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-       if (r) {
-               dev_err(&pdev->dev, "no usable DMA configuration\n");
-               goto err_free_res;
-       }
-
-       res_base = pci_resource_start(pdev, B3DFG_BAR_REGS);
-       fgdev->regs = ioremap_nocache(res_base, res_len);
-       if (!fgdev->regs) {
-               dev_err(&pdev->dev, "regs ioremap failed\n");
-               r = -EIO;
-               goto err_free_res;
-       }
-
-       fgdev->pdev = pdev;
-       pci_set_drvdata(pdev, fgdev);
-       r = b3dfg_init_dev(fgdev);
-       if (r < 0) {
-               dev_err(&pdev->dev, "failed to initalize device\n");
-               goto err_unmap;
-       }
-
-       r = request_irq(pdev->irq, b3dfg_intr, IRQF_SHARED, DRIVER_NAME, fgdev);
-       if (r) {
-               dev_err(&pdev->dev, "couldn't request irq %d\n", pdev->irq);
-               goto err_free_bufs;
-       }
-
-       return 0;
-
-err_free_bufs:
-       free_all_frame_buffers(fgdev);
-err_unmap:
-       iounmap(fgdev->regs);
-err_free_res:
-       pci_release_regions(pdev);
-err_disable:
-       pci_disable_device(pdev);
-err_dev_unreg:
-       device_destroy(b3dfg_class, devno);
-err_del_cdev:
-       cdev_del(&fgdev->chardev);
-err_release_minor:
-       b3dfg_devices[minor] = 0;
-err_free:
-       kfree(fgdev);
-       return r;
-}
-
-static void __devexit b3dfg_remove(struct pci_dev *pdev)
-{
-       struct b3dfg_dev *fgdev = pci_get_drvdata(pdev);
-       unsigned int minor = MINOR(fgdev->chardev.dev);
-
-       dev_dbg(&pdev->dev, "remove\n");
-
-       free_irq(pdev->irq, fgdev);
-       iounmap(fgdev->regs);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       device_destroy(b3dfg_class, MKDEV(MAJOR(b3dfg_devt), minor));
-       cdev_del(&fgdev->chardev);
-       free_all_frame_buffers(fgdev);
-       kfree(fgdev);
-       b3dfg_devices[minor] = 0;
-}
-
-static struct pci_driver b3dfg_driver = {
-       .name = DRIVER_NAME,
-       .id_table = b3dfg_ids,
-       .probe = b3dfg_probe,
-       .remove = __devexit_p(b3dfg_remove),
-};
-
-static int __init b3dfg_module_init(void)
-{
-       int r;
-
-       if (b3dfg_nbuf < 2) {
-               printk(KERN_ERR DRIVER_NAME
-                          ": buffer_count is out of range (must be >= 2)");
-               return -EINVAL;
-       }
-
-       printk(KERN_INFO DRIVER_NAME ": loaded\n");
-
-       b3dfg_class = class_create(THIS_MODULE, DRIVER_NAME);
-       if (IS_ERR(b3dfg_class))
-               return PTR_ERR(b3dfg_class);
-
-       r = alloc_chrdev_region(&b3dfg_devt, 0, B3DFG_MAX_DEVS, DRIVER_NAME);
-       if (r)
-               goto err1;
-
-       r = pci_register_driver(&b3dfg_driver);
-       if (r)
-               goto err2;
-
-       return r;
-
-err2:
-       unregister_chrdev_region(b3dfg_devt, B3DFG_MAX_DEVS);
-err1:
-       class_destroy(b3dfg_class);
-       return r;
-}
-
-static void __exit b3dfg_module_exit(void)
-{
-       printk(KERN_INFO DRIVER_NAME ": unloaded\n");
-       pci_unregister_driver(&b3dfg_driver);
-       unregister_chrdev_region(b3dfg_devt, B3DFG_MAX_DEVS);
-       class_destroy(b3dfg_class);
-}
-
-module_init(b3dfg_module_init);
-module_exit(b3dfg_module_exit);