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

📄 scsi_kzq.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
				sdp_match++;				break;			}		    }		}		/*		 * If the device name did not match call it RZxx or TZxx.		 * Use the UNKNOWN entry from scsi_devtab (if it exists),		 * otherwise use our internal UNKNOWN entry.		 */		if (!sdp_match) {		    if (usdp)			sdp = usdp;		    else if (idp->perfdt == 0)			sdp = &szp_rz_udt;		    else if (idp->perfdt == 1)			sdp = &szp_tz_udt;		    else			sdp = &szp_cz_udt;		}		/*		 * Update counters and set the pointer to the completion 		 * handler.		 */		if (sdp->devtype & SZ_DISK){			szp_nrz++;			sc->device_comp[targid] = rzcomplete;		}		if (sdp->devtype & SZ_TAPE){			szp_ntz++;			sc->device_comp[targid] = tzcomplete;		}		if (sdp->devtype & SZ_CDROM){			szp_ncz++;			sc->device_comp[targid] = rzcomplete;		}		if ((sdp->devtype == RX23) || (sdp->devtype == RX33)) {			szp_nrx++;			sc->sc_mc_cnt[targid] = 1;			sc->device_comp[targid] = rzcomplete;		}		/* TODO: assumes length < 8 bytes */		bcopy(sdp->sysname, sc->sc_device[targid],			strlen(sdp->sysname));		sc->sc_devtab[targid] = sdp;		sc->sc_devtyp[targid] = sdp->devtype;		sc->sc_dstp[targid] = sdp->disksize;		/*		 * Act on the flags in device's scsi_devtab entry.		 */		if (sdp->flags & SCSI_TRYSYNC)		    sc->sc_siisentsync[targid] = 0;		else		    sc->sc_siisentsync[targid] = 1;		if (sdp->flags & SCSI_REQSNS) {		    sc->sc_curcmd[targid] = SZ_RQSNS;		    sz_bldpkt(sc, targid, SZ_RQSNS, 0, 1);		    kzq_scsistart(sc, targid, 0);		}		if (sdp->flags & SCSI_STARTUNIT) {		    /*		     * Send two start unit commands because a pending unit		     * attention may cause the first one to fail. We don't		     * for the drive to spin up here (happens in rzopen).		     */		    sc->sc_curcmd[targid] = SZ_P_SSUNIT;		    sz_bldpkt(sc, targid, SZ_P_SSUNIT, 0, 1);		    kzq_scsistart(sc, targid, 0);		    kzq_scsistart(sc, targid, 0);		}		if (sdp->flags & SCSI_TESTUNITREADY) {		    sc->sc_curcmd[targid] = SZ_TUR;		    sz_bldpkt(sc, targid, SZ_TUR, 0, 1);		    kzq_scsistart(sc, targid, 0);		}		if (sdp->flags & SCSI_READCAPACITY) {		    sc->sc_curcmd[targid] = SZ_RDCAP;		    sz_bldpkt(sc, targid, SZ_RDCAP, 0, 1);		    kzq_scsistart(sc, targid, 0);		}		if (sdp->probedelay > 0)		    DELAY(sdp->probedelay);		if (sdp->flags & SCSI_NODIAG)		    sz_unit_rcvdiag[(cntlr*NDPS)+targid] = 1;		break;	    }		/* end of switch */	    /*	     * Just to be sure the bus is free after inquiry.	     * RRD40 may hold bus for a while.	     */	    DELAY(kzq_wait_after_inquiry);	}		/* end of for loop */	/*	 * Clean out any left over interrupts.	 */	if (alive) {		kzqaddr->sii_cstat = kzqaddr->sii_cstat;		kzqaddr->sii_dstat = kzqaddr->sii_dstat;		kzqaddr->sii_csr = ( SII_RSE | SII_SLE | SII_PCE | SII_IE);#ifdef mips    		wbflush();#endif mips	}	/*	 * TODO: should use map to allocate 128KB buffer	 *	 * If last (really 2nd) call to kzq_probe,	 * or only one controller configured,	 * assign 128K data buffer slots.	 *	 * 128K data buffer allocation strategy:	 *	1KB  - SII controller for non READ/WRITE DMA transfers	 *	16KB - for each tape unit	 *	 8KB - for each cdrom unit	 *	??KB - for each disk unit	 * ?? is what's left after tapes and cdroms divided by # of disks.	 * ?? must be >= 8KB, should be >= 16KB, if not reduce	 * number of cdroms to 2, then number of tapes to 2.	 * If that don't fix it panic!	 * In any "real" configuration, we should	 * never hit these limits.	 */	if ((nNKZQ == 1) || (kzq_firstcall == 0)) {	    dboff = 0x0;	    /*             * Setup 128 byte ram buffer slots for each target to	     * be used for non READ/WRITE DMA Transfers on the SII.	     */	    for(i=0; i<NDPS; i++) {		sc->sc_siidboff[i] = dboff;		dboff += 128;		}	    dboff = 1024;	    /* determine rz slot size, must be > 16kb */	    cz_slotsize = tz_slotsize = rz_slotsize = 16 * 1024;	    for (cntlr=0; cntlr<nNKZQ; cntlr++) {		sc = &sz_softc[cntlr];		for (targid=0; targid<NDPS; targid++) {		    if (targid == sc->sc_sysid)			continue;		    if (sc->sc_alive[targid] == 0)			continue;		    sc->sc_dboff[targid][0] = dboff;		    sc->sc_dboff[targid][1] = dboff+KZQ_MAX_DMA_XFER_LENGTH;		    sc->sc_segcnt[targid] = 64 * 1024; /* Get rid of in freds code */		    dboff += rz_slotsize;		    PRINTD(targid, 0x20,			("kzq_probe: cntlr=%d targid=%d devtype=%x ", cntlr,			targid, sc->sc_devtyp[targid]));		    PRINTD(targid, 0x20, ("req/ack=%d slotsize=%d\n",			     sc->sc_siireqack[targid], sc->sc_segcnt[targid]));		}	    }	}	if (kzq_firstcall)	    kzq_firstcall = 0;#ifdef SZDEBUG	PRINTD(-1, 0x8, ("kzq_probe: done probing the SCSI bus\n"));	if(kzq_debug_probe) {	    kzqdebug = save_kzqdebug;	    kzqtarget = save_kzqtarget;	}#endif SZDEBUG#ifdef mips   wbflush();#endif mips   return(alive);}/****************************************************************** * * Start a SCSI operation on the SII chip. * ******************************************************************/kzq_scsistart(sc, targid, bp)register struct sz_softc *sc;int targid;register struct buf *bp;{    int cntlr = sc->sc_siinum;    register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr;    volatile char *stv;    int retval;    int timer;    int phase;    u_short cstat, dstat;    int flags;    /*     * 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.     */    kzqaddr->sii_csr |= SII_SLE;#ifdef mips    wbflush();#endif mips    if(bp == (struct buf *)0) {        kzqaddr->sii_csr &= ~(SII_RSE | SII_IE);	sc->scsi_polled_mode = 1;    }    else	{	 /* Have to clear out the rambuffer area.  It is possible for a target	    to not not return all the requested bytes.  We have to make sure	    that at least the extra bytes are cleared. */	    if(sc->sc_rzspecial[targid]) {		struct mode_sel_sns_params *msp;	      /* Some risk here using get_validbuf_kzq() w/out any error checking.		It is probably low, at this point the target should not be		doing anything, and ready for the upcomming command.  Note:		this should be moved into the DMA level code. */				msp = (struct mode_sel_sns_params *)sc->sc_rzparams[targid];		if(sc->sc_actcmd[targid] == SZ_MODSNS)		{		    stv = sc->sc_rambuff +			(sc->sc_dboff[targid][get_validbuf_kzq(sc, targid)] );		    (sc->wmbzero)(stv, msp->msp_length);		}	    }        kzqaddr->sii_csr |= ( SII_RSE | SII_IE);        sc->scsi_polled_mode = 0;    }#ifdef mips    wbflush();#endif mips    /* Perform target arbitration and selection */    if((retval = kzq_select_target(sc, targid)) != SZ_SUCCESS) {	return(retval);    }BEGIN_LOOP:    /* Loop through all bus phases until command complete */    sc->scsi_completed[targid] = 0;    sc->scsi_bus_idle = 0;    cstat = kzqaddr->sii_cstat;    dstat = kzqaddr->sii_dstat;    do {/*XPRINTF(XPR_NFS, "B: %x", sc->sc_siidmacount[targid],0,0,0);cprintf("B: %x %x", sc->sc_siidmacount[targid],bp,0,0);*/	if(cstat & (SII_CI|SII_DI)) {        /* Check for a BUS ERROR */        if(cstat & SII_BER) {  	    kzqaddr->sii_cstat = SII_BER;#ifdef mips            wbflush();#endif mips	}        /* Check for a PARITY ERROR */	if(dstat & SII_IPE) {	    flags = SZ_HARDERR | SZ_LOGREGS;	    scsi_logerr(sc, 0, targid, SZ_ET_PARITY, 0, 0, flags);	    PRINTD(targid, 0x10, ("kzq_scsistart: scsi %d parity error\n",		cntlr));	    goto HANDLE_ABORT;	}	/* Check for a BUS RESET */	if(cstat & SII_RST_ONBUS) {	    kzqaddr->sii_cstat = SII_RST_ONBUS;#ifdef mips            wbflush();#endif mips	    scsi_logerr(sc, 0, -1, SZ_ET_BUSRST, 0, 0, SZ_HARDERR);	    PRINTD(targid, 0x10, ("kzq_scsistart: scsi %d bus reset\n", cntlr));	    goto HANDLE_ABORT;	}        /* Check for a STATE CHANGE */        if(cstat & SII_SCH)	{	  /* If SZ_BUSYTARG is set, the target returned a BUSY status for the	    current command.   The target has disconnected from the bus.	    Return SZ_IP, and allow the interrupt handler take care of the	    disconnect. */	    if( bp && (sc->sc_szflags[targid] & SZ_BUSYTARG) )	    {		PRINTD(targid, 0x4,		    ("kzq_scsistart: target %d BUSY rtn SZ_IP\n", targid ));		return(SZ_IP);	    }	    kzqaddr->sii_cstat = SII_SCH;	/* clear the intr */#ifdef mips	    wbflush();				/* wait for write buffers */#endif mips            if(kzq_state_change(sc, &targid) != SZ_SUCCESS)                goto HANDLE_ABORT;	}	/* If disconnected and went to BUS FREE STATE then break */	if(sc->scsi_bus_idle)	    break;        /* Check for a PHASE MISMATCH */        if(dstat & SII_MIS) {            /* Check for a BUS ERROR */            if(cstat & SII_BER) {  	        kzqaddr->sii_cstat = SII_BER;#ifdef mips    wbflush();#endif mips	    }	    /* Always clear DID DMA flag on a phase change */	    sc->sc_szflags[targid] &= ~SZ_DID_DMA;            /* Handle the current bus phase */            if(kzq_phase_change(sc, dstat) != SZ_SUCCESS)                goto HANDLE_ABORT;            /* Wait for the next bus phase */            if(!sc->scsi_completed[targid] && 		  !(sc->sc_szflags[targid] & (SZ_WAS_DISCON|SZ_DID_DMA))) {		timer = 1000;		while(--timer && !(kzqaddr->sii_dstat & SII_MIS));    		dstat = kzqaddr->sii_dstat;		if(!sc->scsi_polled_mode && (timer == 0) && 			!(dstat & (SII_CI|SII_DI)) && 				(sc->sc_actcmd[targid] != SZ_RQSNS)) {                    PRINTD(targid, 0x4,			("kzq_scsistart: SII_MIS didn't set rtn SZ_IP\n"));		    return(SZ_IP);		}	    }	}	/* Check for fragmented DMA transfers (>8K) */	if(sc->scsi_polled_mode && !(dstat & SII_MIS) &&		(dstat & (SII_TBE|SII_IBF)) &&	  		((sc->sc_fstate == SZ_DATAI_PHA) || 				(sc->sc_fstate == SZ_DATAO_PHA))) {	    /* Restart the DMA transfer */	    if(!kzq_restartdma(sc))		goto HANDLE_ABORT;	}	/* Sometimes the target stays in the same phase */	if((dstat & (SII_IBF|SII_TBE)) && 		!(dstat & SII_MIS) &&			((sc->sc_fstate != SZ_DATAI_PHA) &&				(sc->sc_fstate != SZ_DATAO_PHA))) {            /* Check for a BUS ERROR */            if(cstat & SII_BER) {  	        kzqaddr->sii_cstat = SII_BER;#ifdef mips    wbflush();#endif mips	    }	    /* Handle the current bus phase */	    if(kzq_phase_change(sc, dstat) != SZ_SUCCESS)	        goto HANDLE_ABORT;	  }	}    dstat = kzqaddr->sii_dstat;    cstat = kzqaddr->sii_cstat;   /*   } while(sc->scsi_polled_mode && 	/* dont spin in here!!!! */    } while(!sc->scsi_bus_idle && 		!(sc->sc_szflags[targid] & (SZ_WAS_DISCON|SZ_DID_DMA)));/*XPRINTF(XPR_NFS, "E: %x", sc->sc_siidmacount[targid],0,0,0);cprintf("E: %x", sc->sc_siidmacount[targid],0,0,0);*/    /*     * 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(sc->scsi_bus_idle || (sc->sc_szflags[targid] & SZ_WAS_DISCON)) {        if(sc->scsi_completed[targid]) {            PRINTD(targid, 0x4,		("kzq_scsistart: COMMAND COMPLETED successfully\n"));	    sc->scsi_completed[targid] = 0;            sc->sc_active = 0;	    if (sc->sc_szflags[targid] & SZ_BUSYTARG)		{	        return(SZ_IP);		}    	    if(sc->sc_status[targid] == SZ_GOOD)		{	        return(SZ_SUCCESS);			}	    else		{	        return(SZ_RET_ERR);			}        } 	else if(sc->sc_szflags[targid] & SZ_WAS_DISCON) {            PRINTD(targid, 0x4, 		("kzq_scsistart: COMMAND IN PROGRESS disconnected\n"));	    return(SZ_IP);        }	else {            sc->sc_active = 0;#ifdef NO_TIMER	/* JAG */	    if(sc->sc_szflags[targid] & SZ_TIMERON) {	        untimeout(sii_timer, (caddr_t)sc->sc_unit[targid]);	        sc->sc_szflags[targid] &= ~SZ_TIMERON;	    }#endif NO_TIMER	/* JAG */	    return(SZ_RET_ERR);	}    }     else if(sc->sc_szflags[targid] & SZ_DID_DMA) {	/* Poll and busy wait for DMA completion */	if(sc->scsi_polled_mode) {            PRINTD(targid, 0x4, 		("kzq_scsistart: COMMAND IN PROGRESS dma poll mode\n"));            kzqaddr->sii_csr &= ~SII_IE;#ifdef mips            wbflush();#endif mips            SZWAIT_UNTIL((kzqaddr->sii_dstat & SII_DNE),kzq_wait_count,retval);

⌨️ 快捷键说明

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