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

📄 riointr.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
    WWORD( HostP->ParmMapP->rup_intr , 0 );    p->RIORupCount++;    RupIntr++;    rio_dprintk (RIO_DEBUG_INTR, "rio: RUP interrupt on host %d\n", HostP-p->RIOHosts);    RIOPollHostCommands(p, HostP );  }  if ( RWORD( HostP->ParmMapP->rx_intr ) ) {    int port;    WWORD( HostP->ParmMapP->rx_intr , 0 );    p->RIORxCount++;    RxIntr++;    rio_dprintk (RIO_DEBUG_INTR, "rio: RX interrupt on host %d\n", HostP-p->RIOHosts);    /*    ** Loop through every port. If the port is mapped into    ** the system ( i.e. has /dev/ttyXXXX associated ) then it is    ** worth checking. If the port isn't open, grab any packets    ** hanging on its receive queue and stuff them on the free    ** list; check for commands on the way.    */    for ( port=p->RIOFirstPortsBooted; 	  port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {      struct Port *PortP = p->RIOPortp[port];      struct tty_struct *ttyP;      struct PKT *PacketP;		      /*      ** not mapped in - most of the RIOPortp[] information      ** has not been set up!      ** Optimise: ports come in bundles of eight.      */      if ( !PortP->Mapped ) {	port += 7;	continue; /* with the next port */      }      /*      ** If the host board isn't THIS host board, check the next one.      ** optimise: ports come in bundles of eight.      */      if ( PortP->HostP != HostP ) {	port += 7;	continue;      }      /*      ** Let us see - is the port open? If not, then don't service it.      */      if ( !( PortP->PortState & PORT_ISOPEN ) ) {	continue;      }      /*      ** find corresponding tty structure. The process of mapping      ** the ports puts these here.      */      ttyP = PortP->gs.tty;      /*      ** Lock the port before we begin working on it.      */      rio_spin_lock(&PortP->portSem);      /*      ** Process received data if there is any.      */      if ( can_remove_receive( &PacketP, PortP ) )	RIOReceive(p, PortP);      /*      ** If there is no data left to be read from the port, and      ** it's handshake bit is set, then we must clear the handshake,      ** so that that downstream RTA is re-enabled.      */      if ( !can_remove_receive( &PacketP, PortP ) && 	   ( 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_INTR, "Set RX handshake bit\n");	WWORD( PortP->PhbP->handshake, 	       PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET );      }      rio_spin_unlock(&PortP->portSem);    }  }  if ( RWORD( HostP->ParmMapP->tx_intr ) ) {    int port;    WWORD( HostP->ParmMapP->tx_intr , 0);    p->RIOTxCount++;    TxIntr++;    rio_dprintk (RIO_DEBUG_INTR, "rio: TX interrupt on host %d\n", HostP-p->RIOHosts);    /*    ** Loop through every port.    ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX    ** associated ) then it is worth checking.    */    for ( port=p->RIOFirstPortsBooted; 	  port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {      struct Port *PortP = p->RIOPortp[port];      struct tty_struct *ttyP;      struct PKT *PacketP;      /*      ** not mapped in - most of the RIOPortp[] information      ** has not been set up!      */      if ( !PortP->Mapped ) {	port += 7;	continue; /* with the next port */      }      /*      ** If the host board isn't running, then its data structures      ** are no use to us - continue quietly.      */      if ( PortP->HostP != HostP ) {	port += 7;	continue; /* with the next port */      }      /*      ** Let us see - is the port open? If not, then don't service it.      */      if ( !( PortP->PortState & PORT_ISOPEN ) ) {	continue;      }      rio_dprintk (RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);      /*      ** Lock the port before we begin working on it.      */      rio_spin_lock(&PortP->portSem);      /*      ** If we can't add anything to the transmit queue, then      ** we need do none of this processing.      */      if ( !can_add_transmit( &PacketP, PortP ) ) {	rio_dprintk (RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");	rio_spin_unlock(&PortP->portSem);	continue;      }      /*      ** find corresponding tty structure. The process of mapping      ** the ports puts these here.      */      ttyP = PortP->gs.tty;      /* If ttyP is NULL, the port is getting closed. Forget about it. */      if (!ttyP) {	rio_dprintk (RIO_DEBUG_INTR, "no tty, so skipping.\n");	rio_spin_unlock(&PortP->portSem);	continue;      }      /*      ** If there is more room available we start up the transmit      ** data process again. This can be direct I/O, if the cookmode      ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the      ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch      ** characters via the line discipline. We must always call      ** the line discipline,      ** so that user input characters can be echoed correctly.      **      ** ++++ Update +++++      ** With the advent of double buffering, we now see if      ** TxBufferOut-In is non-zero. If so, then we copy a packet      ** to the output place, and set it going. If this empties      ** the buffer, then we must issue a wakeup( ) on OUT.      ** If it frees space in the buffer then we must issue      ** a wakeup( ) on IN.      **      ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we      ** have to send a WFLUSH command down the PHB, to mark the      ** end point of a WFLUSH. We also need to clear out any      ** data from the double buffer! ( note that WflushFlag is a      ** *count* of the number of WFLUSH commands outstanding! )      **      ** ++++ And there's more!      ** If an RTA is powered off, then on again, and rebooted,      ** whilst it has ports open, then we need to re-open the ports.      ** ( reasonable enough ). We can't do this when we spot the      ** re-boot, in interrupt time, because the queue is probably      ** full. So, when we come in here, we need to test if any      ** ports are in this condition, and re-open the port before      ** we try to send any more data to it. Now, the re-booted      ** RTA will be discarding packets from the PHB until it      ** receives this open packet, but don't worry tooo much      ** about that. The one thing that is interesting is the      ** combination of this effect and the WFLUSH effect!      */      /* For now don't handle RTA reboots. -- REW. 	 Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */      if ( PortP->MagicFlags ) {#if 1	if ( PortP->MagicFlags & MAGIC_REBOOT ) {	  /*	  ** well, the RTA has been rebooted, and there is room	  ** on its queue to add the open packet that is required.	  **	  ** The messy part of this line is trying to decide if	  ** we need to call the Param function as a tty or as	  ** a modem.	  ** DONT USE CLOCAL AS A TEST FOR THIS!	  **	  ** If we can't param the port, then move on to the	  ** next port.	  */	  PortP->InUse = NOT_INUSE;	  rio_spin_unlock(&PortP->portSem);	  if ( RIOParam(PortP, OPEN, ((PortP->Cor2Copy & 				       (COR2_RTSFLOW|COR2_CTSFLOW ) )== 				      (COR2_RTSFLOW|COR2_CTSFLOW ) ) ? 			TRUE : FALSE, DONT_SLEEP ) == RIO_FAIL ) {	    continue; /* with next port */	  }	  rio_spin_lock(&PortP->portSem);	  PortP->MagicFlags &= ~MAGIC_REBOOT;	}#endif	/*	** As mentioned above, this is a tacky hack to cope	** with WFLUSH	*/	if ( PortP->WflushFlag ) {	  rio_dprintk (RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");	  if ( PortP->InUse )	    rio_dprintk (RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");	}					while ( PortP->WflushFlag &&		can_add_transmit( &PacketP, PortP ) && 		( PortP->InUse == NOT_INUSE ) ) {	  int p;	  struct PktCmd *PktCmdP;	  rio_dprintk (RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");	  /*	  ** make it look just like a WFLUSH command	  */	  PktCmdP = ( struct PktCmd * )&PacketP->data[0];	  WBYTE( PktCmdP->Command , WFLUSH );	  p =  PortP->HostPort % ( ushort )PORTS_PER_RTA;	  /*	  ** If second block of ports for 16 port RTA, add 8	  ** to index 8-15.	  */	  if ( PortP->SecondBlock )	    p += PORTS_PER_RTA;	  WBYTE( PktCmdP->PhbNum, p );	  /*	  ** to make debuggery easier	  */	  WBYTE( PacketP->data[ 2], 'W'  );	  WBYTE( PacketP->data[ 3], 'F'  );	  WBYTE( PacketP->data[ 4], 'L'  );	  WBYTE( PacketP->data[ 5], 'U'  );	  WBYTE( PacketP->data[ 6], 'S'  );	  WBYTE( PacketP->data[ 7], 'H'  );	  WBYTE( PacketP->data[ 8], ' '  );	  WBYTE( PacketP->data[ 9], '0'+PortP->WflushFlag );	  WBYTE( PacketP->data[10], ' '  );	  WBYTE( PacketP->data[11], ' '  );	  WBYTE( PacketP->data[12], '\0' );	  /*	  ** its two bytes long!	  */	  WBYTE( PacketP->len , PKT_CMD_BIT | 2 );	  /*	  ** queue it!	  */	  if ( !( PortP->State & RIO_DELETED ) ) {	    add_transmit( PortP );	    /*	    ** Count chars tx'd for port statistics reporting	    */	    if ( PortP->statsGather )	      PortP->txchars += 2;	  }	  if ( --( PortP->WflushFlag ) == 0 ) {	    PortP->MagicFlags &= ~MAGIC_FLUSH;	  }	  rio_dprintk (RIO_DEBUG_INTR, "Wflush count now stands at %d\n", 		 PortP->WflushFlag);	}	if ( PortP->MagicFlags & MORE_OUTPUT_EYGOR ) {	  if ( PortP->MagicFlags & MAGIC_FLUSH ) {	    PortP->MagicFlags |= MORE_OUTPUT_EYGOR;	  }	  else {	    if ( !can_add_transmit( &PacketP, PortP ) ) {	      rio_spin_unlock(&PortP->portSem);	      continue;	    }	    rio_spin_unlock(&PortP->portSem);	    RIOTxEnable((char *)PortP);	    rio_spin_lock(&PortP->portSem);	    PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;	  }	}      }      /*      ** If we can't add anything to the transmit queue, then      ** we need do none of the remaining processing.      */      if (!can_add_transmit( &PacketP, PortP ) ) {	rio_spin_unlock(&PortP->portSem);	continue;      }      rio_spin_unlock(&PortP->portSem);      RIOTxEnable((char *)PortP);    }  }}/*** Routine for handling received data for clist drivers.** NB: Called with the tty locked. The spl from the lockb( ) is passed.** we return the ttySpl level that we re-locked at.*/voidRIOReceive(p, PortP)struct rio_info *	p;struct Port *		PortP;{  struct tty_struct *TtyP;  register ushort transCount;  struct PKT *PacketP;  register uint	DataCnt;  uchar *	ptr;  int copied =0;  static int intCount, RxIntCnt;  /*  ** The receive data process is to remove packets from the  ** PHB until there aren't any more or the current cblock  ** is full. When this occurs, there will be some left over  ** data in the packet, that we must do something with.  ** As we haven't unhooked the packet from the read list  ** yet, we can just leave the packet there, having first  ** made a note of how far we got. This means that we need  ** a pointer per port saying where we start taking the  ** data from - this will normally be zero, but when we  ** run out of space it will be set to the offset of the  ** next byte to copy from the packet data area. The packet  ** length field is decremented by the number of bytes that  ** we succesfully removed from the packet. When this reaches  ** zero, we reset the offset pointer to be zero, and free  ** the packet from the front of the queue.

⌨️ 快捷键说明

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