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

📄 scsi_kzq.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
    tmp_phase = kzqaddr->sii_dstat & SII_PHA_MSK;    tmp_state = kzqaddr->sii_cstat & SII_STATE_MSK;    kzqaddr->sii_comm = (tmp_state | tmp_phase | attn);#ifdef mips    wbflush();#endif mips    /* Send the data to the scsi bus using programmed IO */    if(kzq_use_programmed_io && (sc->sc_siireqack[targid] == 0)) {        for(i=0; i<count; i++) {	SZWAIT_UNTIL((kzqaddr->sii_dstat & SII_TBE),kzq_wait_count,retval);	if (retval >= kzq_wait_count) {	    scsi_logerr(sc, 0, targid, SZ_ET_BUSERR, 0x4a, 0, SZ_HARDERR);	    PRINTD(targid, 0x10, ("kzq_senddata: SII_TBE not set\n"));	    return(SZ_RET_ABORT);	}	kzqaddr->sii_data = *data++;	tmp_phase = kzqaddr->sii_dstat & SII_PHA_MSK;	tmp_state = kzqaddr->sii_cstat & SII_STATE_MSK;	kzqaddr->sii_comm = (SII_INXFER | tmp_state | tmp_phase);#ifdef mips        wbflush();#endif mips    }    kzqaddr->sii_dstat = SII_DNE;#ifdef mips    wbflush();#endif mips    return(SZ_SUCCESS);    }    /* Send the data to the scsi bus using DMA */    else {	u_short aligndata;#ifdef mips       if((u_long)data & 0x1) {	aligndata = (u_short)(*data & 0x00ff);       (sc->wmbcopy)(&aligndata,(sc->sc_rambuff+sc->sc_siidboff[targid]),count);	} 	else	{    	(sc->wmbcopy)(data, (sc->sc_rambuff + sc->sc_siidboff[targid]), count);	}	kzqaddr->sii_dmaddrl = ((sc->sc_siidboff[targid]) & 0x0ffff);	kzqaddr->sii_dmaddrh = ((((sc->sc_siidboff[targid]) & 0x0fffffff))>>16);wbflush();#endif mips    	kzqaddr->sii_dmlotc = count;        kzqaddr->sii_comm = 			(SII_DMA | SII_INXFER | tmp_state | tmp_phase | attn);#ifdef mips        wbflush();#endif mips	/* Wait for DMA to complete */        SZWAIT_UNTIL((kzqaddr->sii_dstat & SII_DNE),kzq_wait_count,retval);        kzqaddr->sii_comm &= ~(SII_INXFER | SII_DMA);	kzqaddr->sii_dstat = SII_DNE;#ifdef mips    wbflush();#endif mips	if(retval >= kzq_wait_count) {	    return(SZ_RET_ABORT);	}	return(SZ_SUCCESS);    }}/****************************************************************** * * Receive data from the scsi bus. * ******************************************************************/#ifdef	ELDEBUG/* Set ID of target to cause buserr 0x49 (bus 0 only) *//* DOES NOT WORK because programmed I/O is never used in kzq_recvdata() */int	sz_eldb_buserr49 = -1;#endif	ELDEBUGkzq_recvdata(sc, data, count)register struct sz_softc *sc;u_char *data;int count;{    int cntlr = sc->sc_siinum;    register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr;    int retval;    int tmp_state;    int tmp_phase;    int i;    int targid = kzq_getactive_target(sc);    /* Move the SII to the new phase */    tmp_phase = kzqaddr->sii_dstat & SII_PHA_MSK;    tmp_state = kzqaddr->sii_cstat & SII_STATE_MSK;    kzqaddr->sii_comm = (tmp_state | tmp_phase);#ifdef mips    wbflush();#endif mips    /* Recieve the data from the scsi bus using programmed IO */    if(kzq_use_programmed_io && (sc->sc_siireqack[targid] == 0)) {        for(i=0; i<count; i++) {	    SZWAIT_UNTIL((kzqaddr->sii_dstat & (SII_IBF|SII_MIS)),		kzq_wait_count, retval);#ifdef	ELDEBUG	    if ((sc->sc_curcmd[targid] == SZ_READ) && (cntlr == 0) &&		(targid == sz_eldb_buserr49)) {		retval = kzq_wait_count + 1;		sz_eldb_buserr49 = -1;	    }#endif	ELDEBUG	    if (retval >= kzq_wait_count) {		scsi_logerr(sc, 0, targid, SZ_ET_BUSERR, 0x49, 0, SZ_HARDERR);		PRINTD(targid, 0x10, ("kzq_recvdata: SII_IBF not set\n"));		return(SZ_RET_ABORT);	    }	    /* If a phase change occured then we are done */	    if(kzqaddr->sii_dstat & SII_MIS)		break;	    *data++ = kzqaddr->sii_data;	    tmp_phase = kzqaddr->sii_dstat & SII_PHA_MSK;	    tmp_state = kzqaddr->sii_cstat & SII_STATE_MSK;	    kzqaddr->sii_comm = (SII_INXFER | tmp_state | tmp_phase);#ifdef mips	    wbflush();#endif mips	}	kzqaddr->sii_comm &= ~SII_INXFER;	kzqaddr->sii_dstat = SII_DNE;#ifdef mips	wbflush();#endif mips	return(SZ_SUCCESS);    }    /* Recieve the data from the scsi bus using DMA */    else {#ifdef vax    	kzqaddr->sii_dmaddrl = (sc->sc_siidboff[targid] & 0xffff);    	kzqaddr->sii_dmaddrh = (sc->sc_siidboff[targid] >> 16);#endif vax#ifdef mips    	kzqaddr->sii_dmaddrl = ((sc->sc_siidboff[targid]) & 0x0ffffff);    	kzqaddr->sii_dmaddrh = ((((sc->sc_siidboff[targid]) & 0x0fffffff))>>16);    wbflush();    	kzqaddr->sii_dmlotc = count;        kzqaddr->sii_comm = (SII_DMA | SII_INXFER | tmp_state | tmp_phase);    wbflush();#endif mips      /* Wait for DMA to complete, MIS is also checked.  If the target changes	phases, this loop will not have to time out. */        SZWAIT_UNTIL((kzqaddr->sii_dstat & (SII_DNE|SII_MIS)), kzq_wait_count,	    retval);        kzqaddr->sii_comm &= ~(SII_INXFER | SII_DMA);	/* set DNE */	if(retval >= kzq_wait_count && !(kzqaddr->sii_dstat & SII_DNE))	{	    i = 10000;			/* wait for DNE */	    while(--i && ((kzqaddr->sii_dstat & SII_DNE) == 0))		;	    kzqaddr->sii_dstat = SII_DNE;	}	else	    kzqaddr->sii_dstat = SII_DNE;	kzqaddr->sii_dmlotc = 0;#ifdef mips    wbflush();#endif mips	if(retval >= kzq_wait_count && !(kzqaddr->sii_dstat & SII_MIS))	    return(SZ_RET_ABORT);    	(sc->rmbcopy)((sc->sc_rambuff + sc->sc_siidboff[targid]), data, count);#ifdef mips    wbflush();#endif mips	return(SZ_SUCCESS);    }}/****************************************************************** * * Clear all disconnected IO tasks due to a BUS RESET. * ******************************************************************/kzq_clear_discon_io_tasks(sc)register struct sz_softc *sc;{    int targid;    int unit;    struct buf *dp, *bp;    PRINTD(targid, 0x10, ("kzq_clear_discon_io_tasks: scanning IDs\n"));    /* Find out if any targets have I/O requests that disconnected */    for(targid=0; targid<NDPS; targid++) {	if( sc->sc_siireqack[targid] !=0 )/* if set: need to renegotiate */	    sc->sc_siisentsync[targid] = 0;	if(targid == sc->sc_sysid)	/* skip initiator */	    continue;	if(sc->sc_alive[targid] == 0)	/* non existent target */	    continue;	unit = sc->sc_unit[targid];	dp = (struct buf *)&szutab[unit];	if(!dp->b_active)		/* target not active */	    continue;	if (dp->b_actf == NULL)	    continue;			/* no IO requests pending */	if(!(sc->sc_szflags[targid] & SZ_WAS_DISCON))	{	    sc->sc_resid[targid] = sc->sc_b_bcount[targid];	    continue;			/* was not disconnected */	}	PRINTD(targid, 0x10,	    ("kzq_clear_discon_io_tasks: clearing ID %d\n", targid));	bp = dp->b_actf;	dp->b_actf = bp->av_forw;	dp->b_active = 0;	bp->b_resid = sc->sc_resid[targid];	bp->b_flags |= B_ERROR;	bp->b_error = EIO;	biodone(bp);	sc->sc_xstate[targid] = SZ_NEXT;	sc->sc_xevent[targid] = SZ_BEGIN;    }}/****************************************************************** * * Reset the SII chip. * ******************************************************************/kzq_reset(sc)register struct sz_softc *sc;{    int cntlr = sc->sc_siinum;    register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr;    int targid;    /* Reset the SII chip. */    kzqaddr->sii_comm = SII_CHRESET;    /* SII is always ID 7, and set up max REQ/ACK offset. */    kzqaddr->sii_id = SII_ID_IO | sc->sc_sysid;     /* Enable SII to drive SCSI bus. */    kzqaddr->sii_dictrl = SII_PRE;    /*     * Assert SCSI bus reset for at least 25 Usec to clear the      * world. SII_RST is self clearing.     */    kzqaddr->sii_comm = SII_RST;    DELAY(25);    /*     * Clear any pending interrupts from the reset.     */    kzqaddr->sii_cstat = kzqaddr->sii_cstat;    kzqaddr->sii_dstat = kzqaddr->sii_dstat;    /************************************************************/    /*								*/    /* Clear out KZQ DMA registers.				*/    /************************************************************/    kzqaddr->kzq_lbar = 0;    kzqaddr->kzq_qbar = 0;    kzqaddr->kzq_wc = 0;    /*     * Set up SII for SCSI parity checking,     * Select Enable, Reselect Enable, and Interrupt Enable.     */    kzqaddr->sii_csr = ( SII_RSE |SII_SLE | SII_PCE | SII_IE);        /*     * Clear all Active and Disconnected IO requests.     */    kzq_clear_discon_io_tasks(sc);    sc->sii_was_reset = 1;    DELAY(sz_wait_for_devices * 1000000);}/****************************************************************** * * Reset all the SII controllers (crash dump reset only). * ******************************************************************/kzqreset(){#ifdef mips    register struct sz_softc *sc = &sz_softc[0];    register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr;#endif mips    /* Reset the SII chip. */    kzqaddr->sii_comm = SII_CHRESET;    /* SII is always ID 7, and set up max REQ/ACK offset. */    kzqaddr->sii_id = SII_ID_IO | sc->sc_sysid;     /* Enable SII to drive SCSI bus. */    kzqaddr->sii_dictrl = SII_PRE;    /*     * Assert SCSI bus reset for at least 25 Usec to clear the      * world. SII_RST is self clearing.     */    kzqaddr->sii_comm = SII_RST;    DELAY(25);    /*     * Clear any pending interrupts from the reset.     */    kzqaddr->sii_cstat = kzqaddr->sii_cstat;    kzqaddr->sii_dstat = kzqaddr->sii_dstat;    /*     * Set up SII for SCSI parity checking,     * Select Enable, Reselect Enable, and Interrupt Enable.     */    kzqaddr->sii_csr = ( SII_RSE |SII_SLE | SII_PCE | SII_IE);    DELAY(5000000);}/****************************************************************** * * Handle interrupts from the SII chip. * ******************************************************************/#ifdef	ELDEBUG/* Set to ID of target to log a parity error (bus 0 only) */int	sz_eldb_parity = -1;/* Set to ID of target to log a reset detected error (bus 0 only) */int	sz_eldb_busrst = -1;#endif	ELDEBUGkzq_intr(cntlr)int cntlr;{    register struct sz_softc *sc = &sz_softc[cntlr];    register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr;    int targid, retval, timer;    int dmacount, offset, tmp_phase, tmp_state;    int handle_reselect;    u_short cstat, dstat;    int flags;#ifdef mips    if(kzq_stray_intr[cntlr] != 1) { /* Stray interrupt on reboot */    		/* Reset the SII chip. */    		kzqaddr->sii_comm = SII_CHRESET;                printf("kzq_intr: noprobe intr\n");		return;    }#endif mips    /* Initialize variables */    targid = kzq_getactive_target(sc);#ifdef vax    sc->scsi_bus_idle = 0;    sc->scsi_completed[targid] = 0;#endif vax    handle_reselect = 0;    /*the toggling of the IE bit in the csr is to allow the latched IRQ */    /* line to toggle. On the Ibus there is no latch, since it is based */    /* on levels. On the Qbus the transition is necessary.		*/    /* Thus the reset/set of the enable allows the latch to reflect	*/    /* the new incoming state and thus to pass that to the SII IRQ	*/    /* line. Without this toggle it is possible to miss an interrupt.	*/    kzqaddr->sii_csr &= ~SII_IE;	/*reset/set IE to toggle kzq IRQ */    cstat = kzqaddr->sii_cstat;    dstat = kzqaddr->sii_dstat;    kzqaddr->sii_csr |= SII_IE;		/* enable ints after grabbing regs */    /* Check for interrupt from a disconnected target */    if(targid == -1 || sc->sc_active == 0) {	/* Check if there are valid interrupts pending */	if(cstat & (SII_CI|SII_DI)) {	    /* We must wait for a STATE CHANGE to occur first */	    timer = 10000;	    while(--timer && ((kzqaddr->sii_cstat & SII_SCH) == 0));	    if(timer == 0) {/*cprintf("timer expired in interrupt, cstat= %x, dstat= %x\n", cstat, dstat);*/		/*		 * Check if a reselect occurred without the STATE		 * CHANGE bit (SII_SCH) being set. This condition		 * can occur when a reselect immediately follows a		 * disconnect and therefore we only get one STATE		 * CHANGE interrupt.		 */		cstat = kzqaddr->sii_cstat;		if((cstat & SII_DST_ONBUS) && 				(cstat & SII_CON))		    handle_reselect = 1;		else {		if(cstat & SII_RST_ONBUS) {			kzqaddr->sii_cstat &= ~SII_IE;			kzqaddr->sii_cstat = SII_RST_ONBUS;			kzqaddr->sii_cstat = SII_SCH;			kzqaddr->sii_cstat = SII_IE;#ifdef mips                        wbflush();#endif mips		}	    		return;		}            }        }	/* No interrupts pending, spurious interrupt occurred */	else {	    PRINTD(0xFF, 0x1,		("kzq_intr: spurious interrupt from inactive target\n"));	    return;	}    }/*end of int from disconnected target.*/#ifdef	ELDEBUG	if ((sc->sc_curcmd[targid] == SZ_READ) && (cntlr == 0) &&	    (targid == sz_eldb_parity)) {	    flags = SZ_HARDERR | SZ_LOGREGS;	    scsi_logerr(sc, 0, targid, SZ_ET_PARITY, 1, 0, flags);	    sz_eldb_parity = -1;	}	if ((sc->sc_curcmd[targid] == SZ_READ) && (cntlr == 0) &&	    (targid == sz_eldb_busrst)) {	    scsi_logerr(sc, 0, -1, SZ_ET_BUSRST, 1, 0, SZ_HARDERR);	    sz_eldb_busrst = -1;	    goto HANDLE_ERROR;	}#endif	ELDEBUG	XPRINTF(XPR_NFS, "intB: %x %x %x %x", sc->sc_siidmacount[targid],cstat,dstat,kzqaddr->sii_comm);    offset = (sc->sc_bpcount[targid] - sc->sc_siidmacount[targid]);	if(cstat & (SII_CI|SII_DI)) {

⌨️ 快捷键说明

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