riocmd.c

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

C
962
字号
/*** -----------------------------------------------------------------------------****  Perle Specialix driver for Linux**  ported from the existing SCO driver source** * *  (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		: riocmd.c**	SID		: 1.2**	Last Modified	: 11/6/98 10:33:41**	Retrieved	: 11/6/98 10:33:49****  ident @(#)riocmd.c	1.2**** -----------------------------------------------------------------------------*/#ifdef SCCS_LABELSstatic char *_riocmd_c_sccs_ = "@(#)riocmd.c	1.2";#endif#include <linux/module.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/tty.h>#include <asm/io.h>#include <asm/system.h>#include <asm/string.h>#include <asm/semaphore.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"static struct IdentifyRta IdRta;static struct KillNeighbour KillUnit;int RIOFoadRta(struct Host *HostP, struct Map *MapP){	struct CmdBlk *CmdBlkP;	rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA\n");	CmdBlkP = RIOGetCmdBlk();	if (!CmdBlkP) {		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");		return -ENXIO;	}	CmdBlkP->Packet.dest_unit = MapP->ID;	CmdBlkP->Packet.dest_port = BOOT_RUP;	CmdBlkP->Packet.src_unit = 0;	CmdBlkP->Packet.src_port = BOOT_RUP;	CmdBlkP->Packet.len = 0x84;	CmdBlkP->Packet.data[0] = IFOAD;	CmdBlkP->Packet.data[1] = 0;	CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF;	CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF;	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");		return -EIO;	}	return 0;}int RIOZombieRta(struct Host *HostP, struct Map *MapP){	struct CmdBlk *CmdBlkP;	rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA\n");	CmdBlkP = RIOGetCmdBlk();	if (!CmdBlkP) {		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");		return -ENXIO;	}	CmdBlkP->Packet.dest_unit = MapP->ID;	CmdBlkP->Packet.dest_port = BOOT_RUP;	CmdBlkP->Packet.src_unit = 0;	CmdBlkP->Packet.src_port = BOOT_RUP;	CmdBlkP->Packet.len = 0x84;	CmdBlkP->Packet.data[0] = ZOMBIE;	CmdBlkP->Packet.data[1] = 0;	CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF;	CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF;	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");		return -EIO;	}	return 0;}int RIOCommandRta(struct rio_info *p, uint RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP)){	uint Host;	rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%x func 0x%x\n", RtaUnique, (int) func);	if (!RtaUnique)		return (0);	for (Host = 0; Host < p->RIONumHosts; Host++) {		uint Rta;		struct Host *HostP = &p->RIOHosts[Host];		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {			struct Map *MapP = &HostP->Mapping[Rta];			if (MapP->RtaUniqueNum == RtaUnique) {				uint Link;				/*				 ** now, lets just check we have a route to it...				 ** IF the routing stuff is working, then one of the				 ** topology entries for this unit will have a legit				 ** route *somewhere*. We care not where - if its got				 ** any connections, we can get to it.				 */				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {					if (MapP->Topology[Link].Unit <= (uchar) MAX_RUP) {						/*						 ** Its worth trying the operation...						 */						return (*func) (HostP, MapP);					}				}			}		}	}	return -ENXIO;}int RIOIdentifyRta(struct rio_info *p, caddr_t arg){	uint Host;	if (copyin((int) arg, (caddr_t) & IdRta, sizeof(IdRta)) == COPYFAIL) {		rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");		p->RIOError.Error = COPYIN_FAILED;		return -EFAULT;	}	for (Host = 0; Host < p->RIONumHosts; Host++) {		uint Rta;		struct Host *HostP = &p->RIOHosts[Host];		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {			struct Map *MapP = &HostP->Mapping[Rta];			if (MapP->RtaUniqueNum == IdRta.RtaUnique) {				uint Link;				/*				 ** now, lets just check we have a route to it...				 ** IF the routing stuff is working, then one of the				 ** topology entries for this unit will have a legit				 ** route *somewhere*. We care not where - if its got				 ** any connections, we can get to it.				 */				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {					if (MapP->Topology[Link].Unit <= (uchar) MAX_RUP) {						/*						 ** Its worth trying the operation...						 */						struct CmdBlk *CmdBlkP;						rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA\n");						CmdBlkP = RIOGetCmdBlk();						if (!CmdBlkP) {							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");							return -ENXIO;						}						CmdBlkP->Packet.dest_unit = MapP->ID;						CmdBlkP->Packet.dest_port = BOOT_RUP;						CmdBlkP->Packet.src_unit = 0;						CmdBlkP->Packet.src_port = BOOT_RUP;						CmdBlkP->Packet.len = 0x84;						CmdBlkP->Packet.data[0] = IDENTIFY;						CmdBlkP->Packet.data[1] = 0;						CmdBlkP->Packet.data[2] = IdRta.ID;						if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");							return -EIO;						}						return 0;					}				}			}		}	}	return -ENOENT;}int RIOKillNeighbour(struct rio_info *p, caddr_t arg){	uint Host;	uint ID;	struct Host *HostP;	struct CmdBlk *CmdBlkP;	rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");	if (copyin((int) arg, (caddr_t) & KillUnit, sizeof(KillUnit)) == COPYFAIL) {		rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");		p->RIOError.Error = COPYIN_FAILED;		return -EFAULT;	}	if (KillUnit.Link > 3)		return -ENXIO;	CmdBlkP = RIOGetCmdBlk();	if (!CmdBlkP) {		rio_dprintk(RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");		return -ENXIO;	}	CmdBlkP->Packet.dest_unit = 0;	CmdBlkP->Packet.src_unit = 0;	CmdBlkP->Packet.dest_port = BOOT_RUP;	CmdBlkP->Packet.src_port = BOOT_RUP;	CmdBlkP->Packet.len = 0x84;	CmdBlkP->Packet.data[0] = UFOAD;	CmdBlkP->Packet.data[1] = KillUnit.Link;	CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF;	CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF;	for (Host = 0; Host < p->RIONumHosts; Host++) {		ID = 0;		HostP = &p->RIOHosts[Host];		if (HostP->UniqueNum == KillUnit.UniqueNum) {			if (RIOQueueCmdBlk(HostP, RTAS_PER_HOST + KillUnit.Link, CmdBlkP) == RIO_FAIL) {				rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");				return -EIO;			}			return 0;		}		for (ID = 0; ID < RTAS_PER_HOST; ID++) {			if (HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum) {				CmdBlkP->Packet.dest_unit = ID + 1;				if (RIOQueueCmdBlk(HostP, ID, CmdBlkP) == RIO_FAIL) {					rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");					return -EIO;				}				return 0;			}		}	}	RIOFreeCmdBlk(CmdBlkP);	return -ENXIO;}int RIOSuspendBootRta(struct Host *HostP, int ID, int Link){	struct CmdBlk *CmdBlkP;	rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);	CmdBlkP = RIOGetCmdBlk();	if (!CmdBlkP) {		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");		return -ENXIO;	}	CmdBlkP->Packet.dest_unit = ID;	CmdBlkP->Packet.dest_port = BOOT_RUP;	CmdBlkP->Packet.src_unit = 0;	CmdBlkP->Packet.src_port = BOOT_RUP;	CmdBlkP->Packet.len = 0x84;	CmdBlkP->Packet.data[0] = IWAIT;	CmdBlkP->Packet.data[1] = Link;	CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF;	CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF;	if (RIOQueueCmdBlk(HostP, ID - 1, CmdBlkP) == RIO_FAIL) {		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");		return -EIO;	}	return 0;}int RIOFoadWakeup(struct rio_info *p){	int port;	register struct Port *PortP;	unsigned long flags;	for (port = 0; port < RIO_PORTS; port++) {		PortP = p->RIOPortp[port];		rio_spin_lock_irqsave(&PortP->portSem, flags);		PortP->Config = 0;		PortP->State = 0;		PortP->InUse = NOT_INUSE;		PortP->PortState = 0;		PortP->FlushCmdBodge = 0;		PortP->ModemLines = 0;		PortP->ModemState = 0;		PortP->CookMode = 0;		PortP->ParamSem = 0;		PortP->Mapped = 0;		PortP->WflushFlag = 0;		PortP->MagicFlags = 0;		PortP->RxDataStart = 0;		PortP->TxBufferIn = 0;		PortP->TxBufferOut = 0;		rio_spin_unlock_irqrestore(&PortP->portSem, flags);	}	return (0);}/*** Incoming command on the COMMAND_RUP to be processed.*/static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP){	struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data;	struct Port *PortP;	struct UnixRup *UnixRupP;	ushort SysPort;	ushort ReportedModemStatus;	ushort rup;	ushort subCommand;	unsigned long flags;	func_enter();	/*	 ** 16 port RTA note:	 ** Command rup packets coming from the RTA will have pkt->data[1] (which	 ** translates to PktCmdP->PhbNum) set to the host port number for the	 ** particular unit. To access the correct BaseSysPort for a 16 port RTA,	 ** we can use PhbNum to get the rup number for the appropriate 8 port	 ** block (for the first block, this should be equal to 'Rup').	 */	rup = RBYTE(PktCmdP->PhbNum) / (ushort) PORTS_PER_RTA;	UnixRupP = &HostP->UnixRups[rup];	SysPort = UnixRupP->BaseSysPort + (RBYTE(PktCmdP->PhbNum) % (ushort) PORTS_PER_RTA);	rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);	if (UnixRupP->BaseSysPort == NO_PORT) {		rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n");		rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n", HostP - p->RIOHosts, HostP->Name);		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number  0x%x\n", rup);		if (Rup >= (ushort) MAX_RUP) {			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name);		} else			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", PacketP->dest_unit, PacketP->dest_port);		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source	  0x%x:0x%x\n", PacketP->src_unit, PacketP->src_port);		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length	  0x%x (%d)\n", PacketP->len, PacketP->len);		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control	 0x%x (%d)\n", PacketP->control, PacketP->control);		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check	   0x%x (%d)\n", PacketP->csum, PacketP->csum);		rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command);		return TRUE;	}	PortP = p->RIOPortp[SysPort];	rio_spin_lock_irqsave(&PortP->portSem, flags);	switch (RBYTE(PktCmdP->Command)) {	case BREAK_RECEIVED:		rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n");		/* If the current line disc. is not multi-threading and		   the current processor is not the default, reset rup_intr		   and return FALSE to ensure that the command packet is		   not freed. */		/* Call tmgr HANGUP HERE */		/* Fix this later when every thing works !!!! RAMRAJ */		gs_got_break(&PortP->gs);		break;	case COMPLETE:		rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %d\n", RBYTE(PktCmdP->PhbNum), HostP - p->RIOHosts);		subCommand = 1;		switch (RBYTE(PktCmdP->SubCommand)) {		case MEMDUMP:			rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr));			break;		case READ_REGISTER:			rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr));			p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST);			break;		default:			subCommand = 0;			break;		}		if (subCommand)			break;		rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", RBYTE(PktCmdP->PortStatus), PortP->PortState);		if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) {			rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n");			PortP->PortState = RBYTE(PktCmdP->PortStatus);			/* What should we do here ...			   wakeup( &PortP->PortState );			 */		} else			rio_dprintk(RIO_DEBUG_CMD, "No change\n");		/* FALLTHROUGH */	case MODEM_STATUS:		/*		 ** Knock out the tbusy and tstop bits, as these are not relevant		 ** to the check for modem status change (they're just there because		 ** it's a convenient place to put them!).		 */		ReportedModemStatus = RBYTE(PktCmdP->ModemStatus);		if ((PortP->ModemState & MSVR1_HOST) == (ReportedModemStatus & MSVR1_HOST)) {			rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);			/*			 ** Update ModemState just in case tbusy or tstop states have			 ** changed.			 */			PortP->ModemState = ReportedModemStatus;		} else {			rio_dprintk(RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus);			PortP->ModemState = ReportedModemStatus;#ifdef MODEM_SUPPORT

⌨️ 快捷键说明

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