2005-04-16 15:20:36 -07:00
/*
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
* * 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 0213 9 , 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>
2006-03-24 03:18:28 -08:00
# include <asm/uaccess.h>
2005-04-16 15:20:36 -07:00
# 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"
static struct IdentifyRta IdRta ;
static struct KillNeighbour KillUnit ;
2006-01-11 12:17:49 -08:00
int RIOFoadRta ( struct Host * HostP , struct Map * MapP )
2005-04-16 15:20:36 -07:00
{
struct CmdBlk * CmdBlkP ;
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " FOAD RTA \n " ) ;
2005-04-16 15:20:36 -07:00
CmdBlkP = RIOGetCmdBlk ( ) ;
2006-01-11 12:17:49 -08:00
if ( ! CmdBlkP ) {
rio_dprintk ( RIO_DEBUG_CMD , " FOAD RTA: GetCmdBlk failed \n " ) ;
2005-04-16 15:20:36 -07:00
return - ENXIO ;
}
CmdBlkP - > Packet . dest_unit = MapP - > ID ;
CmdBlkP - > Packet . dest_port = BOOT_RUP ;
2006-01-11 12:17:49 -08:00
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 " ) ;
2005-04-16 15:20:36 -07:00
return - EIO ;
}
return 0 ;
}
2006-01-11 12:17:49 -08:00
int RIOZombieRta ( struct Host * HostP , struct Map * MapP )
2005-04-16 15:20:36 -07:00
{
struct CmdBlk * CmdBlkP ;
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " ZOMBIE RTA \n " ) ;
2005-04-16 15:20:36 -07:00
CmdBlkP = RIOGetCmdBlk ( ) ;
2006-01-11 12:17:49 -08:00
if ( ! CmdBlkP ) {
rio_dprintk ( RIO_DEBUG_CMD , " ZOMBIE RTA: GetCmdBlk failed \n " ) ;
2005-04-16 15:20:36 -07:00
return - ENXIO ;
}
CmdBlkP - > Packet . dest_unit = MapP - > ID ;
CmdBlkP - > Packet . dest_port = BOOT_RUP ;
2006-01-11 12:17:49 -08:00
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 " ) ;
2005-04-16 15:20:36 -07:00
return - EIO ;
}
return 0 ;
}
2006-03-24 03:18:28 -08:00
int RIOCommandRta ( struct rio_info * p , unsigned long RtaUnique , int ( * func ) ( struct Host * HostP , struct Map * MapP ) )
2005-04-16 15:20:36 -07:00
{
2006-03-24 03:18:28 -08:00
unsigned int Host ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:32 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Command RTA 0x%lx func %p \n " , RtaUnique , func ) ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
if ( ! RtaUnique )
return ( 0 ) ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
for ( Host = 0 ; Host < p - > RIONumHosts ; Host + + ) {
2006-03-24 03:18:28 -08:00
unsigned int Rta ;
2005-04-16 15:20:36 -07:00
struct Host * HostP = & p - > RIOHosts [ Host ] ;
2006-01-11 12:17:49 -08:00
for ( Rta = 0 ; Rta < RTAS_PER_HOST ; Rta + + ) {
2005-04-16 15:20:36 -07:00
struct Map * MapP = & HostP - > Mapping [ Rta ] ;
2006-01-11 12:17:49 -08:00
if ( MapP - > RtaUniqueNum = = RtaUnique ) {
2005-04-16 15:20:36 -07:00
uint Link ;
/*
2006-01-11 12:17:49 -08:00
* * 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 + + ) {
2006-03-24 03:18:28 -08:00
if ( MapP - > Topology [ Link ] . Unit < = ( u8 ) MAX_RUP ) {
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * Its worth trying the operation . . .
*/
return ( * func ) ( HostP , MapP ) ;
2005-04-16 15:20:36 -07:00
}
}
}
}
}
return - ENXIO ;
}
2006-05-27 00:08:25 -04:00
int RIOIdentifyRta ( struct rio_info * p , void __user * arg )
2005-04-16 15:20:36 -07:00
{
2006-03-24 03:18:28 -08:00
unsigned int Host ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:28 -08:00
if ( copy_from_user ( & IdRta , arg , sizeof ( IdRta ) ) ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " RIO_IDENTIFY_RTA copy failed \n " ) ;
2005-04-16 15:20:36 -07:00
p - > RIOError . Error = COPYIN_FAILED ;
return - EFAULT ;
}
2006-01-11 12:17:49 -08:00
for ( Host = 0 ; Host < p - > RIONumHosts ; Host + + ) {
2006-03-24 03:18:28 -08:00
unsigned int Rta ;
2005-04-16 15:20:36 -07:00
struct Host * HostP = & p - > RIOHosts [ Host ] ;
2006-01-11 12:17:49 -08:00
for ( Rta = 0 ; Rta < RTAS_PER_HOST ; Rta + + ) {
2005-04-16 15:20:36 -07:00
struct Map * MapP = & HostP - > Mapping [ Rta ] ;
2006-01-11 12:17:49 -08:00
if ( MapP - > RtaUniqueNum = = IdRta . RtaUnique ) {
2005-04-16 15:20:36 -07:00
uint Link ;
/*
2006-01-11 12:17:49 -08:00
* * 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 + + ) {
2006-03-24 03:18:28 -08:00
if ( MapP - > Topology [ Link ] . Unit < = ( u8 ) MAX_RUP ) {
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * Its worth trying the operation . . .
*/
2005-04-16 15:20:36 -07:00
struct CmdBlk * CmdBlkP ;
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " IDENTIFY RTA \n " ) ;
2005-04-16 15:20:36 -07:00
CmdBlkP = RIOGetCmdBlk ( ) ;
2006-01-11 12:17:49 -08:00
if ( ! CmdBlkP ) {
rio_dprintk ( RIO_DEBUG_CMD , " IDENTIFY RTA: GetCmdBlk failed \n " ) ;
2005-04-16 15:20:36 -07:00
return - ENXIO ;
}
2006-01-11 12:17:49 -08:00
2005-04-16 15:20:36 -07:00
CmdBlkP - > Packet . dest_unit = MapP - > ID ;
CmdBlkP - > Packet . dest_port = BOOT_RUP ;
2006-01-11 12:17:49 -08:00
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 " ) ;
2005-04-16 15:20:36 -07:00
return - EIO ;
}
return 0 ;
}
}
}
}
2006-01-11 12:17:49 -08:00
}
2005-04-16 15:20:36 -07:00
return - ENOENT ;
}
2006-05-27 00:08:25 -04:00
int RIOKillNeighbour ( struct rio_info * p , void __user * arg )
2005-04-16 15:20:36 -07:00
{
uint Host ;
uint ID ;
struct Host * HostP ;
struct CmdBlk * CmdBlkP ;
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " KILL HOST NEIGHBOUR \n " ) ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:28 -08:00
if ( copy_from_user ( & KillUnit , arg , sizeof ( KillUnit ) ) ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " RIO_KILL_NEIGHBOUR copy failed \n " ) ;
2005-04-16 15:20:36 -07:00
p - > RIOError . Error = COPYIN_FAILED ;
return - EFAULT ;
}
2006-01-11 12:17:49 -08:00
if ( KillUnit . Link > 3 )
2005-04-16 15:20:36 -07:00
return - ENXIO ;
2006-01-11 12:17:49 -08:00
2005-04-16 15:20:36 -07:00
CmdBlkP = RIOGetCmdBlk ( ) ;
2006-01-11 12:17:49 -08:00
if ( ! CmdBlkP ) {
rio_dprintk ( RIO_DEBUG_CMD , " UFOAD: GetCmdBlk failed \n " ) ;
2005-04-16 15:20:36 -07:00
return - ENXIO ;
}
CmdBlkP - > Packet . dest_unit = 0 ;
2006-01-11 12:17:49 -08:00
CmdBlkP - > Packet . src_unit = 0 ;
2005-04-16 15:20:36 -07:00
CmdBlkP - > Packet . dest_port = BOOT_RUP ;
2006-01-11 12:17:49 -08:00
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 + + ) {
2005-04-16 15:20:36 -07:00
ID = 0 ;
HostP = & p - > RIOHosts [ Host ] ;
2006-01-11 12:17:49 -08:00
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 " ) ;
2005-04-16 15:20:36 -07:00
return - EIO ;
}
return 0 ;
}
2006-01-11 12:17:49 -08:00
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 " ) ;
2005-04-16 15:20:36 -07:00
return - EIO ;
}
return 0 ;
}
}
}
2006-01-11 12:17:49 -08:00
RIOFreeCmdBlk ( CmdBlkP ) ;
2005-04-16 15:20:36 -07:00
return - ENXIO ;
}
2006-01-11 12:17:49 -08:00
int RIOSuspendBootRta ( struct Host * HostP , int ID , int Link )
2005-04-16 15:20:36 -07:00
{
struct CmdBlk * CmdBlkP ;
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " SUSPEND BOOT ON RTA ID %d, link %c \n " , ID , ' A ' + Link ) ;
2005-04-16 15:20:36 -07:00
CmdBlkP = RIOGetCmdBlk ( ) ;
2006-01-11 12:17:49 -08:00
if ( ! CmdBlkP ) {
rio_dprintk ( RIO_DEBUG_CMD , " SUSPEND BOOT ON RTA: GetCmdBlk failed \n " ) ;
2005-04-16 15:20:36 -07:00
return - ENXIO ;
}
CmdBlkP - > Packet . dest_unit = ID ;
CmdBlkP - > Packet . dest_port = BOOT_RUP ;
2006-01-11 12:17:49 -08:00
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 " ) ;
2005-04-16 15:20:36 -07:00
return - EIO ;
}
return 0 ;
}
2006-01-11 12:17:49 -08:00
int RIOFoadWakeup ( struct rio_info * p )
2005-04-16 15:20:36 -07:00
{
int port ;
2006-03-24 03:18:28 -08:00
struct Port * PortP ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
2006-01-11 12:17:49 -08:00
for ( port = 0 ; port < RIO_PORTS ; port + + ) {
2005-04-16 15:20:36 -07:00
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 ) ;
}
2006-01-11 12:17:49 -08:00
return ( 0 ) ;
2005-04-16 15:20:36 -07:00
}
/*
* * Incoming command on the COMMAND_RUP to be processed .
*/
2006-05-27 00:08:25 -04:00
static int RIOCommandRup ( struct rio_info * p , uint Rup , struct Host * HostP , struct PKT __iomem * PacketP )
2005-04-16 15:20:36 -07:00
{
2006-05-27 00:08:25 -04:00
struct PktCmd __iomem * PktCmdP = ( struct PktCmd __iomem * ) PacketP - > data ;
2005-04-16 15:20:36 -07:00
struct Port * PortP ;
struct UnixRup * UnixRupP ;
2006-03-24 03:18:28 -08:00
unsigned short SysPort ;
unsigned short ReportedModemStatus ;
unsigned short rup ;
unsigned short subCommand ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
2006-01-11 12:17:49 -08:00
func_enter ( ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * 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 ' ) .
*/
2006-03-24 03:18:28 -08:00
rup = readb ( & PktCmdP - > PhbNum ) / ( unsigned short ) PORTS_PER_RTA ;
2005-04-16 15:20:36 -07:00
UnixRupP = & HostP - > UnixRups [ rup ] ;
2006-03-24 03:18:28 -08:00
SysPort = UnixRupP - > BaseSysPort + ( readb ( & PktCmdP - > PhbNum ) % ( unsigned short ) PORTS_PER_RTA ) ;
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Command on rup %d, port %d \n " , rup , SysPort ) ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
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 " ) ;
2006-03-24 03:18:28 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " CONTROL information: Host number %Zd, name ``%s'' \n " , HostP - p - > RIOHosts , HostP - > Name ) ;
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " CONTROL information: Rup number 0x%x \n " , rup ) ;
2006-03-24 03:18:28 -08:00
if ( Rup > = ( unsigned short ) MAX_RUP ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " CONTROL information: This is the RUP for RTA ``%s'' \n " , HostP - > Mapping [ Rup ] . Name ) ;
2005-04-16 15:20:36 -07:00
} else
2006-01-11 12:17:49 -08:00
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 ) ;
2006-03-24 03:18:32 -08:00
return 1 ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
PortP = p - > RIOPortp [ SysPort ] ;
2005-04-16 15:20:36 -07:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2006-03-24 03:18:28 -08:00
switch ( readb ( & PktCmdP - > Command ) ) {
2006-01-11 12:17:49 -08:00
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
2006-03-24 03:18:32 -08:00
and return 0 to ensure that the command packet is
2006-01-11 12:17:49 -08:00
not freed . */
/* Call tmgr HANGUP HERE */
/* Fix this later when every thing works !!!! RAMRAJ */
gs_got_break ( & PortP - > gs ) ;
break ;
case COMPLETE :
2006-03-24 03:18:28 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Command complete on phb %d host %Zd \n " , readb ( & PktCmdP - > PhbNum ) , HostP - p - > RIOHosts ) ;
2006-01-11 12:17:49 -08:00
subCommand = 1 ;
2006-03-24 03:18:28 -08:00
switch ( readb ( & PktCmdP - > SubCommand ) ) {
2006-01-11 12:17:49 -08:00
case MEMDUMP :
2006-03-24 03:18:28 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Memory dump cmd (0x%x) from addr 0x%x \n " , readb ( & PktCmdP - > SubCommand ) , readw ( & PktCmdP - > SubAddr ) ) ;
2005-04-16 15:20:36 -07:00
break ;
2006-01-11 12:17:49 -08:00
case READ_REGISTER :
2006-03-24 03:18:28 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Read register (0x%x) \n " , readw ( & PktCmdP - > SubAddr ) ) ;
p - > CdRegister = ( readb ( & PktCmdP - > ModemStatus ) & MSVR1_HOST ) ;
2006-01-11 12:17:49 -08:00
break ;
default :
subCommand = 0 ;
break ;
}
if ( subCommand )
break ;
2006-03-24 03:18:28 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " New status is 0x%x was 0x%x \n " , readb ( & PktCmdP - > PortStatus ) , PortP - > PortState ) ;
if ( PortP - > PortState ! = readb ( & PktCmdP - > PortStatus ) ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Mark status & wakeup \n " ) ;
2006-03-24 03:18:28 -08:00
PortP - > PortState = readb ( & PktCmdP - > PortStatus ) ;
2006-01-11 12:17:49 -08:00
/* What should we do here ...
wakeup ( & PortP - > PortState ) ;
*/
} else
rio_dprintk ( RIO_DEBUG_CMD , " No change \n " ) ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
/* 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 ! ) .
*/
2006-03-24 03:18:28 -08:00
ReportedModemStatus = readb ( & PktCmdP - > ModemStatus ) ;
2006-01-11 12:17:49 -08:00
if ( ( PortP - > ModemState & MSVR1_HOST ) = = ( ReportedModemStatus & MSVR1_HOST ) ) {
rio_dprintk ( RIO_DEBUG_CMD , " Modem status unchanged 0x%x \n " , PortP - > ModemState ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * 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 ;
2005-04-16 15:20:36 -07:00
# ifdef MODEM_SUPPORT
2006-01-11 12:17:49 -08:00
if ( PortP - > Mapped ) {
2005-04-16 15:20:36 -07:00
/***********************************************************\
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * *
* * * M O D E M S T A T E C H A N G E * * *
* * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
2006-01-11 12:17:49 -08:00
* * If the device is a modem , then check the modem
* * carrier .
*/
2005-04-16 15:20:36 -07:00
if ( PortP - > gs . tty = = NULL )
break ;
if ( PortP - > gs . tty - > termios = = NULL )
break ;
2006-01-11 12:17:49 -08:00
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 ?
*/
2005-04-16 15:20:36 -07:00
if ( ! ( PortP - > State & RIO_CARR_ON ) ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Carrier just came up. \n " ) ;
2005-04-16 15:20:36 -07:00
PortP - > State | = RIO_CARR_ON ;
2006-01-11 12:17:49 -08:00
/*
* * wakeup anyone in WOPEN
*/
if ( PortP - > State & ( PORT_ISOPEN | RIO_WOPEN ) )
wake_up_interruptible ( & PortP - > gs . open_wait ) ;
}
2005-04-16 15:20:36 -07:00
} else {
2006-01-11 12:17:49 -08:00
/*
* * Has carrier just dropped ?
*/
2005-04-16 15:20:36 -07:00
if ( PortP - > State & RIO_CARR_ON ) {
2006-01-11 12:17:49 -08:00
if ( PortP - > State & ( PORT_ISOPEN | RIO_WOPEN | RIO_MOPEN ) )
tty_hangup ( PortP - > gs . tty ) ;
2005-04-16 15:20:36 -07:00
PortP - > State & = ~ RIO_CARR_ON ;
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Carrirer just went down \n " ) ;
}
}
}
2005-04-16 15:20:36 -07:00
}
# endif
2006-01-11 12:17:49 -08:00
}
break ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
default :
2006-03-24 03:18:28 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Unknown command %d on CMD_RUP of host %Zd \n " , readb ( & PktCmdP - > Command ) , HostP - p - > RIOHosts ) ;
2006-01-11 12:17:49 -08:00
break ;
2005-04-16 15:20:36 -07:00
}
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2006-01-11 12:17:49 -08:00
func_exit ( ) ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:32 -08:00
return 1 ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
2005-04-16 15:20:36 -07:00
/*
* * 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 .
*/
2006-01-11 12:17:49 -08:00
struct CmdBlk * RIOGetCmdBlk ( void )
2005-04-16 15:20:36 -07:00
{
struct CmdBlk * CmdBlkP ;
2006-03-24 03:18:28 -08:00
CmdBlkP = ( struct CmdBlk * ) kmalloc ( sizeof ( struct CmdBlk ) , GFP_ATOMIC ) ;
2005-04-16 15:20:36 -07:00
if ( CmdBlkP )
2006-03-24 03:18:28 -08:00
memset ( CmdBlkP , 0 , sizeof ( struct CmdBlk ) ) ;
2005-04-16 15:20:36 -07:00
return CmdBlkP ;
}
/*
* * Return a block to the head of the free list .
*/
2006-01-11 12:17:49 -08:00
void RIOFreeCmdBlk ( struct CmdBlk * CmdBlkP )
2005-04-16 15:20:36 -07:00
{
2006-03-24 03:18:28 -08:00
kfree ( CmdBlkP ) ;
2005-04-16 15:20:36 -07:00
}
/*
* * attach a command block to the list of commands to be performed for
* * a given rup .
*/
2006-01-11 12:17:49 -08:00
int RIOQueueCmdBlk ( struct Host * HostP , uint Rup , struct CmdBlk * CmdBlkP )
2005-04-16 15:20:36 -07:00
{
struct CmdBlk * * Base ;
struct UnixRup * UnixRupP ;
unsigned long flags ;
2006-03-24 03:18:28 -08:00
if ( Rup > = ( unsigned short ) ( MAX_RUP + LINKS_PER_UNIT ) ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Illegal rup number %d in RIOQueueCmdBlk \n " , Rup ) ;
RIOFreeCmdBlk ( CmdBlkP ) ;
2005-04-16 15:20:36 -07:00
return RIO_FAIL ;
}
UnixRupP = & HostP - > UnixRups [ Rup ] ;
rio_spin_lock_irqsave ( & UnixRupP - > RupLock , flags ) ;
/*
2006-01-11 12:17:49 -08:00
* * If the RUP is currently inactive , then put the request
* * straight on the RUP . . . .
*/
2006-03-24 03:18:28 -08:00
if ( ( UnixRupP - > CmdsWaitingP = = NULL ) & & ( UnixRupP - > CmdPendingP = = NULL ) & & ( readw ( & UnixRupP - > RupP - > txcontrol ) = = TX_RUP_INACTIVE ) & & ( CmdBlkP - > PreFuncP ? ( * CmdBlkP - > PreFuncP ) ( CmdBlkP - > PreArg , CmdBlkP )
2006-03-24 03:18:32 -08:00
: 1 ) ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " RUP inactive-placing command straight on. Cmd byte is 0x%x \n " , CmdBlkP - > Packet . data [ 0 ] ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * Whammy ! blat that pack !
*/
2006-05-27 00:08:25 -04:00
HostP - > Copy ( & CmdBlkP - > Packet , RIO_PTR ( HostP - > Caddr , UnixRupP - > RupP - > txpkt ) , sizeof ( struct PKT ) ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * place command packet on the pending position .
*/
2005-04-16 15:20:36 -07:00
UnixRupP - > CmdPendingP = CmdBlkP ;
/*
2006-01-11 12:17:49 -08:00
* * set the command register
*/
2006-03-24 03:18:28 -08:00
writew ( TX_PACKET_READY , & UnixRupP - > RupP - > txcontrol ) ;
2005-04-16 15:20:36 -07:00
rio_spin_unlock_irqrestore ( & UnixRupP - > RupLock , flags ) ;
2006-03-24 03:18:32 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " RUP active - en-queing \n " ) ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
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 " ) ;
2006-03-24 03:18:28 -08:00
if ( readw ( & UnixRupP - > RupP - > txcontrol ) ! = TX_RUP_INACTIVE )
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Rup active - command rup not ready \n " ) ;
2005-04-16 15:20:36 -07:00
Base = & UnixRupP - > CmdsWaitingP ;
2006-03-24 03:18:32 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " First try to queue cmdblk %p at %p \n " , CmdBlkP , Base ) ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
while ( * Base ) {
2006-03-24 03:18:32 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Command cmdblk %p here \n " , * Base ) ;
2005-04-16 15:20:36 -07:00
Base = & ( ( * Base ) - > NextP ) ;
2006-03-24 03:18:32 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Now try to queue cmd cmdblk %p at %p \n " , CmdBlkP , Base ) ;
2005-04-16 15:20:36 -07:00
}
2006-03-24 03:18:32 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Will queue cmdblk %p at %p \n " , CmdBlkP , Base ) ;
2005-04-16 15:20:36 -07:00
* Base = CmdBlkP ;
CmdBlkP - > NextP = NULL ;
rio_spin_unlock_irqrestore ( & UnixRupP - > RupLock , flags ) ;
2006-03-24 03:18:32 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
/*
* * Here we go - if there is an empty rup , fill it !
* * must be called at splrio ( ) or higher .
*/
2006-01-11 12:17:49 -08:00
void RIOPollHostCommands ( struct rio_info * p , struct Host * HostP )
2005-04-16 15:20:36 -07:00
{
2006-03-24 03:18:28 -08:00
struct CmdBlk * CmdBlkP ;
struct UnixRup * UnixRupP ;
2006-05-27 00:08:25 -04:00
struct PKT __iomem * PacketP ;
2006-03-24 03:18:28 -08:00
unsigned short Rup ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
2006-01-11 12:17:49 -08:00
Rup = MAX_RUP + LINKS_PER_UNIT ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
do { /* do this loop for each RUP */
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * locate the rup we are processing & lock it
*/
2005-04-16 15:20:36 -07:00
UnixRupP = & HostP - > UnixRups [ - - Rup ] ;
spin_lock_irqsave ( & UnixRupP - > RupLock , flags ) ;
/*
2006-01-11 12:17:49 -08:00
* * First check for incoming commands :
*/
2006-03-24 03:18:28 -08:00
if ( readw ( & UnixRupP - > RupP - > rxcontrol ) ! = RX_RUP_INACTIVE ) {
2005-04-16 15:20:36 -07:00
int FreeMe ;
2006-05-27 00:08:25 -04:00
PacketP = ( struct PKT __iomem * ) RIO_PTR ( HostP - > Caddr , readw ( & UnixRupP - > RupP - > rxpkt ) ) ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:28 -08:00
switch ( readb ( & PacketP - > dest_port ) ) {
2006-01-11 12:17:49 -08:00
case BOOT_RUP :
2006-03-24 03:18:28 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Incoming Boot %s packet '%x' \n " , readb ( & PacketP - > len ) & 0x80 ? " Command " : " Data " , readb ( & PacketP - > data [ 0 ] ) ) ;
2006-01-11 12:17:49 -08:00
rio_spin_unlock_irqrestore ( & UnixRupP - > RupLock , flags ) ;
FreeMe = RIOBootRup ( p , Rup , HostP , PacketP ) ;
rio_spin_lock_irqsave ( & UnixRupP - > RupLock , flags ) ;
break ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
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 ) {
2006-03-24 03:18:28 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Memdump from 0x%x complete \n " , * ( unsigned short * ) & ( PacketP - > data [ 6 ] ) ) ;
2006-05-27 01:55:52 -04:00
rio_memcpy_fromio ( p - > RIOMemDump , & ( PacketP - > data [ 8 ] ) , 32 ) ;
2006-01-11 12:17:49 -08:00
}
rio_spin_lock_irqsave ( & UnixRupP - > RupLock , flags ) ;
break ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
case ROUTE_RUP :
rio_spin_unlock_irqrestore ( & UnixRupP - > RupLock , flags ) ;
FreeMe = RIORouteRup ( p , Rup , HostP , PacketP ) ;
rio_spin_lock_irqsave ( & UnixRupP - > RupLock , flags ) ;
break ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
default :
2006-03-24 03:18:28 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Unknown RUP %d \n " , readb ( & PacketP - > dest_port ) ) ;
2006-01-11 12:17:49 -08:00
FreeMe = 1 ;
break ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( FreeMe ) {
rio_dprintk ( RIO_DEBUG_CMD , " Free processed incoming command packet \n " ) ;
put_free_end ( HostP , PacketP ) ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:28 -08:00
writew ( RX_RUP_INACTIVE , & UnixRupP - > RupP - > rxcontrol ) ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:28 -08:00
if ( readw ( & UnixRupP - > RupP - > handshake ) = = PHB_HANDSHAKE_SET ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Handshake rup %d \n " , Rup ) ;
2006-03-24 03:18:28 -08:00
writew ( PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET , & UnixRupP - > RupP - > handshake ) ;
2005-04-16 15:20:36 -07:00
}
}
}
/*
2006-01-11 12:17:49 -08:00
* * IF a command was running on the port ,
* * and it has completed , then tidy it up .
*/
if ( ( CmdBlkP = UnixRupP - > CmdPendingP ) & & /* ASSIGN! */
2006-03-24 03:18:28 -08:00
( readw ( & UnixRupP - > RupP - > txcontrol ) = = TX_RUP_INACTIVE ) ) {
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * 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 ] ) ;
2006-03-24 03:18:32 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Command %p completed \n " , CmdBlkP ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * Clear the Rup lock to prevent mutual exclusion .
*/
if ( CmdBlkP - > PostFuncP ) {
2005-04-16 15:20:36 -07:00
rio_spin_unlock_irqrestore ( & UnixRupP - > RupLock , flags ) ;
2006-01-11 12:17:49 -08:00
( * CmdBlkP - > PostFuncP ) ( CmdBlkP - > PostArg , CmdBlkP ) ;
2005-04-16 15:20:36 -07:00
rio_spin_lock_irqsave ( & UnixRupP - > RupLock , flags ) ;
}
/*
2006-01-11 12:17:49 -08:00
* * . . . . clear the pending flag . . . .
*/
2005-04-16 15:20:36 -07:00
UnixRupP - > CmdPendingP = NULL ;
/*
2006-01-11 12:17:49 -08:00
* * . . . . and return the command block to the freelist .
*/
RIOFreeCmdBlk ( CmdBlkP ) ;
2005-04-16 15:20:36 -07:00
}
/*
2006-01-11 12:17:49 -08:00
* * If there is a command for this rup , and the rup
* * is idle , then process the command
*/
if ( ( CmdBlkP = UnixRupP - > CmdsWaitingP ) & & /* ASSIGN! */
2006-03-24 03:18:28 -08:00
( UnixRupP - > CmdPendingP = = NULL ) & & ( readw ( & UnixRupP - > RupP - > txcontrol ) = = TX_RUP_INACTIVE ) ) {
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * if the pre - function is non - zero , call it .
* * If it returns RIO_FAIL then don ' t
* * send this command yet !
*/
2006-03-24 03:18:32 -08:00
if ( ! ( CmdBlkP - > PreFuncP ? ( * CmdBlkP - > PreFuncP ) ( CmdBlkP - > PreArg , CmdBlkP ) : 1 ) ) {
rio_dprintk ( RIO_DEBUG_CMD , " Not ready to start command %p \n " , CmdBlkP ) ;
2006-01-11 12:17:49 -08:00
} else {
2006-03-24 03:18:32 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Start new command %p Cmd byte is 0x%x \n " , CmdBlkP , CmdBlkP - > Packet . data [ 0 ] ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * Whammy ! blat that pack !
*/
2006-05-27 00:08:25 -04:00
HostP - > Copy ( & CmdBlkP - > Packet , RIO_PTR ( HostP - > Caddr , UnixRupP - > RupP - > txpkt ) , sizeof ( struct PKT ) ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * remove the command from the rup command queue . . .
*/
2005-04-16 15:20:36 -07:00
UnixRupP - > CmdsWaitingP = CmdBlkP - > NextP ;
/*
2006-01-11 12:17:49 -08:00
* * . . . and place it on the pending position .
*/
2005-04-16 15:20:36 -07:00
UnixRupP - > CmdPendingP = CmdBlkP ;
/*
2006-01-11 12:17:49 -08:00
* * set the command register
*/
2006-03-24 03:18:28 -08:00
writew ( TX_PACKET_READY , & UnixRupP - > RupP - > txcontrol ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * the command block will be freed
* * when the command has been processed .
*/
2005-04-16 15:20:36 -07:00
}
}
spin_unlock_irqrestore ( & UnixRupP - > RupLock , flags ) ;
2006-01-11 12:17:49 -08:00
} while ( Rup ) ;
2005-04-16 15:20:36 -07:00
}
2006-03-24 03:18:28 -08:00
int RIOWFlushMark ( unsigned long iPortP , struct CmdBlk * CmdBlkP )
2005-04-16 15:20:36 -07:00
{
2006-01-11 12:17:49 -08:00
struct Port * PortP = ( struct Port * ) iPortP ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
PortP - > WflushFlag + + ;
PortP - > MagicFlags | = MAGIC_FLUSH ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2006-01-11 12:17:49 -08:00
return RIOUnUse ( iPortP , CmdBlkP ) ;
2005-04-16 15:20:36 -07:00
}
2006-03-24 03:18:28 -08:00
int RIORFlushEnable ( unsigned long iPortP , struct CmdBlk * CmdBlkP )
2005-04-16 15:20:36 -07:00
{
2006-01-11 12:17:49 -08:00
struct Port * PortP = ( struct Port * ) iPortP ;
2006-05-27 00:08:25 -04:00
struct PKT __iomem * PacketP ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2006-01-11 12:17:49 -08:00
while ( can_remove_receive ( & PacketP , PortP ) ) {
2005-04-16 15:20:36 -07:00
remove_receive ( PortP ) ;
2006-01-11 12:17:49 -08:00
put_free_end ( PortP - > HostP , PacketP ) ;
2005-04-16 15:20:36 -07:00
}
2006-03-24 03:18:28 -08:00
if ( readw ( & PortP - > PhbP - > handshake ) = = PHB_HANDSHAKE_SET ) {
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * 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 " ) ;
2006-03-24 03:18:28 -08:00
writew ( PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET , & PortP - > PhbP - > handshake ) ;
2005-04-16 15:20:36 -07:00
}
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2006-01-11 12:17:49 -08:00
return RIOUnUse ( iPortP , CmdBlkP ) ;
2005-04-16 15:20:36 -07:00
}
2006-03-24 03:18:28 -08:00
int RIOUnUse ( unsigned long iPortP , struct CmdBlk * CmdBlkP )
2005-04-16 15:20:36 -07:00
{
2006-01-11 12:17:49 -08:00
struct Port * PortP = ( struct Port * ) iPortP ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_CMD , " Decrement in use count for port \n " ) ;
2005-04-16 15:20:36 -07:00
if ( PortP - > InUse ) {
2006-01-11 12:17:49 -08:00
if ( - - PortP - > InUse ! = NOT_INUSE ) {
2005-04-16 15:20:36 -07:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
return 0 ;
}
}
/*
2006-01-11 12:17:49 -08:00
* * 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 500 ms 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 500 ms 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 .
*/
2006-03-24 03:18:28 -08:00
writew ( 1 , & PortP - > HostP - > ParmMapP - > tx_intr ) ;
2005-04-16 15:20:36 -07:00
/* What to do here ..
2006-01-11 12:17:49 -08:00
wakeup ( ( caddr_t ) & ( PortP - > InUse ) ) ;
*/
2005-04-16 15:20:36 -07:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
return 0 ;
}
/*
* *
* * 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 ( ) .
* *
*/