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

📄 riointr.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	  ** 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.*/static 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.  */  intCount++;  TtyP = PortP->gs.tty;  if (!TtyP) {    rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");    return;  }  if (PortP->State & RIO_THROTTLE_RX) {    rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");    return;  }  if ( PortP->State & RIO_DELETED )    {      while ( can_remove_receive( &PacketP, PortP ) )	{	  remove_receive( PortP );	  put_free_end( PortP->HostP, PacketP );	}    }  else    {      /*      ** loop, just so long as:      **   i ) there's some data ( i.e. can_remove_receive )      **  ii ) we haven't been blocked      ** iii ) there's somewhere to put the data      **  iv ) we haven't outstayed our welcome      */      transCount = 1;      while ( can_remove_receive(&PacketP, PortP)	      && transCount)	{#ifdef STATS	  PortP->Stat.RxIntCnt++;#endif /* STATS */	  RxIntCnt++;	  /*	  ** check that it is not a command!	  */	  if ( PacketP->len & PKT_CMD_BIT ) {	    rio_dprintk (RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");	    /*	    rio_dprint(RIO_DEBUG_INTR, (" sysport   = %d\n", p->RIOPortp->PortNum)); */	    rio_dprintk (RIO_DEBUG_INTR, " dest_unit = %d\n", PacketP->dest_unit);	    rio_dprintk (RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port);	    rio_dprintk (RIO_DEBUG_INTR, " src_unit  = %d\n", PacketP->src_unit);	    rio_dprintk (RIO_DEBUG_INTR, " src_port  = %d\n", PacketP->src_port);	    rio_dprintk (RIO_DEBUG_INTR, " len	   = %d\n", PacketP->len);	    rio_dprintk (RIO_DEBUG_INTR, " control   = %d\n", PacketP->control);	    rio_dprintk (RIO_DEBUG_INTR, " csum	   = %d\n", PacketP->csum);	    rio_dprintk (RIO_DEBUG_INTR, "	 data bytes: ");	    for ( DataCnt=0; DataCnt<PKT_MAX_DATA_LEN; DataCnt++ )	      rio_dprintk (RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]);	    remove_receive( PortP );	    put_free_end( PortP->HostP, PacketP );	    continue; /* with next packet */	  }	  /*	  ** How many characters can we move 'upstream' ?	  **	  ** Determine the minimum of the amount of data	  ** available and the amount of space in which to	  ** put it.	  **	  ** 1.	Get the packet length by masking 'len'	  **	for only the length bits.	  ** 2.	Available space is [buffer size] - [space used]	  **	  ** Transfer count is the minimum of packet length	  ** and available space.	  */				  transCount = min_t(unsigned int, PacketP->len & PKT_LEN_MASK,			   TTY_FLIPBUF_SIZE - TtyP->flip.count);	  rio_dprintk (RIO_DEBUG_REC,  "port %d: Copy %d bytes\n", 				      PortP->PortNum, transCount);	  /*	  ** To use the following 'kkprintfs' for debugging - change the '#undef'	  ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the	  ** driver).	  */#undef ___DEBUG_IT___#ifdef ___DEBUG_IT___	  kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ",		   intCount,		   RxIntCnt,		   PortP->PortNum,		   TtyP->rxqueue.count,		   transCount,		   TtyP->flags );#endif	  ptr = (uchar *) PacketP->data + PortP->RxDataStart;	  rio_memcpy_fromio (TtyP->flip.char_buf_ptr, ptr, transCount);	  memset(TtyP->flip.flag_buf_ptr, TTY_NORMAL, transCount);#ifdef STATS	  /*	  ** keep a count for statistical purposes	  */	  PortP->Stat.RxCharCnt	+= transCount;#endif	  PortP->RxDataStart	+= transCount;	  PacketP->len		-= transCount;	  copied += transCount;	  TtyP->flip.count += transCount;	  TtyP->flip.char_buf_ptr += transCount;	  TtyP->flip.flag_buf_ptr += transCount;#ifdef ___DEBUG_IT___	  kkprintf("T:%d L:%d\n", DataCnt, PacketP->len );#endif	  if ( PacketP->len == 0 )	    {				/*				** If we have emptied the packet, then we can				** free it, and reset the start pointer for				** the next packet.				*/	      remove_receive( PortP );	      put_free_end( PortP->HostP, PacketP );	      PortP->RxDataStart = 0;#ifdef STATS				/*				** more lies ( oops, I mean statistics )				*/	      PortP->Stat.RxPktCnt++;#endif /* STATS */	    }	}    }  if (copied) {    rio_dprintk (RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);    tty_flip_buffer_push (TtyP);  }  return;}#ifdef FUTURE_RELEASE/*** The proc routine called by the line discipline to do the work for it.** The proc routine works hand in hand with the interrupt routine.*/intriotproc(p, tp, cmd, port)struct rio_info *	p;register struct ttystatics *tp;int cmd;int	port;{	register struct Port *PortP;	int SysPort;	struct PKT *PacketP;	SysPort = port;	/* Believe me, it works. */	if ( SysPort < 0 || SysPort >= RIO_PORTS ) {		rio_dprintk (RIO_DEBUG_INTR, "Illegal port %d derived from TTY in riotproc()\n",SysPort);		return 0;	}	PortP = p->RIOPortp[SysPort];	if ((uint)PortP->PhbP < (uint)PortP->Caddr || 			(uint)PortP->PhbP >= (uint)PortP->Caddr+SIXTY_FOUR_K ) {		rio_dprintk (RIO_DEBUG_INTR, "RIO: NULL or BAD PhbP on sys port %d in proc routine\n",							SysPort);		rio_dprintk (RIO_DEBUG_INTR, "	 PortP = 0x%x\n",PortP);		rio_dprintk (RIO_DEBUG_INTR, "	 PortP->PhbP = 0x%x\n",PortP->PhbP);		rio_dprintk (RIO_DEBUG_INTR, "	 PortP->Caddr = 0x%x\n",PortP->PhbP);		rio_dprintk (RIO_DEBUG_INTR, "	 PortP->HostPort = 0x%x\n",PortP->HostPort);		return 0;	}	switch(cmd) {		case T_WFLUSH:			rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH\n");			/*			** Because of the spooky way the RIO works, we don't need			** to issue a flush command on any of the SET*F commands,			** as that causes trouble with getty and login, which issue			** these commands to incur a READ flush, and rely on the fact			** that the line discipline does a wait for drain for them.			** As the rio doesn't wait for drain, the write flush would			** destroy the Password: prompt. This isn't very friendly, so			** here we only issue a WFLUSH command if we are in the interrupt			** routine, or we aren't executing a SET*F command.			*/			if ( PortP->HostP->InIntr || !PortP->FlushCmdBodge ) {				/*				** form a wflush packet - 1 byte long, no data				*/				if ( PortP->State & RIO_DELETED ) {					rio_dprintk (RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n");				}				else {					if ( RIOPreemptiveCmd(p, PortP, WFLUSH ) == RIO_FAIL ) {						rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command failed\n");					}					else						rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command\n");				}				/*				** WFLUSH operation - flush the data!				*/				PortP->TxBufferIn = PortP->TxBufferOut = 0;			}			else {				rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n");			}			/*			** sort out the line discipline			*/			if (PortP->CookMode == COOK_WELL)				goto start;			break;			case T_RESUME:			rio_dprintk (RIO_DEBUG_INTR, "T_RESUME\n");			/*			** send pre-emptive resume packet			*/			if ( PortP->State & RIO_DELETED ) {				rio_dprintk (RIO_DEBUG_INTR, "RESUME on deleted RTA\n");			}			else {				if ( RIOPreemptiveCmd(p, PortP, RESUME ) == RIO_FAIL ) {					rio_dprintk (RIO_DEBUG_INTR, "T_RESUME Command failed\n");				}			}			/*			** and re-start the sender software!			*/			if (PortP->CookMode == COOK_WELL)				goto start;			break;			case T_TIME:			rio_dprintk (RIO_DEBUG_INTR, "T_TIME\n");			/*			** T_TIME is called when xDLY is set in oflags and			** the line discipline timeout has expired. It's			** function in life is to clear the TIMEOUT flag			** and to re-start output to the port.			*/			/*			** Fall through and re-start output			*/		case T_OUTPUT:start:			if ( PortP->MagicFlags & MAGIC_FLUSH ) {				PortP->MagicFlags |= MORE_OUTPUT_EYGOR;				return 0;			}			RIOTxEnable((char *)PortP);			PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;			/*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n");*/			break;			case T_SUSPEND:			rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND\n");			/*			** send a suspend pre-emptive packet.			*/			if ( PortP->State & RIO_DELETED ) {				rio_dprintk (RIO_DEBUG_INTR, "SUSPEND deleted RTA\n");			}			else {				if ( RIOPreemptiveCmd(p, PortP, SUSPEND ) == RIO_FAIL ) {					rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND Command failed\n");				}			}			/*			** done!			*/			break;			case T_BLOCK:			rio_dprintk (RIO_DEBUG_INTR, "T_BLOCK\n");			break;			case T_RFLUSH:			rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH\n");			if ( PortP->State & RIO_DELETED ) {				rio_dprintk (RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n");				PortP->RxDataStart = 0;			}			else {				if ( RIOPreemptiveCmd( p, PortP, RFLUSH ) == RIO_FAIL ) {					rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH Command failed\n");					return 0;				}				PortP->RxDataStart = 0;				while ( can_remove_receive(&PacketP, PortP) ) {					remove_receive(PortP);					ShowPacket(DBG_PROC, PacketP );					put_free_end(PortP->HostP, PacketP );				}				if ( PortP->PhbP->handshake == PHB_HANDSHAKE_SET ) {					/*					** MAGIC!					*/					rio_dprintk (RIO_DEBUG_INTR, "Set receive handshake bit\n");					PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET;				}			}			break;			/* FALLTHROUGH */		case T_UNBLOCK:			rio_dprintk (RIO_DEBUG_INTR, "T_UNBLOCK\n");			/*			** If there is any data to receive set a timeout to service it.			*/			RIOReceive(p, PortP);			break;			case T_BREAK:			rio_dprintk (RIO_DEBUG_INTR, "T_BREAK\n");			/*			** Send a break command. For Sys V			** this is a timed break, so we			** send a SBREAK[time] packet			*/			/*			** Build a BREAK command			*/			if ( PortP->State & RIO_DELETED ) {				rio_dprintk (RIO_DEBUG_INTR, "BREAK on deleted RTA\n");			}			else {				if (RIOShortCommand(PortP,SBREAK,2,								p->RIOConf.BreakInterval)==RIO_FAIL) {			   		rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");				}			}				/*			** done!			*/			break;			case T_INPUT:			rio_dprintk (RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n");			break;		case T_PARM:			rio_dprintk (RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n");			break;			case T_SWTCH:			rio_dprintk (RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n");			break;			default:			rio_dprintk (RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n",cmd);	}	/*	** T_OUTPUT returns without passing through this point!	*/	/*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n");*/	return(0);}#endif

⌨️ 快捷键说明

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