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

📄 scsi_5380.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	/*	 * Keep the select timer running until 250 MS	 * timeout expires or the target asserts BSY.	 */	if (((szaddr->scs_curstat & SCS_BSY) == 0) &&	    ((szaddr->scs_curstat & SCS_BSY) == 0) &&	    ((szaddr->scs_curstat & SCS_BSY) == 0)) {	    if (++sc->sc_swcount < 5) {		timeout(sz_timer3, (caddr_t)unit, 5);	/* 50 MS */		splx(s);		return;	    }	}	/*	 * Call the sz_start routine, which will call	 * sz_scsistart() to handle the select timeout	 * or complete the select, depending on whether	 * or not the target asserted BSY within 250 MS.	 */	sz_start(sc, targid);	splx(s);}/* * * Name:		sz_timer1	-hung bus detection timer * * Abstract:		This timeout occurs every 0.2 seconds. It is *			strated in the probe routine. If the driver *			thinks the bus is idle (sc_active == 0) and *			the bus is hung, then sz_timer1 resets the bus *			and all software state information. sz_start *			is called to get things going again. We declare *			the bus hung if BSY is true and SEL is false *			for 1 MS. *			NOTE: have not tested the case where both *			      busses hang at the same time. *			NOTE: cannot access 5380 registers if bus active. *			NOTE: just return if bus reset in progress. * * Inputs:		None. * * Outputs:		None. * * Return Values:	None. * * Side Effects: *			IPL raised to 15. *			The SCSI bus may be reset. *			sz_start() called. *			Another .2 second timeout will be queued. * */#ifdef	ELDEBUG/* set to cntlr # to cause error */int	sz_eldb_rstbus0 = -1;/* set to 0 to cause error, MUST also force an abort in szintr */int	sz_eldb_rstbus1 = -1;/* set to 0 to cause error, MUST also force an abort in scsistart */int	sz_eldb_rstbus2 = -1;/* set to cntlr # to cause error */int	sz_eldb_busrst = -1;/* set to cntrl # to cause a parity error */int	sz_eldb_parity = -1;/* Set to ID of target for command abort (on bus 0 only) */int	sz_eldb_cmdabrtd0 = -1;int	sz_eldb_cmdabrtd3 = -1;#endif	ELDEBUGsz_timer1(unused)int unused;{	register struct sz_softc *sc;	register struct sz_regs *szaddr;	int i, s;	int cntlr;	int wedged;	int flags;#ifdef	ELDEBUG	int inicmd_tmp;#endif	ELDEBUG	while (1) {	    s = spl5();	    if (sz_do_timer1 == 0)		break;	    for (cntlr = 0; cntlr < nNSCSI; cntlr++) {		sc = &sz_softc[cntlr];		if (sc->sc_cntlr_alive == 0)	/* cntlr does not exist */		    continue;		if (sc->sc_rip)			/* bus reset in progress */		    continue;		if (sc->sc_active)		/* bus active, not safe to */		    continue;			/* access 5380's registers */		/*		 * We assume bus hung if BSY stuck for 1 MS.		 */		szaddr = (struct sz_regs *)szmem + cntlr;#ifdef	ELDEBUG		if (cntlr == sz_eldb_busrst) {		    /* NOTE: spl5 - no need to mask interrupts */		    szaddr->scs_inicmd = SCS_INI_RST;		    DELAY(25);		    szaddr->scs_inicmd = 0;		    sz_eldb_busrst = -1;		}		if (cntlr == sz_eldb_parity) {		    /* NOTE: read undriven data bus to cause parity error */		    i = szaddr->scs_curdata;		    sz_eldb_parity = -1;		}#endif	ELDEBUG		wedged = 1;		for (i = 0; i < 1000; i++) {		    if (((szaddr->scs_curstat & SCS_BSY) == 0) &&			((szaddr->scs_curstat & SCS_BSY) == 0) &&			((szaddr->scs_curstat & SCS_BSY) == 0)) {			    wedged = 0;			    break;		    }		    DELAY(1);		}#ifdef	ELDEBUG		if (cntlr == sz_eldb_rstbus0) {		    wedged = 1;		    sz_eldb_rstbus0 = -1;		}#endif	ELDEBUG		if (wedged == 0)		    continue;		/*		 * BSY stuck, we assume bus is hung.		 * Reset the bus and driver state.		 * Restart I/O operations.		 */		flags = SZ_HARDERR | SZ_LOGREGS;		scsi_logerr(sc, 0, -1, SZ_ET_RSTBUS, 0, 0, flags);		if (sz_t1_dorst == 0) {		/* TODO: debug */		    splx(s);		    return;	/* kill timer, so we don't loop! */		}		sz_reset(cntlr);	    }	    break;	}	/* queue another timer and return */	timeout(sz_timer1, 0, 20);	/* 0.2 sec */	splx(s);	return;}/* * If set to one, move the zeroing of the mode * register to before the spin on phase loop in szintr(). * The idea is to match Martin's note. * Never proved this made any difference one way or * the other. Leave as is because all testing done * with the code this way (sz_i_moveit = 1). */int	sz_i_moveit = 1;/* * Controls whether on not we timeout * disconnected disks. * Leave this control on (sz_do_rsto = 1). */int	sz_do_rsto = 1;/* * Count the number of Save Data Pointers, * Restore Data Pointers messages, and Implied * Save Data Pointers (disconnect not preceded by * a save data pointer message). * NOTE: this is debug information that came in handy *	 so many times I decided to keep it around. */extern	int	sz_sdp[];extern	int	sz_rdp[];extern	int	sz_isdp[];/* * These variables control the new code which * uses a phase mismatch interrupt instead of spinning * waiting for the phase to change (in critical cases). * To use the interrupt, set 1 & 3, but not 2. * TODO: this code needs more work. */int	sz_no_spin1 = 1;int	sz_no_spin2 = 0;int	sz_no_spin3 = 1;#ifdef	SZ_DSP_DEBUGint	sz_nsp_print = 0;	/* print, if command didn't do status phase */#endif	SZ_DSP_DEBUGint	sz_do_reset = 1;	/* TODO: debug (cntl reset hung bus) */int	wakeup();extern int hz;/* * Controls whether we reset the bus or * just ignore the reselect attempt, * when multiple IDs are detected. * Set to one to reset the bus. * TODO: not usre which is correct. */int	sz_i_midrst = 0;/* * DEBUG - normally off * * If set, causes stray interrupt and reselect timeout * messages to console (they always go to the error log). *//* * If set, do an implied save data pointer * if the target disconnects without SDP. */int	sz_do_isdp = 1;/* * * Name:		szintr		-Interrupt service routine * * Abstract:		This routine fields interrupts from the SCSI bus *			controllers (A & B) and performs the appropriate *			actions. General flow is as follows: * *			If the bus is active (target selected): * *			  1. Find ID and bring target into context. *			  2. Check for disconnect (loss of BSY). *			  3. Follow phases set by target. * *			If the bus is not active (no target selected): *			  1. If its not a reselect - log stray interrupt. *			  2. If reselect, bring target into context and *			     follow phases set by target. * * Inputs: * * IPL_device		Device IPL is 14 (IPL 16 in critical code path). * cntlr		SCSI bus controller number (0 = bus A, 1 = bus B). * * Interrupts		A target reselects the initiator. *			EOP - DMA count reaches zero (NOT USED). *			Bus Parity Error (NOT USED). *			Phase Mismatch (instead of EOP). *			A target disconnected from the bus. *			SCSI bus reset (NOT LATCHED!). * * * Outputs:		None. * * Return Values:	None. * * * Side Effects: * *			Target's context in sz_softc is updated. *			DMA transfers may be initiated or continued. *			The SCSI bus can be reset (if hung). *			Next command started by calling sz_start(). *			Error messages may be logged to the console *			and/or the error log. * *//* * BSY timing loop count (see SZ_DISCON: in SZ_MESSI:). * Don't change, 500 is a good balance for both * 90 and 60 NS CPUs. * NOTE: to disable BSY timing, set sz_i_btcnt = 1. */int	sz_i_btcnt = 500;/*#define SZ_BT_DEBUG*/#ifdef	SZ_BT_DEBUGint	sz_i_bt[64];	/* 64 units - allows for 8 5380 cntlrs */#endif	SZ_BT_DEBUG#ifdef	ELDEBUG/* Set ID of target to cause reselect error 0 (on bus 0 only) */int	sz_eldb_reselerr0 = -1;/* Set to cntlr # to cause error */int	sz_eldb_stryintr0 = -1;int	sz_eldb_stryintr1 = -1;/* Set ID of target to cause activity status error (on bus 0 only) */int	sz_eldb_actstat = -1;/* Set ID of target to cause DBBR message to be logged (on bus 0 only) */int	sz_eldb_dbbr0 = -1;int	sz_eldb_dbbr1 = -1;int	sz_eldb_dbbr2 = -1;int	sz_eldb_dbbr3 = -1;/* Set ID of target to cause REQ failed to set (on bus 0 only) */int	sz_eldb_buserra0 = -1;/* Set ID of target to cause REQ failed to clear (on bus 0 only) */int	sz_eldb_buserr31 = -1;/* Set ID of target to cause rcv < 5 data bytes (on bus 0 only) */int	sz_eldb_buserr12 = -1;/* Set ID of target to cause unknown message (on bus 0 only) */int	sz_eldb_buserr73 = -1;int	sz_eldb_buserrf3 = -1;/* Set ID of target to cause BSY hung on CMDCPT (on bus 0 only) */int	sz_eldb_buserr74 = -1;/* Set ID of target to cause BSY not set on phase change (on bus 0 only) */int	sz_eldb_buserr4e = -1;/* Set ID of target to cause REQ not set on phase change (on bus 0 only) */int	sz_eldb_buserr4f = -1;#endif	ELDEBUGszintr(cntlr)int cntlr;{    int unit, targid;    int curstat, save_selstat;    int tid, scsi_id, nbits;    register struct sz_softc *sc;    register struct buf *dp;    register struct buf *bp;    register struct sz_regs *szaddr = (struct sz_regs *)szmem + cntlr;    register struct nb_regs *sziaddr = (struct nb_regs *)nexus;    register int reg_cnt;	/* MUST be a register for timing */    char *stv;			/* virtual address of st page tables	      */    struct pte *pte, *mpte;	/* used for mapping page table entries	      */    char *bufp;    unsigned v;    int o, npf;    struct proc *rp;    u_char *byteptr;    int i, s, retval, count;    int cmdcnt;    int complete;    int	num_expected, num_received;    u_char cmd_type;    int exmsg_byte, exmsg_len, exmsg_cnt, exmsg_sdtr, exmsg_data;    int ftt;    int wedged, force_reset;    int flags, subtyp;    struct format_params *fp;    struct reassign_params *rbp;    struct read_defect_params *rdp;    struct defect_descriptors *dd;    struct mode_sel_sns_params *msp;    struct io_uxfer *iox;    int datacnt;    force_reset = 0;    sc = &sz_softc[cntlr];#ifdef	ELDEBUG    if (cntlr == sz_eldb_stryintr0) {	flags = SZ_HARDERR | SZ_LOGREGS;	scsi_logerr(sc, 0, -1, SZ_ET_STRYINTR, 0, 0, flags); /* ELDEBUG */	sz_eldb_stryintr0 = -1;    }    if (cntlr == sz_eldb_stryintr1) {	flags = SZ_HARDERR | SZ_LOGREGS | SZ_LOGSELST;	scsi_logerr(sc, 0, -1, SZ_ET_STRYINTR, 1, 0, flags); /* ELDEBUG */	sz_eldb_stryintr1 = -1;    }#endif	ELDEBUG    /*     * Ingore interrupts if bus reset in progress.     * No interrupts should occur during reset wait period.     */    if (sc->sc_rip) {	i = szaddr->scs_reset;	return;    }    ftt = 1;    targid = -1;	/* So sz_start() won't be called in abort: below */    /*     *	The RST bit in the scs_curstat register is not latched!     *	So, we use the PARCK bit in the mode register to detect     *	a bus reset. We set PARCK and never clear it, so if it     *	gets cleared we assume a bus reset did it.     *	If we detect a bus reset, we abort the current operation,     *	then force another bus reset. This makes sure we get back     *	to a known state if the reset was a glitch (not every     *	device detected the reset).     */    if ((szaddr->scs_curstat & SCS_RST) ||	((szaddr->scs_mode & SCS_PARCK) == 0)) {	scsi_logerr(sc, 0, -1, SZ_ET_BUSRST, 0, 0, SZ_HARDERR);	force_reset = 1;    }    /*     * Use SCSI target ID to establish needed context.     * If channel active use sc_active.     * If not, read SCSI data bus during reselect.     */    if (sc->sc_active) {	for (targid = 0; targid < NDPS; targid++)	    if (sc->sc_active & (1 << targid))		break;	if (szaddr->scs_status & SCS_PARERR) {	    flags = SZ_HARDERR | SZ_LOGREGS;	    scsi_logerr(sc, 0, targid, SZ_ET_PARITY, 0, 0, flags);

⌨️ 快捷键说明

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