rioroute.c

来自「linux2.6.16版本」· C语言 代码 · 共 1,069 行 · 第 1/3 页

C
1,069
字号
/*** -----------------------------------------------------------------------------****  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;	/*	 ** 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.		 */		if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) {			if (RtaType == TYPE_RTA16) {				ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2);			} else				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit);			/*			 ** If we have no knowledge of booting it, then the host has			 ** been re-booted, and so we must kill the RTA, so that it			 ** will be booted again (potentially with new bins)			 ** and it will then re-ask for an ID, which we will service.			 */			if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) {				if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) {					if (!p->RIONoMessage)						cprintf("RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name);					HostP->Mapping[ThisUnit].Flags |= MSG_DONE;				}				PktReplyP->Command = ROUTE_FOAD;				HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);				RIOQueueCmdBlk(HostP, Rup, CmdBlkP);				return TRUE;

⌨️ 快捷键说明

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