[patch 4/5] Staging: vme: add Tundra TSI148 VME-PCI Bridge driver

Emilio G. Cota cota at braap.org
Sun Aug 9 00:09:48 UTC 2009


Greg, Martyn,

please have a look at our tsi148 driver, available at:
http://repo.or.cz/w/tsi148vmebridge.git
Whenever you encounter a reference to 'CES', ignore it,
it's a CERN thing for easing our lives porting drivers from
LynxOS.

I could post the driver to LKML for review if you want; I would
remove that CES crap before posting. I put this off because
I knew it would never get merged before there was some generic
vme glue supporting it. However now we're getting there so
it's probably a good time to get cracking with this task.

Martyn, a few comments about your driver, haven't had much
time to dig very deep.

- again, use mutexes instead of semaphores
- The DMA code looks rather messy; I mean stuff like this:
> +#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) {
and the ifdefs 0..

- correct me if I'm wrong, but does the slave need to know the
  window number he wants for his device? See:
> +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;

If that's the case, this is totally broken; in fact, even if you
kept a list somewhere up on the generic vme layer keeping track
of the already used windows (images?) to avoid any clashes,
in practice you'd very soon run out of windows: 8 modules, 8
mappings, 8 windows. And you're dead.

In a crate we have up to 20 modules, each of them with at least
one address space to be mapped. To make this work we do the
following:

* The tsi148 has 1GB of address space available for mapping,
  which is further divided into 8 windows, with a unique address
  modifier per window.
* Say you have 15 modules that need to map 1MB each, all of them
  with the same address modifier (AM).
Then what the slave driver requests is *not* a window, is what we
call a 'vme mapping', which means "do whatever you want but give
me a kernel address that points at this VME address, mapping with
this size and AM".

Our tsi148 driver notices then that there's already a window for
that AM, so it just appends the mapping to the existing window.
So at the end of the day only one window is used for all those
mappings, which are nicely piled together.

Please clarify me how this is handled in your driver. The
bottom line is to ensure that
a) Many different modules can peacefully co-exist on a crate
b) Drivers should know nothing about what else is on your crate

E.

(I keep this here for the added Cc)
Greg K-H wrote:
> From: Martyn Welch <martyn.welch at gefanuc.com>
> 
> Signed-off-by: Martyn Welch <martyn.welch at gefanuc.com>
> Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
> 
> ---
>  drivers/staging/vme/bridges/Kconfig      |    6 
>  drivers/staging/vme/bridges/Makefile     |    1 
>  drivers/staging/vme/bridges/vme_tsi148.c | 2912 +++++++++++++++++++++++++++++++
>  drivers/staging/vme/bridges/vme_tsi148.h | 1387 ++++++++++++++
>  4 files changed, 4306 insertions(+)
> 
> --- a/drivers/staging/vme/bridges/Kconfig
> +++ b/drivers/staging/vme/bridges/Kconfig
> @@ -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.
> --- a/drivers/staging/vme/bridges/Makefile
> +++ b/drivers/staging/vme/bridges/Makefile
> @@ -1 +1,2 @@
>  obj-$(CONFIG_VME_CA91CX42)	+= vme_ca91cx42.o
> +obj-$(CONFIG_VME_TSI148)	+= vme_tsi148.o
> --- /dev/null
> +++ b/drivers/staging/vme/bridges/vme_tsi148.c
> @@ -0,0 +1,2912 @@
> +/*
> + * Support for the Tundra TSI148 VME-PCI Bridge Chip
> + *
> + * Author: Martyn Welch <martyn.welch at 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
> --- /dev/null
> +++ b/drivers/staging/vme/bridges/vme_tsi148.h
> @@ -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 */
> 
> 



More information about the devel mailing list