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

📄 scsi_sii.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
		    if (targid == sc->sc_sysid)			continue;		    if (sc->sc_alive[targid] == 0)			continue;		    /* TODO: check for dboff pase end of 128K buffer? */		    if (sc->sc_devtyp[targid] & SZ_CDROM) {			if (++ncz > szp_ncz) {			    sc->sc_alive[targid] = 0;			    continue;			}			sc->sc_dboff[targid] = dboff;			sc->sc_segcnt[targid] = cz_slotsize;			dboff += cz_slotsize;		    }		    else if (sc->sc_devtyp[targid] & SZ_TAPE) {			if (++ntz > szp_ntz) {			    sc->sc_alive[targid] = 0;			    continue;			}			sc->sc_dboff[targid] = dboff;			sc->sc_segcnt[targid] = tz_slotsize;			dboff += tz_slotsize;		    }		    else if (sc->sc_devtyp[targid] & SZ_DISK) {			sc->sc_dboff[targid] = dboff;			sc->sc_segcnt[targid] = rz_slotsize;			dboff += rz_slotsize;		    }		    else			continue;#ifdef SZDEBUG		    PRINTD(-1, 0x8, ("sii_probe: cntlr=%d targid=%d ",			     cntlr, targid));		    PRINTD(-1, 0x8, ("devtype=%x req/ack=%d slotsize=%d\n",			     sc->sc_devtyp[targid], sc->sc_siireqack[targid], 			     sc->sc_segcnt[targid]));#endif SZDEBUG		}	    }	}	if (sii_firstcall)	    sii_firstcall = 0;#ifdef SZDEBUG	PRINTD(-1, 0x8, ("sii_probe: done probing the SCSI bus\n"));	if(sii_debug_probe) {	    siidebug = save_siidebug;	    siitarget = save_siitarget;	}#endif SZDEBUG	return(alive);}/****************************************************************** * * Name:	sii_timer 	 * * Abstract:	Handle command timeouts on the SII chip.  * * Inputs: * unit		The ULTRIX logical unit number of the scsi device. * * Outputs:	None. * * Return values: None. ******************************************************************/sii_timer(unit)int unit;{    int cntlr, targid, s, retval;    register struct sz_softc *sc;    register struct sii_regs *siiaddr;    int flags;    s = spl5();    cntlr = (unit >> 3) & 1;    siiaddr = (struct sii_regs *)cvqmsi + cntlr;    sc = &sz_softc[cntlr];    targid = unit & 7;    /* Ignore timeouts for the tape device */    if(sc->sc_devtyp[targid] & SZ_TAPE) {#ifdef SZDEBUG    	PRINTD(targid, 0x4,	    ("sii_timer: SZ_TAPE cmd timeout (bus=%d target=%d cmd=0x%x)\n",	    	cntlr, targid, sc->sc_curcmd[targid]));#endif SZDEBUG	flags = SZ_HARDERR | SZ_LOGCMD | SZ_LOGREGS;	scsi_logerr(sc, 0, targid, SZ_ET_CMDTIMO, 0, 0, flags);	sc->sc_szflags[targid] &= ~SZ_TIMERON;	splx(s);	return;    }    /*     * The target disconnected and never reselected the SII.     * If we can select the target then issue a Bus Device     * Reset message to reset that target. This will cause     * the SII to go to the bus free state. In the interrupt     * routine the SII will then call "sz_start()" to finish     * up this command. If we cannot select the target then     * we simply reset the SCSI bus.     */    if(sc->sc_szflags[targid] & SZ_WAS_DISCON) {	/* Wait for scsi bus to be idle */	if (sc->sc_active) {    	    timeout(sii_timer, (caddr_t)sc->sc_unit[targid], 10);	    splx(s);	    return;	}#ifdef SZDEBUG    	PRINTD(targid, 0x4,	    ("sii_timer: DISCON cmd timeout (bus=%d target=%d cmd=0x%x)\n",	    	cntlr, targid, sc->sc_curcmd[targid]));#endif SZDEBUG	flags = SZ_HARDERR | SZ_LOGCMD | SZ_LOGREGS;	scsi_logerr(sc, 0, targid, SZ_ET_CMDTIMO, 1, 0, flags);        /* Try to select the disconnected target */        switch(retval = sii_select_target(sc, targid)) {	case SZ_BUSBUSY:	    /* Target reselected so handle it now. */	    if((siiaddr->sii_destat & SII_IDMSK) != targid)    	        timeout(sii_timer, (caddr_t)sc->sc_unit[targid], 10);	    else    	        timeout(sii_timer, (caddr_t)sc->sc_unit[targid], 30*hz);	    break;	case SZ_SUCCESS:	    /* Target selected so set flag to reset it. */	    sc->sc_szflags[targid] = SZ_RESET_DEV;	    break;	default:	    /* Target is hung so reset the SCSI bus. */	    scsi_logerr(sc, 0, -1, SZ_ET_RSTBUS, 0, 0, SZ_HARDERR);            sii_reset(sc);	}    }    /*     * The currently active target has hung the SCSI bus.     * Reset the SCSI bus and then return.     */    else {#ifdef SZDEBUG    	PRINTD(targid, 0x4,	    ("sii_timer: ACTIVE cmd timeout (bus=%d target=%d cmd=0x%x)\n",	    	cntlr, targid, sc->sc_curcmd[targid]));#endif SZDEBUG	flags = SZ_HARDERR | SZ_LOGCMD | SZ_LOGREGS;	scsi_logerr(sc, 0, targid, SZ_ET_CMDTIMO, 2, 0, flags);	scsi_logerr(sc, 0, -1, SZ_ET_RSTBUS, 1, 0, SZ_HARDERR);        sii_reset(sc);    }    splx(s);}/****************************************************************** * * Name:	sii_scsistart * * Abstract:	Start a SCSI operation on the SII chip. * * Inputs: * sc		Pointer to sz_softc structure for this controller. * targid	Target Id of device (0 - 7). * bp		Buffer pointer for I/O request. * * Outputs:	None. * * Return values: * SZ_SUCCESS		Command completed successfully. * SZ_IP		Command in progress waiting for interrupt. * SZ_RET_ERR		Command failed (returned bad status). * SZ_RET_ABORT		Command aborted. * SZ_BUSBUSY		Bus is busy, retry the command later. * SZ_RET_RESET		Resetting bus, retry command after bus reset. ******************************************************************/sii_scsistart(sc, targid, bp)register struct sz_softc *sc;int targid;register struct buf *bp;{    int cntlr = sc - &sz_softc[0];    register struct sii_regs *siiaddr = (struct sii_regs *)cvqmsi + cntlr;    int retval, phase, timer, tvalue;    int flags;    /* Initialize variables */    scsi_bus_idle = 0;    scsi_completed[targid] = 0;    scsi_polled_mode = 0;    sii_sent_cmd = 0;    /*     * If "bp" is "0" we use polled scsi mode, disallow reselect     * attempts, and disable interrupts for all DMA transfers. We      * poll for DMA completion instead of allowing interrupts.     */    siiaddr->sii_csr |= (SII_RSE | SII_IE | SII_SLE);    if(bp == (struct buf *)0) {        siiaddr->sii_csr &= ~(SII_RSE | SII_IE);	scsi_polled_mode = 1;    }    /* Perform target arbitration and selection */    if((retval = sii_select_target(sc, targid)) != SZ_SUCCESS)	return(retval);    /* Make sure that the command is in the sz_timetable. */    if (sc->sz_opcode < SZ_TIMETBL_SZ) {	/* Set the timeout value for the current scsi command */	sc->sc_szflags[targid] |= SZ_TIMERON;	if(sz_timetable[sc->sz_opcode] == 0) {	    tvalue = 2;	    timeout(sii_timer, (caddr_t)sc->sc_unit[targid], tvalue*30*hz);	}	else {	    tvalue = sz_timetable[sc->sz_opcode];	    timeout(sii_timer, (caddr_t)sc->sc_unit[targid], tvalue*30*hz);	}    }BEGIN_LOOP:    /* Loop through all bus phases until command complete */    do {        /* Check for a BUS ERROR */        if(siiaddr->sii_cstat & SII_BER)  	    siiaddr->sii_cstat = SII_BER;        /* Check for a PARITY ERROR */	if(siiaddr->sii_dstat & SII_IPE) {	    flags = SZ_HARDERR | SZ_LOGREGS;	    scsi_logerr(sc, 0, targid, SZ_ET_PARITY, 0, 0, flags);#ifdef SZDEBUG	    PRINTD(targid, 0x4, 		("sii_scsistart: scsi %d parity error\n", cntlr));#endif SZDEBUG	    goto HANDLE_ERROR;	}	/* Check for a BUS RESET */	if(siiaddr->sii_cstat & SII_RST_ONBUS) {	    siiaddr->sii_cstat = SII_RST_ONBUS;	    scsi_logerr(sc, 0, -1, SZ_ET_BUSRST, 0, 0, SZ_HARDERR);#ifdef SZDEBUG	    PRINTD(targid, 0x4, 		("sii_scsistart: scsi %d bus reset\n", cntlr));#endif SZDEBUG	    goto HANDLE_ERROR;	}        /* Check for a STATE CHANGE */        if(siiaddr->sii_cstat & SII_SCH) {	    siiaddr->sii_cstat = SII_SCH;            sii_state_change(sc, &targid);	}	/* If disconnected and went to BUS FREE STATE then break */	if(scsi_bus_idle)	    break;        /* Check for a PHASE CHANGE */        if(siiaddr->sii_dstat & SII_MIS) {            /* Check for a BUS ERROR */            if(siiaddr->sii_cstat & SII_BER)  	        siiaddr->sii_cstat = SII_BER;	    /* Always clear DID DMA flag on a phase change */	    sc->sc_szflags[targid] &= ~SZ_DID_DMA;            /* Handle the current bus phase */            if(sii_phase_change(sc, targid) != SZ_SUCCESS)                goto HANDLE_ERROR;            /* Wait for the next bus phase */            if(!scsi_completed[targid] && 		  !(sc->sc_szflags[targid] & (SZ_WAS_DISCON|SZ_DID_DMA))) {		if(!scsi_polled_mode && sii_sent_cmd &&			!(siiaddr->sii_cstat & (SII_CI|SII_DI)) &&				(sc->sc_actcmd[targid] != SZ_RQSNS))		    return(SZ_IP);	    }	}	/* Check for fragmented DMA transfers (>8K) */	if(scsi_polled_mode && !(siiaddr->sii_dstat & SII_MIS) &&		(siiaddr->sii_dstat & (SII_TBE|SII_IBF)) &&		    !(sc->sc_szflags[targid] & SZ_DID_DMA) &&	  		((sc->sc_fstate == SZ_DATAI_PHA) || 				(sc->sc_fstate == SZ_DATAO_PHA))) {	    /* Restart the DMA transfer */	    if(!sii_restartdma(sc, targid)) {#ifdef SZDEBUG		PRINTD(targid, 0x4,		    ("sii_scsistart: DMA error in sii_restartdma\n"));#endif SZDEBUG		scsi_logerr(sc, 0, targid, SZ_ET_BUSERR, 0x0cd, 0, SZ_HARDERR);	        goto HANDLE_ERROR;	    }	}	/* Sometimes the target stays in the same phase */	if((siiaddr->sii_dstat & (SII_IBF|SII_TBE)) && 		!(siiaddr->sii_dstat & SII_MIS) &&			((sc->sc_fstate != SZ_DATAI_PHA) &&				(sc->sc_fstate != SZ_DATAO_PHA))) {            /* Check for a BUS ERROR */            if(siiaddr->sii_cstat & SII_BER)  	        siiaddr->sii_cstat = SII_BER;	    /* Handle the current bus phase */	    if(sii_phase_change(sc, targid) != SZ_SUCCESS)	        goto HANDLE_ERROR;	}    } while(!scsi_bus_idle && 		!(sc->sc_szflags[targid] & (SZ_WAS_DISCON|SZ_DID_DMA)));    /*     * Check the status of the current SCSI operation. If the SCSI     * operation completed or disconnected then start the next SCSI      * operation, otherwise wait for the DMA to complete.     *      */    if(scsi_bus_idle || (sc->sc_szflags[targid] & SZ_WAS_DISCON)) {	/* Handle BUS DEVICE RESET and ABORT processing. */        if(sc->sc_szflags[targid] & (SZ_RESET_DEV|SZ_ABORT_CMD)) {#ifdef SZDEBUG            PRINTD(targid, 0x4,		("sii_scsistart: BUS DEVICE RESET and ABORT processing\n"));#endif SZDEBUG	    if(sc->sc_szflags[targid] & SZ_TIMERON) {	        untimeout(sii_timer, (caddr_t)sc->sc_unit[targid]);	        sc->sc_szflags[targid] &= ~SZ_TIMERON;	    }	    if (sc->sc_dkn[targid] >= 0)	        dk_busy &= ~(1 << sc->sc_dkn[targid]);	    /* For a BUS DEVICE RESET we must wait for device. */            if(sc->sc_szflags[targid] & SZ_RESET_DEV) {		scsi_logerr(sc, 0, targid, SZ_ET_RSTTARG, 0, 0, SZ_HARDERR);                timeout(sii_restart_target, 			sc->sc_unit[targid], sz_wait_for_devices*hz);            	sc->sc_active = 0;	        sc->sc_fstate = 0;		return(SZ_RET_RESET);	    }	    /* For an ABORT we simply retry the command. */	    else {	        sc->sc_active = 0;	        sc->sc_fstate = 0;	        sc->sc_szflags[targid] = (SZ_NEED_SENSE|SZ_RETRY_CMD);	        return(SZ_RET_ERR);	    }	}        else if(scsi_completed[targid]) {#ifdef SZDEBUG            PRINTD(targid, 0x8,		("sii_scsistart: COMMAND COMPLETED successfully\n"));#endif SZDEBUG	    if(sc->sc_szflags[targid] & SZ_TIMERON) {	        untimeout(sii_timer, (caddr_t)sc->sc_unit[targid]);	        sc->sc_szflags[targid] &= ~SZ_TIMERON;	    }            sc->sc_active = 0;    	    if(sc->sc_status[targid] == SZ_GOOD)	        return(SZ_SUCCESS);		    else	        return(SZ_RET_ERR);	        } 	else if(sc->sc_szflags[targid] & SZ_WAS_DISCON) {#ifdef SZDEBUG            PRINTD(targid, 0x8,		("sii_scsistart: COMMAND IN PROGRESS disconnected\n"));#endif SZDEBUG	    return(SZ_IP);        }	else {#ifdef SZDEBUG            PRINTD(targid, 0x4,		("sii_scsistart: (targid=%d) went to BUS FREE unexpectedly\n",			targid));#endif SZDEBUG            sc->sc_active = 0;	    if(sc->sc_szflags[targid] & SZ_TIMERON) {	        untimeout(sii_timer, (caddr_t)sc->sc_unit[targid]);	        sc->sc_szflags[targid] &= ~SZ_TIMERON;	    }	    return(SZ_RET_ERR);	}     }      else if(sc->sc_szflags[targid] & SZ_DID_DMA) {	/* Poll and busy wait for DMA completion */	if(scsi_polled_mode) {#ifdef SZDEBUG            PRINTD(targid, 0x8,

⌨️ 快捷键说明

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