Staging: altpciechdma: remove driver
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 23 Dec 2009 00:38:10 +0000 (16:38 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 4 Mar 2010 00:42:34 +0000 (16:42 -0800)
No one seems to be able to maintain this, or merge it into mainline, so
remove it.

Acked-by: Leon Woestenberg <leon@sidebranch.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/altpciechdma/Kconfig [deleted file]
drivers/staging/altpciechdma/Makefile [deleted file]
drivers/staging/altpciechdma/TODO [deleted file]
drivers/staging/altpciechdma/altpciechdma.c [deleted file]

index e43cab46e2cb83dddd43c498ceaec4b4aba18b25..9543174360bf49d11885ace86770efc09c14170e 100644 (file)
@@ -71,8 +71,6 @@ source "drivers/staging/asus_oled/Kconfig"
 
 source "drivers/staging/panel/Kconfig"
 
-source "drivers/staging/altpciechdma/Kconfig"
-
 source "drivers/staging/rtl8187se/Kconfig"
 
 source "drivers/staging/rtl8192su/Kconfig"
index c2f0ca9a7a15ff977b9e997db0b40d3a09641de9..394327a1f789bf5f903f1dbdb6950a09d7709594 100644 (file)
@@ -18,7 +18,6 @@ obj-$(CONFIG_RT2870)          += rt2870/
 obj-$(CONFIG_COMEDI)           += comedi/
 obj-$(CONFIG_ASUS_OLED)                += asus_oled/
 obj-$(CONFIG_PANEL)            += panel/
-obj-$(CONFIG_ALTERA_PCIE_CHDMA)        += altpciechdma/
 obj-$(CONFIG_R8187SE)          += rtl8187se/
 obj-$(CONFIG_RTL8192SU)                += rtl8192su/
 obj-$(CONFIG_RTL8192U)         += rtl8192u/
diff --git a/drivers/staging/altpciechdma/Kconfig b/drivers/staging/altpciechdma/Kconfig
deleted file mode 100644 (file)
index 0f4bf92..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-config ALTERA_PCIE_CHDMA
-       tristate "Altera PCI Express Chaining DMA driver"
-       depends on PCI
-       default N
-       ---help---
-         A reference driver that exercises the Chaining DMA logic reference
-         design generated along the Altera FPGA PCI Express soft or hard core,
-         only if instantiated using the MegaWizard, not the SOPC builder, of
-         Quartus 8.1.
-
diff --git a/drivers/staging/altpciechdma/Makefile b/drivers/staging/altpciechdma/Makefile
deleted file mode 100644 (file)
index c08c843..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_ALTERA_PCIE_CHDMA)        += altpciechdma.o
-
diff --git a/drivers/staging/altpciechdma/TODO b/drivers/staging/altpciechdma/TODO
deleted file mode 100644 (file)
index 12c945f..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-DONE:
-    - functionality similar to logic testbench
-
-TODO:
-       - checkpatch.pl cleanups.
-       - keep state of DMA engines.
-       - keep data structure that keeps state of each transfer.
-       - interrupt handler should iterate over outstanding descriptor tables.
-       - complete userspace cdev to read/write using the DMA engines.
-       - split off the DMA support functions in a module, re-usable by custom
-         drivers.
-
-Please coordinate work with, and send patches to
-Leon Woestenberg <leon@sidebranch.com>
-
diff --git a/drivers/staging/altpciechdma/altpciechdma.c b/drivers/staging/altpciechdma/altpciechdma.c
deleted file mode 100644 (file)
index 2a02f8e..0000000
+++ /dev/null
@@ -1,1182 +0,0 @@
-/**
- * Driver for Altera PCIe core chaining DMA reference design.
- *
- * Copyright (C) 2008 Leon Woestenberg  <leon.woestenberg@axon.tv>
- * Copyright (C) 2008 Nickolas Heppermann  <heppermannwdt@gmail.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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *
- * Rationale: This driver exercises the chaining DMA read and write engine
- * in the reference design. It is meant as a complementary reference
- * driver that can be used for testing early designs as well as a basis to
- * write your custom driver.
- *
- * Status: Test results from Leon Woestenberg  <leon.woestenberg@axon.tv>:
- *
- * Sendero Board w/ Cyclone II EP2C35F672C6N, PX1011A PCIe x1 PHY on a
- * Dell Precision 370 PC, x86, kernel 2.6.20 from Ubuntu 7.04.
- *
- * Sendero Board w/ Cyclone II EP2C35F672C6N, PX1011A PCIe x1 PHY on a
- * Freescale MPC8313E-RDB board, PowerPC, 2.6.24 w/ Freescale patches.
- *
- * Driver tests passed with PCIe Compiler 8.1. With PCIe 8.0 the DMA
- * loopback test had reproducable compare errors. I assume a change
- * in the compiler or reference design, but could not find evidence nor
- * documentation on a change or fix in that direction.
- *
- * The reference design does not have readable locations and thus a
- * dummy read, used to flush PCI posted writes, cannot be performed.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/cdev.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-
-/* by default do not build the character device interface */
-/* XXX It is non-functional yet */
-#ifndef ALTPCIECHDMA_CDEV
-#  define ALTPCIECHDMA_CDEV 0
-#endif
-
-/* build the character device interface? */
-#if ALTPCIECHDMA_CDEV
-#  define MAX_CHDMA_SIZE (8 * 1024 * 1024)
-#  include "mapper_user_to_sg.h"
-#endif
-
-/** driver name, mimicks Altera naming of the reference design */
-#define DRV_NAME "altpciechdma"
-/** number of BARs on the device */
-#define APE_BAR_NUM (6)
-/** BAR number where the RCSLAVE memory sits */
-#define APE_BAR_RCSLAVE (0)
-/** BAR number where the Descriptor Header sits */
-#define APE_BAR_HEADER (2)
-
-/** maximum size in bytes of the descriptor table, chdma logic limit */
-#define APE_CHDMA_TABLE_SIZE (4096)
-/* single transfer must not exceed 255 table entries. worst case this can be
- * achieved by 255 scattered pages, with only a single byte in the head and
- * tail pages. 253 * PAGE_SIZE is a safe upper bound for the transfer size.
- */
-#define APE_CHDMA_MAX_TRANSFER_LEN (253 * PAGE_SIZE)
-
-/**
- * Specifies those BARs to be mapped and the length of each mapping.
- *
- * Zero (0) means do not map, otherwise specifies the BAR lengths to be mapped.
- * If the actual BAR length is less, this is considered an error; then
- * reconfigure your PCIe core.
- *
- * @see ug_pci_express 8.0, table 7-2 at page 7-13.
- */
-static const unsigned long bar_min_len[APE_BAR_NUM] =
-       { 32768, 0, 256, 0, 32768, 0 };
-
-/**
- * Descriptor Header, controls the DMA read engine or write engine.
- *
- * The descriptor header is the main data structure for starting DMA transfers.
- *
- * It sits in End Point (FPGA) memory BAR[2] for 32-bit or BAR[3:2] for 64-bit.
- * It references a descriptor table which exists in Root Complex (PC) memory.
- * Writing the rclast field starts the DMA operation, thus all other structures
- * and fields must be setup before doing so.
- *
- * @see ug_pci_express 8.0, tables 7-3, 7-4 and 7-5 at page 7-14.
- * @note This header must be written in four 32-bit (PCI DWORD) writes.
- */
-struct ape_chdma_header {
-       /**
-        * w0 consists of two 16-bit fields:
-        * lsb u16 number; number of descriptors in ape_chdma_table
-        * msb u16 control; global control flags
-        */
-       u32 w0;
-       /* bus address to ape_chdma_table in Root Complex memory */
-       u32 bdt_addr_h;
-       u32 bdt_addr_l;
-       /**
-        * w3 consists of two 16-bit fields:
-        * - lsb u16 rclast; last descriptor number available in Root Complex
-        *    - zero (0) means the first descriptor is ready,
-        *    - one (1) means two descriptors are ready, etc.
-        * - msb u16 reserved;
-        *
-        * @note writing to this memory location starts the DMA operation!
-        */
-       u32 w3;
-} __attribute__ ((packed));
-
-/**
- * Descriptor Entry, describing a (non-scattered) single memory block transfer.
- *
- * There is one descriptor for each memory block involved in the transfer, a
- * block being a contiguous address range on the bus.
- *
- * Multiple descriptors are chained by means of the ape_chdma_table data
- * structure.
- *
- * @see ug_pci_express 8.0, tables 7-6, 7-7 and 7-8 at page 7-14 and page 7-15.
- */
-struct ape_chdma_desc {
-       /**
-        * w0 consists of two 16-bit fields:
-        * number of DWORDS to transfer
-        * - lsb u16 length;
-        * global control
-        * - msb u16 control;
-        */
-       u32 w0;
-       /* address of memory in the End Point */
-       u32 ep_addr;
-       /* bus address of source or destination memory in the Root Complex */
-       u32 rc_addr_h;
-       u32 rc_addr_l;
-} __attribute__ ((packed));
-
-/**
- * Descriptor Table, an array of descriptors describing a chained transfer.
- *
- * An array of descriptors, preceded by workspace for the End Point.
- * It exists in Root Complex memory.
- *
- * The End Point can update its last completed descriptor number in the
- * eplast field if requested by setting the EPLAST_ENA bit either
- * globally in the header's or locally in any descriptor's control field.
- *
- * @note this structure may not exceed 4096 bytes. This results in a
- * maximum of 4096 / (4 * 4) - 1 = 255 descriptors per chained transfer.
- *
- * @see ug_pci_express 8.0, tables 7-9, 7-10 and 7-11 at page 7-17 and page 7-18.
- */
-struct ape_chdma_table {
-       /* workspace 0x00-0x0b, reserved */
-       u32 reserved1[3];
-       /* workspace 0x0c-0x0f, last descriptor handled by End Point */
-       u32 w3;
-       /* the actual array of descriptors
-    * 0x10-0x1f, 0x20-0x2f, ... 0xff0-0xfff (255 entries)
-    */
-       struct ape_chdma_desc desc[255];
-} __attribute__ ((packed));
-
-/**
- * Altera PCI Express ('ape') board specific book keeping data
- *
- * Keeps state of the PCIe core and the Chaining DMA controller
- * application.
- */
-struct ape_dev {
-       /** the kernel pci device data structure provided by probe() */
-       struct pci_dev *pci_dev;
-       /**
-        * kernel virtual address of the mapped BAR memory and IO regions of
-        * the End Point. Used by map_bars()/unmap_bars().
-        */
-       void * __iomem bar[APE_BAR_NUM];
-       /** kernel virtual address for Descriptor Table in Root Complex memory */
-       struct ape_chdma_table *table_virt;
-       /**
-        * bus address for the Descriptor Table in Root Complex memory, in
-        * CPU-native endianess
-        */
-       dma_addr_t table_bus;
-       /* if the device regions could not be allocated, assume and remember it
-        * is in use by another driver; this driver must not disable the device.
-        */
-       int in_use;
-       /* whether this driver enabled msi for the device */
-       int msi_enabled;
-       /* whether this driver could obtain the regions */
-       int got_regions;
-       /* irq line successfully requested by this driver, -1 otherwise */
-       int irq_line;
-       /* board revision */
-       u8 revision;
-       /* interrupt count, incremented by the interrupt handler */
-       int irq_count;
-#if ALTPCIECHDMA_CDEV
-       /* character device */
-       dev_t cdevno;
-       struct cdev cdev;
-       /* user space scatter gather mapper */
-       struct sg_mapping_t *sgm;
-#endif
-};
-
-/**
- * Using the subsystem vendor id and subsystem id, it is possible to
- * distinguish between different cards bases around the same
- * (third-party) logic core.
- *
- * Default Altera vendor and device ID's, and some (non-reserved)
- * ID's are now used here that are used amongst the testers/developers.
- */
-static const struct pci_device_id ids[] = {
-       { PCI_DEVICE(0x1172, 0xE001), },
-       { PCI_DEVICE(0x2071, 0x2071), },
-       { 0, }
-};
-MODULE_DEVICE_TABLE(pci, ids);
-
-#if ALTPCIECHDMA_CDEV
-/* prototypes for character device */
-static int sg_init(struct ape_dev *ape);
-static void sg_exit(struct ape_dev *ape);
-#endif
-
-/**
- * altpciechdma_isr() - Interrupt handler
- *
- */
-static irqreturn_t altpciechdma_isr(int irq, void *dev_id)
-{
-       struct ape_dev *ape = (struct ape_dev *)dev_id;
-       if (!ape)
-               return IRQ_NONE;
-       ape->irq_count++;
-       return IRQ_HANDLED;
-}
-
-static int __devinit scan_bars(struct ape_dev *ape, struct pci_dev *dev)
-{
-       int i;
-       for (i = 0; i < APE_BAR_NUM; i++) {
-               unsigned long bar_start = pci_resource_start(dev, i);
-               if (bar_start) {
-                       unsigned long bar_end = pci_resource_end(dev, i);
-                       unsigned long bar_flags = pci_resource_flags(dev, i);
-                       printk(KERN_DEBUG "BAR%d 0x%08lx-0x%08lx flags 0x%08lx\n",
-                         i, bar_start, bar_end, bar_flags);
-               }
-       }
-       return 0;
-}
-
-/**
- * Unmap the BAR regions that had been mapped earlier using map_bars()
- */
-static void unmap_bars(struct ape_dev *ape, struct pci_dev *dev)
-{
-       int i;
-       for (i = 0; i < APE_BAR_NUM; i++) {
-         /* is this BAR mapped? */
-               if (ape->bar[i]) {
-                       /* unmap BAR */
-                       pci_iounmap(dev, ape->bar[i]);
-                       ape->bar[i] = NULL;
-               }
-       }
-}
-
-/**
- * Map the device memory regions into kernel virtual address space after
- * verifying their sizes respect the minimum sizes needed, given by the
- * bar_min_len[] array.
- */
-static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev)
-{
-       int rc;
-       int i;
-       /* iterate through all the BARs */
-       for (i = 0; i < APE_BAR_NUM; i++) {
-               unsigned long bar_start = pci_resource_start(dev, i);
-               unsigned long bar_end = pci_resource_end(dev, i);
-               unsigned long bar_length = bar_end - bar_start + 1;
-               ape->bar[i] = NULL;
-               /* do not map, and skip, BARs with length 0 */
-               if (!bar_min_len[i])
-                       continue;
-               /* do not map BARs with address 0 */
-               if (!bar_start || !bar_end) {
-                       printk(KERN_DEBUG "BAR #%d is not present?!\n", i);
-                       rc = -1;
-                       goto fail;
-               }
-               bar_length = bar_end - bar_start + 1;
-               /* BAR length is less than driver requires? */
-               if (bar_length < bar_min_len[i]) {
-                       printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver "
-                       "requires at least %lu bytes\n",
-                       i, bar_length, bar_min_len[i]);
-                       rc = -1;
-                       goto fail;
-               }
-               /* map the device memory or IO region into kernel virtual
-                * address space */
-               ape->bar[i] = pci_iomap(dev, i, bar_min_len[i]);
-               if (!ape->bar[i]) {
-                       printk(KERN_DEBUG "Could not map BAR #%d.\n", i);
-                       rc = -1;
-                       goto fail;
-               }
-               printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i,
-               ape->bar[i], bar_min_len[i], bar_length);
-       }
-       /* successfully mapped all required BAR regions */
-       rc = 0;
-       goto success;
-fail:
-       /* unmap any BARs that we did map */
-       unmap_bars(ape, dev);
-success:
-       return rc;
-}
-
-#if 0 /* not yet implemented fully FIXME add opcode */
-static void __devinit rcslave_test(struct ape_dev *ape, struct pci_dev *dev)
-{
-       u32 *rcslave_mem = (u32 *)ape->bar[APE_BAR_RCSLAVE];
-       u32 result = 0;
-       /** this number is assumed to be different each time this test runs */
-       u32 seed = (u32)jiffies;
-       u32 value = seed;
-       int i;
-
-       /* write loop */
-       value = seed;
-       for (i = 1024; i < 32768 / 4 ; i++) {
-               printk(KERN_DEBUG "Writing 0x%08x to 0x%p.\n",
-                       (u32)value, (void *)rcslave_mem + i);
-               iowrite32(value, rcslave_mem + i);
-               value++;
-       }
-       /* read-back loop */
-       value = seed;
-       for (i = 1024; i < 32768 / 4; i++) {
-               result = ioread32(rcslave_mem + i);
-               if (result != value) {
-                       printk(KERN_DEBUG "Wrote 0x%08x to 0x%p, but read back 0x%08x.\n",
-                               (u32)value, (void *)rcslave_mem + i, (u32)result);
-                       break;
-               }
-               value++;
-       }
-}
-#endif
-
-/* obtain the 32 most significant (high) bits of a 32-bit or 64-bit address */
-#define pci_dma_h(addr) ((addr >> 16) >> 16)
-/* obtain the 32 least significant (low) bits of a 32-bit or 64-bit address */
-#define pci_dma_l(addr) (addr & 0xffffffffUL)
-
-/* ape_fill_chdma_desc() - Fill a Altera PCI Express Chaining DMA descriptor
- *
- * @desc pointer to descriptor to be filled
- * @addr root complex address
- * @ep_addr end point address
- * @len number of bytes, must be a multiple of 4.
- */
-static inline void ape_chdma_desc_set(struct ape_chdma_desc *desc, dma_addr_t addr, u32 ep_addr, int len)
-{
-  BUG_ON(len & 3);
-       desc->w0 = cpu_to_le32(len / 4);
-       desc->ep_addr = cpu_to_le32(ep_addr);
-       desc->rc_addr_h = cpu_to_le32(pci_dma_h(addr));
-       desc->rc_addr_l = cpu_to_le32(pci_dma_l(addr));
-}
-
-#if ALTPCIECHDMA_CDEV
-/*
- * ape_sg_to_chdma_table() - Create a device descriptor table from a scatterlist.
- *
- * The scatterlist must have been mapped by pci_map_sg(sgm->sgl).
- *
- * @sgl scatterlist.
- * @nents Number of entries in the scatterlist.
- * @first Start index in the scatterlist sgm->sgl.
- * @ep_addr End Point address for the scatter/gather transfer.
- * @desc pointer to first descriptor
- *
- * Returns Number of entries in the table on success, -1 on error.
- */
-static int ape_sg_to_chdma_table(struct scatterlist *sgl, int nents, int first, struct ape_chdma_desc *desc, u32 ep_addr)
-{
-       int i = first, j = 0;
-       /* inspect first entry */
-       dma_addr_t addr = sg_dma_address(&sgl[i]);
-       unsigned int len = sg_dma_len(&sgl[i]);
-       /* contiguous block */
-       dma_addr_t cont_addr = addr;
-       unsigned int cont_len = len;
-       /* iterate over remaining entries */
-       for (; j < 25 && i < nents - 1; i++) {
-               /* bus address of next entry i + 1 */
-               dma_addr_t next = sg_dma_address(&sgl[i + 1]);
-               /* length of this entry i */
-               len = sg_dma_len(&sgl[i]);
-               printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i,
-                       (unsigned long long)addr, len);
-               /* entry i + 1 is non-contiguous with entry i? */
-               if (next != addr + len) {
-                       /* TODO create entry here (we could overwrite i) */
-                       printk(KERN_DEBUG "%4d: cont_addr=0x%Lx cont_len=0x%08x\n", j,
-                               (unsigned long long)cont_addr, cont_len);
-                       /* set descriptor for contiguous transfer */
-                       ape_chdma_desc_set(&desc[j], cont_addr, ep_addr, cont_len);
-                       /* next end point memory address */
-                       ep_addr += cont_len;
-                       /* start new contiguous block */
-                       cont_addr = next;
-                       cont_len = 0;
-                       j++;
-               }
-               /* add entry i + 1 to current contiguous block */
-               cont_len += len;
-               /* goto entry i + 1 */
-               addr = next;
-       }
-       /* TODO create entry here  (we could overwrite i) */
-       printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i,
-               (unsigned long long)addr, len);
-       printk(KERN_DEBUG "%4d: cont_addr=0x%Lx length=0x%08x\n", j,
-               (unsigned long long)cont_addr, cont_len);
-       j++;
-       return j;
-}
-#endif
-
-/* compare buffers */
-static inline int compare(u32 *p, u32 *q, int len)
-{
-       int result = -1;
-       int fail = 0;
-       int i;
-       for (i = 0; i < len / 4; i++) {
-               if (*p == *q) {
-                       /* every so many u32 words, show equals */
-                       if ((i & 255) == 0)
-                               printk(KERN_DEBUG "[%p] = 0x%08x    [%p] = 0x%08x\n", p, *p, q, *q);
-               } else {
-                       fail++;
-                       /* show the first few miscompares */
-                       if (fail < 10)
-                               printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q);
-                               /* but stop after a while */
-                       else if (fail == 10)
-                               printk(KERN_DEBUG "---more errors follow! not printed---\n");
-                       else
-                               /* stop compare after this many errors */
-                       break;
-               }
-               p++;
-               q++;
-       }
-       if (!fail)
-               result = 0;
-       return result;
-}
-
-/* dma_test() - Perform DMA loop back test to end point and back to root complex.
- *
- * Allocate a cache-coherent buffer in host memory, consisting of four pages.
- *
- * Fill the four memory pages such that each 32-bit word contains its own address.
- *
- * Now perform a loop back test, have the end point device copy the first buffer
- * half to end point memory, then have it copy back into the second half.
- *
- *   Create a descriptor table to copy the first buffer half into End Point
- *   memory. Instruct the End Point to do a DMA read using that table.
- *
- *   Create a descriptor table to copy End Point memory to the second buffer
- *   half. Instruct the End Point to do a DMA write using that table.
- *
- * Compare results, fail or pass.
- *
- */
-static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
-{
-       /* test result; guilty until proven innocent */
-       int result = -1;
-       /* the DMA read header sits at address 0x00 of the DMA engine BAR */
-       struct ape_chdma_header *write_header = (struct ape_chdma_header *)ape->bar[APE_BAR_HEADER];
-       /* the write DMA header sits after the read header at address 0x10 */
-       struct ape_chdma_header *read_header = write_header + 1;
-       /* virtual address of the allocated buffer */
-       u8 *buffer_virt = 0;
-       /* bus address of the allocated buffer */
-       dma_addr_t buffer_bus = 0;
-       int i, n = 0, irq_count;
-
-       /* temporary value used to construct 32-bit data words */
-       u32 w;
-
-       printk(KERN_DEBUG "bar_tests(), PAGE_SIZE = 0x%0x\n", (int)PAGE_SIZE);
-       printk(KERN_DEBUG "write_header = 0x%p.\n", write_header);
-       printk(KERN_DEBUG "read_header = 0x%p.\n", read_header);
-       printk(KERN_DEBUG "&write_header->w3 = 0x%p\n", &write_header->w3);
-       printk(KERN_DEBUG "&read_header->w3 = 0x%p\n", &read_header->w3);
-       printk(KERN_DEBUG "ape->table_virt = 0x%p.\n", ape->table_virt);
-
-       if (!write_header || !read_header || !ape->table_virt)
-               goto fail;
-
-       /* allocate and map coherently-cached memory for a DMA-able buffer */
-       /* @see Documentation/PCI/PCI-DMA-mapping.txt, near line 318 */
-       buffer_virt = (u8 *)pci_alloc_consistent(dev, PAGE_SIZE * 4, &buffer_bus);
-       if (!buffer_virt) {
-               printk(KERN_DEBUG "Could not allocate coherent DMA buffer.\n");
-               goto fail;
-       }
-       printk(KERN_DEBUG "Allocated cache-coherent DMA buffer (virtual address = %p, bus address = 0x%016llx).\n",
-              buffer_virt, (u64)buffer_bus);
-
-       /* fill first half of buffer with its virtual address as data */
-       for (i = 0; i < 4 * PAGE_SIZE; i += 4)
-#if 0
-               *(u32 *)(buffer_virt + i) = i / PAGE_SIZE + 1;
-#else
-               *(u32 *)(buffer_virt + i) = (u32)(unsigned long)(buffer_virt + i);
-#endif
-#if 0
-  compare((u32 *)buffer_virt, (u32 *)(buffer_virt + 2 * PAGE_SIZE), 8192);
-#endif
-
-#if 0
-       /* fill second half of buffer with zeroes */
-       for (i = 2 * PAGE_SIZE; i < 4 * PAGE_SIZE; i += 4)
-               *(u32 *)(buffer_virt + i) = 0;
-#endif
-
-       /* invalidate EPLAST, outside 0-255, 0xFADE is from the testbench */
-       ape->table_virt->w3 = cpu_to_le32(0x0000FADE);
-
-       /* fill in first descriptor */
-       n = 0;
-       /* read 8192 bytes from RC buffer to EP address 4096 */
-       ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus, 4096, 2 * PAGE_SIZE);
-#if 1
-       for (i = 0; i < 255; i++)
-               ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus, 4096, 2 * PAGE_SIZE);
-       /* index of last descriptor */
-       n = i - 1;
-#endif
-#if 0
-       /* fill in next descriptor */
-       n++;
-       /* read 1024 bytes from RC buffer to EP address 4096 + 1024 */
-       ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 1024, 4096 + 1024, 1024);
-#endif
-
-#if 1
-       /* enable MSI after the last descriptor is completed */
-       if (ape->msi_enabled)
-               ape->table_virt->desc[n].w0 |= cpu_to_le32(1UL << 16)/*local MSI*/;
-#endif
-#if 0
-       /* dump descriptor table for debugging */
-       printk(KERN_DEBUG "Descriptor Table (Read, in Root Complex Memory, # = %d)\n", n + 1);
-       for (i = 0; i < 4 + (n + 1) * 4; i += 4) {
-               u32 *p = (u32 *)ape->table_virt;
-               p += i;
-               printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (LEN=0x%x)\n", (u32)p, (u32)p & 15, *p, 4 * le32_to_cpu(*p));
-               p++;
-               printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (EPA=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-               p++;
-               printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCH=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-               p++;
-               printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCL=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-       }
-#endif
-       /* set available number of descriptors in table */
-       w = (u32)(n + 1);
-       w |= (1UL << 18)/*global EPLAST_EN*/;
-#if 0
-       if (ape->msi_enabled)
-               w |= (1UL << 17)/*global MSI*/;
-#endif
-       printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", w, (void *)&read_header->w0);
-       iowrite32(w, &read_header->w0);
-
-       /* write table address (higher 32-bits) */
-       printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)((ape->table_bus >> 16) >> 16), (void *)&read_header->bdt_addr_h);
-       iowrite32(pci_dma_h(ape->table_bus), &read_header->bdt_addr_h);
-
-       /* write table address (lower 32-bits) */
-       printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)(ape->table_bus & 0xffffffffUL), (void *)&read_header->bdt_addr_l);
-       iowrite32(pci_dma_l(ape->table_bus), &read_header->bdt_addr_l);
-
-       /* memory write barrier */
-       wmb();
-       printk(KERN_DEBUG "Flush posted writes\n");
-       /** FIXME Add dummy read to flush posted writes but need a readable location! */
-#if 0
-       (void)ioread32();
-#endif
-
-       /* remember IRQ count before the transfer */
-       irq_count = ape->irq_count;
-       /* write number of descriptors - this starts the DMA */
-       printk(KERN_DEBUG "\nStart DMA read\n");
-       printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)n, (void *)&read_header->w3);
-       iowrite32(n, &read_header->w3);
-       printk(KERN_DEBUG "EPLAST = %lu\n", le32_to_cpu(*(u32 *)&ape->table_virt->w3) & 0xffffUL);
-
-       /** memory write barrier */
-       wmb();
-       /* dummy read to flush posted writes */
-       /* FIXME Need a readable location! */
-#if 0
-       (void)ioread32();
-#endif
-       printk(KERN_DEBUG "POLL FOR READ:\n");
-       /* poll for chain completion, 1000 times 1 millisecond */
-       for (i = 0; i < 100; i++) {
-               volatile u32 *p = &ape->table_virt->w3;
-               u32 eplast = le32_to_cpu(*p) & 0xffffUL;
-               printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
-               if (eplast == n) {
-                       printk(KERN_DEBUG "DONE\n");
-                       /* print IRQ count before the transfer */
-                       printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
-                       break;
-               }
-               udelay(100);
-       }
-
-       /* invalidate EPLAST, outside 0-255, 0xFADE is from the testbench */
-       ape->table_virt->w3 = cpu_to_le32(0x0000FADE);
-
-       /* setup first descriptor */
-       n = 0;
-       ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
-#if 1
-       for (i = 0; i < 255; i++)
-               ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
-
-       /* index of last descriptor */
-       n = i - 1;
-#endif
-#if 1 /* test variable, make a module option later */
-       if (ape->msi_enabled)
-               ape->table_virt->desc[n].w0 |= cpu_to_le32(1UL << 16)/*local MSI*/;
-#endif
-#if 0
-       /* dump descriptor table for debugging */
-       printk(KERN_DEBUG "Descriptor Table (Write, in Root Complex Memory, # = %d)\n", n + 1);
-       for (i = 0; i < 4 + (n + 1) * 4; i += 4) {
-               u32 *p = (u32 *)ape->table_virt;
-               p += i;
-               printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (LEN=0x%x)\n", (u32)p, (u32)p & 15, *p, 4 * le32_to_cpu(*p));
-               p++;
-               printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (EPA=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-               p++;
-               printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCH=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-               p++;
-               printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCL=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-       }
-#endif
-
-       /* set number of available descriptors in the table */
-       w = (u32)(n + 1);
-       /* enable updates of eplast for each descriptor completion */
-       w |= (u32)(1UL << 18)/*global EPLAST_EN*/;
-#if 0   /* test variable, make a module option later */
-       /* enable MSI for each descriptor completion */
-       if (ape->msi_enabled)
-               w |= (1UL << 17)/*global MSI*/;
-#endif
-       iowrite32(w, &write_header->w0);
-       iowrite32(pci_dma_h(ape->table_bus), &write_header->bdt_addr_h);
-       iowrite32(pci_dma_l(ape->table_bus), &write_header->bdt_addr_l);
-
-       /** memory write barrier and flush posted writes */
-       wmb();
-       /* dummy read to flush posted writes */
-       /* FIXME Need a readable location! */
-#if 0
-       (void)ioread32();
-#endif
-       irq_count = ape->irq_count;
-
-       printk(KERN_DEBUG "\nStart DMA write\n");
-       iowrite32(n, &write_header->w3);
-
-       /** memory write barrier */
-       wmb();
-       /** dummy read to flush posted writes */
-       /* (void) ioread32(); */
-
-       printk(KERN_DEBUG "POLL FOR WRITE:\n");
-       /* poll for completion, 1000 times 1 millisecond */
-       for (i = 0; i < 100; i++) {
-               volatile u32 *p = &ape->table_virt->w3;
-               u32 eplast = le32_to_cpu(*p) & 0xffffUL;
-               printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
-               if (eplast == n) {
-                       printk(KERN_DEBUG "DONE\n");
-                       /* print IRQ count before the transfer */
-                       printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
-                       break;
-               }
-               udelay(100);
-       }
-       /* soft-reset DMA write engine */
-       iowrite32(0x0000ffffUL, &write_header->w0);
-       /* soft-reset DMA read engine */
-       iowrite32(0x0000ffffUL, &read_header->w0);
-
-       /** memory write barrier */
-       wmb();
-       /* dummy read to flush posted writes */
-       /* FIXME Need a readable location! */
-#if 0
-       (void)ioread32();
-#endif
-       /* compare first half of buffer with second half, should be identical */
-       result = compare((u32 *)buffer_virt, (u32 *)(buffer_virt + 2 * PAGE_SIZE), 8192);
-       printk(KERN_DEBUG "DMA loop back test %s.\n", result ? "FAILED" : "PASSED");
-
-       pci_free_consistent(dev, 4 * PAGE_SIZE, buffer_virt, buffer_bus);
-fail:
-       printk(KERN_DEBUG "bar_tests() end, result %d\n", result);
-       return result;
-}
-
-/* Called when the PCI sub system thinks we can control the given device.
- * Inspect if we can support the device and if so take control of it.
- *
- * Return 0 when we have taken control of the given device.
- *
- * - allocate board specific bookkeeping
- * - allocate coherently-mapped memory for the descriptor table
- * - enable the board
- * - verify board revision
- * - request regions
- * - query DMA mask
- * - obtain and request irq
- * - map regions into kernel address space
- */
-static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       int rc = 0;
-       struct ape_dev *ape = NULL;
-       u8 irq_pin, irq_line;
-       printk(KERN_DEBUG "probe(dev = 0x%p, pciid = 0x%p)\n", dev, id);
-
-       /* allocate memory for per-board book keeping */
-       ape = kzalloc(sizeof(struct ape_dev), GFP_KERNEL);
-       if (!ape) {
-               printk(KERN_DEBUG "Could not kzalloc()ate memory.\n");
-               goto err_ape;
-       }
-       ape->pci_dev = dev;
-       dev_set_drvdata(&dev->dev, ape);
-       printk(KERN_DEBUG "probe() ape = 0x%p\n", ape);
-
-       printk(KERN_DEBUG "sizeof(struct ape_chdma_table) = %d.\n",
-               (int)sizeof(struct ape_chdma_table));
-       /* the reference design has a size restriction on the table size */
-       BUG_ON(sizeof(struct ape_chdma_table) > APE_CHDMA_TABLE_SIZE);
-
-       /* allocate and map coherently-cached memory for a descriptor table */
-       /* @see LDD3 page 446 */
-       ape->table_virt = (struct ape_chdma_table *)pci_alloc_consistent(dev,
-               APE_CHDMA_TABLE_SIZE, &ape->table_bus);
-       /* could not allocate table? */
-       if (!ape->table_virt) {
-               printk(KERN_DEBUG "Could not dma_alloc()ate_coherent memory.\n");
-               goto err_table;
-       }
-
-       printk(KERN_DEBUG "table_virt = %p, table_bus = 0x%16llx.\n",
-               ape->table_virt, (u64)ape->table_bus);
-
-       /* enable device */
-       rc = pci_enable_device(dev);
-       if (rc) {
-               printk(KERN_DEBUG "pci_enable_device() failed\n");
-               goto err_enable;
-       }
-
-       /* enable bus master capability on device */
-       pci_set_master(dev);
-       /* enable message signaled interrupts */
-       rc = pci_enable_msi(dev);
-       /* could not use MSI? */
-       if (rc) {
-               /* resort to legacy interrupts */
-               printk(KERN_DEBUG "Could not enable MSI interrupting.\n");
-               ape->msi_enabled = 0;
-       /* MSI enabled, remember for cleanup */
-       } else {
-               printk(KERN_DEBUG "Enabled MSI interrupting.\n");
-               ape->msi_enabled = 1;
-       }
-
-       pci_read_config_byte(dev, PCI_REVISION_ID, &ape->revision);
-#if 0 /* example */
-       /* (for example) this driver does not support revision 0x42 */
-    if (ape->revision == 0x42) {
-               printk(KERN_DEBUG "Revision 0x42 is not supported by this driver.\n");
-               rc = -ENODEV;
-               goto err_rev;
-       }
-#endif
-       /** XXX check for native or legacy PCIe endpoint? */
-
-       rc = pci_request_regions(dev, DRV_NAME);
-       /* could not request all regions? */
-       if (rc) {
-               /* assume device is in use (and do not disable it later!) */
-               ape->in_use = 1;
-               goto err_regions;
-       }
-       ape->got_regions = 1;
-
-#if 1   /* @todo For now, disable 64-bit, because I do not understand the implications (DAC!) */
-       /* query for DMA transfer */
-       /* @see Documentation/PCI/PCI-DMA-mapping.txt */
-       if (!pci_set_dma_mask(dev, DMA_BIT_MASK(64))) {
-               pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64));
-               /* use 64-bit DMA */
-               printk(KERN_DEBUG "Using a 64-bit DMA mask.\n");
-       } else
-#endif
-       if (!pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
-               printk(KERN_DEBUG "Could not set 64-bit DMA mask.\n");
-               pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(32));
-               /* use 32-bit DMA */
-               printk(KERN_DEBUG "Using a 32-bit DMA mask.\n");
-       } else {
-               printk(KERN_DEBUG "No suitable DMA possible.\n");
-               /** @todo Choose proper error return code */
-               rc = -1;
-               goto err_mask;
-       }
-
-       rc = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
-       /* could not read? */
-       if (rc)
-               goto err_irq;
-       printk(KERN_DEBUG "IRQ pin #%d (0=none, 1=INTA#...4=INTD#).\n", irq_pin);
-
-       /* @see LDD3, page 318 */
-       rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_line);
-       /* could not read? */
-       if (rc) {
-               printk(KERN_DEBUG "Could not query PCI_INTERRUPT_LINE, error %d\n", rc);
-               goto err_irq;
-       }
-       printk(KERN_DEBUG "IRQ line #%d.\n", irq_line);
-#if 1
-       irq_line = dev->irq;
-       /* @see LDD3, page 259 */
-       rc = request_irq(irq_line, altpciechdma_isr, IRQF_SHARED, DRV_NAME, (void *)ape);
-       if (rc) {
-               printk(KERN_DEBUG "Could not request IRQ #%d, error %d\n", irq_line, rc);
-               ape->irq_line = -1;
-               goto err_irq;
-       }
-       /* remember which irq we allocated */
-       ape->irq_line = (int)irq_line;
-       printk(KERN_DEBUG "Successfully requested IRQ #%d with dev_id 0x%p\n", irq_line, ape);
-#endif
-       /* show BARs */
-       scan_bars(ape, dev);
-       /* map BARs */
-       rc = map_bars(ape, dev);
-       if (rc)
-               goto err_map;
-#if ALTPCIECHDMA_CDEV
-       /* initialize character device */
-       rc = sg_init(ape);
-       if (rc)
-               goto err_cdev;
-#endif
-       /* perform DMA engines loop back test */
-       rc = dma_test(ape, dev);
-       (void)rc;
-       /* successfully took the device */
-       rc = 0;
-       printk(KERN_DEBUG "probe() successful.\n");
-       goto end;
-#if ALTPCIECHDMA_CDEV
-err_cdev:
-       /* unmap the BARs */
-       unmap_bars(ape, dev);
-#endif
-err_map:
-       /* free allocated irq */
-       if (ape->irq_line >= 0)
-               free_irq(ape->irq_line, (void *)ape);
-err_irq:
-       if (ape->msi_enabled)
-               pci_disable_msi(dev);
-       /* disable the device iff it is not in use */
-       if (!ape->in_use)
-               pci_disable_device(dev);
-       if (ape->got_regions)
-               pci_release_regions(dev);
-err_mask:
-err_regions:
-/*err_rev:*/
-/* clean up everything before device enable() */
-err_enable:
-       if (ape->table_virt)
-               pci_free_consistent(dev, APE_CHDMA_TABLE_SIZE, ape->table_virt, ape->table_bus);
-/* clean up everything before allocating descriptor table */
-err_table:
-       if (ape)
-               kfree(ape);
-err_ape:
-end:
-       return rc;
-}
-
-static void __devexit remove(struct pci_dev *dev)
-{
-       struct ape_dev *ape = dev_get_drvdata(&dev->dev);
-
-       printk(KERN_DEBUG "remove(0x%p)\n", dev);
-       printk(KERN_DEBUG "remove(dev = 0x%p) where ape = 0x%p\n", dev, ape);
-
-       /* remove character device */
-#if ALTPCIECHDMA_CDEV
-       sg_exit(ape);
-#endif
-
-       if (ape->table_virt)
-               pci_free_consistent(dev, APE_CHDMA_TABLE_SIZE, ape->table_virt, ape->table_bus);
-
-       /* free IRQ
-        * @see LDD3 page 279
-        */
-       if (ape->irq_line >= 0) {
-               printk(KERN_DEBUG "Freeing IRQ #%d for dev_id 0x%08lx.\n",
-               ape->irq_line, (unsigned long)ape);
-               free_irq(ape->irq_line, (void *)ape);
-       }
-       /* MSI was enabled? */
-       if (ape->msi_enabled) {
-               /* Disable MSI @see Documentation/MSI-HOWTO.txt */
-               pci_disable_msi(dev);
-               ape->msi_enabled = 0;
-       }
-       /* unmap the BARs */
-       unmap_bars(ape, dev);
-       if (!ape->in_use)
-               pci_disable_device(dev);
-       if (ape->got_regions)
-               /* to be called after device disable */
-               pci_release_regions(dev);
-}
-
-#if ALTPCIECHDMA_CDEV
-
-/*
- * Called when the device goes from unused to used.
- */
-static int sg_open(struct inode *inode, struct file *file)
-{
-       struct ape_dev *ape;
-       printk(KERN_DEBUG DRV_NAME "_open()\n");
-       /* pointer to containing data structure of the character device inode */
-       ape = container_of(inode->i_cdev, struct ape_dev, cdev);
-       /* create a reference to our device state in the opened file */
-       file->private_data = ape;
-       /* create virtual memory mapper */
-       ape->sgm = sg_create_mapper(MAX_CHDMA_SIZE);
-       return 0;
-}
-
-/*
- * Called when the device goes from used to unused.
- */
-static int sg_close(struct inode *inode, struct file *file)
-{
-       /* fetch device specific data stored earlier during open */
-       struct ape_dev *ape = (struct ape_dev *)file->private_data;
-       printk(KERN_DEBUG DRV_NAME "_close()\n");
-       /* destroy virtual memory mapper */
-       sg_destroy_mapper(ape->sgm);
-       return 0;
-}
-
-static ssize_t sg_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
-{
-       /* fetch device specific data stored earlier during open */
-       struct ape_dev *ape = (struct ape_dev *)file->private_data;
-       (void)ape;
-       printk(KERN_DEBUG DRV_NAME "_read(buf=0x%p, count=%lld, pos=%llu)\n", buf, (s64)count, (u64)*pos);
-       return count;
-}
-
-/* sg_write() - Write to the device
- *
- * @buf userspace buffer
- * @count number of bytes in the userspace buffer
- *
- * Iterate over the userspace buffer, taking at most 255 * PAGE_SIZE bytes for
- * each DMA transfer.
- *   For each transfer, get the user pages, build a sglist, map, build a
- *   descriptor table. submit the transfer. wait for the interrupt handler
- *   to wake us on completion.
- */
-static ssize_t sg_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
-{
-       int hwnents, tents;
-       size_t transfer_len, remaining = count, done = 0;
-       u64 transfer_addr = (u64)buf;
-       /* fetch device specific data stored earlier during open */
-       struct ape_dev *ape = (struct ape_dev *)file->private_data;
-       printk(KERN_DEBUG DRV_NAME "_write(buf=0x%p, count=%lld, pos=%llu)\n",
-               buf, (s64)count, (u64)*pos);
-       /* TODO transfer boundaries at PAGE_SIZE granularity */
-       while (remaining > 0) {
-               /* limit DMA transfer size */
-               transfer_len = (remaining < APE_CHDMA_MAX_TRANSFER_LEN) ? remaining :
-                       APE_CHDMA_MAX_TRANSFER_LEN;
-               /* get all user space buffer pages and create a scattergather list */
-               sgm_map_user_pages(ape->sgm, transfer_addr, transfer_len, 0/*read from userspace*/);
-               printk(KERN_DEBUG DRV_NAME "mapped_pages=%d\n", ape->sgm->mapped_pages);
-               /* map all entries in the scattergather list */
-               hwnents = pci_map_sg(ape->pci_dev, ape->sgm->sgl, ape->sgm->mapped_pages, DMA_TO_DEVICE);
-               printk(KERN_DEBUG DRV_NAME "hwnents=%d\n", hwnents);
-               /* build device descriptor tables and submit them to the DMA engine */
-               tents = ape_sg_to_chdma_table(ape->sgm->sgl, hwnents, 0, &ape->table_virt->desc[0], 4096);
-               printk(KERN_DEBUG DRV_NAME "tents=%d\n", hwnents);
-#if 0
-               while (tables) {
-                       /* TODO build table */
-                       /* TODO submit table to the device */
-                       /* if engine stopped and unfinished work then start engine */
-               }
-               put ourselves on wait queue
-#endif
-
-               dma_unmap_sg(NULL, ape->sgm->sgl, ape->sgm->mapped_pages, DMA_TO_DEVICE);
-               /* dirty and free the pages */
-               sgm_unmap_user_pages(ape->sgm, 1/*dirtied*/);
-               /* book keeping */
-               transfer_addr += transfer_len;
-               remaining -= transfer_len;
-               done += transfer_len;
-       }
-       return done;
-}
-
-/*
- * character device file operations
- */
-static const struct file_operations sg_fops = {
-       .owner = THIS_MODULE,
-       .open = sg_open,
-       .release = sg_close,
-       .read = sg_read,
-       .write = sg_write,
-};
-
-/* sg_init() - Initialize character device
- *
- * XXX Should ideally be tied to the device, on device probe, not module init.
- */
-static int sg_init(struct ape_dev *ape)
-{
-       int rc;
-       printk(KERN_DEBUG DRV_NAME " sg_init()\n");
-       /* allocate a dynamically allocated character device node */
-       rc = alloc_chrdev_region(&ape->cdevno, 0/*requested minor*/, 1/*count*/, DRV_NAME);
-       /* allocation failed? */
-       if (rc < 0) {
-               printk("alloc_chrdev_region() = %d\n", rc);
-               goto fail_alloc;
-       }
-       /* couple the device file operations to the character device */
-       cdev_init(&ape->cdev, &sg_fops);
-       ape->cdev.owner = THIS_MODULE;
-       /* bring character device live */
-       rc = cdev_add(&ape->cdev, ape->cdevno, 1/*count*/);
-       if (rc < 0) {
-               printk("cdev_add() = %d\n", rc);
-               goto fail_add;
-       }
-       printk(KERN_DEBUG "altpciechdma = %d:%d\n", MAJOR(ape->cdevno), MINOR(ape->cdevno));
-       return 0;
-fail_add:
-       /* free the dynamically allocated character device node */
-    unregister_chrdev_region(ape->cdevno, 1/*count*/);
-fail_alloc:
-       return -1;
-}
-
-/* sg_exit() - Cleanup character device
- *
- * XXX Should ideally be tied to the device, on device remove, not module exit.
- */
-
-static void sg_exit(struct ape_dev *ape)
-{
-       printk(KERN_DEBUG DRV_NAME " sg_exit()\n");
-       /* remove the character device */
-       cdev_del(&ape->cdev);
-       /* free the dynamically allocated character device node */
-       unregister_chrdev_region(ape->cdevno, 1/*count*/);
-}
-
-#endif /* ALTPCIECHDMA_CDEV */
-
-/* used to register the driver with the PCI kernel sub system
- * @see LDD3 page 311
- */
-static struct pci_driver pci_driver = {
-       .name = DRV_NAME,
-       .id_table = ids,
-       .probe = probe,
-       .remove = __devexit_p(remove),
-       /* resume, suspend are optional */
-};
-
-/**
- * alterapciechdma_init() - Module initialization, registers devices.
- */
-static int __init alterapciechdma_init(void)
-{
-       int rc = 0;
-       printk(KERN_DEBUG DRV_NAME " init(), built at " __DATE__ " " __TIME__ "\n");
-       /* register this driver with the PCI bus driver */
-       rc = pci_register_driver(&pci_driver);
-       if (rc < 0)
-               return rc;
-       return 0;
-}
-
-/**
- * alterapciechdma_init() - Module cleanup, unregisters devices.
- */
-static void __exit alterapciechdma_exit(void)
-{
-       printk(KERN_DEBUG DRV_NAME " exit(), built at " __DATE__ " " __TIME__ "\n");
-       /* unregister this driver from the PCI bus driver */
-       pci_unregister_driver(&pci_driver);
-}
-
-MODULE_LICENSE("GPL");
-
-module_init(alterapciechdma_init);
-module_exit(alterapciechdma_exit);
-