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

📄 uqserv.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	pib->lport_name = pccb->lpinfo.name; /* Local port name	*/	pib->type.hwtype = HPT_UQSSP;	/* Local port type		*/	pib->type.dual_path = 0;	/* Single path port		*/	Scaaddr_low( pib->rport_addr ) = *(u_short *)&Pccb.uq_ctlr; /* Remote port address */	Scaaddr_mid( pib->rport_addr ) = 0;	Scaaddr_hi( pib->rport_addr ) = 0;/*	If we can't get a pb then it's no go				*/	s = Splscs();	/* Set IPL to SCS level	*/	if((pb = scs_alloc_pb( PS_OPEN, pccb, pib )) == (PB *)NULL) {		(void)splx(s);		/* Reset IPL			*/		return(0);	}	(void)splx(s);		/* Reset IPL			*/	sib->max_msg = sizeof(MSCP_MAXBUF); /* 	Max message size	*/	sib->npaths = 1;		/* Only 1 path to these devices	*/	bcopy("UQ  ",&sib->swtype,4);	/* Software type is UQ port	*/	bcopy("3.00",&sib->swver,4);	/* Software version		*/	(void)scs_unix_to_vms((struct timeval *)&boottime, &sib->swincrn);	bcopy(uq_cinfo[Lpinfo.uq_type].name,&sib->hwtype,4); /* Controller type in ASCII*/	sib->hwver.val[0] = (long)(Pccb.step4r & 0xF); /* Microcode version number	*/	sib->hwver.val[1] = (long)Pccb.uq_ctlr; /* Controller number	*/	sib->hwver.val[2] = (long)Lpinfo.uq_type; /* Controller model code */	*(u_long *)sib->node_name = pccb->lpinfo.name; /* SCA Node name	*/	bcopy("    ",(u_long *)sib->node_name+1,4);/*	The system id of uq controllers is as follows:			*//*									*//*      47             32 31                                 0          *//*	+----------------+------------------------------------+		*//*	!		 !				      !		*//*	! UQSSP model #  !   Device Address (CSR)	      !		*//*	!		 !				      !		*//*	+----------------+------------------------------------+		*//*									*/	{	register u_long	addr_tmp = *(u_long *)&Pccb.Uqip;	Scaaddr_low( sib->sysid ) = ( addr_tmp & 0xffff );	Scaaddr_mid( sib->sysid ) = ( u_short )(( addr_tmp >> 16 ) & 0xffff );	Scaaddr_hi( sib->sysid ) = *(u_short *)&Lpinfo.uq_type;	}/*	If we can't get a sb then it's no go				*/	s = Splscs();	/* Set IPL to SCS level	*/	if((sb = scs_alloc_sb( sib )) == (SB *)NULL) {		(void)scs_dealloc_pb( pccb,pb ); /* Deallocate PB	*/		(void)splx(s);		/* Reset IPL			*/		return(0);	}	(void)splx(s);		/* Reset IPL			*/	for (i=0; i<NCON; i++)		Lpinfo.uq_credits[i] = 1; /* Give initial credit of 1	*/	s = Splscs();	/* Set IPL to SCS level	*/	Lock_pccb (pccb);	Pccb.pb = pb;			/* Save on pccb			*/	pb->sb = sb;			/* Point to System Block	*/	Insert_entry(pb->flink,Sb->pbs); /* Insert PB on SB queue	*/	Unlock_pccb (pccb);	Lock_scadb ();	Insert_entry(sb->flink,scs_config_db); /* Insert SB on system-wide */					       /* configuration database   */	Unlock_scadb ();	scs_new_path( sb, pb );	(void)splx(s);		/* Reset IPL			*/	return(RET_SUCCESS);}/* * * *	Name:		uq_init_buffers *	 *	Abstract:	Map the communications area and packet buffers. *			Initialize the ring pointers and place the *			packet buffers on the response ring or free queue. *			 *	Inputs: * *	pccb			- Pointer to PCCB for this port *	     pd.uq.uq_mapped	- Set to 1 if the communications area has *				  been mapped. * *	ctlr			- Controller number *	 *	 * *	Outputs: * *	pccb *	     pd.uq.uqptr	- Unibus address of communcations/packet area *	     pd.uq.uq_ubainfo	- Mapping information for communications area *	     pd.uq.uq_mapped	- Set to 1 if the comm area is mapped *	     pd.uq.rsp_cnt	- Number of used response ring entries *	     pd.uq.cmd_cnt	- Number of used command ring entries *	     pd.uq.rsprindx	- Index of next empty response ring entry  *	     pd.uq.cmdrindx	- Index of next empty command ring entry *	     pd.uq.uq_lastrsp	- Index of next response ring entry to poll *	     pd.uq.uq_lastcmd	- Index of next command ring entry to poll *	     pd.uq.uq_freel	- List of free packet buffers *	 *	 * *	Return  *	Values: * *	 *	 *  *	Side		 *	Effects: * */uq_init_buffers(pccb)PCCB *pccb;{	register UQ *uq;	register UQ *uuq;	int i;	cpu_printf (Pccb.init_leader, Pccb.reset_leader, "uq_init_buffers");	uq = Pccb.uq;	if (Pccb.uq_mapped == 0) {	/* Need to map communication area */				/* and command/response packet buffers */		if ((Lpinfo.uq_type == BDA_TYPE) || 		    (Lpinfo.uq_type == KDM_TYPE)) {			Pccb.uqptr = (UQ *) (Pccb.uq_ubainfo = svtophy(uq));		}		else {		     if(Pccb.step1r & UQ_QB) 				   /* it's a Q-22 bus so use all 8k map reg */				Pccb.uq_ubainfo = qballoc(numuba, (caddr_t)uq,						sizeof ( UQ ), 0);			else			    Pccb.uq_ubainfo = uballoc(numuba, (caddr_t)uq,						sizeof ( UQ ), 0);			if(uba_hd[numuba].uba_type & UBAUVI)				Pccb.uqptr = (UQ *)(Pccb.uq_ubainfo & 0x3fffff);			else 			    if(Pccb.step1r & UQ_QB) 				  /* it's a Q-22 bus so use all 8k map reg */				Pccb.uqptr = (UQ *)(Pccb.uq_ubainfo & 0x3fffff);			     else				 Pccb.uqptr = (UQ *)(Pccb.uq_ubainfo & 0x3ffff);		}		Pccb.uq_mapped = 1;	/* Indicate mapping completed	*/	}	if(Lpinfo.uq_type == KDM_TYPE) {	    uq->uqca.ca_xmi.flags = 0;	/* No flags set			*/	    uq->uqca.ca_xmi.psi = SSP_PSI_512; /* Use 512 page size for now */#ifdef notdef	    uq->uqca.ca_xmi.psi = SSP_PSI_4096;	/* MIPS page size = 4096 */#endif notdef	    uq->uqca.ca_xmi.pfn = SSP_PFN_MASK;	/* PFN mask		*/            }	Pccb.rsp_cnt = 0;		/* Clear various counters and	*/	Pccb.cmd_cnt = 0;		/* pointers.			*/	Pccb.rsprindx = 0;			Pccb.cmdrindx = 0;			Pccb.uq_lastrsp = 0;	Pccb.uq_lastcmd = 0;	Pccb.ncon = 0;			/* Mark connection count as 0	*/	Pccb.uq_con = 0;		/* Clear connection vector	*/	Pccb.uq_freel = (uqbq *)NULL;	/* Initialize free list		*/	Init_queue(Pccb.waitq);		/* Initialize command wait queue */	Init_queue(Pccb.scswaitq);	/* Initialize SCS command wait queue */	uuq = Pccb.uqptr;		/* Get unibus address of com area */	for (i = 0;  i < NBUF; i++) {	/* Process buffers		*/			/* Save unibus address of buffer */		Pccb.uq->uq_buf[i].uqh.ua = (long)&uuq->uq_buf[i].app_buf;		/* Place buffer in rsp ring or on free queue if ring is full */		uq_ins_rspring((UQH *)&Pccb.uq->uq_buf[i],pccb);					  	    	}}/* * * *	Name:		uq_ins_rspring	- Insert buffer on response ring *	 *	Abstract:	This routine takes as input a pointer to a buffer. *			It checks the response ring for empty slots. If *			the ring is not full it places the buffer on the ring. *			If the ring is full the buffer is placed on the *			free buffer queue. *			 *	Inputs:		 * *	bp			- Pointer to UQ_header portion of buffer to *				  insert. *	pccb			- Pointer to PCCB for this port *		pd.uq.rsp_cnt	- Count of "used" entries in response ring *		pd.uq.rsprindx	- Pointer to next location in ring to receive *				  packet. *	 *	 * *	Outputs: * *	pccb *	     pd.uq.rsp_cnt	- If buffer added to ring this value is  *				  incremented. *	     pd.uq.rsprinx	- If buffer added to ring this value is *				  incremented mod ring size. *	     pd.uq_freel	- If buffer is added to free list this *				  location now points to new buffer and *				  approriate links are updated. * *	 *	SMP *		The index into the response ring and the count of buffers *		in the ring are incremented.  This must be SMP *		protected. *	 *		If the buffer is placed on the Pccb's buffer free list, then *		that linked list is modified inside the scope of the lock. * *	Return  *	Values: * *	 *	 *  *	Side		 *	Effects: * */uq_ins_rspring( uqbp,pccb )UQH	*uqbp;				/* Pointer to UQ header in buffer */PCCB	*pccb;				/* Pointer to PCCB		  */{UQPPDH	*uqpbp;int 	s;	s = splbio();	Lock_pccb (pccb);	if(Pccb.rsp_cnt < NRSP) {	/* Ring not full		*/		uqpbp = Pos_to_ppdh(uqbp);		uqpbp->uqp_msglen = sizeof(MSCP_MAXBUF) + sizeof(UQPPDH);		/*	 	* NOTE:	 	*	The following two actions MUST be done in separate 	 	*	statements.  This is due to hardware which reads the	 	*	ring entries in two 16-bit reads. A race condition	 	*	exists if the controller reads the low-order 16-bits	 	*	first.  It is possible to get the old low-order and	 	*	the new high-order, resulting in an old command being	 	*	re-executed.  Make sure that the compiler never	 	*	optimizes these two statements.	 	*/		Pccb.uq->uqca.ca_rspdsc[Pccb.rsprindx] =  uqbp->ua;		WBFLUSH;		Pccb.uq->uqca.ca_rspdsc[Pccb.rsprindx] |= (UQ_OWN | UQ_INT);		WBFLUSH;		/* Save physical address of buffer */		Pccb.rspbtab[Pccb.rsprindx] = uqbp;		Pccb.rsp_cnt++;		/* Increment count of used slots */		Pccb.rsprindx++;	/* Increment index into the ring */		Pccb.rsprindx %= NRSP;	/* modulo ring size		 */	}	else	{	/* Ring full - place on free list */		uqbp->flink = Pccb.uq_freel;		Pccb.uq_freel = (uqbq *)uqbp;	}	WBFLUSH;	Unlock_pccb (pccb);	(void)splx(s);}/* * * *	Name:		uq_poll_rspring *	 *	Abstract:	Check the response ring for any new responses. *			If there are any convert them to SCS messages *			and send them on their way. This routine will *			loop until the outstanding response count goes *			to zero or until it encounters an unused entry. * *	Inputs: * *	pccb			- Pointer to PCCB for this port. *	 *	 * *	Outputs: * *	pccb *	     pd.uq.rsp_cnt	- If a response is retrieved this value is *				  decremented. *	     pd.uq.lpinfo.uq_credits[con] - If a response is retrieved the  *				  credits given in the response packet are *				  added to the total for this connection. *	     pd.uq.last_rsp	- If a response is retrieved this value is *				  incremented mod ring size. This value is *				  the next ring entry to examine for a  *				  response. *	 *	 * *	SMP *		The count of buffers loaded into the ring and the ownership *		bits for the buffers in the ring must be modified in an *		smp-safe manner.  The response buffer count is tested before *		locking the pccb; then, after the pccb is locked, we read *		it again to make sure another cpu hasn't come in to do our work *		for us - if it is still not zero then we look at the *		ownership bit for the next response entry; if we own the *		entry, we save it for later in uqbp.  The Pccb gets unlocked.  *		We give uqbp to SCS.  And then we start over again.		 * *	Return  *	Values: * *	 *	 *  *	Side		 *	Effects: * *	If a response is found a call to scs_msg_rec or scs_dg_rec is generated *	depending on the message type of the response. If there is an entry *	on the free buffer queue that entry is placed in the response ring *	in place of used entry. If no buffer is available uq_poll_cring is *	called to scan the command ring for used entries. That routine will *	place any free buffers on the response ring/free queue as described *	in uq_ins_rspring. */uq_poll_rspring(pccb)PCCB	*pccb;{UQH	*uqbp;UQH	*rp;UQPPDH	*uqpbp;SCSH	*scsbp;char	con;u_char	mtype;short	msglen;int	save_ipl, s;int	pb_not_null = 1;	save_ipl = splbio();	/* Raise IPL to muck with rings */	while (Pccb.rsp_cnt != 0) {	/* There are outstanding responses */	Lock_pccb(pccb);	if (Pccb.rsp_cnt != 0) {  /* Is it still != 0, if not then leave */		if (Pccb.uq->uqca.ca_rspdsc[Pccb.uq_lastrsp] & UQ_OWN) {			Unlock_pccb(pccb);			(void)splx(save_ipl);			return;		/* But we don't own any		*/		}			/* Get buffer address */		uqbp = Pccb.rspbtab[Pccb.uq_lastrsp]; 			/* Decrement count of used slots */		--Pccb.rsp_cnt;		Pccb.uq_lastrsp++;	/* Increment response pointer	*/		Pccb.uq_lastrsp %= NRSP;		if (Pccb.pb == NULL)			pb_not_null = 0;		/* We just removed a buffer from the response ring,			so we try to insert another one in */		/* Are there any buffers on the freeq? */		if ((rp = (UQH *)Pccb.uq_freel) != (UQH *)NULL) { 			Pccb.uq_freel = rp->flink; /* Update list pointer */			Unlock_pccb (pccb);			uq_ins_rspring(rp,pccb); /* Fill the slot 	*/		}		else	/* No - Poll the command ring to see if we can 	*/			/* scare some up.				*/			{			Unlock_pccb (pccb);			uq_poll_cring(pccb);			}		uqpbp = Pos_to_ppdh(uqbp); /* position to uqssp header	*/		con = uqpbp->uqp_cid;	/* get connection id		*/		mtype = uqpbp->uqp_msgtype; /* message type		*/		msglen = uqpbp->uqp_msglen; /* message length		*/		/*  Was it a Last fail packet? */		if((Pccb.uq_con & (short)(1 << con)) == 0) {			Pccb.lfptr[con] = uqbp;			(void)splx(save_ipl);			return;		}		Lpinfo.uq_credits[con] += (u_short)uqpbp->uqp_credits;		/*  The uqssp format packet must be converted into			an SCS format packet before we send it up;			see the comments to uq_ins_cring()	*/		scsbp = SCS_msg_header(uqbp);	/* Position to scs header */		scsbp->credit = (short)uqpbp->uqp_credits; /* Update the								credits */		scsbp->rconnid = Pccb.contab[con];    /* Insert remote							connection id */		Store_connid( scsbp->sconnid ) = con; /* Insert sending							   connection id */		if (mtype == UQT_SEQ) {	/* Sequential Message Type	*/			s = Splscs();	/*  Set IPL to SCS level */			scsbp->mtype = SCS_APPL_MSG; /* Application Message */			if (pb_not_null)			  scs_msg_rec( pccb, scsbp, (sizeof(SCSH) + msglen) );			(void)splx(s);	/* Reset IPL			*/		}		if (mtype == UQT_DG) {	/*Datagram Message Type		*/			s = Splscs();	/*  Set IPL to SCS level */			scsbp->mtype = SCS_APPL_DG; 			scs_dg_rec( pccb, scsbp, (sizeof(SCSH) + msglen) );			(void)splx(s);	/* Reset IPL			*/		}	}  /*  end if */		else Unlock_pccb(pccb);	}  /*  end while */	WBFLUSH;	(void)splx(save_ipl);}/* * * *	Name:		uq_ins_cring *	 *	Abstract:	This routine will place a buffer on the command *			ring if there is an available slot. If no slot is *			available the buffer is placed on the wait queue *			for later retrieval. If the command is placed on *			the ring the IP register on the controller is read *			to initiate polling of the ring. *			 * *	Inputs: * *	scsbp			- Pointer to SCS header of buffer to use *	     uqpbp.msglen	- Size of application message *	pccb			- Pointer to PCCB for this port *	     pd.uq.cmd_cnt	- Number of used entries on the command ring *	     pd.uq.cmdrindx	- Index into ring to place next buffer *	     pd.uq.waitq	- Wait queue for queued commands *	     lpinfo.uq.uq_credits[i] - Number of credits available on this *								connection *	Outputs: * *	pccb			- Pointer to PCCB for this port *	     pd.uq.cmd_cnt	- Incremented if command placed on ring *	     pd.uq.cmdbtab[i]	- Address of buffer placed in ring entry i. *				- Valid if command  * * * *	The SCS layer has given us an sca format command and uq *	must convert it into an uqssp format command.   * *	In order to do this uq overwrites the scs sconnid field *	(1 long word) with a uqssp command packet header (1 long word); *	this is done in two steps - in uq_send_msg() uq writes *	in the uq header Size field; here, uq_ins_cring() writes in the *	Credit field, the Message Type field, and the uq Connid.  The uq *	Connid (1 byte) is copied from the low byte of the *	scs-packet's rconnid.  The scs-packet's rconnid is the scs *	sconnid uq_conn() gave to scs at connection startup. * *	When the response packet comes back from the uq controller, *	uq_poll_rspring() inserts the scs rconnid which was saved *	in Pccb.contab by uq_conn() at connection start-up. *	The uqssp header is then overwritten with an scs sconnid; *	this scs sconnid is equal to the uq connid.  (Technically, *	this scs sconnid may be incorrect in its seq-num field; but *	this doesn't matter because it is the rconnid, restored

⌨️ 快捷键说明

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