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

📄 scsi_5380.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	    i = szaddr->scs_reset;	    szaddr->scs_mode = SCS_PARCK;	    goto abort;	}	unit = sc->sc_unit[targid];	dp = &szutab[unit];	bp = dp->b_actf;	if ((dp->b_active == 0) || (bp == 0)) {	    scsi_logerr(sc, 0, targid, SZ_ET_ACTSTAT, 0, 0, SZ_HARDERR);	    i = szaddr->scs_reset;	    if (force_reset)		goto abort;	    else		return;	}	/*	 * TODO:	 *	Debug code. Can't remember ever hitting this one.	 */	if ((sc->sc_selstat[targid] != SZ_SELECT) &&	    (sc->sc_selstat[targid] != SZ_RESELECT)) {	    flags = SZ_HARDERR | SZ_LOGSELST;	    scsi_logerr(sc, 0, targid, SZ_ET_ACTSTAT, 1, 0, flags);	    i = szaddr->scs_reset;	    goto abort;	}#ifdef	ELDEBUG	if ((cntlr == 0) && (targid == sz_eldb_actstat)) {	    flags = SZ_HARDERR | SZ_LOGSELST;	    scsi_logerr(sc, 0, targid, SZ_ET_ACTSTAT, 1, 0, flags);/* ELDEBUG */	    sz_eldb_actstat = -1;	}#endif	ELDEBUG	save_selstat = sc->sc_selstat[targid];	/* if only DMA set, was phase mismatch intr */	if (sz_no_spin1) {	    if (sz_no_spin3)		szaddr->scs_mode &= ~SCS_DMA;	    else		if ((szaddr->scs_mode & (SCS_DMA|SCS_INTEOP)) == SCS_DMA)		    szaddr->scs_mode &= ~SCS_DMA;	}    }    if (force_reset)	/* bus reset detected, but we were not active */	goto abort;    /*     * If BSYERR set, target has disconnected. Say we are no     * longer active. Start disconnect timer if target is a     * disk. Call sz_start() to start next I/O, if possible.     * Could also be a busy target (see below).     */    if((szaddr->scs_status & SCS_BSYERR) == SCS_BSYERR) {	szaddr->scs_mode = SCS_PARCK;		/* clears MONBSY */	i = szaddr->scs_reset;	if (sc->sc_szflags[targid] & SZ_BUSYTARG) {	    /*	     * Not a disconnect. Target returned a busy status and	     * cannot accept a command right now. So we queue a	     * timeout to resend the command later.	     */	    sc->sc_selstat[targid] = SZ_IDLE;	    sc->sc_fstate = 0;/*	    szaddr->scs_mode = SCS_PARCK;	*/	    szaddr->scs_tarcmd = 0;	/* make sure phases match for 5380 */	    szaddr->scs_outdata = 0;	    sc->sc_active = 0;		/*  channel no longer active */	    if (sc->sc_dkn[targid] >= 0)		dk_busy &= ~(1 << sc->sc_dkn[targid]);	    /* TODO: time should be device specific! */	    timeout(sz_timer4, (caddr_t)unit, 50);	/* 0.5 sec */	}	else {sz_i_discon:#ifdef	SZDEBUG	    printd2("szintr: disconnect\n");#endif	SZDEBUG#ifdef	DCT_STATS	    sc->sc_dcstart[targid] = sziaddr->nb_diagtime;#endif	DCT_STATS	    sc->sc_selstat[targid] = SZ_DISCONN;/*	    szaddr->scs_mode = SCS_PARCK;	*/	    szaddr->scs_tarcmd = 0;	/* make sure phases match for 5380 */	    szaddr->scs_outdata = 0;	    sc->sc_active = 0;		/*  channel no longer active */	    if (sz_do_rsto) {		/*		 * TODO: needs more work.		 * Ok for RZ22, RZ23, and RZ55. Who knows for RZxx?		 * Use longer timeout for floppy disk.		 * Do this at all? Use command timeout instead?		 * No timeout on format, reassign, vfy_data, and rdd commands.		 * Only timeout read, write, read capacity commands.		 */		if ((sc->sc_devtyp[targid] & SZ_DISK) &&				!sc->sc_rzspecial[targid]) {		    switch (sc->sc_curcmd[targid]) {		    case SZ_READ:		    case SZ_WRITE:		    case SZ_READ_10:		    case SZ_WRITE_10:		    case SZ_RDCAP:			/* TODO: what about non-DEC floppy? */			if ((sc->sc_devtyp[targid] == RX23) ||			    (sc->sc_devtyp[targid] == RX33)) {			    timeout(sz_timer2, (caddr_t)unit, hz*30);			}			else			    timeout(sz_timer2, (caddr_t)unit, hz*10);			sc->sc_szflags[targid] |= SZ_TIMERON;			break;		    default:			break;		   }		}	    }	}	/*	 * Select enable should already be on, BUT...	 */	szaddr->scs_selena = sc->sc_sysid;	sc->sc_scs_selena = sc->sc_sysid;	DELAY(10);	/*	 * The bus can be busy again by the time we get here	 * because of the delay between the time BSYERR set	 * and we service the loss of BSY interrupt.	 * If SEL is true, then a device (can even be the one	 * that just disconnected) has grabbed the bus. So,	 * we don't call sz_start() to start the next I/O, since	 * the bus would be busy and arbitration would fail.	 * As soon as the IPL drops we will get a reselect interrupt.	 */	if (szaddr->scs_status & SCS_INTREQ) {	    if (szaddr->scs_curstat & SCS_SEL)		return;	}	sz_start(sc, -1);	/* Start next I/O (if one is ready) */	return;    }    /*     * If we are not active, check for reselect.     */    if(sc->sc_active == 0) {	/* NOTE: make sure BSY false for bus settle delay (400 ns) */	/*	 * There is critical timing in the reselect code path.	 * Do not remove the spl6(). Even the clock must not	 * be allowed to interrupt this code. The result could	 * be multiple targets selected on the SCSI bus (very bad).	 */	s = spl6();	curstat = (szaddr->scs_curstat & SCS_BSY);	curstat |= (szaddr->scs_curstat & SCS_BSY);	curstat |= szaddr->scs_curstat;	if ((curstat & (SCS_BSY|SCS_SEL|SCS_IO)) == (SCS_SEL|SCS_IO)) {	    i = szaddr->scs_mode;	    szaddr->scs_mode |= SCS_PARCK;	/* be sure parity checking on */#ifdef	SZDEBUG	    printd2("szintr: reselect\n");#endif	SZDEBUG	    /*	     * Read bus ID bits from current data register.	     * Make sure only two ID bits on the bus	     * and one of them is the initiator's.	     * Don't respond to the reselect if there is a parity error.	     * Only log the parity error if ID bits on the data bus.	     * No IDs on the bus means its not being driven, i.e.,	     * the target droped the reselect after the 5380 set INTREQ.	     */	    scsi_id = szaddr->scs_curdata;	    szaddr->scs_mode = i;	/* restore mode regsiter */	    if (szaddr->scs_status & SCS_PARERR) {		if (scsi_id != 0) {		    flags = SZ_HARDERR | SZ_LOGREGS | SZ_LOGBUS;		    scsi_logerr(sc, 0, -1, SZ_ET_PARITY, 1, scsi_id, flags);		}		i = szaddr->scs_reset;		splx(s);		return;	    }	    nbits = 0;	    for (tid = 0; tid < NDPS; tid++)		if (scsi_id & (1 << tid))		    nbits++;#ifdef	ELDEBUG	    for (tid = 0; tid < NDPS; tid++) {		if ((1 << tid) == sc->sc_sysid)		    continue;	/* skip initiator */		if (scsi_id & (1 << tid))		    break;	    }	    if ((cntlr == 0) && (tid == sz_eldb_reselerr0)) {		nbits = 3;		sz_eldb_reselerr0 = -1;	    }#endif	ELDEBUG	    if ((nbits != 2) || ((scsi_id & sc->sc_sysid) == 0)) {		flags = SZ_HARDERR | SZ_LOGBUS | SZ_LOGREGS;		scsi_logerr(sc, 0, -1, SZ_ET_RESELERR, 0, scsi_id, flags);		i = szaddr->scs_reset;		splx(s);		/* TODO: which way is correct? */		if (sz_i_midrst) {		    force_reset = 1;		    goto abort;		}		else		    return;	    }	    /*	     * Must assert BSY within 200 Usec after we detect	     * reselect, so we set BSY as soon as we can.	     */	    szaddr->scs_inicmd = SCS_INI_BSY;	    for (tid = 0; tid < NDPS; tid++) {		if ((1 << tid) == sc->sc_sysid)		    continue;	/* skip initiator */		if (scsi_id & (1 << tid))		    break;	    }	    sc->sc_active = (scsi_id & ~sc->sc_sysid);	    splx(s);		/* end of critical timing sequence */	    targid = tid;	    save_selstat = sc->sc_selstat[targid];	    if (sc->sc_selstat[targid] != SZ_DISCONN) {		flags = SZ_HARDERR | SZ_LOGSELST;		scsi_logerr(sc, 0, targid, SZ_ET_RESELERR, 1, 0, flags);		i = szaddr->scs_reset;		szaddr->scs_inicmd = 0;	/* clear BSY */		sc->sc_selstat[targid] = save_selstat;		/* TODO: return or abort? */		/* TODO: this error is very bad news! what to do? */		return;	    }	    SZWAIT_WHILE(((szaddr->scs_curstat & SCS_SEL) == SCS_SEL),10000,retval);	    if(retval >= 10000) {		flags = SZ_HARDERR;		scsi_logerr(sc, 0, targid, SZ_ET_RESELERR, 2, 0, flags);		/* TODO: temp read reset reg so don't loose interrupts */		i = szaddr->scs_reset;		szaddr->scs_inicmd = 0;		/* clear BSY */		sc->sc_active = 0;		sc->sc_selstat[targid] = save_selstat;		goto abort;	    }	    szaddr->scs_inicmd = 0;		/* clear BSY */	    /* NOTE: we are looking for BSY from the target */	    DELAY(1);	    if (((szaddr->scs_curstat & SCS_BSY) == 0) &&		((szaddr->scs_curstat & SCS_BSY) == 0) &&		((szaddr->scs_curstat & SCS_BSY) == 0)) {		flags = SZ_HARDERR;		scsi_logerr(sc, 0, targid, SZ_ET_RESELERR, 3, 0, flags);		i = szaddr->scs_reset;		sc->sc_active = 0;		sc->sc_selstat[targid] = save_selstat;		return;	    }	    DELAY(200);	    if (((szaddr->scs_curstat & SCS_BSY) == 0) &&		((szaddr->scs_curstat & SCS_BSY) == 0) &&		((szaddr->scs_curstat & SCS_BSY) == 0)) {		flags = SZ_HARDERR;		scsi_logerr(sc, 0, targid, SZ_ET_RESELERR, 4, 0, flags);		i = szaddr->scs_reset;		sc->sc_active = 0;		sc->sc_selstat[targid] = save_selstat;		return;	    }	    /* NOTE: must turn scs_selena back on for any subsequent error */	    sc->sc_selstat[targid] = SZ_RESELECT;	    unit = sc->sc_unit[targid];	    dp = &szutab[unit];	    bp = dp->b_actf;	    if ((dp->b_active == 0) || (bp == 0)) {		flags = SZ_HARDERR;		scsi_logerr(sc, 0, targid, SZ_ET_RESELERR, 5, 0, flags);		i = szaddr->scs_reset;		sc->sc_active = 0;		szaddr->scs_selena = sc->sc_sysid;		sc->sc_scs_selena = sc->sc_sysid;		sc->sc_selstat[targid] = save_selstat;		return;	    }#ifdef	DCT_STATS	    sc->sc_dcend[targid] = sziaddr->nb_diagtime;	    /* diagtime counter wraps after 16 bits */	    if (sc->sc_dcend[targid] < sc->sc_dcstart[targid])		sc->sc_dcend[targid] += 65536;	    sc->sc_dcdiff[targid] = sc->sc_dcend[targid]-sc->sc_dcstart[targid];	    if (sc->sc_dcdiff[targid] > sc->sc_dclongest[targid])		sc->sc_dclongest[targid] = sc->sc_dcdiff[targid];#endif	DCT_STATS	}	else {	    splx(s);	/* cuz we set spl6() in above if statement */	    /*	     * We get here when an interrupt occurs and we	     * are not active and the bus is free. We	     * assume this is a reselect timeout interrupt.	     * If no disconnected targets, then its a stray interrupt.	     * We reset the controller and ignore the interrupt.	     * We depend on the disconnect timeout (sz_timer2)	     * to kick the target and get it going again.	     * First, check for parity error.	     */	    if (szaddr->scs_status & SCS_PARERR) {		flags = SZ_HARDERR | SZ_LOGREGS;		scsi_logerr(sc, 0, -1, SZ_ET_PARITY, 2, 0, flags);		i = szaddr->scs_reset;		return;	    }	    count = 0;	    for (i = 0; i < NDPS; i++)		count += sc->sc_selstat[i];	    if (count == 0) {		flags = SZ_HARDERR | SZ_LOGREGS;		scsi_logerr(sc, 0, -1, SZ_ET_STRYINTR, 0, 0, flags);	    }	    else {		flags = SZ_HARDERR | SZ_LOGREGS | SZ_LOGSELST;		scsi_logerr(sc, 0, -1, SZ_ET_STRYINTR, 1, 0, flags);	    }	    i = szaddr->scs_reset;	    return;	}    }    /*     * THIS CANNOT HAPPEN, unless the hardware     * goes insane (like the first SCSI/SCSI controller).     */    if (sc->sc_active == 0) {	scsi_logerr(sc, 0, -1, SZ_ET_ACTSTAT, 2, 0, SZ_HARDERR);	if (szaddr->scs_status & SCS_INTREQ)	    i = szaddr->scs_reset;	    return;    }#ifdef	ELDEBUG    if ((cntlr == 0) && (targid != -1) && (targid == sz_eldb_cmdabrtd0)) {	sz_eldb_cmdabrtd0 = -1;	goto abort;    }#endif	ELDEBUG    /*     * The target controls the bus phase. We wait for REQ and BSY     * to be asserted on the bus before determining which phase     * is active.  Once REQ and BSY are asserted, the appropiate action     * is taken.      */    /* TODO: moved from phase spin loop! */    if (sz_i_moveit) {	szaddr->scs_mode = SCS_PARCK;	/*	 * Turn off the SCS_INI_ENOUT driver	 */	inicmd_tmp &= ~SCS_INI_ENOUT;	szaddr->scs_inicmd = inicmd_tmp;    }    /* TODO: end of moved code! */    exmsg_byte = 0;    exmsg_sdtr = 0;    complete = 0;    do {	if (sz_no_spin2) {	    if ((ftt == 0) && (szaddr->scs_status & SCS_MATCH)) {		szaddr->scs_mode |= SCS_DMA;		return;	    }	    ftt = 0;	}	for (retval = 0; retval < 100000; retval++) {	    if (((szaddr->scs_curstat & SCS_BSY) == 0) &&		((szaddr->scs_curstat & SCS_BSY) == 0) &&		((szaddr->scs_curstat & SCS_BSY) == 0)) {		retval = 1000000;		break;	    }	    if (szaddr->scs_curstat & SCS_REQ)		break;	    DELAY(100);	}#ifdef	SPIN_STATS	if ((retval > sc->sc_i_spin1[targid]) && (retval < 100000)) {	    sc->sc_i_spin1[targid] = retval;	    sc->sc_i_spcmd[targid] = sc->sc_curcmd[targid];	    sc->sc_i_phase[targid] = ((szaddr->scs_curstat & SCS_PHA_MSK) >> 2);	}#endif	SPIN_STATS#ifdef	ELDEBUG	if ((cntlr == 0) && (targid == sz_eldb_buserr4e)) {	    retval = 1000000;	    sz_eldb_buserr4e = -1;	}	if ((cntlr == 0) && (targid == sz_eldb_buserr4f)) {	    retval = 100000;	    sz_eldb_buserr4f = -1;	}#endif	ELDEBUG	if (retval >= 100000) {	    if (retval == 1000000)		subtyp = 0x4e;	/* BSY dropped */	    else		subtyp = 0x4f;	/* REQ failed to set */	    flags = SZ_HARDERR | SZ_LOGREGS;	    scsi_logerr(sc, 0, targid, SZ_ET_BUSERR, subtyp, 0, flags);	    /* TODO: temp read reset reg so don't loose interrupts */	    /* TODO: caution, in a loop! */	    i = szaddr->scs_reset;	    sc->sc_active = 0;	    szaddr->scs_selena = sc->sc_sysid;	    sc->sc_scs_selena = sc->sc_sysid;	    /*	     * This code is in a loop. How we handle this error	     * depends on whether or not its the fi

⌨️ 快捷键说明

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