/*
* VME Bridge Framework
*
* Author: Martyn Welch <martyn.welch@ge.com>
* Copyright 2008 GE 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/module.h>
#include <linux/moduleparam.h>
#include <linux/mm.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/poll.h>
#include <linux/highmem.h>
#include <linux/interrupt.h>
#include <linux/pagemap.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/syscalls.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/vme.h>
#include "vme_bridge.h"
/* Bitmask and list of registered buses both protected by common mutex */
static unsigned int vme_bus_numbers;
static LIST_HEAD(vme_bus_list);
static DEFINE_MUTEX(vme_buses_lock);
static void __exit vme_exit(void);
static int __init vme_init(void);
static struct vme_dev *dev_to_vme_dev(struct device *dev)
{
return container_of(dev, struct vme_dev, dev);
}
/*
* Find the bridge that the resource is associated with.
*/
static struct vme_bridge *find_bridge(struct vme_resource *resource)
{
/* Get list to search */
switch (resource->type) {
case VME_MASTER:
return list_entry(resource->entry, struct vme_master_resource,
list)->parent;
break;
case VME_SLAVE:
return list_entry(resource->entry, struct vme_slave_resource,
list)->parent;
break;
case VME_DMA:
return list_entry(resource->entry, struct vme_dma_resource,
list)->parent;
break;
case VME_LM:
return list_entry(resource->entry, struct vme_lm_resource,
list)->parent;
break;
default:
printk(KERN_ERR "Unknown resource type\n");
return NULL;
break;
}
}
/*
* Allocate a contiguous block of memory for use by the driver. This is used to
* create the buffers for the slave windows.
*/
void *vme_alloc_consistent(struct vme_resource *resource, size_t size,
dma_addr_t *dma)
{
struct vme_bridge *bridge;
if (resource == NULL) {
printk(KERN_ERR "No resource\n");
return NULL;
}
bridge = find_bridge(resource);
if (bridge == NULL) {
printk(KERN_ERR "Can't find bridge\n");
return NULL;
}
if (bridge->parent == NULL) {
printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name);
return NULL;
}
if (bridge->alloc_consistent == NULL) {
printk(KERN_ERR "alloc_consistent not supported by bridge %s\n",
bridge->name);
return NULL;
}
return bridge->alloc_consistent(bridge->parent, size, dma);
}
EXPORT_SYMBOL(vme_alloc_consistent);
/*
* Free previously allocated contiguous block of memory.
*/
void vme_free_consistent(struct vme_resource *resource, size_t size,
void *vaddr, dma_addr_t dma)
{
struct vme_bridge *bridge;
if (resource == NULL) {
printk(KERN_ERR "No resource\n");
return;
}
bridge = find_bridge(resource);
if (bridge == NULL) {
printk(KERN_ERR "Can't find bridge\n");
return;
}
if (bridge->parent == NULL) {
printk(KERN_ERR "Dev entry NULL for
|