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

📄 msi_init.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
    u_long			msinum;    register struct sii_regs	*msiregs;    struct siibuf		*msibuf;{    static   u_long		initialized = 0;    register PCCB		*pccb;    register u_long		save_ipl,				status = 0;    /* The steps involved in probing a MSI port are as follows:     *     *  1. IPL is synchronized to IPL_SCS.     *  2. SCS is initialized.     *  3. The Generic Vaxport Driver is initialized.     *  4. A PCCB is allocated.     *  5. Double mapping PTEs are allocated and initialized.     *  6. The PCCB is initialized.     *  7. The PCCB is inserted into the system-wide local port database.     *  8. The MSI port is disabled.     *  9. Initialization of the local MSI port is scheduled through forking.     * 10. IPL is restored.     *     * Steps 2-3 constitute MSI port driver initialization and are only     * executed during probing of the very first local MSI port encountered     * during device auto-configuration.  The remaining steps constitute the     * actual probing of the specified local MSI port and are executed whenever     * this routine is invoked.  Any errors( Steps 2-5 ) encountered during     * either portion of this routine immediately abort probing of the current     * MSI port following logging of the fatal event.  The interrupt service     * routine for the local MSI port is also switched back to the appropriate     * stray interrupt handler.  Any subsequent interrupts on the inoperative     * local port are discarded.     *     * Separate double mapping PTEs are allocated for use by the Transmit and     * Receive Fork Processes( Step 5 ).  These PTEs are used whenever the fork     * processes find it necessary to transfer large amounts of data to or from     * non-System buffers.  Such buffers are NOT within the system address     * space and therefore may not be directly accessed by fork processes.     * Separate mapping PTEs are required because both fork processes maybe     * simultaneously active and making use of their mapping PTEs in a SMP     * environment.  Both sets of PTEs are pre-initialized to the extent that     * only page frame numbers need be inserted during double mapping.     *     * NOTE: The PCCB fork block is only used for clean up and initialization     *	     of the local port.  Therefore, it should always be available for     *	     the port's first initialization.     */    save_ipl = Splscs();    if( initialized == 0 ) {	if(( status = scs_initialize()) == RET_SUCCESS &&	   ( status = gvp_initialize()) == RET_SUCCESS ) {	    status = 0;	    initialized = 1;	} else {	    status = (( status == RET_ALLOCFAIL )				? FE_INIT_NOMEM : FE_INIT_ZEROID );	}    }    if( status == 0 ) {	KM_ALLOC( pccb, PCCB *, sizeof( PCCB ), KM_SCA, KM_NOW_CL_CA )	if( pccb ) {	    msi_adapt[ msinum ] = pccb;	} else {	    status = FE_INIT_NOMEM;	}    } else {	pccb = NULL;    }#ifdef notdef/* *TEMP* MIPSfair II debugging code.  Allocate dynamic memory for caching * SII RAM buffer contents during panics. */{    if( status == 0 ) {        KM_ALLOC( siirambuf, u_char *, sizeof( struct siibuf ), KM_SCA,	      	  KM_NOW_CL_CA )        if( siirambuf == NULL ) {	    status = FE_INIT_NOMEM;        }    }}#endif notdef    if( status == 0 ) {	register u_long		nptes;	nptes = rbtop( MAX_DATA_SIZE ) + 1;	pccb->Rdmap.dmap_baddr = get_sys_ptes( nptes,					       &pccb->Rdmap.dmap_bpteaddr );	pccb->Xdmap.dmap_baddr = get_sys_ptes( nptes,					       &pccb->Xdmap.dmap_bpteaddr );	if( pccb->Rdmap.dmap_baddr && pccb->Xdmap.dmap_baddr ) {	    pccb->Rdmap.protopte = MSI_RPROTOPTE;	    pccb->Xdmap.protopte = MSI_XPROTOPTE;	} else {	    status = FE_INIT_NOPTES;	}    }    if( status ) {	if( pccb ) {	    KM_FREE(( char * )pccb, KM_SCA )	}#ifdef notdef/* *TEMP* MIPSfair II debugging code.  Allocate dynamic memory for caching * SII RAM buffer contents during panics. */{    if( siirambuf ) {        KM_FREE(( char * )siirambuf, KM_SCA )        siirambuf = NULL;    }}#endif notdef	( void )msi_log_initerr( msinum, HPT_SII, status );	( void )splx( save_ipl );	return( 0 );    }    U_long( pccb->size ) = sizeof( PCCB );    pccb->type = DYN_PCCB;    pccb->pdt = &msi_pdt;    Init_pccb_lock( pccb )    pccb->lpinfo.type.hwtype = HPT_SII;    pccb->lpinfo.type.swtype = SPT_MSI;    pccb->lpinfo.type.ictype = ICT_SII;    pccb->lpinfo.name = Ctrl_from_num( "msi ", msinum );    pccb->Fsmstatus.nosanity_chk = 1;    pccb->Contact = msi_cippdcontct;    pccb->Burst = msi_cippdburst;    pccb->Max_cables = MAX_CABLES;    pccb->lpinfo.Max_port = ( MSI_MAXNUM_PORT - 1 );    pccb->lpinfo.Protocol = CIPPD_VERSION;    Init_queue( pccb->Comqh )    Init_queue( pccb->Comql )    Init_queue( pccb->Dfreeq )    Init_queue( pccb->Mfreeq )    pccb->Siiregs = ( u_char * )msiregs;    pccb->Siibuffer = ( u_char * )msibuf;    pccb->Pkt_size = sizeof( MSIBH ) + sizeof( MSI_STRT );    pccb->Msg_ovhd = MSG_OVHD;    pccb->Dg_ovhd = DG_OVHD;    pccb->Retdat_ovhd = RETDAT_OVHD;    pccb->Lretdat_cssize = LRETDAT_CSSIZE;    pccb->Min_msg_size = MSG_OVHD + sizeof( SCSH );    pccb->Max_msg_size = MSG_OVHD + sizeof( SCSH ) + scs_msg_size;    pccb->Min_dg_size = DG_OVHD;    pccb->Max_dg_size = DG_OVHD + sizeof( SCSH ) + scs_dg_size;    pccb->Min_id_size = sizeof( MSI_ID );    pccb->Max_id_size = sizeof( MSI_ID );    pccb->Min_idreq_size = sizeof( MSI_IDREQ );    pccb->Max_idreq_size = sizeof( MSI_IDREQ );    pccb->Min_datreq_size = sizeof( MSI_DATREQ );    pccb->Max_datreq_size = sizeof( MSI_DATREQ );    pccb->Min_sntdat_size = SNTDAT_MINSIZE;    pccb->Max_sntdat_size = SNTDAT_MINSIZE + MAX_DATA_SIZE;    pccb->Msicsr = ( vu_short * )&msiregs->sii_msicsr;    pccb->Msidscr = ( vu_short * )&msiregs->sii_msicr;    pccb->Msidssr = ( vu_short * )&msiregs->sii_msisr;    pccb->Msiidr = ( vu_short * )&msiregs->sii_msiid;    pccb->Msitr = ( vu_short * )&msiregs->sii_msitr;    pccb->Msitlp = ( vu_short * )&msiregs->sii_msiltlp;    pccb->Msiilp = ( vu_short * )&msiregs->sii_msiilp;    pccb->Msidcr = ( vu_short * )&msiregs->sii_msidcr;    pccb->Msicomm = ( vu_short * )&msiregs->sii_msicomm;    pccb->Msidstat = ( vu_short * )&msiregs->sii_msidstat;    pccb->Msiisr3 = ( vu_short * )&msiregs->sii_msiisr3;    pccb->Lpstatus.init = 1;    Init_comqh_lock( pccb )    Init_comql_lock( pccb )    Init_dfree_lock( pccb )    Init_mfree_lock( pccb )    Init_rfp_lock( pccb )    Init_xfp_lock( pccb )    {    register u_long		num;    register MSI_PPORTINFO	*ppi;    for( num = 0, ppi = &pccb->Perport[ 0 ];	 num < MSI_MAXNUM_PORT;	 ++num, ++ppi ) {	Init_queue( ppi->xretryq )    }    }    pccb->lpinfo.Dg_size = sizeof( MSIBH )   +			   sizeof( CIPPDH ) +			   sizeof( SCSH )    +			   scs_dg_size;    pccb->lpinfo.Msg_size = sizeof( MSIBH )   +			    sizeof( CIPPDH ) +			    sizeof( SCSH )    +			    scs_msg_size;    pccb->lpinfo.Pd_ovhd = sizeof( MSIBH )   +			   sizeof( CIPPDH );    pccb->lpinfo.Ppd_ovhd = sizeof( MSIBH );    Insert_entry( pccb->flink, scs_lport_db )    ( void )msi_disable( pccb );    Pccb_fork( pccb, msi_init_port, PANIC_PCCBFB )    ( void )splx( save_ipl );    return( 1 );}/*   Name:	msi_start_port	- Start a Local MSI Port * *   Abstract:	This function starts local MSI ports during local port *		initialization. * *   Inputs: * *   IPL_SCS			- Interrupt processor level *   pccb			- Port Command and Control Block pointer *	pd.msi			-  MSI specific PCCB fields *	    lpstatus.active	-   0 *	ppd.cippd		-  CI PPD specific PCCB fields *	    fsmstatus.online	-   0 * *   Outputs: * *   IPL_SCS			- Interrupt processor level *   pccb			- Port Command and Control Block pointer *	pd.msi			-  MSI specific PCCB fields *	    lpstatus.active	-   1 *	    rbusy		-   First receive-in-progress SIIBUF pointer *	    siiregptrs		-   MSI register pointers *		msicsr		-    Control/Status register *		msidcr		-    DSSI control register *		msidscr		-    DSSI control register *		msiidr		-    ID register *		msiilp		-    Initiator list pointer register *		msitlp		-    Target list pointer register *		msitr		-    Timeout register *	    xbusy		-   First transmit-in-progress SIIBUF pointer *	    xfree		-   First free transmit SIIBUF pointer * *   SMP:	The PCCB specific XFP and RFP are locked( EXTERNALLY ) to *		synchronize access to lpstatus.active, a MSI specific PCCB *		field.  This is probably unnecessary because of lack of *		conflict for this status bit due to the single threadedness of *		port clean up and initialization.  It is done anyway to *		guarantee unrestricted access and because stale RFP, XFP and *		XFP_TIMER threads could still be scheduled or even active. */voidmsi_start_port( pccb )    register PCCB	*pccb;{    register siibq	*siibp;    register u_long	nbufs,			nxbufs;    /* The steps involved in starting a local MSI port are as follows:     *     *  1. Indicate to the SII chip it is to use on-board jumper settings to     *     specify the port station address.     *  2. Indicate to the SII chip it is operating on an arbitrated bus.     *  3. Enable SII chip timeouts and set target and initiator timer values.     *  4. Turn on the SII chip DSSI bus drivers.     *  5. Indicate current lack of output and input packets to the SII chip.     *  6. Enable DSSI mode operation of the SII chip.     *  7. Enable SII chip interrupts, parity error reporting, and receptions.     *  8. Subdivide the local port SII RAM buffer into transmit and receive     *	   SIIBUFs, appropriately initializing each of them.     *  9. Hand the SII chip its initial receive buffer list.     * 10. Mark the local MSI port active.     *     * The current lack of output and input packets are indicated to the SII     * chip( Step 5 ) by setting its initator and target list pointers to 0.     *     * Transmit SIIBUFs are appropriately initialized( Step 8 ) and placed onto     * the port specific free transmit SIIBUF circular queue for use by the     * Transmit Fork Process.  Their initialization includes the circular     * threading together of all free transmit SIIBUF command blocks.  Receive     * SIIBUFs are initialized( Step 8 ) and placed onto the port specific     * receive-in-progress circular queue.  Their initialization includes     * enabling of interrupts and the threading together of all receive SIIBUF     * command blocks.  The entire receive buffer list is handed to the local     * MSI port( Step 9 ) by setting its target list pointer to the command     * block of the very first available receive SIIBUF buffer.     *     * NOTE: Initiator( packet transmission ) timeout interval is 2800 usecs.     *     * NOTE: Target( packet reception ) timeout interval is 2400 usecs.     *     * NOTE: The size of the entire RAM buffer is 131,072 bytes.  The size of     *	     a SIIBUF is approximately 4,160 bytes.  This allows the SII RAM     *	     buffer to be divided up into 31 buffers.  Based upon 7 potential     *	     remote ports( the local port is not included ), 14 SIIBUFs are     *	     set aside as transmit SIIBUFs, 2 per remote port.  The remaining     *	     17 SIIBUFs are used as receive SIIBUFs.     *     * NOTE: The SII RAM buffer may not be subdivided until AFTER the local MSI     *	     port registers have been initialized.  It is not accessible until     *	     such initialization has taken place.     */    *pccb->Msiidr  = 0;#ifdef mips	*pccb->Msicsr  = 0;#else	*pccb->Msicsr  = MSICSR_HPM; #endif mips    *pccb->Msitr   = ( MSITR_ENA | MSITR_TTV | MSITR_ITV );    *pccb->Msidcr  = MSIDCR_PRE;    *pccb->Msiilp  = 0;    *pccb->Msitlp  = 0;    *pccb->Msidscr = ( MSIDSCR_DSE | MSIDSCR_ALLCH );#ifdef mips	*pccb->Msicsr  = ( MSICSR_SLE | MSICSR_PCE | MSICSR_IE );#else    *pccb->Msicsr  = ( MSICSR_HPM | MSICSR_SLE | MSICSR_PCE | MSICSR_IE );#endif mips    WBFLUSH;    pccb->Xfree = NULL;    pccb->Rbusy = NULL;    for( siibp = ( siibq * )pccb->Siibuffer,	  nbufs = sizeof( struct siibuf ) / sizeof( SIIBUF ),	  nxbufs = ( 2 * ( MSI_MAXNUM_PORT - 1 ));	 nbufs > 0;	 --nbufs, siibp = ( siibq * )Quad_align( ++Siibp )) {	( void )bzero(( u_char * )Siibp, sizeof( SIIBUF ));	Siibp->size = sizeof( SIIBUF ); 	Siibp->type = DYN_SIIBUF;	Siibp->cmdblkaddr = Siiaddr( pccb, &Siibp->cmdblk );	if( nbufs > nxbufs ) {	    Interrupt_enable( Siibp )	    if( pccb->Rbusy ) {		Thread_cmdblk( pccb->Rbusy, Siibp )		Rinsert_rbusy( pccb, Siibp )	    } else {		pccb->Rbusy = siibp;		Init_queue( *siibp )	    }	} else {	    Siibp->xpktaddr = Siiaddr( pccb, &Siibp->Xpkt );	    if( pccb->Xfree ) {		Thread_cmdblk( pccb->Xfree, Siibp )		Xinsert_xfree( pccb, Siibp )	    } else {		pccb->Xfree = siibp;		Init_queue( *siibp )	    }	}    }    pccb->Xbusy = siibp = pccb->Xfree;    Thread_cmdblk( siibp, siibp )    *pccb->Msitlp = (( SIIBUF * )pccb->Rbusy )->cmdblkaddr;    WBFLUSH;    pccb->Lpstatus.active = 1;}

⌨️ 快捷键说明

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