diff options
Diffstat (limited to 'drivers/char/rio/riocmd.c')
| -rw-r--r-- | drivers/char/rio/riocmd.c | 1041 |
1 files changed, 0 insertions, 1041 deletions
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c deleted file mode 100644 index 533085ec6f1..00000000000 --- a/drivers/char/rio/riocmd.c +++ /dev/null @@ -1,1041 +0,0 @@ -/* -** ----------------------------------------------------------------------------- -** -** 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_LABELS -static 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 (); - -#ifdef CHECK - CheckHost( Host ); - CheckHostP( HostP ); - CheckPacketP( PacketP ); -#endif - - /* - ** 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); - -#ifdef CHECK - CheckRup( rup ); - CheckUnixRupP( UnixRupP ); -#endif - 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; - } - -#ifdef CHECK - CheckSysPort( SysPort ); -#endif - 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 - if ( PortP->Mapped ) { - /***********************************************************\ - ************************************************************* - *** *** - *** M O D E M S T A T E C H A N G E *** - *** *** - ************************************************************* - \***********************************************************/ - /* - ** If the device is a modem, then check the modem - ** carrier. - */ - if (PortP->gs.tty == NULL) - break; - if (PortP->gs.tty->termios == NULL) - break; - - if (!(PortP->gs.tty->termios->c_cflag & CLOCAL) && - ((PortP->State & (RIO_MOPEN|RIO_WOPEN)))) { - - rio_dprintk (RIO_DEBUG_CMD, "Is there a Carrier?\n"); - /* - ** Is there a carrier? - */ - if ( PortP->ModemState & MSVR1_CD ) { - /* - ** Has carrier just appeared? - */ - if (!(PortP->State & RIO_CARR_ON)) { - rio_dprintk (RIO_DEBUG_CMD, "Carrier just came up.\n"); - PortP->State |= RIO_CARR_ON; - /* - ** wakeup anyone in WOPEN - */ - if (PortP->State & (PORT_ISOPEN | RIO_WOPEN) ) - wake_up_interruptible (&PortP->gs.open_wait); -#ifdef STATS - PortP->Stat.ModemOnCnt++; -#endif - } - } else { - /* - ** Has carrier just dropped? - */ - if (PortP->State & RIO_CARR_ON) { - if (PortP->State & (PORT_ISOPEN|RIO_WOPEN|RIO_MOPEN)) - tty_hangup (PortP->gs.tty); - PortP->State &= ~RIO_CARR_ON; - rio_dprintk (RIO_DEBUG_CMD, "Carrirer just went down\n"); -#ifdef STATS - PortP->Stat.ModemOffCnt++; -#endif - } - } - } - } -#endif - } - break; - - default: - rio_dprintk (RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n", - RBYTE(PktCmdP->Command),HostP-p->RIOHosts); - break; - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - - func_exit (); - - return TRUE; -} -/* -** The command mechanism: -** Each rup has a chain of commands associated with it. -** This chain is maintained by routines in this file. -** Periodically we are called and we run a quick check of all the -** active chains to determine if there is a command to be executed, -** and if the rup is ready to accept it. -** -*/ - -/* -** Allocate an empty command block. -*/ -struct CmdBlk * -RIOGetCmdBlk(void) -{ - struct CmdBlk *CmdBlkP; - - CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk)); - if (CmdBlkP) - bzero(CmdBlkP, sizeof(struct CmdBlk)); - - return CmdBlkP; -} - -/* -** Return a block to the head of the free list. -*/ -void -RIOFreeCmdBlk(struct CmdBlk *CmdBlkP) -{ - sysfree((void *)CmdBlkP, sizeof(struct CmdBlk)); -} - -/* -** attach a command block to the list of commands to be performed for -** a given rup. -*/ -int -RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) -{ - struct CmdBlk **Base; - struct UnixRup *UnixRupP; - unsigned long flags; - -#ifdef CHECK - CheckHostP( HostP ); - CheckRup( Rup ); - CheckCmdBlkP( CmdBlkP ); -#endif - if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) { - rio_dprintk (RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n",Rup); - RIOFreeCmdBlk( CmdBlkP ); - return RIO_FAIL; - } - - UnixRupP = &HostP->UnixRups[Rup]; - - rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); - - /* - ** If the RUP is currently inactive, then put the request - ** straight on the RUP.... - */ - if ( (UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && - (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE ) && - (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg,CmdBlkP) - :TRUE)) { - rio_dprintk (RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", - CmdBlkP->Packet.data[0]); - - /* - ** Whammy! blat that pack! - */ - HostP->Copy( (caddr_t)&CmdBlkP->Packet, - RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt ), sizeof(PKT) ); - - /* - ** place command packet on the pending position. - */ - UnixRupP->CmdPendingP = CmdBlkP; - - /* - ** set the command register - */ - WWORD(UnixRupP->RupP->txcontrol , TX_PACKET_READY); - - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - - return RIO_SUCCESS; - } - rio_dprintk (RIO_DEBUG_CMD, "RUP active - en-queing\n"); - - if ( UnixRupP->CmdsWaitingP != NULL) - rio_dprintk (RIO_DEBUG_CMD, "Rup active - command waiting\n"); - if ( UnixRupP->CmdPendingP != NULL ) - rio_dprintk (RIO_DEBUG_CMD, "Rup active - command pending\n"); - if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE ) - rio_dprintk (RIO_DEBUG_CMD, "Rup active - command rup not ready\n"); - - Base = &UnixRupP->CmdsWaitingP; - - rio_dprintk (RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int)CmdBlkP,(int)Base); - - while ( *Base ) { - rio_dprintk (RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int)(*Base)); - Base = &((*Base)->NextP); - rio_dprintk (RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%x at 0x%x\n", - (int)CmdBlkP,(int)Base); - } - - rio_dprintk (RIO_DEBUG_CMD, "Will queue cmdblk 0x%x at 0x%x\n",(int)CmdBlkP,(int)Base); - - *Base = CmdBlkP; - - CmdBlkP->NextP = NULL; - - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - - return RIO_SUCCESS; -} - -/* -** Here we go - if there is an empty rup, fill it! -** must be called at splrio() or higher. -*/ -void -RIOPollHostCommands(struct rio_info *p, struct Host *HostP) -{ - register struct CmdBlk *CmdBlkP; - register struct UnixRup *UnixRupP; - struct PKT *PacketP; - ushort Rup; - unsigned long flags; - - - Rup = MAX_RUP+LINKS_PER_UNIT; - - do { /* do this loop for each RUP */ - /* - ** locate the rup we are processing & lock it - */ - UnixRupP = &HostP->UnixRups[--Rup]; - - spin_lock_irqsave(&UnixRupP->RupLock, flags); - - /* - ** First check for incoming commands: - */ - if ( RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE ) { - int FreeMe; - - PacketP =(PKT *)RIO_PTR(HostP->Caddr,RWORD(UnixRupP->RupP->rxpkt)); - - ShowPacket( DBG_CMD, PacketP ); - - switch ( RBYTE(PacketP->dest_port) ) { - case BOOT_RUP: - rio_dprintk (RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", - RBYTE(PacketP->len) & 0x80 ? "Command":"Data", - RBYTE(PacketP->data[0])); - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - FreeMe= RIOBootRup(p, Rup,HostP,PacketP); - rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); - break; - - case COMMAND_RUP: - /* - ** Free the RUP lock as loss of carrier causes a - ** ttyflush which will (eventually) call another - ** routine that uses the RUP lock. - */ - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - FreeMe= RIOCommandRup(p, Rup,HostP,PacketP); - if (PacketP->data[5] == MEMDUMP) { - rio_dprintk (RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", - *(ushort *) &(PacketP->data[6])); - HostP->Copy( (caddr_t)&(PacketP->data[8]), - (caddr_t)p->RIOMemDump, 32 ); - } - rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); - break; - - case ROUTE_RUP: - rio_spin_unlock_irqrestore( &UnixRupP->RupLock, flags); - FreeMe = RIORouteRup(p, Rup, HostP, PacketP ); - rio_spin_lock_irqsave( &UnixRupP->RupLock, flags ); - break; - - default: - rio_dprintk (RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port)); - FreeMe = 1; - break; - } - - if ( FreeMe ) { - rio_dprintk (RIO_DEBUG_CMD, "Free processed incoming command packet\n"); - put_free_end(HostP,PacketP); - - WWORD(UnixRupP->RupP->rxcontrol , RX_RUP_INACTIVE); - - if ( RWORD(UnixRupP->RupP->handshake)==PHB_HANDSHAKE_SET ) { - rio_dprintk (RIO_DEBUG_CMD, "Handshake rup %d\n",Rup); - WWORD(UnixRupP->RupP->handshake, - PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET); - } - } - } - - /* - ** IF a command was running on the port, - ** and it has completed, then tidy it up. - */ - if ( (CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */ - (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { - /* - ** we are idle. - ** there is a command in pending. - ** Therefore, this command has finished. - ** So, wakeup whoever is waiting for it (and tell them - ** what happened). - */ - if ( CmdBlkP->Packet.dest_port == BOOT_RUP ) - rio_dprintk (RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", - CmdBlkP->Packet.len & 0x80 ? "Command":"Data", - CmdBlkP->Packet.data[0]); - - rio_dprintk (RIO_DEBUG_CMD, "Command 0x%x completed\n",(int)CmdBlkP); - - /* - ** Clear the Rup lock to prevent mutual exclusion. - */ - if ( CmdBlkP->PostFuncP ) { - rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg,CmdBlkP); - rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); - } - - /* - ** ....clear the pending flag.... - */ - UnixRupP->CmdPendingP = NULL; - - /* - ** ....and return the command block to the freelist. - */ - RIOFreeCmdBlk( CmdBlkP ); - } - - /* - ** If there is a command for this rup, and the rup - ** is idle, then process the command - */ - if ( (CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */ - (UnixRupP->CmdPendingP == NULL) && - (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { - /* - ** if the pre-function is non-zero, call it. - ** If it returns RIO_FAIL then don't - ** send this command yet! - */ -#ifdef CHECK - CheckCmdBlkP (CmdBlkP); -#endif - if ( !(CmdBlkP->PreFuncP ? - (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg, CmdBlkP) : TRUE)) { - rio_dprintk (RIO_DEBUG_CMD, "Not ready to start command 0x%x\n",(int)CmdBlkP); - } - else { - rio_dprintk (RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n", - (int)CmdBlkP, CmdBlkP->Packet.data[0]); - /* - ** Whammy! blat that pack! - */ -#ifdef CHECK - CheckPacketP ((PKT *)RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt)); -#endif - HostP->Copy( (caddr_t)&CmdBlkP->Packet, - RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT)); - - /* - ** remove the command from the rup command queue... - */ - UnixRupP->CmdsWaitingP = CmdBlkP->NextP; - - /* - ** ...and place it on the pending position. - */ - UnixRupP->CmdPendingP = CmdBlkP; - - /* - ** set the command register - */ - WWORD(UnixRupP->RupP->txcontrol,TX_PACKET_READY); - - /* - ** the command block will be freed - ** when the command has been processed. - */ - } - } - spin_unlock_irqrestore(&UnixRupP->RupLock, flags); - } while ( Rup ); -} - -int -RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP) -{ - struct Port * PortP = (struct Port *)iPortP; - unsigned long flags; - - rio_spin_lock_irqsave(&PortP->portSem, flags); -#ifdef CHECK - CheckPortP( PortP ); -#endif - PortP->WflushFlag++; - PortP->MagicFlags |= MAGIC_FLUSH; - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return RIOUnUse( iPortP, CmdBlkP ); -} - -int -RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP) -{ - struct Port * PortP = (struct Port *)iPortP; - PKT *PacketP; - unsigned long flags; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - - while ( can_remove_receive(&PacketP, PortP) ) { - remove_receive(PortP); - ShowPacket(DBG_PROC, PacketP ); - put_free_end( PortP->HostP, PacketP ); - } - - if ( RWORD(PortP->PhbP->handshake)==PHB_HANDSHAKE_SET ) { - /* - ** MAGIC! (Basically, handshake the RX buffer, so that - ** the RTAs upstream can be re-enabled.) - */ - rio_dprintk (RIO_DEBUG_CMD, "Util: Set RX handshake bit\n"); - WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET); - } - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return RIOUnUse( iPortP, CmdBlkP ); -} - -int -RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP) -{ - struct Port * PortP = (struct Port *)iPortP; - unsigned long flags; - - rio_spin_lock_irqsave(&PortP->portSem, flags); - -#ifdef CHECK - CheckPortP( PortP ); -#endif - rio_dprintk (RIO_DEBUG_CMD, "Decrement in use count for port\n"); - - if (PortP->InUse) { - if ( --PortP->InUse != NOT_INUSE ) { - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; - } - } - /* - ** While PortP->InUse is set (i.e. a preemptive command has been sent to - ** the RTA and is awaiting completion), any transmit data is prevented from - ** being transferred from the write queue into the transmit packets - ** (add_transmit) and no furthur transmit interrupt will be sent for that - ** data. The next interrupt will occur up to 500ms later (RIOIntr is called - ** twice a second as a saftey measure). This was the case when kermit was - ** used to send data into a RIO port. After each packet was sent, TCFLSH - ** was called to flush the read queue preemptively. PortP->InUse was - ** incremented, thereby blocking the 6 byte acknowledgement packet - ** transmitted back. This acknowledgment hung around for 500ms before - ** being sent, thus reducing input performance substantially!. - ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data - ** hanging around in the transmit buffer is sent immediately. - */ - WWORD(PortP->HostP->ParmMapP->tx_intr, 1); - /* What to do here .. - wakeup( (caddr_t)&(PortP->InUse) ); - */ - rio_spin_unlock_irqrestore(&PortP->portSem, flags); - return 0; -} - -void -ShowPacket(uint Flags, struct PKT *PacketP) -{ -} - -/* -** -** How to use this file: -** -** To send a command down a rup, you need to allocate a command block, fill -** in the packet information, fill in the command number, fill in the pre- -** and post- functions and arguments, and then add the command block to the -** queue of command blocks for the port in question. When the port is idle, -** then the pre-function will be called. If this returns RIO_FAIL then the -** command will be re-queued and tried again at a later date (probably in one -** clock tick). If the pre-function returns NOT RIO_FAIL, then the command -** packet will be queued on the RUP, and the txcontrol field set to the -** command number. When the txcontrol field has changed from being the -** command number, then the post-function will be called, with the argument -** specified earlier, a pointer to the command block, and the value of -** txcontrol. -** -** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer -** to the command block structure allocated, or NULL if there aren't any. -** The block will have been zeroed for you. -** -** The structure has the following fields: -** -** struct CmdBlk -** { -** struct CmdBlk *NextP; ** Pointer to next command block ** -** struct PKT Packet; ** A packet, to copy to the rup ** -** int (*PreFuncP)(); ** The func to call to check if OK ** -** int PreArg; ** The arg for the func ** -** int (*PostFuncP)(); ** The func to call when completed ** -** int PostArg; ** The arg for the func ** -** }; -** -** You need to fill in ALL fields EXCEPT NextP, which is used to link the -** blocks together either on the free list or on the Rup list. -** -** Packet is an actual packet structure to be filled in with the packet -** information associated with the command. You need to fill in everything, -** as the command processore doesn't process the command packet in any way. -** -** The PreFuncP is called before the packet is enqueued on the host rup. -** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must -** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL -** if the packet is NOT to be queued. -** -** The PostFuncP is called when the command has completed. It is called -** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected -** to return a value. PostFuncP does NOT need to free the command block, -** as this happens automatically after PostFuncP returns. -** -** Once the command block has been filled in, it is attached to the correct -** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is -** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer -** to it!), and CmdBlkP is the pointer to the command block allocated using -** RIOGetCmdBlk(). -** -*/ |
