Staging: vme: add Tundra TSI148 VME-PCI Bridge driver
authorMartyn Welch <martyn.welch@gefanuc.com>
Fri, 31 Jul 2009 08:28:17 +0000 (09:28 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 15 Sep 2009 19:02:09 +0000 (12:02 -0700)
Signed-off-by: Martyn Welch <martyn.welch@gefanuc.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/vme/bridges/Kconfig
drivers/staging/vme/bridges/Makefile
drivers/staging/vme/bridges/vme_tsi148.c [new file with mode: 0644]
drivers/staging/vme/bridges/vme_tsi148.h [new file with mode: 0644]

index 3fe55f46ec0fef5618e11dff0231e656bb042dfa..82db2c7e8b31bf88eac49a49bccf19822d3170ec 100644 (file)
@@ -6,3 +6,9 @@ config VME_CA91CX42
        help
         If you say Y here you get support for the Tundra CA91C042 (Universe I)
         and CA91C142 (Universe II) VME bridge chips.
+
+config VME_TSI148
+       tristate "Tempe"
+       help
+        If you say Y here you get support for the Tundra TSI148 VME bridge
+        chip.
index 93d4af8c7e998d7086ee6f84b84d7336735a9f7b..59638afcd5021f0eb8b01d1c719f737df5144437 100644 (file)
@@ -1 +1,2 @@
 obj-$(CONFIG_VME_CA91CX42)     += vme_ca91cx42.o
+obj-$(CONFIG_VME_TSI148)       += vme_tsi148.o
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
new file mode 100644 (file)
index 0000000..ad6fc2d
--- /dev/null
@@ -0,0 +1,2912 @@
+/*
+ * Support for the Tundra TSI148 VME-PCI Bridge Chip
+ *
+ * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ *
+ * Based on work by Tom Armistead and Ajit Prem
+ * Copyright 2004 Motorola Inc.
+ *
+ * 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.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include <linux/poll.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "../vme.h"
+#include "../vme_bridge.h"
+#include "vme_tsi148.h"
+
+static int __init tsi148_init(void);
+static int tsi148_probe(struct pci_dev *, const struct pci_device_id *);
+static void tsi148_remove(struct pci_dev *);
+static void __exit tsi148_exit(void);
+
+
+int tsi148_slave_set(struct vme_slave_resource *, int, unsigned long long,
+       unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t);
+int tsi148_slave_get(struct vme_slave_resource *, int *, unsigned long long *,
+       unsigned long long *, dma_addr_t *, vme_address_t *, vme_cycle_t *);
+
+int tsi148_master_get(struct vme_master_resource *, int *, unsigned long long *,
+        unsigned long long *, vme_address_t *, vme_cycle_t *, vme_width_t *);
+int tsi148_master_set(struct vme_master_resource *, int, unsigned long long,
+       unsigned long long, vme_address_t, vme_cycle_t, vme_width_t);
+ssize_t tsi148_master_read(struct vme_master_resource *, void *, size_t,
+       loff_t);
+ssize_t tsi148_master_write(struct vme_master_resource *, void *, size_t,
+       loff_t);
+unsigned int tsi148_master_rmw(struct vme_master_resource *, unsigned int,
+       unsigned int, unsigned int, loff_t);
+int tsi148_dma_list_add (struct vme_dma_list *, struct vme_dma_attr *,
+       struct vme_dma_attr *, size_t);
+int tsi148_dma_list_exec(struct vme_dma_list *);
+int tsi148_dma_list_empty(struct vme_dma_list *);
+int tsi148_generate_irq(int, int);
+int tsi148_lm_set(unsigned long long, vme_address_t, vme_cycle_t);
+int tsi148_lm_get(unsigned long long *, vme_address_t *, vme_cycle_t *);
+int tsi148_lm_attach(int, void (*callback)(int));
+int tsi148_lm_detach(int);
+int tsi148_slot_get(void);
+
+/* Modue parameter */
+int err_chk = 0;
+
+/* XXX These should all be in a per device structure */
+struct vme_bridge *tsi148_bridge;
+wait_queue_head_t dma_queue[2];
+wait_queue_head_t iack_queue;
+void (*lm_callback[4])(int);   /* Called in interrupt handler, be careful! */
+void *crcsr_kernel;
+dma_addr_t crcsr_bus;
+struct vme_master_resource *flush_image;
+struct semaphore vme_rmw;      /* Only one RMW cycle at a time */
+struct semaphore vme_int;      /*
+                                * Only one VME interrupt can be
+                                * generated at a time, provide locking
+                                */
+struct semaphore vme_irq;      /* Locking for VME irq callback configuration */
+struct semaphore vme_lm;       /* Locking for location monitor operations */
+
+
+static char driver_name[] = "vme_tsi148";
+
+static struct pci_device_id tsi148_ids[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) },
+       { },
+};
+
+static struct pci_driver tsi148_driver = {
+       .name = driver_name,
+       .id_table = tsi148_ids,
+       .probe = tsi148_probe,
+       .remove = tsi148_remove,
+};
+
+static void reg_join(unsigned int high, unsigned int low,
+       unsigned long long *variable)
+{
+       *variable = (unsigned long long)high << 32;
+       *variable |= (unsigned long long)low;
+}
+
+static void reg_split(unsigned long long variable, unsigned int *high,
+       unsigned int *low)
+{
+       *low = (unsigned int)variable & 0xFFFFFFFF;
+       *high = (unsigned int)(variable >> 32);
+}
+
+/*
+ * Wakes up DMA queue.
+ */
+static u32 tsi148_DMA_irqhandler(int channel_mask)
+{
+       u32 serviced = 0;
+
+       if (channel_mask & TSI148_LCSR_INTS_DMA0S) {
+               wake_up(&dma_queue[0]);
+               serviced |= TSI148_LCSR_INTC_DMA0C;
+       }
+       if (channel_mask & TSI148_LCSR_INTS_DMA1S) {
+               wake_up(&dma_queue[1]);
+               serviced |= TSI148_LCSR_INTC_DMA1C;
+       }
+
+       return serviced;
+}
+
+/*
+ * Wake up location monitor queue
+ */
+static u32 tsi148_LM_irqhandler(u32 stat)
+{
+       int i;
+       u32 serviced = 0;
+
+       for (i = 0; i < 4; i++) {
+               if(stat & TSI148_LCSR_INTS_LMS[i]) {
+                       /* We only enable interrupts if the callback is set */
+                       lm_callback[i](i);
+                       serviced |= TSI148_LCSR_INTC_LMC[i];
+               }
+       }
+
+       return serviced;
+}
+
+/*
+ * Wake up mail box queue.
+ *
+ * XXX This functionality is not exposed up though API.
+ */
+static u32 tsi148_MB_irqhandler(u32 stat)
+{
+       int i;
+       u32 val;
+       u32 serviced = 0;
+
+       for (i = 0; i < 4; i++) {
+               if(stat & TSI148_LCSR_INTS_MBS[i]) {
+                       val = ioread32be(tsi148_bridge->base +
+                               TSI148_GCSR_MBOX[i]);
+                       printk("VME Mailbox %d received: 0x%x\n", i, val);
+                       serviced |= TSI148_LCSR_INTC_MBC[i];
+               }
+       }
+
+       return serviced;
+}
+
+/*
+ * Display error & status message when PERR (PCI) exception interrupt occurs.
+ */
+static u32 tsi148_PERR_irqhandler(void)
+{
+       printk(KERN_ERR
+               "PCI Exception at address: 0x%08x:%08x, attributes: %08x\n",
+               ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPAU),
+               ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPAL),
+               ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPAT)
+               );
+       printk(KERN_ERR
+               "PCI-X attribute reg: %08x, PCI-X split completion reg: %08x\n",
+               ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPXA),
+               ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPXS)
+               );
+
+       iowrite32be(TSI148_LCSR_EDPAT_EDPCL,
+               tsi148_bridge->base + TSI148_LCSR_EDPAT);
+
+       return TSI148_LCSR_INTC_PERRC;
+}
+
+/*
+ * Save address and status when VME error interrupt occurs.
+ */
+static u32 tsi148_VERR_irqhandler(void)
+{
+       unsigned int error_addr_high, error_addr_low;
+       unsigned long long error_addr;
+       u32 error_attrib;
+       struct vme_bus_error *error;
+
+       error_addr_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_VEAU);
+       error_addr_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_VEAL);
+       error_attrib = ioread32be(tsi148_bridge->base + TSI148_LCSR_VEAT);
+
+       reg_join(error_addr_high, error_addr_low, &error_addr);
+
+       /* Check for exception register overflow (we have lost error data) */
+       if(error_attrib & TSI148_LCSR_VEAT_VEOF) {
+               printk(KERN_ERR "VME Bus Exception Overflow Occurred\n");
+       }
+
+       error = (struct vme_bus_error *)kmalloc(sizeof (struct vme_bus_error),
+               GFP_ATOMIC);
+       if (error) {
+               error->address = error_addr;
+               error->attributes = error_attrib;
+               list_add_tail(&(error->list), &(tsi148_bridge->vme_errors));
+       } else {
+               printk(KERN_ERR
+                       "Unable to alloc memory for VMEbus Error reporting\n");
+               printk(KERN_ERR
+                       "VME Bus Error at address: 0x%llx, attributes: %08x\n",
+                       error_addr, error_attrib);
+       }
+
+       /* Clear Status */
+       iowrite32be(TSI148_LCSR_VEAT_VESCL,
+               tsi148_bridge->base + TSI148_LCSR_VEAT);
+
+       return TSI148_LCSR_INTC_VERRC;
+}
+
+/*
+ * Wake up IACK queue.
+ */
+static u32 tsi148_IACK_irqhandler(void)
+{
+       printk("tsi148_IACK_irqhandler\n");
+       wake_up(&iack_queue);
+
+       return TSI148_LCSR_INTC_IACKC;
+}
+
+/*
+ * Calling VME bus interrupt callback if provided.
+ */
+static u32 tsi148_VIRQ_irqhandler(u32 stat)
+{
+       int vec, i, serviced = 0;
+       void (*call)(int, int, void *);
+       void *priv_data;
+
+       for (i = 7; i > 0; i--) {
+               if (stat & (1 << i)) {
+                       /*
+                        *      Note:   Even though the registers are defined
+                        *      as 32-bits in the spec, we only want to issue
+                        *      8-bit IACK cycles on the bus, read from offset
+                        *      3.
+                        */
+                       vec = ioread8(tsi148_bridge->base +
+                               TSI148_LCSR_VIACK[i] + 3);
+
+                       call = tsi148_bridge->irq[i - 1].callback[vec].func;
+                       priv_data =
+                               tsi148_bridge->irq[i-1].callback[vec].priv_data;
+
+                       if (call != NULL)
+                               call(i, vec, priv_data);
+                       else
+                               printk("Spurilous VME interrupt, level:%x, "
+                                       "vector:%x\n", i, vec);
+
+                       serviced |= (1 << i);
+               }
+       }
+
+       return serviced;
+}
+
+/*
+ * Top level interrupt handler.  Clears appropriate interrupt status bits and
+ * then calls appropriate sub handler(s).
+ */
+static irqreturn_t tsi148_irqhandler(int irq, void *dev_id)
+{
+       u32 stat, enable, serviced = 0;
+
+       /* Determine which interrupts are unmasked and set */
+       enable = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+       stat = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTS);
+
+       /* Only look at unmasked interrupts */
+       stat &= enable;
+
+       if (unlikely(!stat)) {
+               return IRQ_NONE;
+       }
+
+       /* Call subhandlers as appropriate */
+       /* DMA irqs */
+       if (stat & (TSI148_LCSR_INTS_DMA1S | TSI148_LCSR_INTS_DMA0S))
+               serviced |= tsi148_DMA_irqhandler(stat);
+
+       /* Location monitor irqs */
+       if (stat & (TSI148_LCSR_INTS_LM3S | TSI148_LCSR_INTS_LM2S |
+                       TSI148_LCSR_INTS_LM1S | TSI148_LCSR_INTS_LM0S))
+               serviced |= tsi148_LM_irqhandler(stat);
+
+       /* Mail box irqs */
+       if (stat & (TSI148_LCSR_INTS_MB3S | TSI148_LCSR_INTS_MB2S |
+                       TSI148_LCSR_INTS_MB1S | TSI148_LCSR_INTS_MB0S))
+               serviced |= tsi148_MB_irqhandler(stat);
+
+       /* PCI bus error */
+       if (stat & TSI148_LCSR_INTS_PERRS)
+               serviced |= tsi148_PERR_irqhandler();
+
+       /* VME bus error */
+       if (stat & TSI148_LCSR_INTS_VERRS)
+               serviced |= tsi148_VERR_irqhandler();
+
+       /* IACK irq */
+       if (stat & TSI148_LCSR_INTS_IACKS)
+               serviced |= tsi148_IACK_irqhandler();
+
+       /* VME bus irqs */
+       if (stat & (TSI148_LCSR_INTS_IRQ7S | TSI148_LCSR_INTS_IRQ6S |
+                       TSI148_LCSR_INTS_IRQ5S | TSI148_LCSR_INTS_IRQ4S |
+                       TSI148_LCSR_INTS_IRQ3S | TSI148_LCSR_INTS_IRQ2S |
+                       TSI148_LCSR_INTS_IRQ1S))
+               serviced |= tsi148_VIRQ_irqhandler(stat);
+
+       /* Clear serviced interrupts */
+       iowrite32be(serviced, tsi148_bridge->base + TSI148_LCSR_INTC);
+
+       return IRQ_HANDLED;
+}
+
+static int tsi148_irq_init(struct vme_bridge *bridge)
+{
+       int result;
+       unsigned int tmp;
+       struct pci_dev *pdev;
+
+       /* Need pdev */
+        pdev = container_of(bridge->parent, struct pci_dev, dev);
+
+       /* Initialise list for VME bus errors */
+       INIT_LIST_HEAD(&(bridge->vme_errors));
+
+       result = request_irq(pdev->irq,
+                            tsi148_irqhandler,
+                            IRQF_SHARED,
+                            driver_name, pdev);
+       if (result) {
+               dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n",
+                       pdev->irq);
+               return result;
+       }
+
+       /* Enable and unmask interrupts */
+       tmp = TSI148_LCSR_INTEO_DMA1EO | TSI148_LCSR_INTEO_DMA0EO |
+               TSI148_LCSR_INTEO_MB3EO | TSI148_LCSR_INTEO_MB2EO |
+               TSI148_LCSR_INTEO_MB1EO | TSI148_LCSR_INTEO_MB0EO |
+               TSI148_LCSR_INTEO_PERREO | TSI148_LCSR_INTEO_VERREO |
+               TSI148_LCSR_INTEO_IACKEO;
+
+       /* XXX This leaves the following interrupts masked.
+        * TSI148_LCSR_INTEO_VIEEO
+        * TSI148_LCSR_INTEO_SYSFLEO
+        * TSI148_LCSR_INTEO_ACFLEO
+        */
+
+       /* Don't enable Location Monitor interrupts here - they will be
+        * enabled when the location monitors are properly configured and
+        * a callback has been attached.
+        * TSI148_LCSR_INTEO_LM0EO
+        * TSI148_LCSR_INTEO_LM1EO
+        * TSI148_LCSR_INTEO_LM2EO
+        * TSI148_LCSR_INTEO_LM3EO
+        */
+
+       /* Don't enable VME interrupts until we add a handler, else the board
+        * will respond to it and we don't want that unless it knows how to
+        * properly deal with it.
+        * TSI148_LCSR_INTEO_IRQ7EO
+        * TSI148_LCSR_INTEO_IRQ6EO
+        * TSI148_LCSR_INTEO_IRQ5EO
+        * TSI148_LCSR_INTEO_IRQ4EO
+        * TSI148_LCSR_INTEO_IRQ3EO
+        * TSI148_LCSR_INTEO_IRQ2EO
+        * TSI148_LCSR_INTEO_IRQ1EO
+        */
+
+       iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
+       iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
+
+       return 0;
+}
+
+static void tsi148_irq_exit(struct pci_dev *pdev)
+{
+       /* Turn off interrupts */
+       iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTEO);
+       iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTEN);
+
+       /* Clear all interrupts */
+       iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_INTC);
+
+       /* Detach interrupt handler */
+       free_irq(pdev->irq, pdev);
+}
+
+/*
+ * Check to see if an IACk has been received, return true (1) or false (0).
+ */
+int tsi148_iack_received(void)
+{
+       u32 tmp;
+
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VICR);
+
+       if (tmp & TSI148_LCSR_VICR_IRQS)
+               return 0;
+       else
+               return 1;
+}
+
+/*
+ * Set up an VME interrupt
+ */
+int tsi148_request_irq(int level, int statid,
+       void (*callback)(int level, int vector, void *priv_data),
+        void *priv_data)
+{
+       u32 tmp;
+
+       /* Get semaphore */
+       down(&(vme_irq));
+
+       if(tsi148_bridge->irq[level - 1].callback[statid].func) {
+               up(&(vme_irq));
+               printk("VME Interrupt already taken\n");
+               return -EBUSY;
+       }
+
+
+       tsi148_bridge->irq[level - 1].count++;
+       tsi148_bridge->irq[level - 1].callback[statid].priv_data = priv_data;
+       tsi148_bridge->irq[level - 1].callback[statid].func = callback;
+
+       /* Enable IRQ level */
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+       tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1];
+       iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+       tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1];
+       iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN);
+
+       /* Release semaphore */
+       up(&(vme_irq));
+
+       return 0;
+}
+
+/*
+ * Free VME interrupt
+ */
+void tsi148_free_irq(int level, int statid)
+{
+       u32 tmp;
+
+       /* Get semaphore */
+       down(&(vme_irq));
+
+       tsi148_bridge->irq[level - 1].callback[statid].func = NULL;
+       tsi148_bridge->irq[level - 1].callback[statid].priv_data = NULL;
+       tsi148_bridge->irq[level - 1].count--;
+
+       /* Disable IRQ level */
+       if (tsi148_bridge->irq[level - 1].count == 0) {
+               tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+               tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1];
+               iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+
+               tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+               tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1];
+               iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN);
+       }
+
+       /* Release semaphore */
+       up(&(vme_irq));
+}
+
+/*
+ * Generate a VME bus interrupt at the requested level & vector. Wait for
+ * interrupt to be acked.
+ *
+ * Only one interrupt can be generated at a time - so add a semaphore.
+ */
+int tsi148_generate_irq(int level, int statid)
+{
+       u32 tmp;
+
+       /* Get semaphore */
+       down(&(vme_int));
+
+       /* Read VICR register */
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VICR);
+
+       /* Set Status/ID */
+       tmp = (tmp & ~TSI148_LCSR_VICR_STID_M) |
+               (statid & TSI148_LCSR_VICR_STID_M);
+       iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VICR);
+
+       /* Assert VMEbus IRQ */
+       tmp = tmp | TSI148_LCSR_VICR_IRQL[level];
+       iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VICR);
+
+       /* XXX Consider implementing a timeout? */
+       wait_event_interruptible(iack_queue, tsi148_iack_received());
+
+       /* Release semaphore */
+       up(&(vme_int));
+
+       return 0;
+}
+
+/*
+ * Find the first error in this address range
+ */
+static struct vme_bus_error *tsi148_find_error(vme_address_t aspace,
+       unsigned long long address, size_t count)
+{
+       struct list_head *err_pos;
+       struct vme_bus_error *vme_err, *valid = NULL;
+       unsigned long long bound;
+
+       bound = address + count;
+
+       /*
+        * XXX We are currently not looking at the address space when parsing
+        *     for errors. This is because parsing the Address Modifier Codes
+        *     is going to be quite resource intensive to do properly. We
+        *     should be OK just looking at the addresses and this is certainly
+        *     much better than what we had before.
+        */
+       err_pos = NULL;
+       /* Iterate through errors */
+       list_for_each(err_pos, &(tsi148_bridge->vme_errors)) {
+               vme_err = list_entry(err_pos, struct vme_bus_error, list);
+               if((vme_err->address >= address) && (vme_err->address < bound)){
+                       valid = vme_err;
+                       break;
+               }
+       }
+
+       return valid;
+}
+
+/*
+ * Clear errors in the provided address range.
+ */
+static void tsi148_clear_errors(vme_address_t aspace,
+       unsigned long long address, size_t count)
+{
+       struct list_head *err_pos, *temp;
+       struct vme_bus_error *vme_err;
+       unsigned long long bound;
+
+       bound = address + count;
+
+       /*
+        * XXX We are currently not looking at the address space when parsing
+        *     for errors. This is because parsing the Address Modifier Codes
+        *     is going to be quite resource intensive to do properly. We
+        *     should be OK just looking at the addresses and this is certainly
+        *     much better than what we had before.
+        */
+       err_pos = NULL;
+       /* Iterate through errors */
+       list_for_each_safe(err_pos, temp, &(tsi148_bridge->vme_errors)) {
+               vme_err = list_entry(err_pos, struct vme_bus_error, list);
+
+               if((vme_err->address >= address) && (vme_err->address < bound)){
+                       list_del(err_pos);
+                       kfree(vme_err);
+               }
+       }
+}
+
+/*
+ * Initialize a slave window with the requested attributes.
+ */
+int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
+       unsigned long long vme_base, unsigned long long size,
+       dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle)
+{
+       unsigned int i, addr = 0, granularity = 0;
+       unsigned int temp_ctl = 0;
+       unsigned int vme_base_low, vme_base_high;
+       unsigned int vme_bound_low, vme_bound_high;
+       unsigned int pci_offset_low, pci_offset_high;
+       unsigned long long vme_bound, pci_offset;
+
+#if 0
+        printk("Set slave image %d to:\n", image->number);
+       printk("\tEnabled: %s\n", (enabled == 1)? "yes" : "no");
+       printk("\tVME Base:0x%llx\n", vme_base);
+       printk("\tWindow Size:0x%llx\n", size);
+       printk("\tPCI Base:0x%lx\n", (unsigned long)pci_base);
+       printk("\tAddress Space:0x%x\n", aspace);
+       printk("\tTransfer Cycle Properties:0x%x\n", cycle);
+#endif
+
+       i = image->number;
+
+       switch (aspace) {
+       case VME_A16:
+               granularity = 0x10;
+               addr |= TSI148_LCSR_ITAT_AS_A16;
+               break;
+       case VME_A24:
+               granularity = 0x1000;
+               addr |= TSI148_LCSR_ITAT_AS_A24;
+               break;
+       case VME_A32:
+               granularity = 0x10000;
+               addr |= TSI148_LCSR_ITAT_AS_A32;
+               break;
+       case VME_A64:
+               granularity = 0x10000;
+               addr |= TSI148_LCSR_ITAT_AS_A64;
+               break;
+       case VME_CRCSR:
+       case VME_USER1:
+       case VME_USER2:
+       case VME_USER3:
+       case VME_USER4:
+       default:
+               printk("Invalid address space\n");
+               return -EINVAL;
+               break;
+       }
+
+       /* Convert 64-bit variables to 2x 32-bit variables */
+       reg_split(vme_base, &vme_base_high, &vme_base_low);
+
+       /*
+        * Bound address is a valid address for the window, adjust
+        * accordingly
+        */
+       vme_bound = vme_base + size - granularity;
+       reg_split(vme_bound, &vme_bound_high, &vme_bound_low);
+       pci_offset = (unsigned long long)pci_base - vme_base;
+       reg_split(pci_offset, &pci_offset_high, &pci_offset_low);
+
+       if (vme_base_low & (granularity - 1)) {
+               printk("Invalid VME base alignment\n");
+               return -EINVAL;
+       }
+       if (vme_bound_low & (granularity - 1)) {
+               printk("Invalid VME bound alignment\n");
+               return -EINVAL;
+       }
+       if (pci_offset_low & (granularity - 1)) {
+               printk("Invalid PCI Offset alignment\n");
+               return -EINVAL;
+       }
+
+#if 0
+       printk("\tVME Bound:0x%llx\n", vme_bound);
+       printk("\tPCI Offset:0x%llx\n", pci_offset);
+#endif
+
+       /*  Disable while we are mucking around */
+       temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITAT);
+       temp_ctl &= ~TSI148_LCSR_ITAT_EN;
+       iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITAT);
+
+       /* Setup mapping */
+       iowrite32be(vme_base_high, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITSAU);
+       iowrite32be(vme_base_low, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITSAL);
+       iowrite32be(vme_bound_high, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITEAU);
+       iowrite32be(vme_bound_low, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITEAL);
+       iowrite32be(pci_offset_high, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITOFU);
+       iowrite32be(pci_offset_low, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITOFL);
+
+/* XXX Prefetch stuff currently unsupported */
+#if 0
+
+       for (x = 0; x < 4; x++) {
+               if ((64 << x) >= vmeIn->prefetchSize) {
+                       break;
+               }
+       }
+       if (x == 4)
+               x--;
+       temp_ctl |= (x << 16);
+
+       if (vmeIn->prefetchThreshold)
+               if (vmeIn->prefetchThreshold)
+                       temp_ctl |= 0x40000;
+#endif
+
+       /* Setup 2eSST speeds */
+       temp_ctl &= ~TSI148_LCSR_ITAT_2eSSTM_M;
+       switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
+       case VME_2eSST160:
+               temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_160;
+               break;
+       case VME_2eSST267:
+               temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_267;
+               break;
+       case VME_2eSST320:
+               temp_ctl |= TSI148_LCSR_ITAT_2eSSTM_320;
+               break;
+       }
+
+       /* Setup cycle types */
+       temp_ctl &= ~(0x1F << 7);
+       if (cycle & VME_BLT)
+               temp_ctl |= TSI148_LCSR_ITAT_BLT;
+       if (cycle & VME_MBLT)
+               temp_ctl |= TSI148_LCSR_ITAT_MBLT;
+       if (cycle & VME_2eVME)
+               temp_ctl |= TSI148_LCSR_ITAT_2eVME;
+       if (cycle & VME_2eSST)
+               temp_ctl |= TSI148_LCSR_ITAT_2eSST;
+       if (cycle & VME_2eSSTB)
+               temp_ctl |= TSI148_LCSR_ITAT_2eSSTB;
+
+       /* Setup address space */
+       temp_ctl &= ~TSI148_LCSR_ITAT_AS_M;
+       temp_ctl |= addr;
+
+       temp_ctl &= ~0xF;
+       if (cycle & VME_SUPER)
+               temp_ctl |= TSI148_LCSR_ITAT_SUPR ;
+       if (cycle & VME_USER)
+               temp_ctl |= TSI148_LCSR_ITAT_NPRIV;
+       if (cycle & VME_PROG)
+               temp_ctl |= TSI148_LCSR_ITAT_PGM;
+       if (cycle & VME_DATA)
+               temp_ctl |= TSI148_LCSR_ITAT_DATA;
+
+       /* Write ctl reg without enable */
+       iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITAT);
+
+       if (enabled)
+               temp_ctl |= TSI148_LCSR_ITAT_EN;
+
+       iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITAT);
+
+       return 0;
+}
+
+/*
+ * Get slave window configuration.
+ *
+ * XXX Prefetch currently unsupported.
+ */
+int tsi148_slave_get(struct vme_slave_resource *image, int *enabled,
+       unsigned long long *vme_base, unsigned long long *size,
+       dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle)
+{
+       unsigned int i, granularity = 0, ctl = 0;
+       unsigned int vme_base_low, vme_base_high;
+       unsigned int vme_bound_low, vme_bound_high;
+       unsigned int pci_offset_low, pci_offset_high;
+       unsigned long long vme_bound, pci_offset;
+
+
+       i = image->number;
+
+       /* Read registers */
+       ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITAT);
+
+       vme_base_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITSAU);
+       vme_base_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITSAL);
+       vme_bound_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITEAU);
+       vme_bound_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITEAL);
+       pci_offset_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITOFU);
+       pci_offset_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+               TSI148_LCSR_OFFSET_ITOFL);
+
+       /* Convert 64-bit variables to 2x 32-bit variables */
+       reg_join(vme_base_high, vme_base_low, vme_base);
+       reg_join(vme_bound_high, vme_bound_low, &vme_bound);
+       reg_join(pci_offset_high, pci_offset_low, &pci_offset);
+
+       *pci_base = (dma_addr_t)vme_base + pci_offset;
+
+       *enabled = 0;
+       *aspace = 0;
+       *cycle = 0;
+
+       if (ctl & TSI148_LCSR_ITAT_EN)
+               *enabled = 1;
+
+       if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A16) {
+               granularity = 0x10;
+               *aspace |= VME_A16;
+       }
+       if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A24) {
+               granularity = 0x1000;
+               *aspace |= VME_A24;
+       }
+       if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A32) {
+               granularity = 0x10000;
+               *aspace |= VME_A32;
+       }
+       if ((ctl & TSI148_LCSR_ITAT_AS_M) == TSI148_LCSR_ITAT_AS_A64) {
+               granularity = 0x10000;
+               *aspace |= VME_A64;
+       }
+
+       /* Need granularity before we set the size */
+       *size = (unsigned long long)((vme_bound - *vme_base) + granularity);
+
+
+       if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_160)
+               *cycle |= VME_2eSST160;
+       if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_267)
+               *cycle |= VME_2eSST267;
+       if ((ctl & TSI148_LCSR_ITAT_2eSSTM_M) == TSI148_LCSR_ITAT_2eSSTM_320)
+               *cycle |= VME_2eSST320;
+
+       if (ctl & TSI148_LCSR_ITAT_BLT)
+               *cycle |= VME_BLT;
+       if (ctl & TSI148_LCSR_ITAT_MBLT)
+               *cycle |= VME_MBLT;
+       if (ctl & TSI148_LCSR_ITAT_2eVME)
+               *cycle |= VME_2eVME;
+       if (ctl & TSI148_LCSR_ITAT_2eSST)
+               *cycle |= VME_2eSST;
+       if (ctl & TSI148_LCSR_ITAT_2eSSTB)
+               *cycle |= VME_2eSSTB;
+
+       if (ctl & TSI148_LCSR_ITAT_SUPR)
+               *cycle |= VME_SUPER;
+       if (ctl & TSI148_LCSR_ITAT_NPRIV)
+               *cycle |= VME_USER;
+       if (ctl & TSI148_LCSR_ITAT_PGM)
+               *cycle |= VME_PROG;
+       if (ctl & TSI148_LCSR_ITAT_DATA)
+               *cycle |= VME_DATA;
+
+       return 0;
+}
+
+/*
+ * Allocate and map PCI Resource
+ */
+static int tsi148_alloc_resource(struct vme_master_resource *image,
+       unsigned long long size)
+{
+       unsigned long long existing_size;
+       int retval = 0;
+       struct pci_dev *pdev;
+
+       /* Find pci_dev container of dev */
+        if (tsi148_bridge->parent == NULL) {
+                printk("Dev entry NULL\n");
+                return -EINVAL;
+        }
+        pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev);
+
+       existing_size = (unsigned long long)(image->pci_resource.end -
+               image->pci_resource.start);
+
+       /* If the existing size is OK, return */
+       if (existing_size == (size - 1))
+               return 0;
+
+       if (existing_size != 0) {
+               iounmap(image->kern_base);
+               image->kern_base = NULL;
+               if (image->pci_resource.name != NULL)
+                       kfree(image->pci_resource.name);
+               release_resource(&(image->pci_resource));
+               memset(&(image->pci_resource), 0, sizeof(struct resource));
+       }
+
+       if (image->pci_resource.name == NULL) {
+               image->pci_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
+               if (image->pci_resource.name == NULL) {
+                       printk(KERN_ERR "Unable to allocate memory for resource"
+                               " name\n");
+                       retval = -ENOMEM;
+                       goto err_name;
+               }
+       }
+
+       sprintf((char *)image->pci_resource.name, "%s.%d", tsi148_bridge->name,
+               image->number);
+
+       image->pci_resource.start = 0;
+       image->pci_resource.end = (unsigned long)size;
+       image->pci_resource.flags = IORESOURCE_MEM;
+
+       retval = pci_bus_alloc_resource(pdev->bus,
+               &(image->pci_resource), size, size, PCIBIOS_MIN_MEM,
+               0, NULL, NULL);
+       if (retval) {
+               printk(KERN_ERR "Failed to allocate mem resource for "
+                       "window %d size 0x%lx start 0x%lx\n",
+                       image->number, (unsigned long)size,
+                       (unsigned long)image->pci_resource.start);
+               goto err_resource;
+       }
+
+       image->kern_base = ioremap_nocache(
+               image->pci_resource.start, size);
+       if (image->kern_base == NULL) {
+               printk(KERN_ERR "Failed to remap resource\n");
+               retval = -ENOMEM;
+               goto err_remap;
+       }
+
+       return 0;
+
+       iounmap(image->kern_base);
+       image->kern_base = NULL;
+err_remap:
+       release_resource(&(image->pci_resource));
+err_resource:
+       kfree(image->pci_resource.name);
+       memset(&(image->pci_resource), 0, sizeof(struct resource));
+err_name:
+       return retval;
+}
+
+/*
+ * Free and unmap PCI Resource
+ */
+static void tsi148_free_resource(struct vme_master_resource *image)
+{
+       iounmap(image->kern_base);
+       image->kern_base = NULL;
+       release_resource(&(image->pci_resource));
+       kfree(image->pci_resource.name);
+       memset(&(image->pci_resource), 0, sizeof(struct resource));
+}
+
+/*
+ * Set the attributes of an outbound window.
+ */
+int tsi148_master_set( struct vme_master_resource *image, int enabled,
+       unsigned long long vme_base, unsigned long long size,
+       vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
+{
+       int retval = 0;
+       unsigned int i;
+       unsigned int temp_ctl = 0;
+       unsigned int pci_base_low, pci_base_high;
+       unsigned int pci_bound_low, pci_bound_high;
+       unsigned int vme_offset_low, vme_offset_high;
+       unsigned long long pci_bound, vme_offset, pci_base;
+
+       /* Verify input data */
+       if (vme_base & 0xFFFF) {
+               printk("Invalid VME Window alignment\n");
+               retval = -EINVAL;
+               goto err_window;
+       }
+       if (size < 0x10000) {
+               printk("Invalid VME Window size\n");
+               retval = -EINVAL;
+               goto err_window;
+       }
+
+       spin_lock(&(image->lock));
+
+       /* Let's allocate the resource here rather than further up the stack as
+        * it avoids pushing loads of bus dependant stuff up the stack
+        */
+       retval = tsi148_alloc_resource(image, size);
+       if (retval) {
+               spin_unlock(&(image->lock));
+               printk(KERN_ERR "Unable to allocate memory for resource "
+                       "name\n");
+               retval = -ENOMEM;
+               goto err_res;
+       }
+
+       pci_base = (unsigned long long)image->pci_resource.start;
+
+
+       /*
+        * Bound address is a valid address for the window, adjust
+        * according to window granularity.
+        */
+       pci_bound = pci_base + (size - 0x10000);
+       vme_offset = vme_base - pci_base;
+
+       /* Convert 64-bit variables to 2x 32-bit variables */
+       reg_split(pci_base, &pci_base_high, &pci_base_low);
+       reg_split(pci_bound, &pci_bound_high, &pci_bound_low);
+       reg_split(vme_offset, &vme_offset_high, &vme_offset_low);
+
+       if (pci_base_low & 0xFFFF) {
+               spin_unlock(&(image->lock));
+               printk("Invalid PCI base alignment\n");
+               retval = -EINVAL;
+               goto err_gran;
+       }
+       if (pci_bound_low & 0xFFFF) {
+               spin_unlock(&(image->lock));
+               printk("Invalid PCI bound alignment\n");
+               retval = -EINVAL;
+               goto err_gran;
+       }
+       if (vme_offset_low & 0xFFFF) {
+               spin_unlock(&(image->lock));
+               printk("Invalid VME Offset alignment\n");
+               retval = -EINVAL;
+               goto err_gran;
+       }
+
+       i = image->number;
+
+       /* Disable while we are mucking around */
+       temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTAT);
+       temp_ctl &= ~TSI148_LCSR_OTAT_EN;
+       iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTAT);
+
+/* XXX Prefetch stuff currently unsupported */
+#if 0
+       if (vmeOut->prefetchEnable) {
+               temp_ctl |= 0x40000;
+               for (x = 0; x < 4; x++) {
+                       if ((2 << x) >= vmeOut->prefetchSize)
+                               break;
+               }
+               if (x == 4)
+                       x = 3;
+               temp_ctl |= (x << 16);
+       }
+#endif
+
+       /* Setup 2eSST speeds */
+       temp_ctl &= ~TSI148_LCSR_OTAT_2eSSTM_M;
+       switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
+       case VME_2eSST160:
+               temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_160;
+               break;
+       case VME_2eSST267:
+               temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_267;
+               break;
+       case VME_2eSST320:
+               temp_ctl |= TSI148_LCSR_OTAT_2eSSTM_320;
+               break;
+       }
+
+       /* Setup cycle types */
+       if (cycle & VME_BLT) {
+               temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
+               temp_ctl |= TSI148_LCSR_OTAT_TM_BLT;
+       }
+       if (cycle & VME_MBLT) {
+               temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
+               temp_ctl |= TSI148_LCSR_OTAT_TM_MBLT;
+       }
+       if (cycle & VME_2eVME) {
+               temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
+               temp_ctl |= TSI148_LCSR_OTAT_TM_2eVME;
+       }
+       if (cycle & VME_2eSST) {
+               temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
+               temp_ctl |= TSI148_LCSR_OTAT_TM_2eSST;
+       }
+       if (cycle & VME_2eSSTB) {
+               printk("Currently not setting Broadcast Select Registers\n");
+               temp_ctl &= ~TSI148_LCSR_OTAT_TM_M;
+               temp_ctl |= TSI148_LCSR_OTAT_TM_2eSSTB;
+       }
+
+       /* Setup data width */
+       temp_ctl &= ~TSI148_LCSR_OTAT_DBW_M;
+       switch (dwidth) {
+       case VME_D16:
+               temp_ctl |= TSI148_LCSR_OTAT_DBW_16;
+               break;
+       case VME_D32:
+               temp_ctl |= TSI148_LCSR_OTAT_DBW_32;
+               break;
+       default:
+               spin_unlock(&(image->lock));
+               printk("Invalid data width\n");
+               retval = -EINVAL;
+               goto err_dwidth;
+       }
+
+       /* Setup address space */
+       temp_ctl &= ~TSI148_LCSR_OTAT_AMODE_M;
+       switch (aspace) {
+       case VME_A16:
+               temp_ctl |= TSI148_LCSR_OTAT_AMODE_A16;
+               break;
+       case VME_A24:
+               temp_ctl |= TSI148_LCSR_OTAT_AMODE_A24;
+               break;
+       case VME_A32:
+               temp_ctl |= TSI148_LCSR_OTAT_AMODE_A32;
+               break;
+       case VME_A64:
+               temp_ctl |= TSI148_LCSR_OTAT_AMODE_A64;
+               break;
+       case VME_CRCSR:
+               temp_ctl |= TSI148_LCSR_OTAT_AMODE_CRCSR;
+               break;
+       case VME_USER1:
+               temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER1;
+               break;
+       case VME_USER2:
+               temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER2;
+               break;
+       case VME_USER3:
+               temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER3;
+               break;
+       case VME_USER4:
+               temp_ctl |= TSI148_LCSR_OTAT_AMODE_USER4;
+               break;
+       default:
+               spin_unlock(&(image->lock));
+               printk("Invalid address space\n");
+               retval = -EINVAL;
+               goto err_aspace;
+               break;
+       }
+
+       temp_ctl &= ~(3<<4);
+       if (cycle & VME_SUPER)
+               temp_ctl |= TSI148_LCSR_OTAT_SUP;
+       if (cycle & VME_PROG)
+               temp_ctl |= TSI148_LCSR_OTAT_PGM;
+
+       /* Setup mapping */
+       iowrite32be(pci_base_high, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTSAU);
+       iowrite32be(pci_base_low, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTSAL);
+       iowrite32be(pci_bound_high, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTEAU);
+       iowrite32be(pci_bound_low, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTEAL);
+       iowrite32be(vme_offset_high, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTOFU);
+       iowrite32be(vme_offset_low, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTOFL);
+
+/* XXX We need to deal with OTBS */
+#if 0
+       iowrite32be(vmeOut->bcastSelect2esst, tsi148_bridge->base +
+               TSI148_LCSR_OT[i] + TSI148_LCSR_OFFSET_OTBS);
+#endif
+
+       /* Write ctl reg without enable */
+       iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTAT);
+
+       if (enabled)
+               temp_ctl |= TSI148_LCSR_OTAT_EN;
+
+       iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTAT);
+
+       spin_unlock(&(image->lock));
+       return 0;
+
+err_aspace:
+err_dwidth:
+err_gran:
+       tsi148_free_resource(image);
+err_res:
+err_window:
+       return retval;
+
+}
+
+/*
+ * Set the attributes of an outbound window.
+ *
+ * XXX Not parsing prefetch information.
+ */
+int __tsi148_master_get( struct vme_master_resource *image, int *enabled,
+       unsigned long long *vme_base, unsigned long long *size,
+       vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
+{
+       unsigned int i, ctl;
+       unsigned int pci_base_low, pci_base_high;
+       unsigned int pci_bound_low, pci_bound_high;
+       unsigned int vme_offset_low, vme_offset_high;
+
+       unsigned long long pci_base, pci_bound, vme_offset;
+
+       i = image->number;
+
+       ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTAT);
+
+       pci_base_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTSAU);
+       pci_base_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTSAL);
+       pci_bound_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTEAU);
+       pci_bound_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTEAL);
+       vme_offset_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTOFU);
+       vme_offset_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTOFL);
+
+       /* Convert 64-bit variables to 2x 32-bit variables */
+       reg_join(pci_base_high, pci_base_low, &pci_base);
+       reg_join(pci_bound_high, pci_bound_low, &pci_bound);
+       reg_join(vme_offset_high, vme_offset_low, &vme_offset);
+
+       *vme_base = pci_base + vme_offset;
+       *size = (unsigned long long)(pci_bound - pci_base) + 0x10000;
+
+       *enabled = 0;
+       *aspace = 0;
+       *cycle = 0;
+       *dwidth = 0;
+
+       if (ctl & TSI148_LCSR_OTAT_EN)
+               *enabled = 1;
+
+       /* Setup address space */
+       if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A16)
+               *aspace |= VME_A16;
+       if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A24)
+               *aspace |= VME_A24;
+       if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A32)
+               *aspace |= VME_A32;
+       if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_A64)
+               *aspace |= VME_A64;
+       if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_CRCSR)
+               *aspace |= VME_CRCSR;
+       if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER1)
+               *aspace |= VME_USER1;
+       if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER2)
+               *aspace |= VME_USER2;
+       if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER3)
+               *aspace |= VME_USER3;
+       if ((ctl & TSI148_LCSR_OTAT_AMODE_M) == TSI148_LCSR_OTAT_AMODE_USER4)
+               *aspace |= VME_USER4;
+
+       /* Setup 2eSST speeds */
+       if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_160)
+               *cycle |= VME_2eSST160;
+       if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_267)
+               *cycle |= VME_2eSST267;
+       if ((ctl & TSI148_LCSR_OTAT_2eSSTM_M) == TSI148_LCSR_OTAT_2eSSTM_320)
+               *cycle |= VME_2eSST320;
+
+       /* Setup cycle types */
+       if ((ctl & TSI148_LCSR_OTAT_TM_M ) == TSI148_LCSR_OTAT_TM_SCT)
+               *cycle |= VME_SCT;
+       if ((ctl & TSI148_LCSR_OTAT_TM_M ) == TSI148_LCSR_OTAT_TM_BLT)
+               *cycle |= VME_BLT;
+       if ((ctl & TSI148_LCSR_OTAT_TM_M ) == TSI148_LCSR_OTAT_TM_MBLT)
+               *cycle |= VME_MBLT;
+       if ((ctl & TSI148_LCSR_OTAT_TM_M ) == TSI148_LCSR_OTAT_TM_2eVME)
+               *cycle |= VME_2eVME;
+       if ((ctl & TSI148_LCSR_OTAT_TM_M ) == TSI148_LCSR_OTAT_TM_2eSST)
+               *cycle |= VME_2eSST;
+       if ((ctl & TSI148_LCSR_OTAT_TM_M ) == TSI148_LCSR_OTAT_TM_2eSSTB)
+               *cycle |= VME_2eSSTB;
+
+       if (ctl & TSI148_LCSR_OTAT_SUP)
+               *cycle |= VME_SUPER;
+       else
+               *cycle |= VME_USER;
+
+       if (ctl & TSI148_LCSR_OTAT_PGM)
+               *cycle |= VME_PROG;
+       else
+               *cycle |= VME_DATA;
+
+       /* Setup data width */
+       if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_16)
+               *dwidth = VME_D16;
+       if ((ctl & TSI148_LCSR_OTAT_DBW_M) == TSI148_LCSR_OTAT_DBW_32)
+               *dwidth = VME_D32;
+
+       return 0;
+}
+
+
+int tsi148_master_get( struct vme_master_resource *image, int *enabled,
+       unsigned long long *vme_base, unsigned long long *size,
+       vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
+{
+       int retval;
+
+       spin_lock(&(image->lock));
+
+       retval = __tsi148_master_get(image, enabled, vme_base, size, aspace,
+               cycle, dwidth);
+
+       spin_unlock(&(image->lock));
+
+       return retval;
+}
+
+ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
+       size_t count, loff_t offset)
+{
+       int retval, enabled;
+       unsigned long long vme_base, size;
+       vme_address_t aspace;
+       vme_cycle_t cycle;
+       vme_width_t dwidth;
+       struct vme_bus_error *vme_err = NULL;
+
+       spin_lock(&(image->lock));
+
+       memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count);
+       retval = count;
+
+       if (!err_chk)
+               goto skip_chk;
+
+       __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle,
+               &dwidth);
+
+       vme_err = tsi148_find_error(aspace, vme_base + offset, count);
+       if(vme_err != NULL) {
+               dev_err(image->parent->parent, "First VME read error detected "
+                       "an at address 0x%llx\n", vme_err->address);
+               retval = vme_err->address - (vme_base + offset);
+               /* Clear down save errors in this address range */
+               tsi148_clear_errors(aspace, vme_base + offset, count);
+       }
+
+skip_chk:
+       spin_unlock(&(image->lock));
+
+       return retval;
+}
+
+
+/* XXX We need to change vme_master_resource->sem to a spinlock so that read
+ *     and write functions can be used in an interrupt context
+ */
+ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
+       size_t count, loff_t offset)
+{
+       int retval = 0, enabled;
+       unsigned long long vme_base, size;
+       vme_address_t aspace;
+       vme_cycle_t cycle;
+       vme_width_t dwidth;
+
+       struct vme_bus_error *vme_err = NULL;
+
+       spin_lock(&(image->lock));
+
+       memcpy_toio(image->kern_base + offset, buf, (unsigned int)count);
+       retval = count;
+
+       /*
+        * Writes are posted. We need to do a read on the VME bus to flush out
+        * all of the writes before we check for errors. We can't guarentee
+        * that reading the data we have just written is safe. It is believed
+        * that there isn't any read, write re-ordering, so we can read any
+        * location in VME space, so lets read the Device ID from the tsi148's
+        * own registers as mapped into CR/CSR space.
+        *
+        * We check for saved errors in the written address range/space.
+        */
+
+       if (!err_chk)
+               goto skip_chk;
+
+       /*
+        * Get window info first, to maximise the time that the buffers may
+        * fluch on their own
+        */
+       __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle,
+               &dwidth);
+
+       ioread16(flush_image->kern_base + 0x7F000);
+
+       vme_err = tsi148_find_error(aspace, vme_base + offset, count);
+       if(vme_err != NULL) {
+               printk("First VME write error detected an at address 0x%llx\n",
+                       vme_err->address);
+               retval = vme_err->address - (vme_base + offset);
+               /* Clear down save errors in this address range */
+               tsi148_clear_errors(aspace, vme_base + offset, count);
+       }
+
+skip_chk:
+       spin_unlock(&(image->lock));
+
+       return retval;
+}
+
+/*
+ * Perform an RMW cycle on the VME bus.
+ *
+ * Requires a previously configured master window, returns final value.
+ */
+unsigned int tsi148_master_rmw(struct vme_master_resource *image,
+       unsigned int mask, unsigned int compare, unsigned int swap,
+       loff_t offset)
+{
+       unsigned long long pci_addr;
+       unsigned int pci_addr_high, pci_addr_low;
+       u32 tmp, result;
+       int i;
+
+
+       /* Find the PCI address that maps to the desired VME address */
+       i = image->number;
+
+       /* Locking as we can only do one of these at a time */
+       down(&(vme_rmw));
+
+       /* Lock image */
+       spin_lock(&(image->lock));
+
+       pci_addr_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTSAU);
+       pci_addr_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+               TSI148_LCSR_OFFSET_OTSAL);
+
+       reg_join(pci_addr_high, pci_addr_low, &pci_addr);
+       reg_split(pci_addr + offset, &pci_addr_high, &pci_addr_low);
+
+       /* Configure registers */
+       iowrite32be(mask, tsi148_bridge->base + TSI148_LCSR_RMWEN);
+       iowrite32be(compare, tsi148_bridge->base + TSI148_LCSR_RMWC);
+       iowrite32be(swap, tsi148_bridge->base + TSI148_LCSR_RMWS);
+       iowrite32be(pci_addr_high, tsi148_bridge->base + TSI148_LCSR_RMWAU);
+       iowrite32be(pci_addr_low, tsi148_bridge->base + TSI148_LCSR_RMWAL);
+
+       /* Enable RMW */
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+       tmp |= TSI148_LCSR_VMCTRL_RMWEN;
+       iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+
+       /* Kick process off with a read to the required address. */
+       result = ioread32be(image->kern_base + offset);
+
+       /* Disable RMW */
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+       tmp &= ~TSI148_LCSR_VMCTRL_RMWEN;
+       iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+
+       spin_unlock(&(image->lock));
+
+       up(&(vme_rmw));
+
+       return result;
+}
+
+static int tsi148_dma_set_vme_src_attributes (u32 *attr, vme_address_t aspace,
+       vme_cycle_t cycle, vme_width_t dwidth)
+{
+       /* Setup 2eSST speeds */
+       switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
+       case VME_2eSST160:
+               *attr |= TSI148_LCSR_DSAT_2eSSTM_160;
+               break;
+       case VME_2eSST267:
+               *attr |= TSI148_LCSR_DSAT_2eSSTM_267;
+               break;
+       case VME_2eSST320:
+               *attr |= TSI148_LCSR_DSAT_2eSSTM_320;
+               break;
+       }
+
+       /* Setup cycle types */
+       if (cycle & VME_SCT) {
+               *attr |= TSI148_LCSR_DSAT_TM_SCT;
+       }
+       if (cycle & VME_BLT) {
+               *attr |= TSI148_LCSR_DSAT_TM_BLT;
+       }
+       if (cycle & VME_MBLT) {
+               *attr |= TSI148_LCSR_DSAT_TM_MBLT;
+       }
+       if (cycle & VME_2eVME) {
+               *attr |= TSI148_LCSR_DSAT_TM_2eVME;
+       }
+       if (cycle & VME_2eSST) {
+               *attr |= TSI148_LCSR_DSAT_TM_2eSST;
+       }
+       if (cycle & VME_2eSSTB) {
+               printk("Currently not setting Broadcast Select Registers\n");
+               *attr |= TSI148_LCSR_DSAT_TM_2eSSTB;
+       }
+
+       /* Setup data width */
+       switch (dwidth) {
+       case VME_D16:
+               *attr |= TSI148_LCSR_DSAT_DBW_16;
+               break;
+       case VME_D32:
+               *attr |= TSI148_LCSR_DSAT_DBW_32;
+               break;
+       default:
+               printk("Invalid data width\n");
+               return -EINVAL;
+       }
+
+       /* Setup address space */
+       switch (aspace) {
+       case VME_A16:
+               *attr |= TSI148_LCSR_DSAT_AMODE_A16;
+               break;
+       case VME_A24:
+               *attr |= TSI148_LCSR_DSAT_AMODE_A24;
+               break;
+       case VME_A32:
+               *attr |= TSI148_LCSR_DSAT_AMODE_A32;
+               break;
+       case VME_A64:
+               *attr |= TSI148_LCSR_DSAT_AMODE_A64;
+               break;
+       case VME_CRCSR:
+               *attr |= TSI148_LCSR_DSAT_AMODE_CRCSR;
+               break;
+       case VME_USER1:
+               *attr |= TSI148_LCSR_DSAT_AMODE_USER1;
+               break;
+       case VME_USER2:
+               *attr |= TSI148_LCSR_DSAT_AMODE_USER2;
+               break;
+       case VME_USER3:
+               *attr |= TSI148_LCSR_DSAT_AMODE_USER3;
+               break;
+       case VME_USER4:
+               *attr |= TSI148_LCSR_DSAT_AMODE_USER4;
+               break;
+       default:
+               printk("Invalid address space\n");
+               return -EINVAL;
+               break;
+       }
+
+       if (cycle & VME_SUPER)
+               *attr |= TSI148_LCSR_DSAT_SUP;
+       if (cycle & VME_PROG)
+               *attr |= TSI148_LCSR_DSAT_PGM;
+
+       return 0;
+}
+
+static int tsi148_dma_set_vme_dest_attributes(u32 *attr, vme_address_t aspace,
+       vme_cycle_t cycle, vme_width_t dwidth)
+{
+       /* Setup 2eSST speeds */
+       switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
+       case VME_2eSST160:
+               *attr |= TSI148_LCSR_DDAT_2eSSTM_160;
+               break;
+       case VME_2eSST267:
+               *attr |= TSI148_LCSR_DDAT_2eSSTM_267;
+               break;
+       case VME_2eSST320:
+               *attr |= TSI148_LCSR_DDAT_2eSSTM_320;
+               break;
+       }
+
+       /* Setup cycle types */
+       if (cycle & VME_SCT) {
+               *attr |= TSI148_LCSR_DDAT_TM_SCT;
+       }
+       if (cycle & VME_BLT) {
+               *attr |= TSI148_LCSR_DDAT_TM_BLT;
+       }
+       if (cycle & VME_MBLT) {
+               *attr |= TSI148_LCSR_DDAT_TM_MBLT;
+       }
+       if (cycle & VME_2eVME) {
+               *attr |= TSI148_LCSR_DDAT_TM_2eVME;
+       }
+       if (cycle & VME_2eSST) {
+               *attr |= TSI148_LCSR_DDAT_TM_2eSST;
+       }
+       if (cycle & VME_2eSSTB) {
+               printk("Currently not setting Broadcast Select Registers\n");
+               *attr |= TSI148_LCSR_DDAT_TM_2eSSTB;
+       }
+
+       /* Setup data width */
+       switch (dwidth) {
+       case VME_D16:
+               *attr |= TSI148_LCSR_DDAT_DBW_16;
+               break;
+       case VME_D32:
+               *attr |= TSI148_LCSR_DDAT_DBW_32;
+               break;
+       default:
+               printk("Invalid data width\n");
+               return -EINVAL;
+       }
+
+       /* Setup address space */
+       switch (aspace) {
+       case VME_A16:
+               *attr |= TSI148_LCSR_DDAT_AMODE_A16;
+               break;
+       case VME_A24:
+               *attr |= TSI148_LCSR_DDAT_AMODE_A24;
+               break;
+       case VME_A32:
+               *attr |= TSI148_LCSR_DDAT_AMODE_A32;
+               break;
+       case VME_A64:
+               *attr |= TSI148_LCSR_DDAT_AMODE_A64;
+               break;
+       case VME_CRCSR:
+               *attr |= TSI148_LCSR_DDAT_AMODE_CRCSR;
+               break;
+       case VME_USER1:
+               *attr |= TSI148_LCSR_DDAT_AMODE_USER1;
+               break;
+       case VME_USER2:
+               *attr |= TSI148_LCSR_DDAT_AMODE_USER2;
+               break;
+       case VME_USER3:
+               *attr |= TSI148_LCSR_DDAT_AMODE_USER3;
+               break;
+       case VME_USER4:
+               *attr |= TSI148_LCSR_DDAT_AMODE_USER4;
+               break;
+       default:
+               printk("Invalid address space\n");
+               return -EINVAL;
+               break;
+       }
+
+       if (cycle & VME_SUPER)
+               *attr |= TSI148_LCSR_DDAT_SUP;
+       if (cycle & VME_PROG)
+               *attr |= TSI148_LCSR_DDAT_PGM;
+
+       return 0;
+}
+
+/*
+ * Add a link list descriptor to the list
+ *
+ * XXX Need to handle 2eSST Broadcast select bits
+ */
+int tsi148_dma_list_add (struct vme_dma_list *list, struct vme_dma_attr *src,
+       struct vme_dma_attr *dest, size_t count)
+{
+       struct tsi148_dma_entry *entry, *prev;
+       u32 address_high, address_low;
+       struct vme_dma_pattern *pattern_attr;
+       struct vme_dma_pci *pci_attr;
+       struct vme_dma_vme *vme_attr;
+       dma_addr_t desc_ptr;
+       int retval = 0;
+
+       /* XXX descriptor must be aligned on 64-bit boundaries */
+       entry = (struct tsi148_dma_entry *)kmalloc(
+               sizeof(struct tsi148_dma_entry), GFP_KERNEL);
+       if (entry == NULL) {
+               printk("Failed to allocate memory for dma resource "
+                       "structure\n");
+               retval = -ENOMEM;
+               goto err_mem;
+       }
+
+       /* Test descriptor alignment */
+       if ((unsigned long)&(entry->descriptor) & 0x7) {
+               printk("Descriptor not aligned to 8 byte boundary as "
+                       "required: %p\n", &(entry->descriptor));
+               retval = -EINVAL;
+               goto err_align;
+       }
+
+       /* Given we are going to fill out the structure, we probably don't
+        * need to zero it, but better safe than sorry for now.
+        */
+       memset(&(entry->descriptor), 0, sizeof(struct tsi148_dma_descriptor));
+
+       /* Fill out source part */
+       switch (src->type) {
+       case VME_DMA_PATTERN:
+               pattern_attr = (struct vme_dma_pattern *)src->private;
+
+               entry->descriptor.dsal = pattern_attr->pattern;
+               entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_PAT;
+               /* Default behaviour is 32 bit pattern */
+               if (pattern_attr->type & VME_DMA_PATTERN_BYTE) {
+                       entry->descriptor.dsat |= TSI148_LCSR_DSAT_PSZ;
+               }
+               /* It seems that the default behaviour is to increment */
+               if ((pattern_attr->type & VME_DMA_PATTERN_INCREMENT) == 0) {
+                       entry->descriptor.dsat |= TSI148_LCSR_DSAT_NIN;
+               }
+               break;
+       case VME_DMA_PCI:
+               pci_attr = (struct vme_dma_pci *)src->private;
+
+               reg_split((unsigned long long)pci_attr->address, &address_high,
+                       &address_low);
+               entry->descriptor.dsau = address_high;
+               entry->descriptor.dsal = address_low;
+               entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_PCI;
+               break;
+       case VME_DMA_VME:
+               vme_attr = (struct vme_dma_vme *)src->private;
+
+               reg_split((unsigned long long)vme_attr->address, &address_high,
+                       &address_low);
+               entry->descriptor.dsau = address_high;
+               entry->descriptor.dsal = address_low;
+               entry->descriptor.dsat = TSI148_LCSR_DSAT_TYP_VME;
+
+               retval = tsi148_dma_set_vme_src_attributes(
+                       &(entry->descriptor.dsat), vme_attr->aspace,
+                       vme_attr->cycle, vme_attr->dwidth);
+               if(retval < 0 )
+                       goto err_source;
+               break;
+       default:
+               printk("Invalid source type\n");
+               retval = -EINVAL;
+               goto err_source;
+               break;
+       }
+
+       /* Assume last link - this will be over-written by adding another */
+       entry->descriptor.dnlau = 0;
+       entry->descriptor.dnlal = TSI148_LCSR_DNLAL_LLA;
+
+
+       /* Fill out destination part */
+       switch (dest->type) {
+       case VME_DMA_PCI:
+               pci_attr = (struct vme_dma_pci *)dest->private;
+
+               reg_split((unsigned long long)pci_attr->address, &address_high,
+                       &address_low);
+               entry->descriptor.ddau = address_high;
+               entry->descriptor.ddal = address_low;
+               entry->descriptor.ddat = TSI148_LCSR_DDAT_TYP_PCI;
+               break;
+       case VME_DMA_VME:
+               vme_attr = (struct vme_dma_vme *)dest->private;
+
+               reg_split((unsigned long long)vme_attr->address, &address_high,
+                       &address_low);
+               entry->descriptor.ddau = address_high;
+               entry->descriptor.ddal = address_low;
+               entry->descriptor.ddat = TSI148_LCSR_DDAT_TYP_VME;
+
+               retval = tsi148_dma_set_vme_dest_attributes(
+                       &(entry->descriptor.ddat), vme_attr->aspace,
+                       vme_attr->cycle, vme_attr->dwidth);
+               if(retval < 0 )
+                       goto err_dest;
+               break;
+       default:
+               printk("Invalid destination type\n");
+               retval = -EINVAL;
+               goto err_dest;
+               break;
+       }
+
+       /* Fill out count */
+       entry->descriptor.dcnt = (u32)count;
+
+       /* Add to list */
+       list_add_tail(&(entry->list), &(list->entries));
+
+       /* Fill out previous descriptors "Next Address" */
+       if(entry->list.prev != &(list->entries)){
+               prev = list_entry(entry->list.prev, struct tsi148_dma_entry,
+                       list);
+               /* We need the bus address for the pointer */
+               desc_ptr = virt_to_bus(&(entry->descriptor));
+               reg_split(desc_ptr, &(prev->descriptor.dnlau),
+                       &(prev->descriptor.dnlal));
+       }
+
+       return 0;
+
+err_dest:
+err_source:
+err_align:
+               kfree(entry);
+err_mem:
+       return retval;
+}
+
+/*
+ * Check to see if the provided DMA channel is busy.
+ */
+static int tsi148_dma_busy(int channel)
+{
+       u32 tmp;
+
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
+               TSI148_LCSR_OFFSET_DSTA);
+
+       if (tmp & TSI148_LCSR_DSTA_BSY)
+               return 0;
+       else
+               return 1;
+
+}
+
+/*
+ * Execute a previously generated link list
+ *
+ * XXX Need to provide control register configuration.
+ */
+int tsi148_dma_list_exec(struct vme_dma_list *list)
+{
+       struct vme_dma_resource *ctrlr;
+       int channel, retval = 0;
+       struct tsi148_dma_entry *entry;
+       dma_addr_t bus_addr;
+       u32 bus_addr_high, bus_addr_low;
+       u32 val, dctlreg = 0;
+#if 0
+       int x;
+#endif
+
+       ctrlr = list->parent;
+
+       down(&(ctrlr->sem));
+
+       channel = ctrlr->number;
+
+       if (! list_empty(&(ctrlr->running))) {
+               /*
+                * XXX We have an active DMA transfer and currently haven't
+                *     sorted out the mechanism for "pending" DMA transfers.
+                *     Return busy.
+                */
+               /* Need to add to pending here */
+               up(&(ctrlr->sem));
+               return -EBUSY;
+       } else {
+               list_add(&(list->list), &(ctrlr->running));
+       }
+#if 0
+       /* XXX Still todo */
+       for (x = 0; x < 8; x++) {       /* vme block size */
+               if ((32 << x) >= vmeDma->maxVmeBlockSize) {
+                       break;
+               }
+       }
+       if (x == 8)
+               x = 7;
+       dctlreg |= (x << 12);
+
+       for (x = 0; x < 8; x++) {       /* pci block size */
+               if ((32 << x) >= vmeDma->maxPciBlockSize) {
+                       break;
+               }
+       }
+       if (x == 8)
+               x = 7;
+       dctlreg |= (x << 4);
+
+       if (vmeDma->vmeBackOffTimer) {
+               for (x = 1; x < 8; x++) {       /* vme timer */
+                       if ((1 << (x - 1)) >= vmeDma->vmeBackOffTimer) {
+                               break;
+                       }
+               }
+               if (x == 8)
+                       x = 7;
+               dctlreg |= (x << 8);
+       }
+
+       if (vmeDma->pciBackOffTimer) {
+               for (x = 1; x < 8; x++) {       /* pci timer */
+                       if ((1 << (x - 1)) >= vmeDma->pciBackOffTimer) {
+                               break;
+                       }
+               }
+               if (x == 8)
+                       x = 7;
+               dctlreg |= (x << 0);
+       }
+#endif
+
+       /* Get first bus address and write into registers */
+       entry = list_first_entry(&(list->entries), struct tsi148_dma_entry,
+               list);
+
+       bus_addr = virt_to_bus(&(entry->descriptor));
+
+       up(&(ctrlr->sem));
+
+       reg_split(bus_addr, &bus_addr_high, &bus_addr_low);
+
+       iowrite32be(bus_addr_high, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU);
+       iowrite32be(bus_addr_low, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAL);
+
+       /* Start the operation */
+       iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
+
+       wait_event_interruptible(dma_queue[channel], tsi148_dma_busy(channel));
+       /*
+        * Read status register, this register is valid until we kick off a
+        * new transfer.
+        */
+       val = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
+               TSI148_LCSR_OFFSET_DSTA);
+
+       if (val & TSI148_LCSR_DSTA_VBE) {
+               printk(KERN_ERR "tsi148: DMA Error. DSTA=%08X\n", val);
+               retval = -EIO;
+       }
+
+       /* Remove list from running list */
+       down(&(ctrlr->sem));
+       list_del(&(list->list));
+       up(&(ctrlr->sem));
+
+       return retval;
+}
+
+/*
+ * Clean up a previously generated link list
+ *
+ * We have a separate function, don't assume that the chain can't be reused.
+ */
+int tsi148_dma_list_empty(struct vme_dma_list *list)
+{
+       struct list_head *pos, *temp;
+        struct tsi148_dma_entry *entry;
+
+       /* detach and free each entry */
+       list_for_each_safe(pos, temp, &(list->entries)) {
+               list_del(pos);
+               entry = list_entry(pos, struct tsi148_dma_entry, list);
+               kfree(entry);
+       }
+
+       return (0);
+}
+
+/*
+ * All 4 location monitors reside at the same base - this is therefore a
+ * system wide configuration.
+ *
+ * This does not enable the LM monitor - that should be done when the first
+ * callback is attached and disabled when the last callback is removed.
+ */
+int tsi148_lm_set(unsigned long long lm_base, vme_address_t aspace,
+       vme_cycle_t cycle)
+{
+       u32 lm_base_high, lm_base_low, lm_ctl = 0;
+       int i;
+
+       /* Get semaphore */
+       down(&(vme_lm));
+
+       /* If we already have a callback attached, we can't move it! */
+       for (i = 0; i < 4; i++) {
+               if(lm_callback[i] != NULL) {
+                       up(&(vme_lm));
+                       printk("Location monitor callback attached, can't "
+                               "reset\n");
+                       return -EBUSY;
+               }
+       }
+
+       switch (aspace) {
+       case VME_A16:
+               lm_ctl |= TSI148_LCSR_LMAT_AS_A16;
+               break;
+       case VME_A24:
+               lm_ctl |= TSI148_LCSR_LMAT_AS_A24;
+               break;
+       case VME_A32:
+               lm_ctl |= TSI148_LCSR_LMAT_AS_A32;
+               break;
+       case VME_A64:
+               lm_ctl |= TSI148_LCSR_LMAT_AS_A64;
+               break;
+       default:
+               up(&(vme_lm));
+               printk("Invalid address space\n");
+               return -EINVAL;
+               break;
+       }
+
+       if (cycle & VME_SUPER)
+               lm_ctl |= TSI148_LCSR_LMAT_SUPR ;
+       if (cycle & VME_USER)
+               lm_ctl |= TSI148_LCSR_LMAT_NPRIV;
+       if (cycle & VME_PROG)
+               lm_ctl |= TSI148_LCSR_LMAT_PGM;
+       if (cycle & VME_DATA)
+               lm_ctl |= TSI148_LCSR_LMAT_DATA;
+
+       reg_split(lm_base, &lm_base_high, &lm_base_low);
+
+       iowrite32be(lm_base_high, tsi148_bridge->base + TSI148_LCSR_LMBAU);
+       iowrite32be(lm_base_low, tsi148_bridge->base + TSI148_LCSR_LMBAL);
+       iowrite32be(lm_ctl, tsi148_bridge->base + TSI148_LCSR_LMAT);
+
+       up(&(vme_lm));
+
+       return 0;
+}
+
+/* Get configuration of the callback monitor and return whether it is enabled
+ * or disabled.
+ */
+int tsi148_lm_get(unsigned long long *lm_base, vme_address_t *aspace,
+       vme_cycle_t *cycle)
+{
+       u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0;
+
+       /* Get semaphore */
+       down(&(vme_lm));
+
+       lm_base_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMBAU);
+       lm_base_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMBAL);
+       lm_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMAT);
+
+       reg_join(lm_base_high, lm_base_low, lm_base);
+
+       if (lm_ctl & TSI148_LCSR_LMAT_EN)
+               enabled = 1;
+
+       if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A16) {
+               *aspace |= VME_A16;
+       }
+       if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A24) {
+               *aspace |= VME_A24;
+       }
+       if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A32) {
+               *aspace |= VME_A32;
+       }
+       if ((lm_ctl & TSI148_LCSR_LMAT_AS_M) == TSI148_LCSR_LMAT_AS_A64) {
+               *aspace |= VME_A64;
+       }
+
+       if (lm_ctl & TSI148_LCSR_LMAT_SUPR)
+               *cycle |= VME_SUPER;
+       if (lm_ctl & TSI148_LCSR_LMAT_NPRIV)
+               *cycle |= VME_USER;
+       if (lm_ctl & TSI148_LCSR_LMAT_PGM)
+               *cycle |= VME_PROG;
+       if (lm_ctl & TSI148_LCSR_LMAT_DATA)
+               *cycle |= VME_DATA;
+
+       up(&(vme_lm));
+
+       return enabled;
+}
+
+/*
+ * Attach a callback to a specific location monitor.
+ *
+ * Callback will be passed the monitor triggered.
+ */
+int tsi148_lm_attach(int monitor, void (*callback)(int))
+{
+       u32 lm_ctl, tmp;
+
+       /* Get semaphore */
+       down(&(vme_lm));
+
+       /* Ensure that the location monitor is configured - need PGM or DATA */
+       lm_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMAT);
+       if ((lm_ctl & (TSI148_LCSR_LMAT_PGM | TSI148_LCSR_LMAT_DATA)) == 0) {
+               up(&(vme_lm));
+               printk("Location monitor not properly configured\n");
+               return -EINVAL;
+       }
+
+       /* Check that a callback isn't already attached */
+       if (lm_callback[monitor] != NULL) {
+               up(&(vme_lm));
+               printk("Existing callback attached\n");
+               return -EBUSY;
+       }
+
+       /* Attach callback */
+       lm_callback[monitor] = callback;
+
+       /* Enable Location Monitor interrupt */
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+       tmp |= TSI148_LCSR_INTEN_LMEN[monitor];
+       iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN);
+
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+       tmp |= TSI148_LCSR_INTEO_LMEO[monitor];
+       iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+
+       /* Ensure that global Location Monitor Enable set */
+       if ((lm_ctl & TSI148_LCSR_LMAT_EN) == 0) {
+               lm_ctl |= TSI148_LCSR_LMAT_EN;
+               iowrite32be(lm_ctl, tsi148_bridge->base + TSI148_LCSR_LMAT);
+       }
+
+       up(&(vme_lm));
+
+       return 0;
+}
+
+/*
+ * Detach a callback function forn a specific location monitor.
+ */
+int tsi148_lm_detach(int monitor)
+{
+       u32 lm_en, tmp;
+
+       /* Get semaphore */
+       down(&(vme_lm));
+
+       /* Disable Location Monitor and ensure previous interrupts are clear */
+       lm_en = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+       lm_en &= ~TSI148_LCSR_INTEN_LMEN[monitor];
+       iowrite32be(lm_en, tsi148_bridge->base + TSI148_LCSR_INTEN);
+
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+       tmp &= ~TSI148_LCSR_INTEO_LMEO[monitor];
+       iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+
+       iowrite32be(TSI148_LCSR_INTC_LMC[monitor],
+                tsi148_bridge->base + TSI148_LCSR_INTEO);
+
+       /* Detach callback */
+       lm_callback[monitor] = NULL;
+
+       /* If all location monitors disabled, disable global Location Monitor */
+       if ((lm_en & (TSI148_LCSR_INTS_LM0S | TSI148_LCSR_INTS_LM1S |
+                       TSI148_LCSR_INTS_LM2S | TSI148_LCSR_INTS_LM3S)) == 0) {
+               tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMAT);
+               tmp &= ~TSI148_LCSR_LMAT_EN;
+               iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_LMAT);
+       }
+
+       up(&(vme_lm));
+
+       return 0;
+}
+
+/*
+ * Determine Geographical Addressing
+ */
+int tsi148_slot_get(void)
+{
+        u32 slot = 0;
+
+       slot = ioread32be(tsi148_bridge->base + TSI148_LCSR_VSTAT);
+       slot = slot & TSI148_LCSR_VSTAT_GA_M;
+       return (int)slot;
+}
+
+static int __init tsi148_init(void)
+{
+       return pci_register_driver(&tsi148_driver);
+}
+
+/*
+ * Configure CR/CSR space
+ *
+ * Access to the CR/CSR can be configured at power-up. The location of the
+ * CR/CSR registers in the CR/CSR address space is determined by the boards
+ * Auto-ID or Geographic address. This function ensures that the window is
+ * enabled at an offset consistent with the boards geopgraphic address.
+ *
+ * Each board has a 512kB window, with the highest 4kB being used for the
+ * boards registers, this means there is a fix length 508kB window which must
+ * be mapped onto PCI memory.
+ */
+static int tsi148_crcsr_init(struct pci_dev *pdev)
+{
+       u32 cbar, crat, vstat;
+       u32 crcsr_bus_high, crcsr_bus_low;
+       int retval;
+
+       /* Allocate mem for CR/CSR image */
+       crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
+               &crcsr_bus);
+       if (crcsr_kernel == NULL) {
+               dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR "
+                       "image\n");
+               return -ENOMEM;
+       }
+
+       memset(crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
+
+       reg_split(crcsr_bus, &crcsr_bus_high, &crcsr_bus_low);
+
+       iowrite32be(crcsr_bus_high, tsi148_bridge->base + TSI148_LCSR_CROU);
+       iowrite32be(crcsr_bus_low, tsi148_bridge->base + TSI148_LCSR_CROL);
+
+       /* Ensure that the CR/CSR is configured at the correct offset */
+       cbar = ioread32be(tsi148_bridge->base + TSI148_CBAR);
+       cbar = (cbar & TSI148_CRCSR_CBAR_M)>>3;
+
+       vstat = tsi148_slot_get();
+
+       if (cbar != vstat) {
+               dev_info(&pdev->dev, "Setting CR/CSR offset\n");
+               iowrite32be(cbar<<3, tsi148_bridge->base + TSI148_CBAR);
+       }
+       dev_info(&pdev->dev, "CR/CSR Offset: %d\n", cbar);
+
+       crat = ioread32be(tsi148_bridge->base + TSI148_LCSR_CRAT);
+       if (crat & TSI148_LCSR_CRAT_EN) {
+               dev_info(&pdev->dev, "Enabling CR/CSR space\n");
+               iowrite32be(crat | TSI148_LCSR_CRAT_EN,
+                       tsi148_bridge->base + TSI148_LCSR_CRAT);
+       } else
+               dev_info(&pdev->dev, "CR/CSR already enabled\n");
+
+       /* If we want flushed, error-checked writes, set up a window
+        * over the CR/CSR registers. We read from here to safely flush
+        * through VME writes.
+        */
+       if(err_chk) {
+               retval = tsi148_master_set(flush_image, 1, (vstat * 0x80000),
+                       0x80000, VME_CRCSR, VME_SCT, VME_D16);
+               if (retval)
+                       dev_err(&pdev->dev, "Configuring flush image failed\n");
+       }
+
+       return 0;
+
+}
+
+static void tsi148_crcsr_exit(struct pci_dev *pdev)
+{
+       u32 crat;
+
+       /* Turn off CR/CSR space */
+       crat = ioread32be(tsi148_bridge->base + TSI148_LCSR_CRAT);
+       iowrite32be(crat & ~TSI148_LCSR_CRAT_EN,
+               tsi148_bridge->base + TSI148_LCSR_CRAT);
+
+       /* Free image */
+       iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_CROU);
+       iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_CROL);
+
+       pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, crcsr_kernel, crcsr_bus);
+}
+
+static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       int retval, i, master_num;
+       u32 data;
+       struct list_head *pos = NULL;
+       struct vme_master_resource *master_image;
+       struct vme_slave_resource *slave_image;
+       struct vme_dma_resource *dma_ctrlr;
+
+       /* If we want to support more than one of each bridge, we need to
+        * dynamically generate this so we get one per device
+        */
+       tsi148_bridge = (struct vme_bridge *)kmalloc(sizeof(struct vme_bridge),
+               GFP_KERNEL);
+       if (tsi148_bridge == NULL) {
+               dev_err(&pdev->dev, "Failed to allocate memory for device "
+                       "structure\n");
+               retval = -ENOMEM;
+               goto err_struct;
+       }
+
+       memset(tsi148_bridge, 0, sizeof(struct vme_bridge));
+
+       /* Enable the device */
+       retval = pci_enable_device(pdev);
+       if (retval) {
+               dev_err(&pdev->dev, "Unable to enable device\n");
+               goto err_enable;
+       }
+
+       /* Map Registers */
+       retval = pci_request_regions(pdev, driver_name);
+       if (retval) {
+               dev_err(&pdev->dev, "Unable to reserve resources\n");
+               goto err_resource;
+       }
+
+       /* map registers in BAR 0 */
+       tsi148_bridge->base = ioremap_nocache(pci_resource_start(pdev, 0), 4096);
+       if (!tsi148_bridge->base) {
+               dev_err(&pdev->dev, "Unable to remap CRG region\n");
+               retval = -EIO;
+               goto err_remap;
+       }
+
+       /* Check to see if the mapping worked out */
+       data = ioread32(tsi148_bridge->base + TSI148_PCFS_ID) & 0x0000FFFF;
+       if (data != PCI_VENDOR_ID_TUNDRA) {
+               dev_err(&pdev->dev, "CRG region check failed\n");
+               retval = -EIO;
+               goto err_test;
+       }
+
+       /* Initialize wait queues & mutual exclusion flags */
+       /* XXX These need to be moved to the vme_bridge structure */
+       init_waitqueue_head(&dma_queue[0]);
+       init_waitqueue_head(&dma_queue[1]);
+       init_waitqueue_head(&iack_queue);
+       init_MUTEX(&(vme_int));
+       init_MUTEX(&(vme_irq));
+       init_MUTEX(&(vme_rmw));
+       init_MUTEX(&(vme_lm));
+
+       tsi148_bridge->parent = &(pdev->dev);
+       strcpy(tsi148_bridge->name, driver_name);
+
+       /* Setup IRQ */
+       retval = tsi148_irq_init(tsi148_bridge);
+       if (retval != 0) {
+               dev_err(&pdev->dev, "Chip Initialization failed.\n");
+               goto err_irq;
+       }
+
+       /* If we are going to flush writes, we need to read from the VME bus.
+        * We need to do this safely, thus we read the devices own CR/CSR
+        * register. To do this we must set up a window in CR/CSR space and
+        * hence have one less master window resource available.
+        */
+       master_num = TSI148_MAX_MASTER;
+       if(err_chk){
+               master_num--;
+               /* XXX */
+               flush_image = (struct vme_master_resource *)kmalloc(
+                       sizeof(struct vme_master_resource), GFP_KERNEL);
+               if (flush_image == NULL) {
+                       dev_err(&pdev->dev, "Failed to allocate memory for "
+                       "flush resource structure\n");
+                       retval = -ENOMEM;
+                       goto err_master;
+               }
+               flush_image->parent = tsi148_bridge;
+               spin_lock_init(&(flush_image->lock));
+               flush_image->locked = 1;
+               flush_image->number = master_num;
+               flush_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
+                       VME_A64;
+               flush_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
+                       VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
+                       VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
+                       VME_PROG | VME_DATA;
+               flush_image->width_attr = VME_D16 | VME_D32;
+               memset(&(flush_image->pci_resource), 0,
+                       sizeof(struct resource));
+               flush_image->kern_base  = NULL;
+       }
+
+       /* Add master windows to list */
+       INIT_LIST_HEAD(&(tsi148_bridge->master_resources));
+       for (i = 0; i < master_num; i++) {
+               master_image = (struct vme_master_resource *)kmalloc(
+                       sizeof(struct vme_master_resource), GFP_KERNEL);
+               if (master_image == NULL) {
+                       dev_err(&pdev->dev, "Failed to allocate memory for "
+                       "master resource structure\n");
+                       retval = -ENOMEM;
+                       goto err_master;
+               }
+               master_image->parent = tsi148_bridge;
+               spin_lock_init(&(master_image->lock));
+               master_image->locked = 0;
+               master_image->number = i;
+               master_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
+                       VME_A64;
+               master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
+                       VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
+                       VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
+                       VME_PROG | VME_DATA;
+               master_image->width_attr = VME_D16 | VME_D32;
+               memset(&(master_image->pci_resource), 0,
+                       sizeof(struct resource));
+               master_image->kern_base  = NULL;
+               list_add_tail(&(master_image->list),
+                       &(tsi148_bridge->master_resources));
+       }
+
+       /* Add slave windows to list */
+       INIT_LIST_HEAD(&(tsi148_bridge->slave_resources));
+       for (i = 0; i < TSI148_MAX_SLAVE; i++) {
+               slave_image = (struct vme_slave_resource *)kmalloc(
+                       sizeof(struct vme_slave_resource), GFP_KERNEL);
+               if (slave_image == NULL) {
+                       dev_err(&pdev->dev, "Failed to allocate memory for "
+                       "slave resource structure\n");
+                       retval = -ENOMEM;
+                       goto err_slave;
+               }
+               slave_image->parent = tsi148_bridge;
+               init_MUTEX(&(slave_image->sem));
+               slave_image->locked = 0;
+               slave_image->number = i;
+               slave_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
+                       VME_A64 | VME_CRCSR | VME_USER1 | VME_USER2 |
+                       VME_USER3 | VME_USER4;
+               slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
+                       VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
+                       VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
+                       VME_PROG | VME_DATA;
+               list_add_tail(&(slave_image->list),
+                       &(tsi148_bridge->slave_resources));
+       }
+
+       /* Add dma engines to list */
+       INIT_LIST_HEAD(&(tsi148_bridge->dma_resources));
+       for (i = 0; i < TSI148_MAX_DMA; i++) {
+               dma_ctrlr = (struct vme_dma_resource *)kmalloc(
+                       sizeof(struct vme_dma_resource), GFP_KERNEL);
+               if (dma_ctrlr == NULL) {
+                       dev_err(&pdev->dev, "Failed to allocate memory for "
+                       "dma resource structure\n");
+                       retval = -ENOMEM;
+                       goto err_dma;
+               }
+               dma_ctrlr->parent = tsi148_bridge;
+               init_MUTEX(&(dma_ctrlr->sem));
+               dma_ctrlr->locked = 0;
+               dma_ctrlr->number = i;
+               INIT_LIST_HEAD(&(dma_ctrlr->pending));
+               INIT_LIST_HEAD(&(dma_ctrlr->running));
+               list_add_tail(&(dma_ctrlr->list),
+                       &(tsi148_bridge->dma_resources));
+       }
+
+       tsi148_bridge->slave_get = tsi148_slave_get;
+       tsi148_bridge->slave_set = tsi148_slave_set;
+       tsi148_bridge->master_get = tsi148_master_get;
+       tsi148_bridge->master_set = tsi148_master_set;
+       tsi148_bridge->master_read = tsi148_master_read;
+       tsi148_bridge->master_write = tsi148_master_write;
+       tsi148_bridge->master_rmw = tsi148_master_rmw;
+       tsi148_bridge->dma_list_add = tsi148_dma_list_add;
+       tsi148_bridge->dma_list_exec = tsi148_dma_list_exec;
+       tsi148_bridge->dma_list_empty = tsi148_dma_list_empty;
+       tsi148_bridge->request_irq = tsi148_request_irq;
+       tsi148_bridge->free_irq = tsi148_free_irq;
+       tsi148_bridge->generate_irq = tsi148_generate_irq;
+       tsi148_bridge->lm_set = tsi148_lm_set;
+       tsi148_bridge->lm_get = tsi148_lm_get;
+       tsi148_bridge->lm_attach = tsi148_lm_attach;
+       tsi148_bridge->lm_detach = tsi148_lm_detach;
+       tsi148_bridge->slot_get = tsi148_slot_get;
+
+       data = ioread32be(tsi148_bridge->base + TSI148_LCSR_VSTAT);
+       dev_info(&pdev->dev, "Board is%s the VME system controller\n",
+               (data & TSI148_LCSR_VSTAT_SCONS)? "" : " not");
+       dev_info(&pdev->dev, "VME geographical address is %d\n",
+               data & TSI148_LCSR_VSTAT_GA_M);
+       dev_info(&pdev->dev, "VME Write and flush and error check is %s\n",
+               err_chk ? "enabled" : "disabled");
+
+       if(tsi148_crcsr_init(pdev)) {
+               dev_err(&pdev->dev, "CR/CSR configuration failed.\n");
+               goto err_crcsr;
+
+       }
+
+       /* Need to save tsi148_bridge pointer locally in link list for use in
+        * tsi148_remove()
+        */
+       retval = vme_register_bridge(tsi148_bridge);
+       if (retval != 0) {
+               dev_err(&pdev->dev, "Chip Registration failed.\n");
+               goto err_reg;
+       }
+
+       /* Clear VME bus "board fail", and "power-up reset" lines */
+       data = ioread32be(tsi148_bridge->base + TSI148_LCSR_VSTAT);
+       data &= ~TSI148_LCSR_VSTAT_BRDFL;
+       data |= TSI148_LCSR_VSTAT_CPURST;
+       iowrite32be(data, tsi148_bridge->base + TSI148_LCSR_VSTAT);
+
+       return 0;
+
+       vme_unregister_bridge(tsi148_bridge);
+err_reg:
+       tsi148_crcsr_exit(pdev);
+err_crcsr:
+err_dma:
+       /* resources are stored in link list */
+       list_for_each(pos, &(tsi148_bridge->dma_resources)) {
+               dma_ctrlr = list_entry(pos, struct vme_dma_resource, list);
+               list_del(pos);
+               kfree(dma_ctrlr);
+       }
+err_slave:
+       /* resources are stored in link list */
+       list_for_each(pos, &(tsi148_bridge->slave_resources)) {
+               slave_image = list_entry(pos, struct vme_slave_resource, list);
+               list_del(pos);
+               kfree(slave_image);
+       }
+err_master:
+       /* resources are stored in link list */
+       list_for_each(pos, &(tsi148_bridge->master_resources)) {
+               master_image = list_entry(pos, struct vme_master_resource,                              list);
+               list_del(pos);
+               kfree(master_image);
+       }
+
+       tsi148_irq_exit(pdev);
+err_irq:
+err_test:
+       iounmap(tsi148_bridge->base);
+err_remap:
+       pci_release_regions(pdev);
+err_resource:
+       pci_disable_device(pdev);
+err_enable:
+       kfree(tsi148_bridge);
+err_struct:
+       return retval;
+
+}
+
+static void tsi148_remove(struct pci_dev *pdev)
+{
+       struct list_head *pos = NULL;
+       struct vme_master_resource *master_image;
+       struct vme_slave_resource *slave_image;
+       struct vme_dma_resource *dma_ctrlr;
+       int i;
+
+       dev_dbg(&pdev->dev, "Driver is being unloaded.\n");
+
+       /* XXX We need to find the pdev->dev in the list of vme_bridge->dev's */
+
+       /*
+        *  Shutdown all inbound and outbound windows.
+        */
+       for (i = 0; i < 8; i++) {
+               iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+                       TSI148_LCSR_OFFSET_ITAT);
+               iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+                       TSI148_LCSR_OFFSET_OTAT);
+       }
+
+       /*
+        *  Shutdown Location monitor.
+        */
+       iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_LMAT);
+
+       /*
+        *  Shutdown CRG map.
+        */
+       iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_CSRAT);
+
+       /*
+        *  Clear error status.
+        */
+       iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_EDPAT);
+       iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_VEAT);
+       iowrite32be(0x07000700, tsi148_bridge->base + TSI148_LCSR_PSTAT);
+
+       /*
+        *  Remove VIRQ interrupt (if any)
+        */
+       if (ioread32be(tsi148_bridge->base + TSI148_LCSR_VICR) & 0x800) {
+               iowrite32be(0x8000, tsi148_bridge->base + TSI148_LCSR_VICR);
+       }
+
+       /*
+        *  Disable and clear all interrupts.
+        */
+       iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTEO);
+       iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_INTC);
+       iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_INTEN);
+
+       /*
+        *  Map all Interrupts to PCI INTA
+        */
+       iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTM1);
+       iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTM2);
+
+       tsi148_irq_exit(pdev);
+
+       vme_unregister_bridge(tsi148_bridge);
+
+       tsi148_crcsr_exit(pdev);
+
+       /* resources are stored in link list */
+       list_for_each(pos, &(tsi148_bridge->dma_resources)) {
+               dma_ctrlr = list_entry(pos, struct vme_dma_resource, list);
+               list_del(pos);
+               kfree(dma_ctrlr);
+       }
+
+       /* resources are stored in link list */
+       list_for_each(pos, &(tsi148_bridge->slave_resources)) {
+               slave_image = list_entry(pos, struct vme_slave_resource, list);
+               list_del(pos);
+               kfree(slave_image);
+       }
+
+       /* resources are stored in link list */
+       list_for_each(pos, &(tsi148_bridge->master_resources)) {
+               master_image = list_entry(pos, struct vme_master_resource,                              list);
+               list_del(pos);
+               kfree(master_image);
+       }
+
+       tsi148_irq_exit(pdev);
+
+       iounmap(tsi148_bridge->base);
+
+       pci_release_regions(pdev);
+
+       pci_disable_device(pdev);
+
+       kfree(tsi148_bridge);
+}
+
+static void __exit tsi148_exit(void)
+{
+       pci_unregister_driver(&tsi148_driver);
+
+       printk(KERN_DEBUG "Driver removed.\n");
+}
+
+MODULE_PARM_DESC(err_chk, "Check for VME errors on reads and writes");
+module_param(err_chk, bool, 0);
+
+MODULE_DESCRIPTION("VME driver for the Tundra Tempe VME bridge");
+MODULE_LICENSE("GPL");
+
+module_init(tsi148_init);
+module_exit(tsi148_exit);
+
+/*----------------------------------------------------------------------------
+ * STAGING
+ *--------------------------------------------------------------------------*/
+
+#if 0
+/*
+ * Direct Mode DMA transfer
+ *
+ * XXX Not looking at direct mode for now, we can always use link list mode
+ *     with a single entry.
+ */
+int tsi148_dma_run(struct vme_dma_resource *resource, struct vme_dma_attr src,
+       struct vme_dma_attr dest, size_t count)
+{
+       u32 dctlreg = 0;
+       unsigned int tmp;
+       int val;
+       int channel, x;
+       struct vmeDmaPacket *cur_dma;
+       struct tsi148_dma_descriptor *dmaLL;
+
+       /* direct mode */
+       dctlreg = 0x800000;
+
+       for (x = 0; x < 8; x++) {       /* vme block size */
+               if ((32 << x) >= vmeDma->maxVmeBlockSize) {
+                       break;
+               }
+       }
+       if (x == 8)
+               x = 7;
+       dctlreg |= (x << 12);
+
+       for (x = 0; x < 8; x++) {       /* pci block size */
+               if ((32 << x) >= vmeDma->maxPciBlockSize) {
+                       break;
+               }
+       }
+       if (x == 8)
+               x = 7;
+       dctlreg |= (x << 4);
+
+       if (vmeDma->vmeBackOffTimer) {
+               for (x = 1; x < 8; x++) {       /* vme timer */
+                       if ((1 << (x - 1)) >= vmeDma->vmeBackOffTimer) {
+                               break;
+                       }
+               }
+               if (x == 8)
+                       x = 7;
+               dctlreg |= (x << 8);
+       }
+
+       if (vmeDma->pciBackOffTimer) {
+               for (x = 1; x < 8; x++) {       /* pci timer */
+                       if ((1 << (x - 1)) >= vmeDma->pciBackOffTimer) {
+                               break;
+                       }
+               }
+               if (x == 8)
+                       x = 7;
+               dctlreg |= (x << 0);
+       }
+
+       /* Program registers for DMA transfer */
+       iowrite32be(dmaLL->dsau, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DSAU);
+       iowrite32be(dmaLL->dsal, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DSAL);
+       iowrite32be(dmaLL->ddau, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDAU);
+       iowrite32be(dmaLL->ddal, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDAL);
+       iowrite32be(dmaLL->dsat, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DSAT);
+       iowrite32be(dmaLL->ddat, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDAT);
+       iowrite32be(dmaLL->dcnt, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCNT);
+       iowrite32be(dmaLL->ddbs, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDBS);
+
+       /* Start the operation */
+       iowrite32be(dctlreg | 0x2000000, tsi148_bridge->base +
+               TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
+
+       tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
+               TSI148_LCSR_OFFSET_DSTA);
+       wait_event_interruptible(dma_queue[channel], (tmp & 0x1000000) == 0);
+
+       /*
+        * Read status register, we should probably do this in some error
+        * handler rather than here so that we can be sure we haven't kicked off
+        * another DMA transfer.
+        */
+       val = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
+               TSI148_LCSR_OFFSET_DSTA);
+
+       vmeDma->vmeDmaStatus = 0;
+       if (val & 0x10000000) {
+               printk(KERN_ERR
+                       "DMA Error in DMA_tempe_irqhandler DSTA=%08X\n",
+                       val);
+               vmeDma->vmeDmaStatus = val;
+
+       }
+       return (0);
+}
+#endif
+
+#if 0
+
+/* Global VME controller information */
+struct pci_dev *vme_pci_dev;
+
+/*
+ * Set the VME bus arbiter with the requested attributes
+ */
+int tempe_set_arbiter(vmeArbiterCfg_t * vmeArb)
+{
+       int temp_ctl = 0;
+       int gto = 0;
+
+       temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VCTRL);
+       temp_ctl &= 0xFFEFFF00;
+
+       if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) {
+               gto = 8;
+       } else if (vmeArb->globalTimeoutTimer > 2048) {
+               return (-EINVAL);
+       } else if (vmeArb->globalTimeoutTimer == 0) {
+               gto = 0;
+       } else {
+               gto = 1;
+               while ((16 * (1 << (gto - 1))) < vmeArb->globalTimeoutTimer) {
+                       gto += 1;
+               }
+       }
+       temp_ctl |= gto;
+
+       if (vmeArb->arbiterMode != VME_PRIORITY_MODE) {
+               temp_ctl |= 1 << 6;
+       }
+
+       if (vmeArb->arbiterTimeoutFlag) {
+               temp_ctl |= 1 << 7;
+       }
+
+       if (vmeArb->noEarlyReleaseFlag) {
+               temp_ctl |= 1 << 20;
+       }
+       iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_VCTRL);
+
+       return (0);
+}
+
+/*
+ * Return the attributes of the VME bus arbiter.
+ */
+int tempe_get_arbiter(vmeArbiterCfg_t * vmeArb)
+{
+       int temp_ctl = 0;
+       int gto = 0;
+
+
+       temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VCTRL);
+
+       gto = temp_ctl & 0xF;
+       if (gto != 0) {
+               vmeArb->globalTimeoutTimer = (16 * (1 << (gto - 1)));
+       }
+
+       if (temp_ctl & (1 << 6)) {
+               vmeArb->arbiterMode = VME_R_ROBIN_MODE;
+       } else {
+               vmeArb->arbiterMode = VME_PRIORITY_MODE;
+       }
+
+       if (temp_ctl & (1 << 7)) {
+               vmeArb->arbiterTimeoutFlag = 1;
+       }
+
+       if (temp_ctl & (1 << 20)) {
+               vmeArb->noEarlyReleaseFlag = 1;
+       }
+
+       return (0);
+}
+
+/*
+ * Set the VME bus requestor with the requested attributes
+ */
+int tempe_set_requestor(vmeRequesterCfg_t * vmeReq)
+{
+       int temp_ctl = 0;
+
+       temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+       temp_ctl &= 0xFFFF0000;
+
+       if (vmeReq->releaseMode == 1) {
+               temp_ctl |= (1 << 3);
+       }
+
+       if (vmeReq->fairMode == 1) {
+               temp_ctl |= (1 << 2);
+       }
+
+       temp_ctl |= (vmeReq->timeonTimeoutTimer & 7) << 8;
+       temp_ctl |= (vmeReq->timeoffTimeoutTimer & 7) << 12;
+       temp_ctl |= vmeReq->requestLevel;
+
+       iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+       return (0);
+}
+
+/*
+ * Return the attributes of the VME bus requestor
+ */
+int tempe_get_requestor(vmeRequesterCfg_t * vmeReq)
+{
+       int temp_ctl = 0;
+
+       temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+
+       if (temp_ctl & 0x18) {
+               vmeReq->releaseMode = 1;
+       }
+
+       if (temp_ctl & (1 << 2)) {
+               vmeReq->fairMode = 1;
+       }
+
+       vmeReq->requestLevel = temp_ctl & 3;
+       vmeReq->timeonTimeoutTimer = (temp_ctl >> 8) & 7;
+       vmeReq->timeoffTimeoutTimer = (temp_ctl >> 12) & 7;
+
+       return (0);
+}
+
+
+#endif
diff --git a/drivers/staging/vme/bridges/vme_tsi148.h b/drivers/staging/vme/bridges/vme_tsi148.h
new file mode 100644 (file)
index 0000000..6f0f705
--- /dev/null
@@ -0,0 +1,1387 @@
+/*
+ * tsi148.h
+ *
+ * Support for the Tundra TSI148 VME Bridge chip
+ *
+ * Author: Tom Armistead
+ * Updated and maintained by Ajit Prem
+ * Copyright 2004 Motorola Inc.
+ *
+ * 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.
+ */
+
+#ifndef TSI148_H
+#define TSI148_H
+
+#ifndef        PCI_VENDOR_ID_TUNDRA
+#define        PCI_VENDOR_ID_TUNDRA 0x10e3
+#endif
+
+#ifndef        PCI_DEVICE_ID_TUNDRA_TSI148
+#define        PCI_DEVICE_ID_TUNDRA_TSI148 0x148
+#endif
+
+/*
+ *  Define the number of each that the Tsi148 supports.
+ */
+#define TSI148_MAX_MASTER              8       /* Max Master Windows */
+#define TSI148_MAX_SLAVE               8       /* Max Slave Windows */
+#define TSI148_MAX_DMA                 2       /* Max DMA Controllers */
+#define TSI148_MAX_MAILBOX             4       /* Max Mail Box registers */
+#define TSI148_MAX_SEMAPHORE           8       /* Max Semaphores */
+
+/*
+ * Layout of a DMAC Linked-List Descriptor
+ *
+ * Note: This structure is accessed via the chip and therefore must be
+ *       correctly laid out - It must also be aligned on 64-bit boundaries.
+ */
+struct tsi148_dma_descriptor {
+       u32 dsau;      /* Source Address */
+       u32 dsal;
+       u32 ddau;      /* Destination Address */
+       u32 ddal;
+       u32 dsat;      /* Source attributes */
+       u32 ddat;      /* Destination attributes */
+       u32 dnlau;     /* Next link address */
+       u32 dnlal;
+       u32 dcnt;      /* Byte count */
+       u32 ddbs;      /* 2eSST Broadcast select */
+};
+
+struct tsi148_dma_entry {
+       /*
+        * The descriptor needs to be aligned on a 64-bit boundary, we increase
+        * the chance of this by putting it first in the structure.
+        */
+       struct tsi148_dma_descriptor descriptor;
+       struct list_head list;
+};
+
+/*
+ *  TSI148 ASIC register structure overlays and bit field definitions.
+ *
+ *      Note:   Tsi148 Register Group (CRG) consists of the following
+ *              combination of registers:
+ *                      PCFS    - PCI Configuration Space Registers
+ *                      LCSR    - Local Control and Status Registers
+ *                      GCSR    - Global Control and Status Registers
+ *                      CR/CSR  - Subset of Configuration ROM /
+ *                                Control and Status Registers
+ */
+
+
+/*
+ *  Command/Status Registers (CRG + $004)
+ */
+#define TSI148_PCFS_ID                 0x0
+#define TSI148_PCFS_CSR                        0x4
+#define TSI148_PCFS_CLASS              0x8
+#define TSI148_PCFS_MISC0              0xC
+#define TSI148_PCFS_MBARL              0x10
+#define TSI148_PCFS_MBARU              0x14
+
+#define TSI148_PCFS_SUBID              0x28
+
+#define TSI148_PCFS_CAPP               0x34
+
+#define TSI148_PCFS_MISC1              0x3C
+
+#define TSI148_PCFS_XCAPP              0x40
+#define TSI148_PCFS_XSTAT              0x44
+
+/*
+ * LCSR definitions
+ */
+
+/*
+ *    Outbound Translations
+ */
+#define TSI148_LCSR_OT0_OTSAU          0x100
+#define TSI148_LCSR_OT0_OTSAL          0x104
+#define TSI148_LCSR_OT0_OTEAU          0x108
+#define TSI148_LCSR_OT0_OTEAL          0x10C
+#define TSI148_LCSR_OT0_OTOFU          0x110
+#define TSI148_LCSR_OT0_OTOFL          0x114
+#define TSI148_LCSR_OT0_OTBS           0x118
+#define TSI148_LCSR_OT0_OTAT           0x11C
+
+#define TSI148_LCSR_OT1_OTSAU          0x120
+#define TSI148_LCSR_OT1_OTSAL          0x124
+#define TSI148_LCSR_OT1_OTEAU          0x128
+#define TSI148_LCSR_OT1_OTEAL          0x12C
+#define TSI148_LCSR_OT1_OTOFU          0x130
+#define TSI148_LCSR_OT1_OTOFL          0x134
+#define TSI148_LCSR_OT1_OTBS           0x138
+#define TSI148_LCSR_OT1_OTAT           0x13C
+
+#define TSI148_LCSR_OT2_OTSAU          0x140
+#define TSI148_LCSR_OT2_OTSAL          0x144
+#define TSI148_LCSR_OT2_OTEAU          0x148
+#define TSI148_LCSR_OT2_OTEAL          0x14C
+#define TSI148_LCSR_OT2_OTOFU          0x150
+#define TSI148_LCSR_OT2_OTOFL          0x154
+#define TSI148_LCSR_OT2_OTBS           0x158
+#define TSI148_LCSR_OT2_OTAT           0x15C
+
+#define TSI148_LCSR_OT3_OTSAU          0x160
+#define TSI148_LCSR_OT3_OTSAL          0x164
+#define TSI148_LCSR_OT3_OTEAU          0x168
+#define TSI148_LCSR_OT3_OTEAL          0x16C
+#define TSI148_LCSR_OT3_OTOFU          0x170
+#define TSI148_LCSR_OT3_OTOFL          0x174
+#define TSI148_LCSR_OT3_OTBS           0x178
+#define TSI148_LCSR_OT3_OTAT           0x17C
+
+#define TSI148_LCSR_OT4_OTSAU          0x180
+#define TSI148_LCSR_OT4_OTSAL          0x184
+#define TSI148_LCSR_OT4_OTEAU          0x188
+#define TSI148_LCSR_OT4_OTEAL          0x18C
+#define TSI148_LCSR_OT4_OTOFU          0x190
+#define TSI148_LCSR_OT4_OTOFL          0x194
+#define TSI148_LCSR_OT4_OTBS           0x198
+#define TSI148_LCSR_OT4_OTAT           0x19C
+
+#define TSI148_LCSR_OT5_OTSAU          0x1A0
+#define TSI148_LCSR_OT5_OTSAL          0x1A4
+#define TSI148_LCSR_OT5_OTEAU          0x1A8
+#define TSI148_LCSR_OT5_OTEAL          0x1AC
+#define TSI148_LCSR_OT5_OTOFU          0x1B0
+#define TSI148_LCSR_OT5_OTOFL          0x1B4
+#define TSI148_LCSR_OT5_OTBS           0x1B8
+#define TSI148_LCSR_OT5_OTAT           0x1BC
+
+#define TSI148_LCSR_OT6_OTSAU          0x1C0
+#define TSI148_LCSR_OT6_OTSAL          0x1C4
+#define TSI148_LCSR_OT6_OTEAU          0x1C8
+#define TSI148_LCSR_OT6_OTEAL          0x1CC
+#define TSI148_LCSR_OT6_OTOFU          0x1D0
+#define TSI148_LCSR_OT6_OTOFL          0x1D4
+#define TSI148_LCSR_OT6_OTBS           0x1D8
+#define TSI148_LCSR_OT6_OTAT           0x1DC
+
+#define TSI148_LCSR_OT7_OTSAU          0x1E0
+#define TSI148_LCSR_OT7_OTSAL          0x1E4
+#define TSI148_LCSR_OT7_OTEAU          0x1E8
+#define TSI148_LCSR_OT7_OTEAL          0x1EC
+#define TSI148_LCSR_OT7_OTOFU          0x1F0
+#define TSI148_LCSR_OT7_OTOFL          0x1F4
+#define TSI148_LCSR_OT7_OTBS           0x1F8
+#define TSI148_LCSR_OT7_OTAT           0x1FC
+
+#define TSI148_LCSR_OT0                0x100
+#define TSI148_LCSR_OT1                0x120
+#define TSI148_LCSR_OT2                0x140
+#define TSI148_LCSR_OT3                0x160
+#define TSI148_LCSR_OT4                0x180
+#define TSI148_LCSR_OT5                0x1A0
+#define TSI148_LCSR_OT6                0x1C0
+#define TSI148_LCSR_OT7                0x1E0
+
+static const int TSI148_LCSR_OT[8] = { TSI148_LCSR_OT0, TSI148_LCSR_OT1,
+                                        TSI148_LCSR_OT2, TSI148_LCSR_OT3,
+                                        TSI148_LCSR_OT4, TSI148_LCSR_OT5,
+                                        TSI148_LCSR_OT6, TSI148_LCSR_OT7 };
+
+#define TSI148_LCSR_OFFSET_OTSAU       0x0
+#define TSI148_LCSR_OFFSET_OTSAL       0x4
+#define TSI148_LCSR_OFFSET_OTEAU       0x8
+#define TSI148_LCSR_OFFSET_OTEAL       0xC
+#define TSI148_LCSR_OFFSET_OTOFU       0x10
+#define TSI148_LCSR_OFFSET_OTOFL       0x14
+#define TSI148_LCSR_OFFSET_OTBS                0x18
+#define TSI148_LCSR_OFFSET_OTAT                0x1C
+
+/*
+ * VMEbus interupt ack
+ * offset  200
+ */
+#define TSI148_LCSR_VIACK1     0x204
+#define TSI148_LCSR_VIACK2     0x208
+#define TSI148_LCSR_VIACK3     0x20C
+#define TSI148_LCSR_VIACK4     0x210
+#define TSI148_LCSR_VIACK5     0x214
+#define TSI148_LCSR_VIACK6     0x218
+#define TSI148_LCSR_VIACK7     0x21C
+
+static const int TSI148_LCSR_VIACK[8] = { 0, TSI148_LCSR_VIACK1,
+                               TSI148_LCSR_VIACK2, TSI148_LCSR_VIACK3,
+                               TSI148_LCSR_VIACK4, TSI148_LCSR_VIACK5,
+                               TSI148_LCSR_VIACK6, TSI148_LCSR_VIACK7 };
+
+/*
+ * RMW
+ * offset    220
+ */
+#define TSI148_LCSR_RMWAU      0x220
+#define TSI148_LCSR_RMWAL      0x224
+#define TSI148_LCSR_RMWEN      0x228
+#define TSI148_LCSR_RMWC       0x22C
+#define TSI148_LCSR_RMWS       0x230
+
+/*
+ * VMEbus control
+ * offset    234
+ */
+#define TSI148_LCSR_VMCTRL     0x234
+#define TSI148_LCSR_VCTRL      0x238
+#define TSI148_LCSR_VSTAT      0x23C
+
+/*
+ * PCI status
+ * offset  240
+ */
+#define TSI148_LCSR_PSTAT      0x240
+
+/*
+ * VME filter.
+ * offset  250
+ */
+#define TSI148_LCSR_VMEFL      0x250
+
+       /*
+        * VME exception.
+        * offset  260
+ */
+#define TSI148_LCSR_VEAU       0x260
+#define TSI148_LCSR_VEAL       0x264
+#define TSI148_LCSR_VEAT       0x268
+
+       /*
+        * PCI error
+        * offset  270
+        */
+#define TSI148_LCSR_EDPAU      0x270
+#define TSI148_LCSR_EDPAL      0x274
+#define TSI148_LCSR_EDPXA      0x278
+#define TSI148_LCSR_EDPXS      0x27C
+#define TSI148_LCSR_EDPAT      0x280
+
+       /*
+        * Inbound Translations
+        * offset  300
+        */
+#define TSI148_LCSR_IT0_ITSAU          0x300
+#define TSI148_LCSR_IT0_ITSAL          0x304
+#define TSI148_LCSR_IT0_ITEAU          0x308
+#define TSI148_LCSR_IT0_ITEAL          0x30C
+#define TSI148_LCSR_IT0_ITOFU          0x310
+#define TSI148_LCSR_IT0_ITOFL          0x314
+#define TSI148_LCSR_IT0_ITAT           0x318
+
+#define TSI148_LCSR_IT1_ITSAU          0x320
+#define TSI148_LCSR_IT1_ITSAL          0x324
+#define TSI148_LCSR_IT1_ITEAU          0x328
+#define TSI148_LCSR_IT1_ITEAL          0x32C
+#define TSI148_LCSR_IT1_ITOFU          0x330
+#define TSI148_LCSR_IT1_ITOFL          0x334
+#define TSI148_LCSR_IT1_ITAT           0x338
+
+#define TSI148_LCSR_IT2_ITSAU          0x340
+#define TSI148_LCSR_IT2_ITSAL          0x344
+#define TSI148_LCSR_IT2_ITEAU          0x348
+#define TSI148_LCSR_IT2_ITEAL          0x34C
+#define TSI148_LCSR_IT2_ITOFU          0x350
+#define TSI148_LCSR_IT2_ITOFL          0x354
+#define TSI148_LCSR_IT2_ITAT           0x358
+
+#define TSI148_LCSR_IT3_ITSAU          0x360
+#define TSI148_LCSR_IT3_ITSAL          0x364
+#define TSI148_LCSR_IT3_ITEAU          0x368
+#define TSI148_LCSR_IT3_ITEAL          0x36C
+#define TSI148_LCSR_IT3_ITOFU          0x370
+#define TSI148_LCSR_IT3_ITOFL          0x374
+#define TSI148_LCSR_IT3_ITAT           0x378
+
+#define TSI148_LCSR_IT4_ITSAU          0x380
+#define TSI148_LCSR_IT4_ITSAL          0x384
+#define TSI148_LCSR_IT4_ITEAU          0x388
+#define TSI148_LCSR_IT4_ITEAL          0x38C
+#define TSI148_LCSR_IT4_ITOFU          0x390
+#define TSI148_LCSR_IT4_ITOFL          0x394
+#define TSI148_LCSR_IT4_ITAT           0x398
+
+#define TSI148_LCSR_IT5_ITSAU          0x3A0
+#define TSI148_LCSR_IT5_ITSAL          0x3A4
+#define TSI148_LCSR_IT5_ITEAU          0x3A8
+#define TSI148_LCSR_IT5_ITEAL          0x3AC
+#define TSI148_LCSR_IT5_ITOFU          0x3B0
+#define TSI148_LCSR_IT5_ITOFL          0x3B4
+#define TSI148_LCSR_IT5_ITAT           0x3B8
+
+#define TSI148_LCSR_IT6_ITSAU          0x3C0
+#define TSI148_LCSR_IT6_ITSAL          0x3C4
+#define TSI148_LCSR_IT6_ITEAU          0x3C8
+#define TSI148_LCSR_IT6_ITEAL          0x3CC
+#define TSI148_LCSR_IT6_ITOFU          0x3D0
+#define TSI148_LCSR_IT6_ITOFL          0x3D4
+#define TSI148_LCSR_IT6_ITAT           0x3D8
+
+#define TSI148_LCSR_IT7_ITSAU          0x3E0
+#define TSI148_LCSR_IT7_ITSAL          0x3E4
+#define TSI148_LCSR_IT7_ITEAU          0x3E8
+#define TSI148_LCSR_IT7_ITEAL          0x3EC
+#define TSI148_LCSR_IT7_ITOFU          0x3F0
+#define TSI148_LCSR_IT7_ITOFL          0x3F4
+#define TSI148_LCSR_IT7_ITAT           0x3F8
+
+
+#define TSI148_LCSR_IT0                0x300
+#define TSI148_LCSR_IT1                0x320
+#define TSI148_LCSR_IT2                0x340
+#define TSI148_LCSR_IT3                0x360
+#define TSI148_LCSR_IT4                0x380
+#define TSI148_LCSR_IT5                0x3A0
+#define TSI148_LCSR_IT6                0x3C0
+#define TSI148_LCSR_IT7                0x3E0
+
+static const int TSI148_LCSR_IT[8] = { TSI148_LCSR_IT0, TSI148_LCSR_IT1,
+                                        TSI148_LCSR_IT2, TSI148_LCSR_IT3,
+                                        TSI148_LCSR_IT4, TSI148_LCSR_IT5,
+                                        TSI148_LCSR_IT6, TSI148_LCSR_IT7 };
+
+#define TSI148_LCSR_OFFSET_ITSAU       0x0
+#define TSI148_LCSR_OFFSET_ITSAL       0x4
+#define TSI148_LCSR_OFFSET_ITEAU       0x8
+#define TSI148_LCSR_OFFSET_ITEAL       0xC
+#define TSI148_LCSR_OFFSET_ITOFU       0x10
+#define TSI148_LCSR_OFFSET_ITOFL       0x14
+#define TSI148_LCSR_OFFSET_ITAT                0x18
+
+       /*
+        * Inbound Translation GCSR
+        * offset  400
+        */
+#define TSI148_LCSR_GBAU       0x400
+#define TSI148_LCSR_GBAL       0x404
+#define TSI148_LCSR_GCSRAT     0x408
+
+       /*
+        * Inbound Translation CRG
+        * offset  40C
+        */
+#define TSI148_LCSR_CBAU       0x40C
+#define TSI148_LCSR_CBAL       0x410
+#define TSI148_LCSR_CSRAT      0x414
+
+       /*
+        * Inbound Translation CR/CSR
+        *         CRG
+        * offset  418
+        */
+#define TSI148_LCSR_CROU       0x418
+#define TSI148_LCSR_CROL       0x41C
+#define TSI148_LCSR_CRAT       0x420
+
+       /*
+        * Inbound Translation Location Monitor
+        * offset  424
+        */
+#define TSI148_LCSR_LMBAU      0x424
+#define TSI148_LCSR_LMBAL      0x428
+#define TSI148_LCSR_LMAT       0x42C
+
+       /*
+        * VMEbus Interrupt Control.
+        * offset  430
+        */
+#define TSI148_LCSR_BCU                0x430
+#define TSI148_LCSR_BCL                0x434
+#define TSI148_LCSR_BPGTR      0x438
+#define TSI148_LCSR_BPCTR      0x43C
+#define TSI148_LCSR_VICR       0x440
+
+       /*
+        * Local Bus Interrupt Control.
+        * offset  448
+        */
+#define TSI148_LCSR_INTEN      0x448
+#define TSI148_LCSR_INTEO      0x44C
+#define TSI148_LCSR_INTS       0x450
+#define TSI148_LCSR_INTC       0x454
+#define TSI148_LCSR_INTM1      0x458
+#define TSI148_LCSR_INTM2      0x45C
+
+       /*
+        * DMA Controllers
+        * offset 500
+        */
+#define TSI148_LCSR_DCTL0      0x500
+#define TSI148_LCSR_DSTA0      0x504
+#define TSI148_LCSR_DCSAU0     0x508
+#define TSI148_LCSR_DCSAL0     0x50C
+#define TSI148_LCSR_DCDAU0     0x510
+#define TSI148_LCSR_DCDAL0     0x514
+#define TSI148_LCSR_DCLAU0     0x518
+#define TSI148_LCSR_DCLAL0     0x51C
+#define TSI148_LCSR_DSAU0      0x520
+#define TSI148_LCSR_DSAL0      0x524
+#define TSI148_LCSR_DDAU0      0x528
+#define TSI148_LCSR_DDAL0      0x52C
+#define TSI148_LCSR_DSAT0      0x530
+#define TSI148_LCSR_DDAT0      0x534
+#define TSI148_LCSR_DNLAU0     0x538
+#define TSI148_LCSR_DNLAL0     0x53C
+#define TSI148_LCSR_DCNT0      0x540
+#define TSI148_LCSR_DDBS0      0x544
+
+#define TSI148_LCSR_DCTL1      0x580
+#define TSI148_LCSR_DSTA1      0x584
+#define TSI148_LCSR_DCSAU1     0x588
+#define TSI148_LCSR_DCSAL1     0x58C
+#define TSI148_LCSR_DCDAU1     0x590
+#define TSI148_LCSR_DCDAL1     0x594
+#define TSI148_LCSR_DCLAU1     0x598
+#define TSI148_LCSR_DCLAL1     0x59C
+#define TSI148_LCSR_DSAU1      0x5A0
+#define TSI148_LCSR_DSAL1      0x5A4
+#define TSI148_LCSR_DDAU1      0x5A8
+#define TSI148_LCSR_DDAL1      0x5AC
+#define TSI148_LCSR_DSAT1      0x5B0
+#define TSI148_LCSR_DDAT1      0x5B4
+#define TSI148_LCSR_DNLAU1     0x5B8
+#define TSI148_LCSR_DNLAL1     0x5BC
+#define TSI148_LCSR_DCNT1      0x5C0
+#define TSI148_LCSR_DDBS1      0x5C4
+
+#define TSI148_LCSR_DMA0       0x500
+#define TSI148_LCSR_DMA1       0x580
+
+
+static const int TSI148_LCSR_DMA[TSI148_MAX_DMA] = { TSI148_LCSR_DMA0,
+                                               TSI148_LCSR_DMA1 };
+
+#define TSI148_LCSR_OFFSET_DCTL                0x0
+#define TSI148_LCSR_OFFSET_DSTA                0x4
+#define TSI148_LCSR_OFFSET_DCSAU       0x8
+#define TSI148_LCSR_OFFSET_DCSAL       0xC
+#define TSI148_LCSR_OFFSET_DCDAU       0x10
+#define TSI148_LCSR_OFFSET_DCDAL       0x14
+#define TSI148_LCSR_OFFSET_DCLAU       0x18
+#define TSI148_LCSR_OFFSET_DCLAL       0x1C
+#define TSI148_LCSR_OFFSET_DSAU                0x20
+#define TSI148_LCSR_OFFSET_DSAL                0x24
+#define TSI148_LCSR_OFFSET_DDAU                0x28
+#define TSI148_LCSR_OFFSET_DDAL                0x2C
+#define TSI148_LCSR_OFFSET_DSAT                0x30
+#define TSI148_LCSR_OFFSET_DDAT                0x34
+#define TSI148_LCSR_OFFSET_DNLAU       0x38
+#define TSI148_LCSR_OFFSET_DNLAL       0x3C
+#define TSI148_LCSR_OFFSET_DCNT                0x40
+#define TSI148_LCSR_OFFSET_DDBS                0x44
+
+       /*
+        * GCSR Register Group
+        */
+
+       /*
+        *         GCSR    CRG
+        * offset   00     600 - DEVI/VENI
+        * offset   04     604 - CTRL/GA/REVID
+        * offset   08     608 - Semaphore3/2/1/0
+        * offset   0C     60C - Seamphore7/6/5/4
+        */
+#define TSI148_GCSR_ID         0x600
+#define TSI148_GCSR_CSR                0x604
+#define TSI148_GCSR_SEMA0      0x608
+#define TSI148_GCSR_SEMA1      0x60C
+
+       /*
+        * Mail Box
+        *         GCSR    CRG
+        * offset   10     610 - Mailbox0
+        */
+#define TSI148_GCSR_MBOX0      0x610
+#define TSI148_GCSR_MBOX1      0x614
+#define TSI148_GCSR_MBOX2      0x618
+#define TSI148_GCSR_MBOX3      0x61C
+
+static const int TSI148_GCSR_MBOX[4] = { TSI148_GCSR_MBOX0,
+                                       TSI148_GCSR_MBOX1,
+                                       TSI148_GCSR_MBOX2,
+                                       TSI148_GCSR_MBOX3 };
+
+       /*
+        * CR/CSR
+        */
+
+       /*
+        *        CR/CSR   CRG
+        * offset  7FFF4   FF4 - CSRBCR
+        * offset  7FFF8   FF8 - CSRBSR
+        * offset  7FFFC   FFC - CBAR
+        */
+#define TSI148_CSRBCR  0xFF4
+#define TSI148_CSRBSR  0xFF8
+#define TSI148_CBAR    0xFFC
+
+
+
+
+       /*
+        *  TSI148 Register Bit Definitions
+        */
+
+       /*
+        *  PFCS Register Set
+        */
+#define TSI148_PCFS_CMMD_SERR          (1<<8)  /* SERR_L out pin ssys err */
+#define TSI148_PCFS_CMMD_PERR          (1<<6)  /* PERR_L out pin  parity */
+#define TSI148_PCFS_CMMD_MSTR          (1<<2)  /* PCI bus master */
+#define TSI148_PCFS_CMMD_MEMSP         (1<<1)  /* PCI mem space access  */
+#define TSI148_PCFS_CMMD_IOSP          (1<<0)  /* PCI I/O space enable */
+
+#define TSI148_PCFS_STAT_RCPVE         (1<<15) /* Detected Parity Error */
+#define TSI148_PCFS_STAT_SIGSE         (1<<14) /* Signalled System Error */
+#define TSI148_PCFS_STAT_RCVMA         (1<<13) /* Received Master Abort */
+#define TSI148_PCFS_STAT_RCVTA         (1<<12) /* Received Target Abort */
+#define TSI148_PCFS_STAT_SIGTA         (1<<11) /* Signalled Target Abort */
+#define TSI148_PCFS_STAT_SELTIM        (3<<9)  /* DELSEL Timing */
+#define TSI148_PCFS_STAT_DPAR          (1<<8)  /* Data Parity Err Reported */
+#define TSI148_PCFS_STAT_FAST          (1<<7)  /* Fast back-to-back Cap */
+#define TSI148_PCFS_STAT_P66M          (1<<5)  /* 66 MHz Capable */
+#define TSI148_PCFS_STAT_CAPL          (1<<4)  /* Capab List - address $34 */
+
+/*
+ *  Revision ID/Class Code Registers   (CRG +$008)
+ */
+#define TSI148_PCFS_CLAS_M             (0xFF<<24)      /* Class ID */
+#define TSI148_PCFS_SUBCLAS_M          (0xFF<<16)      /* Sub-Class ID */
+#define TSI148_PCFS_PROGIF_M           (0xFF<<8)       /* Sub-Class ID */
+#define TSI148_PCFS_REVID_M            (0xFF<<0)       /* Rev ID */
+
+/*
+ * Cache Line Size/ Master Latency Timer/ Header Type Registers (CRG + $00C)
+ */
+#define TSI148_PCFS_HEAD_M             (0xFF<<16)      /* Master Lat Timer */
+#define TSI148_PCFS_MLAT_M             (0xFF<<8)       /* Master Lat Timer */
+#define TSI148_PCFS_CLSZ_M             (0xFF<<0)       /* Cache Line Size */
+
+/*
+ *  Memory Base Address Lower Reg (CRG + $010)
+ */
+#define TSI148_PCFS_MBARL_BASEL_M      (0xFFFFF<<12)   /* Base Addr Lower Mask */
+#define TSI148_PCFS_MBARL_PRE          (1<<3)  /* Prefetch */
+#define TSI148_PCFS_MBARL_MTYPE_M      (3<<1)  /* Memory Type Mask */
+#define TSI148_PCFS_MBARL_IOMEM        (1<<0)  /* I/O Space Indicator */
+
+/*
+ *  Message Signaled Interrupt Capabilities Register (CRG + $040)
+ */
+#define TSI148_PCFS_MSICAP_64BAC       (1<<7)  /* 64-bit Address Capable */
+#define TSI148_PCFS_MSICAP_MME_M       (7<<4)  /* Multiple Msg Enable Mask */
+#define TSI148_PCFS_MSICAP_MMC_M       (7<<1)  /* Multiple Msg Capable Mask */
+#define TSI148_PCFS_MSICAP_MSIEN       (1<<0)  /* Msg signaled INT Enable */
+
+/*
+ *  Message Address Lower Register (CRG +$044)
+ */
+#define TSI148_PCFS_MSIAL_M            (0x3FFFFFFF<<2) /* Mask */
+
+/*
+ *  Message Data Register (CRG + 4C)
+ */
+#define TSI148_PCFS_MSIMD_M            (0xFFFF<<0)     /* Mask */
+
+/*
+ *  PCI-X Capabilities Register (CRG + $050)
+ */
+#define TSI148_PCFS_PCIXCAP_MOST_M     (7<<4)  /* Max outstanding Split Tran */
+#define TSI148_PCFS_PCIXCAP_MMRBC_M    (3<<2)  /* Max Mem Read byte cnt */
+#define TSI148_PCFS_PCIXCAP_ERO        (1<<1)  /* Enable Relaxed Ordering */
+#define TSI148_PCFS_PCIXCAP_DPERE      (1<<0)  /* Data Parity Recover Enable */
+
+/*
+ *  PCI-X Status Register (CRG +$054)
+ */
+#define TSI148_PCFS_PCIXSTAT_RSCEM     (1<<29) /* Recieved Split Comp Error */
+#define TSI148_PCFS_PCIXSTAT_DMCRS_M   (7<<26) /* max Cumulative Read Size */
+#define TSI148_PCFS_PCIXSTAT_DMOST_M   (7<<23) /* max outstanding Split Trans */
+#define TSI148_PCFS_PCIXSTAT_DMMRC_M   (3<<21) /* max mem read byte count */
+#define TSI148_PCFS_PCIXSTAT_DC        (1<<20) /* Device Complexity */
+#define TSI148_PCFS_PCIXSTAT_USC       (1<<19) /* Unexpected Split comp */
+#define TSI148_PCFS_PCIXSTAT_SCD       (1<<18) /* Split completion discard */
+#define TSI148_PCFS_PCIXSTAT_133C      (1<<17) /* 133MHz capable */
+#define TSI148_PCFS_PCIXSTAT_64D       (1<<16) /* 64 bit device */
+#define TSI148_PCFS_PCIXSTAT_BN_M      (0xFF<<8)       /* Bus number */
+#define TSI148_PCFS_PCIXSTAT_DN_M      (0x1F<<3)       /* Device number */
+#define TSI148_PCFS_PCIXSTAT_FN_M      (7<<0)  /* Function Number */
+
+/*
+ *  LCSR Registers
+ */
+
+/*
+ *  Outbound Translation Starting Address Lower
+ */
+#define TSI148_LCSR_OTSAL_M            (0xFFFF<<16)    /* Mask */
+
+/*
+ *  Outbound Translation Ending Address Lower
+ */
+#define TSI148_LCSR_OTEAL_M            (0xFFFF<<16)    /* Mask */
+
+/*
+ *  Outbound Translation Offset Lower
+ */
+#define TSI148_LCSR_OTOFFL_M           (0xFFFF<<16)    /* Mask */
+
+/*
+ *  Outbound Translation 2eSST Broadcast Select
+ */
+#define TSI148_LCSR_OTBS_M             (0xFFFFF<<0)    /* Mask */
+
+/*
+ *  Outbound Translation Attribute
+ */
+#define TSI148_LCSR_OTAT_EN            (1<<31) /* Window Enable */
+#define TSI148_LCSR_OTAT_MRPFD         (1<<18) /* Prefetch Disable */
+
+#define TSI148_LCSR_OTAT_PFS_M         (3<<16) /* Prefetch Size Mask */
+#define TSI148_LCSR_OTAT_PFS_2         (0<<16) /* 2 Cache Lines P Size */
+#define TSI148_LCSR_OTAT_PFS_4         (1<<16) /* 4 Cache Lines P Size */
+#define TSI148_LCSR_OTAT_PFS_8         (2<<16) /* 8 Cache Lines P Size */
+#define TSI148_LCSR_OTAT_PFS_16        (3<<16) /* 16 Cache Lines P Size */
+
+#define TSI148_LCSR_OTAT_2eSSTM_M      (7<<11) /* 2eSST Xfer Rate Mask */
+#define TSI148_LCSR_OTAT_2eSSTM_160    (0<<11) /* 160MB/s 2eSST Xfer Rate */
+#define TSI148_LCSR_OTAT_2eSSTM_267    (1<<11) /* 267MB/s 2eSST Xfer Rate */
+#define TSI148_LCSR_OTAT_2eSSTM_320    (2<<11) /* 320MB/s 2eSST Xfer Rate */
+
+#define TSI148_LCSR_OTAT_TM_M          (7<<8)  /* Xfer Protocol Mask */
+#define TSI148_LCSR_OTAT_TM_SCT        (0<<8)  /* SCT Xfer Protocol */
+#define TSI148_LCSR_OTAT_TM_BLT        (1<<8)  /* BLT Xfer Protocol */
+#define TSI148_LCSR_OTAT_TM_MBLT       (2<<8)  /* MBLT Xfer Protocol */
+#define TSI148_LCSR_OTAT_TM_2eVME      (3<<8)  /* 2eVME Xfer Protocol */
+#define TSI148_LCSR_OTAT_TM_2eSST      (4<<8)  /* 2eSST Xfer Protocol */
+#define TSI148_LCSR_OTAT_TM_2eSSTB     (5<<8)  /* 2eSST Bcast Xfer Protocol */
+
+#define TSI148_LCSR_OTAT_DBW_M         (3<<6)  /* Max Data Width */
+#define TSI148_LCSR_OTAT_DBW_16        (0<<6)  /* 16-bit Data Width */
+#define TSI148_LCSR_OTAT_DBW_32        (1<<6)  /* 32-bit Data Width */
+
+#define TSI148_LCSR_OTAT_SUP           (1<<5)  /* Supervisory Access */
+#define TSI148_LCSR_OTAT_PGM           (1<<4)  /* Program Access */
+
+#define TSI148_LCSR_OTAT_AMODE_M       (0xf<<0)        /* Address Mode Mask */
+#define TSI148_LCSR_OTAT_AMODE_A16     (0<<0)  /* A16 Address Space */
+#define TSI148_LCSR_OTAT_AMODE_A24     (1<<0)  /* A24 Address Space */
+#define TSI148_LCSR_OTAT_AMODE_A32     (2<<0)  /* A32 Address Space */
+#define TSI148_LCSR_OTAT_AMODE_A64     (4<<0)  /* A32 Address Space */
+#define TSI148_LCSR_OTAT_AMODE_CRCSR   (5<<0)  /* CR/CSR Address Space */
+#define TSI148_LCSR_OTAT_AMODE_USER1   (8<<0)  /* User1 Address Space */
+#define TSI148_LCSR_OTAT_AMODE_USER2   (9<<0)  /* User2 Address Space */
+#define TSI148_LCSR_OTAT_AMODE_USER3   (10<<0) /* User3 Address Space */
+#define TSI148_LCSR_OTAT_AMODE_USER4   (11<<0) /* User4 Address Space */
+
+/*
+ *  VME Master Control Register  CRG+$234
+ */
+#define TSI148_LCSR_VMCTRL_VSA         (1<<27) /* VMEbus Stop Ack */
+#define TSI148_LCSR_VMCTRL_VS          (1<<26) /* VMEbus Stop */
+#define TSI148_LCSR_VMCTRL_DHB         (1<<25) /* Device Has Bus */
+#define TSI148_LCSR_VMCTRL_DWB         (1<<24) /* Device Wants Bus */
+
+#define TSI148_LCSR_VMCTRL_RMWEN       (1<<20) /* RMW Enable */
+
+#define TSI148_LCSR_VMCTRL_ATO_M       (7<<16) /* Master Access Time-out Mask */
+#define TSI148_LCSR_VMCTRL_ATO_32      (0<<16) /* 32 us */
+#define TSI148_LCSR_VMCTRL_ATO_128     (1<<16) /* 128 us */
+#define TSI148_LCSR_VMCTRL_ATO_512     (2<<16) /* 512 us */
+#define TSI148_LCSR_VMCTRL_ATO_2M      (3<<16) /* 2 ms */
+#define TSI148_LCSR_VMCTRL_ATO_8M      (4<<16) /* 8 ms */
+#define TSI148_LCSR_VMCTRL_ATO_32M     (5<<16) /* 32 ms */
+#define TSI148_LCSR_VMCTRL_ATO_128M    (6<<16) /* 128 ms */
+#define TSI148_LCSR_VMCTRL_ATO_DIS     (7<<16) /* Disabled */
+
+#define TSI148_LCSR_VMCTRL_VTOFF_M     (7<<12) /* VMEbus Master Time off */
+#define TSI148_LCSR_VMCTRL_VTOFF_0     (0<<12) /* 0us */
+#define TSI148_LCSR_VMCTRL_VTOFF_1     (1<<12) /* 1us */
+#define TSI148_LCSR_VMCTRL_VTOFF_2     (2<<12) /* 2us */
+#define TSI148_LCSR_VMCTRL_VTOFF_4     (3<<12) /* 4us */
+#define TSI148_LCSR_VMCTRL_VTOFF_8     (4<<12) /* 8us */
+#define TSI148_LCSR_VMCTRL_VTOFF_16    (5<<12) /* 16us */
+#define TSI148_LCSR_VMCTRL_VTOFF_32    (6<<12) /* 32us */
+#define TSI148_LCSR_VMCTRL_VTOFF_64    (7<<12) /* 64us */
+
+#define TSI148_LCSR_VMCTRL_VTON_M      (7<<8)  /* VMEbus Master Time On */
+#define TSI148_LCSR_VMCTRL_VTON_4      (0<<8)  /* 8us */
+#define TSI148_LCSR_VMCTRL_VTON_8      (1<<8)  /* 8us */
+#define TSI148_LCSR_VMCTRL_VTON_16     (2<<8)  /* 16us */
+#define TSI148_LCSR_VMCTRL_VTON_32     (3<<8)  /* 32us */
+#define TSI148_LCSR_VMCTRL_VTON_64     (4<<8)  /* 64us */
+#define TSI148_LCSR_VMCTRL_VTON_128    (5<<8)  /* 128us */
+#define TSI148_LCSR_VMCTRL_VTON_256    (6<<8)  /* 256us */
+#define TSI148_LCSR_VMCTRL_VTON_512    (7<<8)  /* 512us */
+
+#define TSI148_LCSR_VMCTRL_VREL_M      (3<<3)  /* VMEbus Master Rel Mode Mask */
+#define TSI148_LCSR_VMCTRL_VREL_T_D    (0<<3)  /* Time on or Done */
+#define TSI148_LCSR_VMCTRL_VREL_T_R_D  (1<<3)  /* Time on and REQ or Done */
+#define TSI148_LCSR_VMCTRL_VREL_T_B_D  (2<<3)  /* Time on and BCLR or Done */
+#define TSI148_LCSR_VMCTRL_VREL_T_D_R  (3<<3)  /* Time on or Done and REQ */
+
+#define TSI148_LCSR_VMCTRL_VFAIR       (1<<2)  /* VMEbus Master Fair Mode */
+#define TSI148_LCSR_VMCTRL_VREQL_M     (3<<0)  /* VMEbus Master Req Level Mask */
+
+/*
+ *  VMEbus Control Register CRG+$238
+ */
+#define TSI148_LCSR_VCTRL_LRE          (1<<31) /* Late Retry Enable */
+
+#define TSI148_LCSR_VCTRL_DLT_M        (0xF<<24)       /* Deadlock Timer */
+#define TSI148_LCSR_VCTRL_DLT_OFF      (0<<24) /* Deadlock Timer Off */
+#define TSI148_LCSR_VCTRL_DLT_16       (1<<24) /* 16 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_32       (2<<24) /* 32 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_64       (3<<24) /* 64 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_128      (4<<24) /* 128 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_256      (5<<24) /* 256 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_512      (6<<24) /* 512 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_1024     (7<<24) /* 1024 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_2048     (8<<24) /* 2048 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_4096     (9<<24) /* 4096 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_8192     (0xA<<24)       /* 8192 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_16384    (0xB<<24)       /* 16384 VCLKS */
+#define TSI148_LCSR_VCTRL_DLT_32768    (0xC<<24)       /* 32768 VCLKS */
+
+#define TSI148_LCSR_VCTRL_NERBB        (1<<20) /* No Early Release of Bus Busy */
+
+#define TSI148_LCSR_VCTRL_SRESET       (1<<17) /* System Reset */
+#define TSI148_LCSR_VCTRL_LRESET       (1<<16) /* Local Reset */
+
+#define TSI148_LCSR_VCTRL_SFAILAI      (1<<15) /* SYSFAIL Auto Slot ID */
+#define TSI148_LCSR_VCTRL_BID_M        (0x1F<<8)       /* Broadcast ID Mask */
+
+#define TSI148_LCSR_VCTRL_ATOEN        (1<<7)  /* Arbiter Time-out Enable */
+#define TSI148_LCSR_VCTRL_ROBIN        (1<<6)  /* VMEbus Round Robin */
+
+#define TSI148_LCSR_VCTRL_GTO_M        (7<<0)  /* VMEbus Global Time-out Mask */
+#define TSI148_LCSR_VCTRL_GTO_8              (0<<0)    /* 8 us */
+#define TSI148_LCSR_VCTRL_GTO_16             (1<<0)    /* 16 us */
+#define TSI148_LCSR_VCTRL_GTO_32             (2<<0)    /* 32 us */
+#define TSI148_LCSR_VCTRL_GTO_64             (3<<0)    /* 64 us */
+#define TSI148_LCSR_VCTRL_GTO_128      (4<<0)  /* 128 us */
+#define TSI148_LCSR_VCTRL_GTO_256      (5<<0)  /* 256 us */
+#define TSI148_LCSR_VCTRL_GTO_512      (6<<0)  /* 512 us */
+#define TSI148_LCSR_VCTRL_GTO_DIS      (7<<0)  /* Disabled */
+
+/*
+ *  VMEbus Status Register  CRG + $23C
+ */
+#define TSI148_LCSR_VSTAT_CPURST       (1<<15) /* Clear power up reset */
+#define TSI148_LCSR_VSTAT_BRDFL        (1<<14) /* Board fail */
+#define TSI148_LCSR_VSTAT_PURSTS       (1<<12) /* Power up reset status */
+#define TSI148_LCSR_VSTAT_BDFAILS      (1<<11) /* Board Fail Status */
+#define TSI148_LCSR_VSTAT_SYSFAILS     (1<<10) /* System Fail Status */
+#define TSI148_LCSR_VSTAT_ACFAILS      (1<<9)  /* AC fail status */
+#define TSI148_LCSR_VSTAT_SCONS        (1<<8)  /* System Cont Status */
+#define TSI148_LCSR_VSTAT_GAP          (1<<5)  /* Geographic Addr Parity */
+#define TSI148_LCSR_VSTAT_GA_M         (0x1F<<0)       /* Geographic Addr Mask */
+
+/*
+ *  PCI Configuration Status Register CRG+$240
+ */
+#define TSI148_LCSR_PSTAT_REQ64S       (1<<6)  /* Request 64 status set */
+#define TSI148_LCSR_PSTAT_M66ENS       (1<<5)  /* M66ENS 66Mhz enable */
+#define TSI148_LCSR_PSTAT_FRAMES       (1<<4)  /* Frame Status */
+#define TSI148_LCSR_PSTAT_IRDYS        (1<<3)  /* IRDY status */
+#define TSI148_LCSR_PSTAT_DEVSELS      (1<<2)  /* DEVL status */
+#define TSI148_LCSR_PSTAT_STOPS        (1<<1)  /* STOP status */
+#define TSI148_LCSR_PSTAT_TRDYS        (1<<0)  /* TRDY status */
+
+/*
+ *  VMEbus Exception Attributes Register  CRG + $268
+ */
+#define TSI148_LCSR_VEAT_VES           (1<<31) /* Status */
+#define TSI148_LCSR_VEAT_VEOF          (1<<30) /* Overflow */
+#define TSI148_LCSR_VEAT_VESCL         (1<<29) /* Status Clear */
+#define TSI148_LCSR_VEAT_2EOT          (1<<21) /* 2e Odd Termination */
+#define TSI148_LCSR_VEAT_2EST          (1<<20) /* 2e Slave terminated */
+#define TSI148_LCSR_VEAT_BERR          (1<<19) /* Bus Error */
+#define TSI148_LCSR_VEAT_LWORD         (1<<18) /* LWORD_ signal state */
+#define TSI148_LCSR_VEAT_WRITE         (1<<17) /* WRITE_ signal state */
+#define TSI148_LCSR_VEAT_IACK          (1<<16) /* IACK_ signal state */
+#define TSI148_LCSR_VEAT_DS1           (1<<15) /* DS1_ signal state */
+#define TSI148_LCSR_VEAT_DS0           (1<<14) /* DS0_ signal state */
+#define TSI148_LCSR_VEAT_AM_M          (0x3F<<8)       /* Address Mode Mask */
+#define TSI148_LCSR_VEAT_XAM_M         (0xFF<<0)       /* Master AMode Mask */
+
+
+/*
+ * VMEbus PCI Error Diagnostics PCI/X Attributes Register  CRG + $280
+ */
+#define TSI148_LCSR_EDPAT_EDPCL        (1<<29)
+
+/*
+ *  Inbound Translation Starting Address Lower
+ */
+#define TSI148_LCSR_ITSAL6432_M        (0xFFFF<<16)    /* Mask */
+#define TSI148_LCSR_ITSAL24_M          (0x00FFF<<12)   /* Mask */
+#define TSI148_LCSR_ITSAL16_M          (0x0000FFF<<4)  /* Mask */
+
+/*
+ *  Inbound Translation Ending Address Lower
+ */
+#define TSI148_LCSR_ITEAL6432_M        (0xFFFF<<16)    /* Mask */
+#define TSI148_LCSR_ITEAL24_M          (0x00FFF<<12)   /* Mask */
+#define TSI148_LCSR_ITEAL16_M          (0x0000FFF<<4)  /* Mask */
+
+/*
+ *  Inbound Translation Offset Lower
+ */
+#define TSI148_LCSR_ITOFFL6432_M       (0xFFFF<<16)    /* Mask */
+#define TSI148_LCSR_ITOFFL24_M         (0xFFFFF<<12)   /* Mask */
+#define TSI148_LCSR_ITOFFL16_M         (0xFFFFFFF<<4)  /* Mask */
+
+/*
+ *  Inbound Translation Attribute
+ */
+#define TSI148_LCSR_ITAT_EN            (1<<31) /* Window Enable */
+#define TSI148_LCSR_ITAT_TH            (1<<18) /* Prefetch Threshold */
+
+#define TSI148_LCSR_ITAT_VFS_M         (3<<16) /* Virtual FIFO Size Mask */
+#define TSI148_LCSR_ITAT_VFS_64        (0<<16) /* 64 bytes Virtual FIFO Size */
+#define TSI148_LCSR_ITAT_VFS_128       (1<<16) /* 128 bytes Virtual FIFO Sz */
+#define TSI148_LCSR_ITAT_VFS_256       (2<<16) /* 256 bytes Virtual FIFO Sz */
+#define TSI148_LCSR_ITAT_VFS_512       (3<<16) /* 512 bytes Virtual FIFO Sz */
+
+#define TSI148_LCSR_ITAT_2eSSTM_M      (7<<12) /* 2eSST Xfer Rate Mask */
+#define TSI148_LCSR_ITAT_2eSSTM_160    (0<<12) /* 160MB/s 2eSST Xfer Rate */
+#define TSI148_LCSR_ITAT_2eSSTM_267    (1<<12) /* 267MB/s 2eSST Xfer Rate */
+#define TSI148_LCSR_ITAT_2eSSTM_320    (2<<12) /* 320MB/s 2eSST Xfer Rate */
+
+#define TSI148_LCSR_ITAT_2eSSTB        (1<<11) /* 2eSST Bcast Xfer Protocol */
+#define TSI148_LCSR_ITAT_2eSST         (1<<10) /* 2eSST Xfer Protocol */
+#define TSI148_LCSR_ITAT_2eVME         (1<<9)  /* 2eVME Xfer Protocol */
+#define TSI148_LCSR_ITAT_MBLT          (1<<8)  /* MBLT Xfer Protocol */
+#define TSI148_LCSR_ITAT_BLT           (1<<7)  /* BLT Xfer Protocol */
+
+#define TSI148_LCSR_ITAT_AS_M          (7<<4)  /* Address Space Mask */
+#define TSI148_LCSR_ITAT_AS_A16        (0<<4)  /* A16 Address Space */
+#define TSI148_LCSR_ITAT_AS_A24        (1<<4)  /* A24 Address Space */
+#define TSI148_LCSR_ITAT_AS_A32        (2<<4)  /* A32 Address Space */
+#define TSI148_LCSR_ITAT_AS_A64        (4<<4)  /* A64 Address Space */
+
+#define TSI148_LCSR_ITAT_SUPR          (1<<3)  /* Supervisor Access */
+#define TSI148_LCSR_ITAT_NPRIV         (1<<2)  /* Non-Priv (User) Access */
+#define TSI148_LCSR_ITAT_PGM           (1<<1)  /* Program Access */
+#define TSI148_LCSR_ITAT_DATA          (1<<0)  /* Data Access */
+
+/*
+ *  GCSR Base Address Lower Address  CRG +$404
+ */
+#define TSI148_LCSR_GBAL_M             (0x7FFFFFF<<5)  /* Mask */
+
+/*
+ *  GCSR Attribute Register CRG + $408
+ */
+#define TSI148_LCSR_GCSRAT_EN          (1<<7)  /* Enable access to GCSR */
+
+#define TSI148_LCSR_GCSRAT_AS_M        (7<<4)  /* Address Space Mask */
+#define TSI148_LCSR_GCSRAT_AS_A16       (0<<4) /* Address Space 16 */
+#define TSI148_LCSR_GCSRAT_AS_A24       (1<<4) /* Address Space 24 */
+#define TSI148_LCSR_GCSRAT_AS_A32       (2<<4) /* Address Space 32 */
+#define TSI148_LCSR_GCSRAT_AS_A64       (4<<4) /* Address Space 64 */
+
+#define TSI148_LCSR_GCSRAT_SUPR        (1<<3)  /* Sup set -GCSR decoder */
+#define TSI148_LCSR_GCSRAT_NPRIV       (1<<2)  /* Non-Privliged set - CGSR */
+#define TSI148_LCSR_GCSRAT_PGM         (1<<1)  /* Program set - GCSR decoder */
+#define TSI148_LCSR_GCSRAT_DATA        (1<<0)  /* DATA set GCSR decoder */
+
+/*
+ *  CRG Base Address Lower Address  CRG + $410
+ */
+#define TSI148_LCSR_CBAL_M             (0xFFFFF<<12)
+
+/*
+ *  CRG Attribute Register  CRG + $414
+ */
+#define TSI148_LCSR_CRGAT_EN           (1<<7)  /* Enable PRG Access */
+
+#define TSI148_LCSR_CRGAT_AS_M         (7<<4)  /* Address Space */
+#define TSI148_LCSR_CRGAT_AS_A16       (0<<4)  /* Address Space 16 */
+#define TSI148_LCSR_CRGAT_AS_A24       (1<<4)  /* Address Space 24 */
+#define TSI148_LCSR_CRGAT_AS_A32       (2<<4)  /* Address Space 32 */
+#define TSI148_LCSR_CRGAT_AS_A64       (4<<4)  /* Address Space 64 */
+
+#define TSI148_LCSR_CRGAT_SUPR         (1<<3)  /* Supervisor Access */
+#define TSI148_LCSR_CRGAT_NPRIV        (1<<2)  /* Non-Privliged(User) Access */
+#define TSI148_LCSR_CRGAT_PGM          (1<<1)  /* Program Access */
+#define TSI148_LCSR_CRGAT_DATA         (1<<0)  /* Data Access */
+
+/*
+ *  CR/CSR Offset Lower Register  CRG + $41C
+ */
+#define TSI148_LCSR_CROL_M             (0x1FFF<<19)    /* Mask */
+
+/*
+ *  CR/CSR Attribute register  CRG + $420
+ */
+#define TSI148_LCSR_CRAT_EN            (1<<7)  /* Enable access to CR/CSR */
+
+/*
+ *  Location Monitor base address lower register  CRG + $428
+ */
+#define TSI148_LCSR_LMBAL_M            (0x7FFFFFF<<5)  /* Mask */
+
+/*
+ *  Location Monitor Attribute Register  CRG + $42C
+ */
+#define TSI148_LCSR_LMAT_EN            (1<<7)  /* Enable Location Monitor */
+
+#define TSI148_LCSR_LMAT_AS_M          (7<<4)  /* Address Space MASK  */
+#define TSI148_LCSR_LMAT_AS_A16        (0<<4)  /* A16 */
+#define TSI148_LCSR_LMAT_AS_A24        (1<<4)  /* A24 */
+#define TSI148_LCSR_LMAT_AS_A32        (2<<4)  /* A32 */
+#define TSI148_LCSR_LMAT_AS_A64        (4<<4)  /* A64 */
+
+#define TSI148_LCSR_LMAT_SUPR          (1<<3)  /* Supervisor Access */
+#define TSI148_LCSR_LMAT_NPRIV         (1<<2)  /* Non-Priv (User) Access */
+#define TSI148_LCSR_LMAT_PGM           (1<<1)  /* Program Access */
+#define TSI148_LCSR_LMAT_DATA          (1<<0)  /* Data Access  */
+
+/*
+ *  Broadcast Pulse Generator Timer Register  CRG + $438
+ */
+#define TSI148_LCSR_BPGTR_BPGT_M       (0xFFFF<<0)     /* Mask */
+
+/*
+ *  Broadcast Programmable Clock Timer Register  CRG + $43C
+ */
+#define TSI148_LCSR_BPCTR_BPCT_M       (0xFFFFFF<<0)   /* Mask */
+
+/*
+ *  VMEbus Interrupt Control Register           CRG + $43C
+ */
+#define TSI148_LCSR_VICR_CNTS_M        (3<<22) /* Cntr Source MASK */
+#define TSI148_LCSR_VICR_CNTS_DIS      (1<<22) /* Cntr Disable */
+#define TSI148_LCSR_VICR_CNTS_IRQ1     (2<<22) /* IRQ1 to Cntr */
+#define TSI148_LCSR_VICR_CNTS_IRQ2     (3<<22) /* IRQ2 to Cntr */
+
+#define TSI148_LCSR_VICR_EDGIS_M       (3<<20) /* Edge interupt MASK */
+#define TSI148_LCSR_VICR_EDGIS_DIS     (1<<20) /* Edge interupt Disable */
+#define TSI148_LCSR_VICR_EDGIS_IRQ1    (2<<20) /* IRQ1 to Edge */
+#define TSI148_LCSR_VICR_EDGIS_IRQ2    (3<<20) /* IRQ2 to Edge */
+
+#define TSI148_LCSR_VICR_IRQIF_M       (3<<18) /* IRQ1* Function MASK */
+#define TSI148_LCSR_VICR_IRQIF_NORM    (1<<18) /* Normal */
+#define TSI148_LCSR_VICR_IRQIF_PULSE   (2<<18) /* Pulse Generator */
+#define TSI148_LCSR_VICR_IRQIF_PROG    (3<<18) /* Programmable Clock */
+#define TSI148_LCSR_VICR_IRQIF_1U      (4<<18) /* 1us Clock */
+
+#define TSI148_LCSR_VICR_IRQ2F_M       (3<<16) /* IRQ2* Function MASK */
+#define TSI148_LCSR_VICR_IRQ2F_NORM    (1<<16) /* Normal */
+#define TSI148_LCSR_VICR_IRQ2F_PULSE   (2<<16) /* Pulse Generator */
+#define TSI148_LCSR_VICR_IRQ2F_PROG    (3<<16) /* Programmable Clock */
+#define TSI148_LCSR_VICR_IRQ2F_1U      (4<<16) /* 1us Clock */
+
+#define TSI148_LCSR_VICR_BIP           (1<<15) /* Broadcast Interrupt Pulse */
+
+#define TSI148_LCSR_VICR_IRQC          (1<<12) /* VMEbus IRQ Clear */
+#define TSI148_LCSR_VICR_IRQS          (1<<11) /* VMEbus IRQ Status */
+
+#define TSI148_LCSR_VICR_IRQL_M        (7<<8)  /* VMEbus SW IRQ Level Mask */
+#define TSI148_LCSR_VICR_IRQL_1        (1<<8)  /* VMEbus SW IRQ Level 1 */
+#define TSI148_LCSR_VICR_IRQL_2        (2<<8)  /* VMEbus SW IRQ Level 2 */
+#define TSI148_LCSR_VICR_IRQL_3        (3<<8)  /* VMEbus SW IRQ Level 3 */
+#define TSI148_LCSR_VICR_IRQL_4        (4<<8)  /* VMEbus SW IRQ Level 4 */
+#define TSI148_LCSR_VICR_IRQL_5        (5<<8)  /* VMEbus SW IRQ Level 5 */
+#define TSI148_LCSR_VICR_IRQL_6        (6<<8)  /* VMEbus SW IRQ Level 6 */
+#define TSI148_LCSR_VICR_IRQL_7        (7<<8)  /* VMEbus SW IRQ Level 7 */
+
+static const int TSI148_LCSR_VICR_IRQL[8] = { 0, TSI148_LCSR_VICR_IRQL_1,
+                       TSI148_LCSR_VICR_IRQL_2, TSI148_LCSR_VICR_IRQL_3,
+                       TSI148_LCSR_VICR_IRQL_4, TSI148_LCSR_VICR_IRQL_5,
+                       TSI148_LCSR_VICR_IRQL_6, TSI148_LCSR_VICR_IRQL_7 };
+
+#define TSI148_LCSR_VICR_STID_M        (0xFF<<0)       /* Status/ID Mask */
+
+/*
+ *  Interrupt Enable Register   CRG + $440
+ */
+#define TSI148_LCSR_INTEN_DMA1EN       (1<<25) /* DMAC 1 */
+#define TSI148_LCSR_INTEN_DMA0EN       (1<<24) /* DMAC 0 */
+#define TSI148_LCSR_INTEN_LM3EN        (1<<23) /* Location Monitor 3 */
+#define TSI148_LCSR_INTEN_LM2EN        (1<<22) /* Location Monitor 2 */
+#define TSI148_LCSR_INTEN_LM1EN        (1<<21) /* Location Monitor 1 */
+#define TSI148_LCSR_INTEN_LM0EN        (1<<20) /* Location Monitor 0 */
+#define TSI148_LCSR_INTEN_MB3EN        (1<<19) /* Mail Box 3 */
+#define TSI148_LCSR_INTEN_MB2EN        (1<<18) /* Mail Box 2 */
+#define TSI148_LCSR_INTEN_MB1EN        (1<<17) /* Mail Box 1 */
+#define TSI148_LCSR_INTEN_MB0EN        (1<<16) /* Mail Box 0 */
+#define TSI148_LCSR_INTEN_PERREN       (1<<13) /* PCI/X Error */
+#define TSI148_LCSR_INTEN_VERREN       (1<<12) /* VMEbus Error */
+#define TSI148_LCSR_INTEN_VIEEN        (1<<11) /* VMEbus IRQ Edge */
+#define TSI148_LCSR_INTEN_IACKEN       (1<<10) /* IACK */
+#define TSI148_LCSR_INTEN_SYSFLEN      (1<<9)  /* System Fail */
+#define TSI148_LCSR_INTEN_ACFLEN       (1<<8)  /* AC Fail */
+#define TSI148_LCSR_INTEN_IRQ7EN       (1<<7)  /* IRQ7 */
+#define TSI148_LCSR_INTEN_IRQ6EN       (1<<6)  /* IRQ6 */
+#define TSI148_LCSR_INTEN_IRQ5EN       (1<<5)  /* IRQ5 */
+#define TSI148_LCSR_INTEN_IRQ4EN       (1<<4)  /* IRQ4 */
+#define TSI148_LCSR_INTEN_IRQ3EN       (1<<3)  /* IRQ3 */
+#define TSI148_LCSR_INTEN_IRQ2EN       (1<<2)  /* IRQ2 */
+#define TSI148_LCSR_INTEN_IRQ1EN       (1<<1)  /* IRQ1 */
+
+static const int TSI148_LCSR_INTEN_LMEN[4] = { TSI148_LCSR_INTEN_LM0EN,
+                                       TSI148_LCSR_INTEN_LM1EN,
+                                       TSI148_LCSR_INTEN_LM2EN,
+                                       TSI148_LCSR_INTEN_LM3EN };
+
+static const int TSI148_LCSR_INTEN_IRQEN[7] = { TSI148_LCSR_INTEN_IRQ1EN,
+                                       TSI148_LCSR_INTEN_IRQ2EN,
+                                       TSI148_LCSR_INTEN_IRQ3EN,
+                                       TSI148_LCSR_INTEN_IRQ4EN,
+                                       TSI148_LCSR_INTEN_IRQ5EN,
+                                       TSI148_LCSR_INTEN_IRQ6EN,
+                                       TSI148_LCSR_INTEN_IRQ7EN };
+
+/*
+ *  Interrupt Enable Out Register CRG + $444
+ */
+#define TSI148_LCSR_INTEO_DMA1EO       (1<<25) /* DMAC 1 */
+#define TSI148_LCSR_INTEO_DMA0EO       (1<<24) /* DMAC 0 */
+#define TSI148_LCSR_INTEO_LM3EO        (1<<23) /* Loc Monitor 3 */
+#define TSI148_LCSR_INTEO_LM2EO        (1<<22) /* Loc Monitor 2 */
+#define TSI148_LCSR_INTEO_LM1EO        (1<<21) /* Loc Monitor 1 */
+#define TSI148_LCSR_INTEO_LM0EO        (1<<20) /* Location Monitor 0 */
+#define TSI148_LCSR_INTEO_MB3EO        (1<<19) /* Mail Box 3 */
+#define TSI148_LCSR_INTEO_MB2EO        (1<<18) /* Mail Box 2 */
+#define TSI148_LCSR_INTEO_MB1EO        (1<<17) /* Mail Box 1 */
+#define TSI148_LCSR_INTEO_MB0EO        (1<<16) /* Mail Box 0 */
+#define TSI148_LCSR_INTEO_PERREO       (1<<13) /* PCI/X Error */
+#define TSI148_LCSR_INTEO_VERREO       (1<<12) /* VMEbus Error */
+#define TSI148_LCSR_INTEO_VIEEO        (1<<11) /* VMEbus IRQ Edge */
+#define TSI148_LCSR_INTEO_IACKEO       (1<<10) /* IACK */
+#define TSI148_LCSR_INTEO_SYSFLEO      (1<<9)  /* System Fail */
+#define TSI148_LCSR_INTEO_ACFLEO       (1<<8)  /* AC Fail */
+#define TSI148_LCSR_INTEO_IRQ7EO       (1<<7)  /* IRQ7 */
+#define TSI148_LCSR_INTEO_IRQ6EO       (1<<6)  /* IRQ6 */
+#define TSI148_LCSR_INTEO_IRQ5EO       (1<<5)  /* IRQ5 */
+#define TSI148_LCSR_INTEO_IRQ4EO       (1<<4)  /* IRQ4 */
+#define TSI148_LCSR_INTEO_IRQ3EO       (1<<3)  /* IRQ3 */
+#define TSI148_LCSR_INTEO_IRQ2EO       (1<<2)  /* IRQ2 */
+#define TSI148_LCSR_INTEO_IRQ1EO       (1<<1)  /* IRQ1 */
+
+static const int TSI148_LCSR_INTEO_LMEO[4] = { TSI148_LCSR_INTEO_LM0EO,
+                                       TSI148_LCSR_INTEO_LM1EO,
+                                       TSI148_LCSR_INTEO_LM2EO,
+                                       TSI148_LCSR_INTEO_LM3EO };
+
+static const int TSI148_LCSR_INTEO_IRQEO[7] = { TSI148_LCSR_INTEO_IRQ1EO,
+                                       TSI148_LCSR_INTEO_IRQ2EO,
+                                       TSI148_LCSR_INTEO_IRQ3EO,
+                                       TSI148_LCSR_INTEO_IRQ4EO,
+                                       TSI148_LCSR_INTEO_IRQ5EO,
+                                       TSI148_LCSR_INTEO_IRQ6EO,
+                                       TSI148_LCSR_INTEO_IRQ7EO };
+
+/*
+ *  Interrupt Status Register CRG + $448
+ */
+#define TSI148_LCSR_INTS_DMA1S         (1<<25) /* DMA 1 */
+#define TSI148_LCSR_INTS_DMA0S         (1<<24) /* DMA 0 */
+#define TSI148_LCSR_INTS_LM3S          (1<<23) /* Location Monitor 3 */
+#define TSI148_LCSR_INTS_LM2S          (1<<22) /* Location Monitor 2 */
+#define TSI148_LCSR_INTS_LM1S          (1<<21) /* Location Monitor 1 */
+#define TSI148_LCSR_INTS_LM0S          (1<<20) /* Location Monitor 0 */
+#define TSI148_LCSR_INTS_MB3S          (1<<19) /* Mail Box 3 */
+#define TSI148_LCSR_INTS_MB2S          (1<<18) /* Mail Box 2 */
+#define TSI148_LCSR_INTS_MB1S          (1<<17) /* Mail Box 1 */
+#define TSI148_LCSR_INTS_MB0S          (1<<16) /* Mail Box 0 */
+#define TSI148_LCSR_INTS_PERRS         (1<<13) /* PCI/X Error */
+#define TSI148_LCSR_INTS_VERRS         (1<<12) /* VMEbus Error */
+#define TSI148_LCSR_INTS_VIES          (1<<11) /* VMEbus IRQ Edge */
+#define TSI148_LCSR_INTS_IACKS         (1<<10) /* IACK */
+#define TSI148_LCSR_INTS_SYSFLS        (1<<9)  /* System Fail */
+#define TSI148_LCSR_INTS_ACFLS         (1<<8)  /* AC Fail */
+#define TSI148_LCSR_INTS_IRQ7S         (1<<7)  /* IRQ7 */
+#define TSI148_LCSR_INTS_IRQ6S         (1<<6)  /* IRQ6 */
+#define TSI148_LCSR_INTS_IRQ5S         (1<<5)  /* IRQ5 */
+#define TSI148_LCSR_INTS_IRQ4S         (1<<4)  /* IRQ4 */
+#define TSI148_LCSR_INTS_IRQ3S         (1<<3)  /* IRQ3 */
+#define TSI148_LCSR_INTS_IRQ2S         (1<<2)  /* IRQ2 */
+#define TSI148_LCSR_INTS_IRQ1S         (1<<1)  /* IRQ1 */
+
+static const int TSI148_LCSR_INTS_LMS[4] = { TSI148_LCSR_INTS_LM0S,
+                                       TSI148_LCSR_INTS_LM1S,
+                                       TSI148_LCSR_INTS_LM2S,
+                                       TSI148_LCSR_INTS_LM3S };
+
+static const int TSI148_LCSR_INTS_MBS[4] = { TSI148_LCSR_INTS_MB0S,
+                                       TSI148_LCSR_INTS_MB1S,
+                                       TSI148_LCSR_INTS_MB2S,
+                                       TSI148_LCSR_INTS_MB3S };
+
+/*
+ *  Interrupt Clear Register CRG + $44C
+ */
+#define TSI148_LCSR_INTC_DMA1C         (1<<25) /* DMA 1 */
+#define TSI148_LCSR_INTC_DMA0C         (1<<24) /* DMA 0 */
+#define TSI148_LCSR_INTC_LM3C          (1<<23) /* Location Monitor 3 */
+#define TSI148_LCSR_INTC_LM2C          (1<<22) /* Location Monitor 2 */
+#define TSI148_LCSR_INTC_LM1C          (1<<21) /* Location Monitor 1 */
+#define TSI148_LCSR_INTC_LM0C          (1<<20) /* Location Monitor 0 */
+#define TSI148_LCSR_INTC_MB3C          (1<<19) /* Mail Box 3 */
+#define TSI148_LCSR_INTC_MB2C          (1<<18) /* Mail Box 2 */
+#define TSI148_LCSR_INTC_MB1C          (1<<17) /* Mail Box 1 */
+#define TSI148_LCSR_INTC_MB0C          (1<<16) /* Mail Box 0 */
+#define TSI148_LCSR_INTC_PERRC         (1<<13) /* VMEbus Error */
+#define TSI148_LCSR_INTC_VERRC         (1<<12) /* VMEbus Access Time-out */
+#define TSI148_LCSR_INTC_VIEC          (1<<11) /* VMEbus IRQ Edge */
+#define TSI148_LCSR_INTC_IACKC         (1<<10) /* IACK */
+#define TSI148_LCSR_INTC_SYSFLC        (1<<9)  /* System Fail */
+#define TSI148_LCSR_INTC_ACFLC         (1<<8)  /* AC Fail */
+
+static const int TSI148_LCSR_INTC_LMC[4] = { TSI148_LCSR_INTC_LM0C,
+                                       TSI148_LCSR_INTC_LM1C,
+                                       TSI148_LCSR_INTC_LM2C,
+                                       TSI148_LCSR_INTC_LM3C };
+
+static const int TSI148_LCSR_INTC_MBC[4] = { TSI148_LCSR_INTC_MB0C,
+                                       TSI148_LCSR_INTC_MB1C,
+                                       TSI148_LCSR_INTC_MB2C,
+                                       TSI148_LCSR_INTC_MB3C };
+
+/*
+ *  Interrupt Map Register 1 CRG + $458
+ */
+#define TSI148_LCSR_INTM1_DMA1M_M      (3<<18) /* DMA 1 */
+#define TSI148_LCSR_INTM1_DMA0M_M      (3<<16) /* DMA 0 */
+#define TSI148_LCSR_INTM1_LM3M_M       (3<<14) /* Location Monitor 3 */
+#define TSI148_LCSR_INTM1_LM2M_M       (3<<12) /* Location Monitor 2 */
+#define TSI148_LCSR_INTM1_LM1M_M       (3<<10) /* Location Monitor 1 */
+#define TSI148_LCSR_INTM1_LM0M_M       (3<<8)  /* Location Monitor 0 */
+#define TSI148_LCSR_INTM1_MB3M_M       (3<<6)  /* Mail Box 3 */
+#define TSI148_LCSR_INTM1_MB2M_M       (3<<4)  /* Mail Box 2 */
+#define TSI148_LCSR_INTM1_MB1M_M       (3<<2)  /* Mail Box 1 */
+#define TSI148_LCSR_INTM1_MB0M_M       (3<<0)  /* Mail Box 0 */
+
+/*
+ *  Interrupt Map Register 2 CRG + $45C
+ */
+#define TSI148_LCSR_INTM2_PERRM_M      (3<<26) /* PCI Bus Error */
+#define TSI148_LCSR_INTM2_VERRM_M      (3<<24) /* VMEbus Error */
+#define TSI148_LCSR_INTM2_VIEM_M       (3<<22) /* VMEbus IRQ Edge */
+#define TSI148_LCSR_INTM2_IACKM_M      (3<<20) /* IACK */
+#define TSI148_LCSR_INTM2_SYSFLM_M     (3<<18) /* System Fail */
+#define TSI148_LCSR_INTM2_ACFLM_M      (3<<16) /* AC Fail */
+#define TSI148_LCSR_INTM2_IRQ7M_M      (3<<14) /* IRQ7 */
+#define TSI148_LCSR_INTM2_IRQ6M_M      (3<<12) /* IRQ6 */
+#define TSI148_LCSR_INTM2_IRQ5M_M      (3<<10) /* IRQ5 */
+#define TSI148_LCSR_INTM2_IRQ4M_M      (3<<8)  /* IRQ4 */
+#define TSI148_LCSR_INTM2_IRQ3M_M      (3<<6)  /* IRQ3 */
+#define TSI148_LCSR_INTM2_IRQ2M_M      (3<<4)  /* IRQ2 */
+#define TSI148_LCSR_INTM2_IRQ1M_M      (3<<2)  /* IRQ1 */
+
+/*
+ *  DMA Control (0-1) Registers CRG + $500
+ */
+#define TSI148_LCSR_DCTL_ABT           (1<<27) /* Abort */
+#define TSI148_LCSR_DCTL_PAU           (1<<26) /* Pause */
+#define TSI148_LCSR_DCTL_DGO           (1<<25) /* DMA Go */
+
+#define TSI148_LCSR_DCTL_MOD           (1<<23) /* Mode */
+
+#define TSI148_LCSR_DCTL_VBKS_M        (7<<12) /* VMEbus block Size MASK */
+#define TSI148_LCSR_DCTL_VBKS_32       (0<<12) /* VMEbus block Size 32 */
+#define TSI148_LCSR_DCTL_VBKS_64       (1<<12) /* VMEbus block Size 64 */
+#define TSI148_LCSR_DCTL_VBKS_128      (2<<12) /* VMEbus block Size 128 */
+#define TSI148_LCSR_DCTL_VBKS_256      (3<<12) /* VMEbus block Size 256 */
+#define TSI148_LCSR_DCTL_VBKS_512      (4<<12) /* VMEbus block Size 512 */
+#define TSI148_LCSR_DCTL_VBKS_1024     (5<<12) /* VMEbus block Size 1024 */
+#define TSI148_LCSR_DCTL_VBKS_2048     (6<<12) /* VMEbus block Size 2048 */
+#define TSI148_LCSR_DCTL_VBKS_4096     (7<<12) /* VMEbus block Size 4096 */
+
+#define TSI148_LCSR_DCTL_VBOT_M        (7<<8)  /* VMEbus back-off MASK */
+#define TSI148_LCSR_DCTL_VBOT_0        (0<<8)  /* VMEbus back-off  0us */
+#define TSI148_LCSR_DCTL_VBOT_1        (1<<8)  /* VMEbus back-off 1us */
+#define TSI148_LCSR_DCTL_VBOT_2        (2<<8)  /* VMEbus back-off 2us */
+#define TSI148_LCSR_DCTL_VBOT_4        (3<<8)  /* VMEbus back-off 4us */
+#define TSI148_LCSR_DCTL_VBOT_8        (4<<8)  /* VMEbus back-off 8us */
+#define TSI148_LCSR_DCTL_VBOT_16       (5<<8)  /* VMEbus back-off 16us */
+#define TSI148_LCSR_DCTL_VBOT_32       (6<<8)  /* VMEbus back-off 32us */
+#define TSI148_LCSR_DCTL_VBOT_64       (7<<8)  /* VMEbus back-off 64us */
+
+#define TSI148_LCSR_DCTL_PBKS_M        (7<<4)  /* PCI block size MASK */
+#define TSI148_LCSR_DCTL_PBKS_32       (0<<4)  /* PCI block size 32 bytes */
+#define TSI148_LCSR_DCTL_PBKS_64       (1<<4)  /* PCI block size 64 bytes */
+#define TSI148_LCSR_DCTL_PBKS_128      (2<<4)  /* PCI block size 128 bytes */
+#define TSI148_LCSR_DCTL_PBKS_256      (3<<4)  /* PCI block size 256 bytes */
+#define TSI148_LCSR_DCTL_PBKS_512      (4<<4)  /* PCI block size 512 bytes */
+#define TSI148_LCSR_DCTL_PBKS_1024     (5<<4)  /* PCI block size 1024 bytes */
+#define TSI148_LCSR_DCTL_PBKS_2048     (6<<4)  /* PCI block size 2048 bytes */
+#define TSI148_LCSR_DCTL_PBKS_4096     (7<<4)  /* PCI block size 4096 bytes */
+
+#define TSI148_LCSR_DCTL_PBOT_M        (7<<0)  /* PCI back off MASK */
+#define TSI148_LCSR_DCTL_PBOT_0        (0<<0)  /* PCI back off 0us */
+#define TSI148_LCSR_DCTL_PBOT_1        (1<<0)  /* PCI back off 1us */
+#define TSI148_LCSR_DCTL_PBOT_2        (2<<0)  /* PCI back off 2us */
+#define TSI148_LCSR_DCTL_PBOT_4        (3<<0)  /* PCI back off 3us */
+#define TSI148_LCSR_DCTL_PBOT_8        (4<<0)  /* PCI back off 4us */
+#define TSI148_LCSR_DCTL_PBOT_16       (5<<0)  /* PCI back off 8us */
+#define TSI148_LCSR_DCTL_PBOT_32       (6<<0)  /* PCI back off 16us */
+#define TSI148_LCSR_DCTL_PBOT_64       (7<<0)  /* PCI back off 32us */
+
+/*
+ *  DMA Status Registers (0-1)  CRG + $504
+ */
+#define TSI148_LCSR_DSTA_SMA           (1<<31) /* PCI Signalled Master Abt */
+#define TSI148_LCSR_DSTA_RTA           (1<<30) /* PCI Received Target Abt */
+#define TSI148_LCSR_DSTA_MRC           (1<<29) /* PCI Max Retry Count */
+#define TSI148_LCSR_DSTA_VBE           (1<<28) /* VMEbus error */
+#define TSI148_LCSR_DSTA_ABT           (1<<27) /* Abort */
+#define TSI148_LCSR_DSTA_PAU           (1<<26) /* Pause */
+#define TSI148_LCSR_DSTA_DON           (1<<25) /* Done */
+#define TSI148_LCSR_DSTA_BSY           (1<<24) /* Busy */
+
+/*
+ *  DMA Current Link Address Lower (0-1)
+ */
+#define TSI148_LCSR_DCLAL_M            (0x3FFFFFF<<6)  /* Mask */
+
+/*
+ *  DMA Source Attribute (0-1) Reg
+ */
+#define TSI148_LCSR_DSAT_TYP_M         (3<<28) /* Source Bus Type */
+#define TSI148_LCSR_DSAT_TYP_PCI       (0<<28) /* PCI Bus */
+#define TSI148_LCSR_DSAT_TYP_VME       (1<<28) /* VMEbus */
+#define TSI148_LCSR_DSAT_TYP_PAT       (2<<28) /* Data Pattern */
+
+#define TSI148_LCSR_DSAT_PSZ           (1<<25) /* Pattern Size */
+#define TSI148_LCSR_DSAT_NIN           (1<<24) /* No Increment */
+
+#define TSI148_LCSR_DSAT_2eSSTM_M      (3<<11) /* 2eSST Trans Rate Mask */
+#define TSI148_LCSR_DSAT_2eSSTM_160    (0<<11) /* 160 MB/s */
+#define TSI148_LCSR_DSAT_2eSSTM_267    (1<<11) /* 267 MB/s */
+#define TSI148_LCSR_DSAT_2eSSTM_320    (2<<11) /* 320 MB/s */
+
+#define TSI148_LCSR_DSAT_TM_M          (7<<8)  /* Bus Transfer Protocol Mask */
+#define TSI148_LCSR_DSAT_TM_SCT        (0<<8)  /* SCT */
+#define TSI148_LCSR_DSAT_TM_BLT        (1<<8)  /* BLT */
+#define TSI148_LCSR_DSAT_TM_MBLT       (2<<8)  /* MBLT */
+#define TSI148_LCSR_DSAT_TM_2eVME      (3<<8)  /* 2eVME */
+#define TSI148_LCSR_DSAT_TM_2eSST      (4<<8)  /* 2eSST */
+#define TSI148_LCSR_DSAT_TM_2eSSTB     (5<<8)  /* 2eSST Broadcast */
+
+#define TSI148_LCSR_DSAT_DBW_M         (3<<6)  /* Max Data Width MASK */
+#define TSI148_LCSR_DSAT_DBW_16        (0<<6)  /* 16 Bits */
+#define TSI148_LCSR_DSAT_DBW_32        (1<<6)  /* 32 Bits */
+
+#define TSI148_LCSR_DSAT_SUP           (1<<5)  /* Supervisory Mode */
+#define TSI148_LCSR_DSAT_PGM           (1<<4)  /* Program Mode */
+
+#define TSI148_LCSR_DSAT_AMODE_M       (0xf<<0)        /* Address Space Mask */
+#define TSI148_LCSR_DSAT_AMODE_A16     (0<<0)  /* A16 */
+#define TSI148_LCSR_DSAT_AMODE_A24     (1<<0)  /* A24 */
+#define TSI148_LCSR_DSAT_AMODE_A32     (2<<0)  /* A32 */
+#define TSI148_LCSR_DSAT_AMODE_A64     (4<<0)  /* A64 */
+#define TSI148_LCSR_DSAT_AMODE_CRCSR   (5<<0)  /* CR/CSR */
+#define TSI148_LCSR_DSAT_AMODE_USER1   (8<<0)  /* User1 */
+#define TSI148_LCSR_DSAT_AMODE_USER2   (9<<0)  /* User2 */
+#define TSI148_LCSR_DSAT_AMODE_USER3   (0xa<<0)        /* User3 */
+#define TSI148_LCSR_DSAT_AMODE_USER4   (0xb<<0)        /* User4 */
+
+/*
+ *  DMA Destination Attribute Registers (0-1)
+ */
+#define TSI148_LCSR_DDAT_TYP_PCI       (0<<28) /* Destination PCI Bus  */
+#define TSI148_LCSR_DDAT_TYP_VME       (1<<28) /* Destination VMEbus */
+
+#define TSI148_LCSR_DDAT_2eSSTM_M      (3<<11) /* 2eSST Transfer Rate Mask */
+#define TSI148_LCSR_DDAT_2eSSTM_160    (0<<11) /* 160 MB/s */
+#define TSI148_LCSR_DDAT_2eSSTM_267    (1<<11) /* 267 MB/s */
+#define TSI148_LCSR_DDAT_2eSSTM_320    (2<<11) /* 320 MB/s */
+
+#define TSI148_LCSR_DDAT_TM_M          (7<<8)  /* Bus Transfer Protocol Mask */
+#define TSI148_LCSR_DDAT_TM_SCT        (0<<8)  /* SCT */
+#define TSI148_LCSR_DDAT_TM_BLT        (1<<8)  /* BLT */
+#define TSI148_LCSR_DDAT_TM_MBLT       (2<<8)  /* MBLT */
+#define TSI148_LCSR_DDAT_TM_2eVME      (3<<8)  /* 2eVME */
+#define TSI148_LCSR_DDAT_TM_2eSST      (4<<8)  /* 2eSST */
+#define TSI148_LCSR_DDAT_TM_2eSSTB     (5<<8)  /* 2eSST Broadcast */
+
+#define TSI148_LCSR_DDAT_DBW_M         (3<<6)  /* Max Data Width MASK */
+#define TSI148_LCSR_DDAT_DBW_16        (0<<6)  /* 16 Bits */
+#define TSI148_LCSR_DDAT_DBW_32        (1<<6)  /* 32 Bits */
+
+#define TSI148_LCSR_DDAT_SUP           (1<<5)  /* Supervisory/User Access */
+#define TSI148_LCSR_DDAT_PGM           (1<<4)  /* Program/Data Access */
+
+#define TSI148_LCSR_DDAT_AMODE_M       (0xf<<0)        /* Address Space Mask */
+#define TSI148_LCSR_DDAT_AMODE_A16      (0<<0) /* A16 */
+#define TSI148_LCSR_DDAT_AMODE_A24      (1<<0) /* A24 */
+#define TSI148_LCSR_DDAT_AMODE_A32      (2<<0) /* A32 */
+#define TSI148_LCSR_DDAT_AMODE_A64      (4<<0) /* A64 */
+#define TSI148_LCSR_DDAT_AMODE_CRCSR   (5<<0)  /* CRC/SR */
+#define TSI148_LCSR_DDAT_AMODE_USER1   (8<<0)  /* User1 */
+#define TSI148_LCSR_DDAT_AMODE_USER2   (9<<0)  /* User2 */
+#define TSI148_LCSR_DDAT_AMODE_USER3   (0xa<<0)        /* User3 */
+#define TSI148_LCSR_DDAT_AMODE_USER4   (0xb<<0)        /* User4 */
+
+/*
+ *  DMA Next Link Address Lower
+ */
+#define TSI148_LCSR_DNLAL_DNLAL_M      (0x3FFFFFF<<6)  /* Address Mask */
+#define TSI148_LCSR_DNLAL_LLA          (1<<0)  /* Last Link Address Indicator */
+
+/*
+ *  DMA 2eSST Broadcast Select
+ */
+#define TSI148_LCSR_DBS_M              (0x1FFFFF<<0)   /* Mask */
+
+/*
+ *  GCSR Register Group
+ */
+
+/*
+ *  GCSR Control and Status Register  CRG + $604
+ */
+#define TSI148_GCSR_GCTRL_LRST         (1<<15) /* Local Reset */
+#define TSI148_GCSR_GCTRL_SFAILEN      (1<<14) /* System Fail enable */
+#define TSI148_GCSR_GCTRL_BDFAILS      (1<<13) /* Board Fail Status */
+#define TSI148_GCSR_GCTRL_SCON         (1<<12) /* System Copntroller */
+#define TSI148_GCSR_GCTRL_MEN          (1<<11) /* Module Enable (READY) */
+
+#define TSI148_GCSR_GCTRL_LMI3S        (1<<7)  /* Loc Monitor 3 Int Status */
+#define TSI148_GCSR_GCTRL_LMI2S        (1<<6)  /* Loc Monitor 2 Int Status */
+#define TSI148_GCSR_GCTRL_LMI1S        (1<<5)  /* Loc Monitor 1 Int Status */
+#define TSI148_GCSR_GCTRL_LMI0S        (1<<4)  /* Loc Monitor 0 Int Status */
+#define TSI148_GCSR_GCTRL_MBI3S        (1<<3)  /* Mail box 3 Int Status */
+#define TSI148_GCSR_GCTRL_MBI2S        (1<<2)  /* Mail box 2 Int Status */
+#define TSI148_GCSR_GCTRL_MBI1S        (1<<1)  /* Mail box 1 Int Status */
+#define TSI148_GCSR_GCTRL_MBI0S        (1<<0)  /* Mail box 0 Int Status */
+
+#define TSI148_GCSR_GAP                (1<<5)  /* Geographic Addr Parity */
+#define TSI148_GCSR_GA_M               (0x1F<<0)       /* Geographic Address Mask */
+
+/*
+ *  CR/CSR Register Group
+ */
+
+/*
+ *  CR/CSR Bit Clear Register CRG + $FF4
+ */
+#define TSI148_CRCSR_CSRBCR_LRSTC      (1<<7)  /* Local Reset Clear */
+#define TSI148_CRCSR_CSRBCR_SFAILC     (1<<6)  /* System Fail Enable Clear */
+#define TSI148_CRCSR_CSRBCR_BDFAILS    (1<<5)  /* Board Fail Status */
+#define TSI148_CRCSR_CSRBCR_MENC       (1<<4)  /* Module Enable Clear */
+#define TSI148_CRCSR_CSRBCR_BERRSC     (1<<3)  /* Bus Error Status Clear */
+
+/*
+ *  CR/CSR Bit Set Register CRG+$FF8
+ */
+#define TSI148_CRCSR_CSRBSR_LISTS      (1<<7)  /* Local Reset Clear */
+#define TSI148_CRCSR_CSRBSR_SFAILS     (1<<6)  /* System Fail Enable Clear */
+#define TSI148_CRCSR_CSRBSR_BDFAILS    (1<<5)  /* Board Fail Status */
+#define TSI148_CRCSR_CSRBSR_MENS       (1<<4)  /* Module Enable Clear */
+#define TSI148_CRCSR_CSRBSR_BERRS      (1<<3)  /* Bus Error Status Clear */
+
+/*
+ *  CR/CSR Base Address Register CRG + FFC
+ */
+#define TSI148_CRCSR_CBAR_M            (0x1F<<3)       /* Mask */
+
+#endif                         /* TSI148_H */