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

📄 uqserv.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	pccb->type = DYN_PCCB;		/* Structure type		*/	pccb->pdt = &uqpdt;		/* Init PDT pointer		*/	Pccb.uq_ctlr = ctlr;		/* Save ctlr number		*/	Pccb.reinit_cnt = UQ_MAX_REINIT; /* Initialize reinit counter	*/	if (uba_hd[numuba].uba_type & UBABDA)		Lpinfo.uq_type = BDA_TYPE; /* BDA is a special case and must */					 /* be flagged now		   */	if (uba_hd[numuba].uba_type & UBAXMI) {		Lpinfo.uq_type = KDM_TYPE; /* KDM is also a special case and */					   /* must be flagged now	     */		xmidata = get_xmi(numxmi);		Pccb.xmipd = (xmidata->xmiintr_dst) | UQ_XMI_LEVEL15;	}	/* the next line must be done before calling uq_port_reset */	Pccb.init_leader = Pccb.reset_leader = CURRENT_CPUDATA->cpu_num;	Lpinfo.uq_flags |= UQ_PRB;	/* Flag that we are in probe	 */	uq_set_reg(pccb, reg);		/* Set up register pointers	*/	if (Lpinfo.uq_type == BDA_TYPE) {		bdar = (struct bda_regs *)((long)(Pccb.Uqip) - UQB_IP);		Pccb.bda_init_vec = bdar->bda_biic.biic_int_ctrl;		Pccb.bda_init_dest = bdar->bda_biic.biic_int_dst;		Pccb.bda_init_errvec = bdar->bda_biic.biic_err;	}	uq_port_reset(pccb);		/* Bang it on the head		 */	count = 0;	while (count < DELAYTEN){	/* Wait for at most 10 seconds 	 */		if ((*Pccb.Uqsa & UQ_STEP1) != 0)			break;		/* We woke it up		*/		DELAY(10000);		count = count +1;	}	if (count == DELAYTEN) return(0);	/* Not there or dead 	*/	if ( (Lpinfo.sa = *Pccb.Uqsa) & UQ_ERR) {		uq_error_log( pccb, UQ_SA_FATAL);		return(0);		/* If error then return 	*/	}	#ifdef mips	KM_ALLOC( pcinfo, struct port_info *, sizeof(struct port_info), 			KM_SCA, KM_NOW_CL_CA | KM_NOCACHE)#else	KM_ALLOC( pcinfo, struct port_info *, sizeof(struct port_info), 			KM_SCA, KM_NOW_CL_CA )#endif mips	if ( pcinfo == (struct port_info *)NULL )		return(0);	pcinfo->pc_ptr = pccb;		/* Save address for later use	*/	Pccb.uq = &pcinfo->uq;		/* Save address of comm area	*/	port_info_ptr[ctlr] = pcinfo; /* Save pointer to port_info struct */	uq_init_buffers( pccb );	/* Map communications area 	*//* Setup bus-specific information					*/	if (uba_hd[numuba].uba_type & UBAXMI) {		/* Allocate controller scratchpad area */		KM_ALLOC( scp, UQ_SCP *, UQ_SCP_SIZE, KM_SCA, KM_NOW_CL_CA )		if ( scp == (UQ_SCP *)NULL )			return(0);		Pccb.uqscp = (struct _uqscp *)svtophy(scp);	}/* Setup controller-specific information				*/	switch(Lpinfo.uq_type) {	      case BDA_TYPE:		Pccb.uq_ivec = 0;	/* BDA gets vector from BIIC reg */		break;	      case KDM_TYPE:		Pccb.uq_ivec = (uba_hd[numuba].uh_lastiv -= 4);			break;	      default:		Pccb.uq_ivec = (uba_hd[numuba].uh_lastiv -= 4);		break;	}/*									*//* Initialize step information						*//*									*/	Pccb.step1w = (((uba_hd[numuba].uba_type & UBAXMI) != 0) ? 0 : UQ_ERR )		| (NCMDL2<<11) | (NRSPL2<<8) | UQ_IE | (Pccb.uq_ivec/4);	Pccb.step2w = ((int)&Pccb.uqptr->uqca.ca_ringbase)|		    (((uba_hd[numuba].uba_type & UBA780) != 0) ? UQ_PI : 0);	Pccb.step3w = ((int)&Pccb.uqptr->uqca.ca_ringbase)>>16;/*									*//*	initialize the SMP lock						*//*									*/	Init_pccb_lock(pccb);/*									*//*	Initialize the port						*//*									*/	if (Lpinfo.uq_type == KDM_TYPE) {		*Pccb.Uqpd = Pccb.xmipd; /* Write interrupt info in PD reg */	}	Lpinfo.uq_state = S_STEP1;	/* Port now in STEP1 state	   */	Pccb.step1r = *Pccb.Uqsa;	/* Save step data in case of error */	if (Lpinfo.uq_type == BDA_TYPE) 		Pccb.step1r &= ~UQ_QB;	/* Necessary to turn off bit    */	SA_W(pccb) = Pccb.step1w; /* Write step 1 data 		*/	if(!(step_wait( pccb, STEP1MASK, STEP1GOOD))) /* Wait for step 2 */		return(0);		/* Step	failed			*/	Pccb.step2r = *Pccb.Uqsa;	/* Save step data in case of error */	Lpinfo.uq_state = S_STEP2;	/* Port now in STEP2 state	*/	SA_W(pccb) = Pccb.step2w; /* Write step 2 data 		*/	if(!(step_wait( pccb, STEP2MASK, STEP2GOOD))) /* Wait for step 3 */		return(0);		/* Step failed			*/	Pccb.step3r = *Pccb.Uqsa;	/* Save step data in case of error */	Lpinfo.uq_state = S_STEP3;	/* Port now in STEP3 state	*/	SA_W(pccb) = Pccb.step3w; /* Write step 3 data 		*/	if(!(step_wait( pccb, STEP3MASK, STEP3GOOD))) /* Wait for step 4 */		return(0);		/* Step failed			*/	Pccb.step4r = *Pccb.Uqsa;	/* Save step data in case of error */	Lpinfo.uq_type = (Pccb.step4r>>4) & 0x7F;	Lpinfo.uq_state = S_STEP4;	/* Port now in STEP3 state	*//*									*//*	Set up SCS info							*//*									*/	pccb->lpinfo.name = Ctrl_from_num( "uq  ", Pccb.uq_ctlr); /* Local port name	*/	Scaaddr_low( pccb->lpinfo.addr ) = *(u_short *)&Pccb.uq_ctlr; /* Remote port address */	Scaaddr_mid( pccb->lpinfo.addr ) = 0;	Scaaddr_hi( pccb->lpinfo.addr ) = 0;	pccb->lpinfo.type.hwtype = HPT_UQSSP; /* Local port hardware type */	pccb->lpinfo.type.swtype = SPT_UQSSP; /* Local port software type */	if( Lpinfo.uq_type == BDA_TYPE ) {    /* Local port interconnect  */	        pccb->lpinfo.type.ictype = ICT_BI;        } else if( Lpinfo.uq_type == KDM_TYPE ) {		pccb->lpinfo.type.ictype = ICT_XMI;	} else if( Pccb.step1r & UQ_QB ) {		pccb->lpinfo.type.ictype = ICT_QB;	} else {		pccb->lpinfo.type.ictype = ICT_UB;	}	pccb->lpinfo.type.dual_path = 0; /* Single path port		*//*									*//*	Insert PCCB on system queue					*//*									*/	s = Splscs();	Lock_scadb ();	Insert_entry(pccb->flink, scs_lport_db); 	Unlock_scadb ();	/* keep ipl up for scs call */	if((i = scs_initialize()) != RET_SUCCESS){ /* Init the SCS layer */		(void)splx(s);		/* Lower IPL			*/		Remove_entry(pccb->flink); /* Remove from lport_db queue */		uq_port_reset(pccb);	 /* Reset the device		*/		Lpinfo.uq_flags &= ~UQ_PRB; /* We are now out of probe	*/		return(0);		/* Return with err if init fails */	}	(void)splx(s);		/* Restore IPL			*/	uq_init_buffers( pccb );	/* Restock the response ring and */					/* free queue after controller	*/					/* stomps on ring.		*/	Pccb.step4w =  (( (uq_cinfo[Lpinfo.uq_type].burst & UQ_BURST) > 0 ? 			(uq_cinfo[Lpinfo.uq_type].burst & UQ_BURST) : 0) <<2)				| UQ_GO | (uqerror ? UQ_LF : 0);	if (uba_hd[numuba].uba_type & UBAXMI) {	    Pccb.uq->uqca.ca_scp_size = UQ_SCP_SIZE; /* Size of scratchpad */	    Pccb.uq->uqca.ca_scp_add = (u_long)Pccb.uqscp; /* Physical address of scratchpad */	    Pccb.step4w |= UQ_CS;        }	SA_W(pccb) = Pccb.step4w; /* Enable the controller 	*/	Lpinfo.uq_state = S_RUN;	/* Controller is online		*/	if(!(uq_create_sys( pccb ))) {	/* Create new system		*/		return(0);		/* Couldn't create the system	*/	}	if(Pccb.poll_rate == 0) 	/* Set the rate for the sa poll	*/		Pccb.poll_rate = hz;/*									*//*	Start the SA register watchdog timer. This time will not start	*//*	running until the timer queues are enabled.			*//*									*/	if ( (Lpinfo.uq_flags & UQ_TIM) == 0 ) { /* If timer not yet on */		Lpinfo.uq_flags |= UQ_TIM; /* Indicate timer now on	*/		timeout(uq_timer,pccb,Pccb.poll_rate); /* Start timer	*/	}	Pccb.init_leader = Pccb.reset_leader = UQPath_Is_Up;	Lpinfo.uq_flags &= ~UQ_PRB;	/* We are now out of probe	*//* *	Return size of device structure.  Because the uq device structure *	contains an extra word for the KDB50 we must check the device type *	and return the size based on that type.  For all but the KDB the *	size is struct uqdevice less one short. */	return( Pccb.uqregsize );}/* * * *	Name:		uq_port_reset *	 *	Abstract:	Perform reset of controller *			 *	Inputs: * *	pccb				- pointer to PCCB for this port *	 *	 * *	Outputs: * *	 *	SMP:		This code should only be entered by the cpu *			currently equal to init_leader, although no *			lock is currently asserted.  Because of this *			design, no calls to lock primitives are done. *			In other words, the caller of uq_port_reset is *			obligated to take care of smp-safety. *	 * *	Return  *	Values: * *	 *	 *  *	Side		 *	Effects: * */void	uq_port_reset( pccb )	/* Reset controller */PCCB	*pccb;{unsigned int	count;						/* A debugging macro */	cpu_printf (Pccb.init_leader, Pccb.reset_leader, "uq_port_reset");	switch(Lpinfo.uq_type) {	      case BDA_TYPE:		{		struct bda_regs	*bdar= (struct bda_regs *)((long)(Pccb.Uqip) - UQB_IP); 		bisst(&bdar->bda_biic.biic_ctrl);		bdar->bda_biic.biic_int_ctrl = (Pccb.bda_init_vec & 0x0ffff); 		bdar->bda_biic.biic_int_dst = Pccb.bda_init_dest; 		bdar->bda_biic.biic_err = Pccb.bda_init_errvec; 	        }		break;	      case KDM_TYPE:		{		struct xmi_reg *xmir= (struct xmi_reg *)((long)(Pccb.Uqip) - UQX_IP); 		u_long vec;		if(Pccb.reinit_cnt >= (UQ_MAX_REINIT-1)) { 			/* Try soft reset first */			*Pccb.Uqip = 1;			xmir->xmi_xbe = xmir->xmi_xbe & XMI_NHALT;			DELAY(600000);		/* delay 600 msec. */			count = 0;			while (count < 400) {				DELAY(1000)	  /* wait one msec. */				count++;				if   ((!(xmir->xmi_xbe & XMI_XBAD)) &&				          (!(xmir->xmi_xbe & XMI_STF)))						break;			}  /* end while */			/* if the while loop timed out, do hard init */			if (count >= 400) xmisst(xmir);				else break;  /* i.e, continue soft init */		}		else {				     /* Else hard init */		     xmisst(xmir);		}	        }		break;	      default:		*Pccb.Uqip = 0;  		break;	}	return;}/* * * *	Name:		uq_set_reg *	 *	Abstract:	Setup uq port register pointers. *			 *	Inputs: * *	pccb				- pointer to PCCB for this port *	reg				- Base address of IP register *	 *	 * *	Outputs:	The port register offsets are added to the IP *			physical address to get the physical address for *			each of the port registers.  The offsets are  *			bus-dependent. * *	 *	 *	 * *	Return  *	Values: * *	 *	 *  *	Side		 *	Effects:	Port registers are accessible via the pccb fields. * */void	uq_set_reg( pccb, reg )	/* Set up pointers to IO registers	*/register PCCB *pccb;caddr_t	reg;{	if (uba_hd[numuba].uba_type & UBABDA) {		Pccb.Uqip = ( u_short * )(( u_char * )reg + UQB_IP_OFF);		Pccb.Uqsa = ( u_short * )(( u_char * )reg + UQB_SA_OFF);		Pccb.Uqsaw = ( u_short * )(( u_char * )reg + UQB_SAW_OFF);		Pccb.uqregsize = 6;	} else 	if (uba_hd[numuba].uba_type & UBAXMI) {		Pccb.Uqip = ( u_short * )(( u_char * )reg + UQX_IP_OFF);		Pccb.Uqsa = ( u_short * )(( u_char * )reg + UQX_SA_OFF);		Pccb.Uqpd = ( u_long * )(( u_char * )reg + UQX_PD_OFF);		Pccb.uqregsize = 12;	} else {		Pccb.Uqip = ( u_short * )(( u_char * )reg + UQ_IP);		Pccb.Uqsa = ( u_short * )(( u_char * )reg + UQ_SA);		Pccb.uqregsize = 4;	}}/* * * *	Name:		step_wait *	 *	Abstract:	Waits for the specified initialization step to *			complete. *			 *	Inputs: * *	pccb				- pointer to PCCB for this port *	mask				- mask of interesting bits *	result				- what those bits should be *	 *	 * *	Outputs: * *	 *	 *	 * *	Return  *	Values: * *	 *	 *  *	Side		 *	Effects: * */u_long	step_wait( pccb, mask, result )		/* Wait for step to complete */PCCB	*pccb;short	mask;short	result;{register int count;	count = 0;	while (count < DELAYTEN){	/* Wait for at most 10 seconds */		if((*Pccb.Uqsa & mask) == result)			break;		/* Got the step - hoo ray 	*/		DELAY(10000);		/* Spin our wheels for 10 ms 	*/		count = count+1;	}	if (count == DELAYTEN) 	{ /* If we timed out then return failure */		return(0);        }	else 		return(RET_SUCCESS);	}	/* * * *	Name:		uq_create_sys	 *					 *	 *	Abstract:	Obtain the necessary data structures to make a system *			known to SCS. Initialize these structures and call the *			appropriate routine to make the system known. *			 *	Inputs: * *	pccb			- Pointer to PCCB for this port * *	     pd.uq.uq_ctlr	- Controller number *	     pd.uq.step4r	- Data read during step 4 of initialization *	     lpinfo.name	- Local port name *	      *	 *	 * *	Outputs: * *	pccb			- Pointer to PCCB for this port * *	     lpinfo.uq.uq_type	- UQSSP model number for this device *	     pd.uq.pb		- Pointer to PB for this port * *	sb			- System block for this port * *	     various fields initialized * *	pb			- Path Block for this port * *	     various fields initialized *	 *	SMP: 	locking not neccessary because only one cpu-thread is *		permitted to an initialization. *	 * *	Return  *	Values: * *	0			- System could not be created *	1			- System could be created *	 *  *	Side		 *	Effects: * *	The SB and PB for the port are allocated and initialized. The PB *	is placed on the System Block PB queue and the SB is place on the *	scs_config_db systemwide queue. scs_new_path is called to notify *	SCS of the existence of a new path to the system. */u_long	uq_create_sys(pccb)PCCB		*pccb;{	register PIB	*pib = &uq_pib;	register SIB	*sib  = &uq_sib;	PB	*pb;	SB	*sb;	int	i, s;		cpu_printf (Pccb.init_leader, Pccb.reset_leader, "uq_create_sys");	(void)bzero( pib, sizeof(PIB)); /* Clear pib			*/	(void)bzero( sib, sizeof(SIB));   /* Clear sib			*/

⌨️ 快捷键说明

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