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

📄 riocmd.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
		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(p, HostP)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(iPortP, CmdBlkP)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(iPortP, CmdBlkP)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(iPortP, CmdBlkP)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(Flags, PacketP)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 + -