⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rioroute.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/*** -----------------------------------------------------------------------------****  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**** -----------------------------------------------------------------------------*/#ifdef SCCS_LABELSstatic char *_rioroute_c_sccs_ = "@(#)rioroute.c	1.3";#endif#include <linux/module.h>#include <linux/slab.h>#include <linux/errno.h>#include <asm/io.h>#include <asm/system.h>#include <asm/string.h>#include <asm/semaphore.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 "typdef.h"#include "pkt.h"#include "daemon.h"#include "rio.h"#include "riospace.h"#include "top.h"#include "cmdpkt.h"#include "map.h"#include "riotypes.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 "error.h"#include "phb.h"#include "link.h"#include "cmdblk.h"#include "route.h"#include "control.h"#include "cirrus.h"#include "rioioctl.h"#include "param.h"#include "list.h"#include "sam.h"static int RIOCheckIsolated(struct rio_info *, struct Host *, uint);static int RIOIsolate(struct rio_info *, struct Host *, uint);static int RIOCheck(struct Host *, uint);static void RIOConCon(struct rio_info *, struct Host *, uint, uint, uint, uint, int);/*** Incoming on the ROUTE_RUP** I wrote this while I was tired. Forgive me.*/int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP ){  struct PktCmd *PktCmdP = (struct PktCmd *)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;  ushort RtaType;  uint RtaUniq;  uint ThisUnit, ThisUnit2;	/* 2 ids to accommodate 16 port RTA */  uint OldUnit, NewUnit, OldLink, NewLink;  char *MyType, *MyName;  int Lies;  unsigned long flags;#ifdef STACK    RIOStackCheck("RIORouteRup");#endif#ifdef CHECK    CheckPacketP(PacketP);    CheckHostP(HostP);    CheckRup(Rup);    CheckHost(Host);#endif  /*  ** Is this unit telling us it's current link topology?  */  if ( RBYTE(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 >= (ushort)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 ( RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) > (ushort)MAX_RUP )	  continue;      for ( NewLink=ThisLinkMin; NewLink < ThisLink; NewLink++ )      {        if ( (RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) ==              RBYTE(PktCmdP->RouteTopology[NewLink].Unit)) &&	     (RBYTE(PktCmdP->RouteTopology[ThisLink].Link) ==              RBYTE(PktCmdP->RouteTopology[NewLink].Link)) )	{          Lies++;	}      }    }    if ( Lies )    {      rio_dprintk (RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n",Lies);      rio_dprintk (RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",          RBYTE(PktCmdP->RouteTopology[0].Unit), 	  'A'+RBYTE(PktCmdP->RouteTopology[0].Link),          RBYTE(PktCmdP->RouteTopology[1].Unit),	  'A'+RBYTE(PktCmdP->RouteTopology[1].Link),          RBYTE(PktCmdP->RouteTopology[2].Unit),	  'A'+RBYTE(PktCmdP->RouteTopology[2].Link),          RBYTE(PktCmdP->RouteTopology[3].Unit),	  'A'+RBYTE(PktCmdP->RouteTopology[3].Link));      return TRUE;    }    /*    ** now, process each link.    */    for ( ThisLink=ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++)    {      /*      ** this is what it was connected to      */      OldUnit = TopP[ThisLink].Unit;      OldLink = TopP[ThisLink].Link;      /*      ** this is what it is now connected to      */      NewUnit = RBYTE(PktCmdP->RouteTopology[ThisLink].Unit);      NewLink = RBYTE(PktCmdP->RouteTopology[ThisLink].Link);      if ( OldUnit != NewUnit || OldLink != NewLink )      {	/*	** something has changed!	*/        if ( NewUnit > MAX_RUP &&	     NewUnit != ROUTE_DISCONNECT &&	     NewUnit != ROUTE_NO_ID &&	     NewUnit != ROUTE_INTERCONNECT )	{	    rio_dprintk (RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n",		  MyType,		  MyName,		  NewUnit,		  NewLink);	}	else	{	  /*	  ** put the new values in	  */	  TopP[ThisLink].Unit = NewUnit;	  TopP[ThisLink].Link = NewLink;	  RIOSetChange(p);	  if ( OldUnit <= MAX_RUP )	  {	    /*	    ** If something has become bust, then re-enable them messages	    */	    if (! p->RIONoMessage)		RIOConCon(p,HostP,ThisUnit,ThisLink,OldUnit,OldLink,DISCONNECT);	  }	  if ( ( NewUnit <= MAX_RUP ) && !p->RIONoMessage )	    RIOConCon(p,HostP,ThisUnit,ThisLink,NewUnit,NewLink,CONNECT);	  if ( NewUnit == ROUTE_NO_ID )	    rio_dprintk (RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n",		    MyType,MyName,'A'+ThisLink);	  if ( NewUnit == ROUTE_INTERCONNECT )	  {	    if (! p->RIONoMessage)		cprintf("%s '%s' (%c) is connected to another network.\n", MyType,MyName,'A'+ThisLink);	  }	  /*	  ** perform an update for 'the other end', so that these messages	  ** only appears once. Only disconnect the other end if it is pointing	  ** at us!	  */	  if ( OldUnit == HOST_ID )	  {	    if ( HostP->Topology[OldLink].Unit == ThisUnit &&		 HostP->Topology[OldLink].Link == ThisLink )	    {	      rio_dprintk (RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink+'A');	      HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;	      HostP->Topology[OldLink].Link = NO_LINK;	    }	    else	    {	      rio_dprintk (RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n",		    OldLink+'A',HostP->Mapping[ThisUnit-1].Name,ThisLink+'A');	    }	  }	  else if ( OldUnit <= MAX_RUP )	  {	    if ( HostP->Mapping[OldUnit-1].Topology[OldLink].Unit == ThisUnit &&	         HostP->Mapping[OldUnit-1].Topology[OldLink].Link == ThisLink )	    {	      rio_dprintk (RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n",				   HostP->Mapping[OldUnit-1].Name,OldLink+'A');	      HostP->Mapping[OldUnit-1].Topology[OldLink].Unit=ROUTE_DISCONNECT;	      HostP->Mapping[OldUnit-1].Topology[OldLink].Link=NO_LINK;	    }	    else	    {	      rio_dprintk (RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n",			    HostP->Mapping[OldUnit-1].Name,OldLink+'A',			    HostP->Mapping[ThisUnit-1].Name,ThisLink+'A');	    }	  }	  if ( NewUnit == HOST_ID )	  {	    rio_dprintk (RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n",				NewLink+'A',MyName,ThisLink+'A');	    HostP->Topology[NewLink].Unit = ThisUnit;	    HostP->Topology[NewLink].Link = ThisLink;	  }	  else if ( NewUnit <= MAX_RUP )	  {	    rio_dprintk (RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n",	      HostP->Mapping[NewUnit-1].Name,NewLink+'A',MyName,ThisLink+'A');	    HostP->Mapping[NewUnit-1].Topology[NewLink].Unit=ThisUnit;	    HostP->Mapping[NewUnit-1].Topology[NewLink].Link=ThisLink;	  }	}	RIOSetChange(p);	RIOCheckIsolated(p, HostP, OldUnit );      }    }    return TRUE;  }  /*  ** The only other command we recognise is a route_request command  */  if ( RBYTE(PktCmdP->Command) != ROUTE_REQUEST )  {    rio_dprintk (RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %d ROUTE_RUP\n", 	   RBYTE(PktCmdP->Command),Rup,(int)HostP);    return TRUE;  }        RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) +	    (RBYTE(PktCmdP->UniqNum[1]) << 8) +	    (RBYTE(PktCmdP->UniqNum[2]) << 16) +	    (RBYTE(PktCmdP->UniqNum[3]) << 24);  /*  ** Determine if 8 or 16 port RTA  */  RtaType = GetUnitType(RtaUniq);  rio_dprintk (RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);  Mod = RBYTE(PktCmdP->ModuleTypes);  Mod1 = LONYBLE(Mod);  if (RtaType == TYPE_RTA16)  {    /*    ** Only one ident is set for a 16 port RTA. To make compatible    ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.    */    Mod2 = Mod1;    rio_dprintk (RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n",     p->RIOModuleTypes[Mod1].Name);  }  else  {    Mod2 = HINYBLE(Mod);    rio_dprintk (RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n",     p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);  }  if ( RtaUniq == 0xffffffff )  {      ShowPacket( DBG_SPECIAL, PacketP );  }  /*  ** try to unhook a command block from the command free list.  */  if ( !(CmdBlkP = RIOGetCmdBlk()) )  {    rio_dprintk (RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");    return 0;  }  /*  ** Fill in the default info on the command block  */  CmdBlkP->Packet.dest_unit = Rup;  CmdBlkP->Packet.dest_port = ROUTE_RUP;  CmdBlkP->Packet.src_unit = HOST_ID;  CmdBlkP->Packet.src_port = ROUTE_RUP;  CmdBlkP->Packet.len = PKT_CMD_BIT | 1;  CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;  PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data;  if (! RIOBootOk(p, HostP, RtaUniq))  {    rio_dprintk (RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n",	  RtaUniq);    PktReplyP->Command = ROUTE_FOAD;    HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);    RIOQueueCmdBlk(HostP, Rup, CmdBlkP);    return TRUE;  }  /*  ** Check to see if the RTA is configured for this host  */  for ( ThisUnit=0; ThisUnit<MAX_RUP; ThisUnit++ )  {    rio_dprintk (RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",			ThisUnit,			HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ?					    "Slot-In-Use":"Not In Use",			HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? 					    "Slot-Tentative":"Not Tentative",			HostP->Mapping[ThisUnit].RtaUniqueNum);    /*    ** We have an entry for it.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -