/*
* RapidIO enumeration and discovery support
*
* Copyright 2005 MontaVista Software, Inc.
* Matt Porter <mporter@kernel.crashing.org>
*
* Copyright 2009 Integrated Device Technology, Inc.
* Alex Bounine <alexandre.bounine@idt.com>
* - Added Port-Write/Error Management initialization and handling
*
* Copyright 2009 Sysgo AG
* Thomas Moll <thomas.moll@sysgo.com>
* - Added Input- Output- enable functionality, to allow full communication
*
* 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/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/rio.h>
#include <linux/rio_drv.h>
#include <linux/rio_ids.h>
#include <linux/rio_regs.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/sched.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include "rio.h"
static void rio_init_em(struct rio_dev *rdev);
static int next_destid = 0;
static int next_comptag = 1;
static int rio_mport_phys_table[] = {
RIO_EFB_PAR_EP_ID,
RIO_EFB_PAR_EP_REC_ID,
RIO_EFB_SER_EP_ID,
RIO_EFB_SER_EP_REC_ID,
-1,
};
/**
* rio_destid_alloc - Allocate next available destID for given network
* @net: RIO network
*
* Returns next available device destination ID for the specified RIO network.
* Marks allocated ID as one in use.
* Returns RIO_INVALID_DESTID if new destID is not available.
*/
static u16 rio_destid_alloc(struct rio_net *net)
{
int destid;
struct rio_id_table *idtab = &net->destid_table;
spin_lock(&idtab->lock);
destid = find_first_zero_bit(idtab->table, idtab->max);
if (destid < idtab->max) {
set_bit(destid, idtab->table);
destid += idtab->start;
} else
destid = RIO_INVALID_DESTID;
spin_unlock(&idtab->lock);
return (u16)destid;
}
/**
* rio_destid_reserve - Reserve the specivied destID
* @net: RIO network
* @destid: destID to reserve
*
* Tries to reserve the specified destID.
* Returns 0 if successfull.
*/
static int rio_destid_reserve(struct rio_net *net, u16 destid)
{
int oldbit;
struct rio_id_table *idtab = &net->destid_table;
destid -= idtab->start;
spin_lock(&idtab->lock);
oldbit = test_and_set_bit(destid, idtab->table);
spin_unlock(&idtab->lock);
return oldbit;
}
/**
* rio_destid_free - free a previously allocated destID
* @net: RIO network
* @destid: destID to free
*
* Makes the specified destID available for use.
*/
static void rio_destid_free(struct rio_net *net, u16 destid)
{
struct rio_id_table *idtab = &net->destid_table;
destid -= idtab->start;
spin_lock(&idtab->lock);
clear_bit(destid, idtab->table);
spin_unlock(&idtab->lock);
}
/**
* rio_destid_first - return first destID in use
* @net: RIO network
*/
static u16 rio_destid_first(struct rio_net *net)
{
int destid;
struct rio_id_table *idtab = &net->destid_table;
spin_lock(&idtab->lock);
destid = find_first_bit(idtab->table, idtab->max);
if (destid >= idtab->max)
destid = RIO_INVALID_DESTID;
else
destid += idtab->start;
spin_unlock(&idtab->lock);
return (