/*
** -----------------------------------------------------------------------------
**
** Perle Specialix driver for Linux
** Ported from existing RIO Driver for SCO sources.
*
* (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
** Module : rioroute.c
** SID : 1.3
** Last Modified : 11/6/98 10:33:46
** Retrieved : 11/6/98 10:33:50
**
** ident @(#)rioroute.c 1.3
**
** -----------------------------------------------------------------------------
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/string.h>
#include <asm/uaccess.h>
#include <linux/termios.h>
#include <linux/serial.h>
#include <linux/generic_serial.h>
#include "linux_compat.h"
#include "rio_linux.h"
#include "pkt.h"
#include "daemon.h"
#include "rio.h"
#include "riospace.h"
#include "cmdpkt.h"
#include "map.h"
#include "rup.h"
#include "port.h"
#include "riodrvr.h"
#include "rioinfo.h"
#include "func.h"
#include "errors.h"
#include "pci.h"
#include "parmmap.h"
#include "unixrup.h"
#include "board.h"
#include "host.h"
#include "phb.h"
#include "link.h"
#include "cmdblk.h"
#include "route.h"
#include "cirrus.h"
#include "rioioctl.h"
#include "param.h"
static int RIOCheckIsolated(struct rio_info *, struct Host *, unsigned int);
static int RIOIsolate(struct rio_info *, struct Host *, unsigned int);
static int RIOCheck(struct Host *, unsigned int);
static void RIOConCon(struct rio_info *, struct Host *, unsigned int, unsigned int, unsigned int, unsigned int, int);
/*
** Incoming on the ROUTE_RUP
** I wrote this while I was tired. Forgive me.
*/
int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP)
{
struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
struct PktCmd_M *PktReplyP;
struct CmdBlk *CmdBlkP;
struct Port *PortP;
struct Map *MapP;
struct Top *TopP;
int ThisLink, ThisLinkMin, ThisLinkMax;
int port;
int Mod, Mod1, Mod2;
unsigned short RtaType;
unsigned int RtaUniq;
unsigned int ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */
unsigned int OldUnit, NewUnit, OldLink, NewLink;
char *MyType, *MyName;
int Lies;
unsigned long flags;
/*
** Is this unit telling us it's current link topology?
*/
if (readb(&PktCmdP->Command) == ROUTE_TOPOLOGY) {
MapP = HostP->Mapping;
/*
** The packet can be sent either by the host or by an RTA.
** If it comes from the host, then we need to fill in the
** Topology array in the host structure. If it came in
** from an RTA then we need to fill in the Mapping structure's
** Topology array for the unit.
*/
if (Rup >= (unsigned short) MAX_RUP) {
ThisUnit = HOST_ID;
TopP = HostP->Topology;
MyType = "Host";
MyName = HostP->Name;
ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
} else {
ThisUnit = Rup + 1;
TopP = HostP->Mapping[Rup].Topology;
MyType = "RTA";
MyName = HostP->Mapping[Rup].Name;
ThisLinkMin = 0;
ThisLinkMax = LINKS_PER_UNIT - 1;
}
/*
** Lies will not be tolerated.
** If any pair of links claim to be connected to the same
** place, then ignore this packet completely.
*/
Lies = 0;
for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) {
/*
** it won't lie about network interconnect, total disconnects
** and no-IDs. (or at least, it doesn't *matter* if it does)
*/
if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (unsigned short) MAX_RUP)
continue;
for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) {
if ((readb