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

📄 riocmd.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
				***													   ***				***		  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.*/voidRIOFreeCmdBlk(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.*/intRIOQueueCmdBlk(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.*/voidRIOPollHostCommands(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 );}intRIOWFlushMark(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 );}intRIORFlushEnable(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 );}intRIOUnUse(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;}voidShowPacket(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().** */

⌨️ 快捷键说明

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