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

📄 stc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * not a cartridge is present.	 */	/* Clear all flags so driver does not lock up after hard error */	sc->sc_flags = 0;	sc->sc_category_flags = 0;	sc->sc_stflags &= ~ST_NODEVICE;	sc->sc_sns.errclass = 0;	/* this allows the mechanism that sends the commands to the 	 * drive to be able to tell that these commands are coming	 * from the open routine and need to be handled in a special	 * way.	 */	st_from_open++;	do {	    sc->sc_sns.snskey = 0;	  if (unit_attn) {	    sc->sc_stflags |= st_rcvdiag(dev);	  }	  if (!(sc->sc_stflags & ST_NODEVICE)) {	    stcommand(dev, ST_TUR, 1);	    if(sc->sc_stflags & ST_NEED_SENSE) {	    stcommand(dev, ST_RQSNS, 1);	    switch(retval = sterror(sc)) {		case ST_SUCCESS:		    break;		case ST_RETRY:		    timeout(wakeup, (caddr_t)sc, hz/2);		    sleep((caddr_t)sc, PZERO + 1);		    retry++;		    if (!(sc->sc_flags & DEV_EOM)) {			sc->sc_flags = 0;		    }		    break;		case ST_FATAL:		    if (!(sc->sc_flags & DEV_EOM)) {			sc->sc_flags = 0;		    }		    if(flag & FNDELAY) {			sc->sc_stflags |= ST_NODEVICE;		    }		    else {			return(ENXIO);		    }		    break;	    }	    }	    else {		retval = ST_SUCCESS;	    }	  }	  else {	    retval = ST_SUCCESS;	  }	} while ((retry < 10) && (retval == ST_RETRY));	if (retry >= 10) {	    if (!(flag & FNDELAY)) {	    	DEV_UGH(sc->sc_device, unit, "offline");	    	return(EIO);	    }	}	/*	 * If ST_NODEVICE is not set, the device exists,	 * and we want to do a ST_MODSEL command	 */	if (!(sc->sc_stflags & ST_NODEVICE)) {	    stcommand(dev, ST_MODSEL, 1);	}	sc->sc_openf = 1;	sc->sc_blkno = (daddr_t)0;	sc->sc_nxrec = INF;	st_from_open = 0;	sc->sc_rate = ST_TIMERRATE;	if ((sc->sc_timer & ST_TIMERON) == 0) {	    sc->sc_timer = ST_TIMERON;	    timeout(st_timer, 0, (sc->sc_rate * hz)); /* schedule timer starting */	}#ifdef STDEBUG	ST_TRACK('O');#endif STDEBUG	return (0);}/*  */int st_rcvdiag(dev)	register dev_t dev;{	register struct st_softc *sc = &st_softc[0];	int unit = UNIT(dev);	int i;	u_char *byteptr;	byteptr = (u_char *)&sc->st_dat;	/* zero the receive data area */	for (i = 0; i < ST_RECDIAG_LEN; i++) {		*byteptr++ = 0;	}	/*	 * Issue this command twice, as the first one	 * after powerup always fails.	 */	stcommand(dev, ST_RECDIAG, 1);	stcommand(dev, ST_RECDIAG, 1);	if (sc->st_dat.dat.recdiag.ctlr_selftest != 0) {		printf("st0: controller failed selftest\n");		return(ST_NODEVICE);	}	if (sc->st_dat.dat.recdiag.drv_selftest != 0 ) {		printf("st0: drive failed selftest, code = 0x%x\n",			sc->st_dat.dat.recdiag.drv_selftest);		return(ST_NODEVICE);	}#ifdef STDEBUG	printd("st_rcvdiag: Rev. %d\n", sc->st_dat.dat.recdiag.ctlr_fw_rev);#endif STDEBUG	if (sc->st_dat.dat.recdiag.ctlr_fw_rev < 32 ) {		printf("st0: controller firmware rev %d not supported\n",			sc->st_dat.dat.recdiag.ctlr_fw_rev);		return(ST_NODEVICE);	}	/* clear unit_attn so that we won't call st_rcvdiag() on each open */	unit_attn = 0;	return(ST_SUCCESS);}/*  *//* * This timer is started in stopen(), and "goes off" every 30 seconds. * Whenever the timer "goes off" sc->sc_ticks is incremented and the * timeout value is looked up in st_timetable[] and checked against the * number sc->sc_ticks.  If the number of ticks in st_timetable[] has * been exceeded, we assume either the TZK50 controller or the TK50 * drive has failed to respond and we attempt to reset the controller * and drive and return all outstanding requests with an error. */st_timer(unused)int unused;{    register struct uba_ctlr *um = stdinfo[0]->ui_mi;    register struct st_softc *sc = &st_softc[0];    register struct buf *dp;    register struct buf *bp;    register struct nb1_regs *staddr = (struct nb1_regs *)qmem;    register struct nb_regs *stiaddr = (struct nb_regs *)nexus;    struct vsbuf *vs;    struct vsdev *vd;    int	i, s, zs, z;    dp = &stutab[0];    bp = dp->b_actf;    vs = &vsbuf;    vd = &vstapedev;#ifdef STDEBUG    printd("tick..");#endif STDEBUG    s = spl5();    /*     * if the drive is not open, return.     */    if (sc->sc_openf == 0) {#ifdef STDEBUG	printd("\n");#endif STDEBUG	sc->sc_timer = 0;	sc->sc_ticks = 0;	splx(s);	return;    }    if (dp->b_actf == dp) {	sc->sc_timer = ST_TIMERON;#ifdef STDEBUG	printd(" No work\n");#endif STDEBUG    }    else {	sc->sc_ticks++;	if (sc->sc_ticks > (char)st_timetable[sc->sc_curcmd]) {	    sc->sc_ticks = 0;#ifdef STDEBUG		printd("st_timer: sc->sc_curcmd = 0x%x\n", sc->sc_curcmd);		if (sc->sc_selstat == ST_DISCONN) {		    printd("st0: waiting for reselect...\n");		}		else {		    printd("st0: timeout -- What to do now?\n");		    st_dump_softc(sc);		}#endif STDEBUG		/* call st_start with ST_RESET to reset the bus */ 		sc->sc_stflags |= ST_ENCR_ERR;		sc->sc_xstate = ST_ERR;		sc->sc_xevent = ST_RESET;		/*		 * If the tape doesn't own the RAM buffer, call vs_bufctl		 * to have it allocated		 */		if (vs->vs_active != vd) {		    vd->vsd_action = VS_ALLOC;		    vd->vsd_funcptr = st_start;		    vs_bufctl(vd);#ifdef STDEBUG		    ST_TRACK('*');#endif STDEBUG		    return;		}		else {		    st_start(sc);		    /*		     * Make sure that the tape isn't hanging the system		     * by keeping the RAM buffer		     */		    if (vs->vs_active == vd) {			vd->vsd_action = VS_DEALLOC;			vs_bufctl(vd);		    }	    }	}#ifdef STDEBUG	else {	    printd(" work\n");	}#endif STDEBUG    }    /* queue another watch dog timer */    sc->sc_timer = ST_TIMERON;    timeout(st_timer, 0, (sc->sc_rate * hz));    splx(s);    return;}/*  */stclose(dev, flag)	register dev_t dev;	register int flag;{	register struct st_softc *sc = &st_softc[0];	register int unit = 0;	register int sel = SEL(dev);#ifdef STDEBUG	ST_TRACK('c');#endif STDEBUG	sc->sc_flags &= ~DEV_EOM;	if (flag == FWRITE || ((flag & FWRITE) &&	    (sc->sc_flags & DEV_WRITTEN))) {		stcommand(dev, ST_WFM, 2);		sc->sc_flags &= ~DEV_EOM;		stcommand(dev, ST_P_BSPACEF, 1);		sc->sc_flags &= ~DEV_EOM;	}	/* if we need to rewind... */	if ((sel == MTLR) || (sel == MTHR)) {		stcommand(dev, ST_REWIND, 0);	}	sc->sc_openf = 0;#ifdef STDEBUG	ST_TRACK('C');#endif STDEBUG}/*  */stcommand(dev, com, count)	register dev_t dev;	register int com;	register int count;{	register struct buf *bp = &cstbuf[UNIT(dev)];#ifdef STDEBUG	ST_TRACK('m');#endif STDEBUG	while (bp->b_flags & B_BUSY) {		if(bp->b_bcount == 0 && (bp->b_flags & B_DONE))			break;		bp->b_flags |= B_WANTED;		sleep((caddr_t)bp, PRIBIO);	}	/* Load the buffer.  The b_count field gets used to hold the command	 * count.  The b_resid field gets used to hold the command mnermonic.	 * These two fields are "known" to be "save" to use for this purpose.	 * (Most other drivers also use these fields in this way.)	 */	bp->b_flags = B_BUSY|B_READ;	bp->b_dev = dev;	bp->b_command = com;	bp->b_bcount = count;	bp->b_blkno = 0;	ststrategy(bp);	/*	 * In the case of rewind from close, don't wait.	 * This is the only case where count can be 0.	 */	if (count == 0)		return;	iowait(bp);	if (bp->b_flags&B_WANTED)		wakeup((caddr_t)bp);	bp->b_flags &= B_ERROR;#ifdef STDEBUG	ST_TRACK('M');#endif STDEBUG}/*  */ststrategy(bp)	register struct buf *bp;{	register struct uba_ctlr *um;	register struct st_softc *sc = &st_softc[0];	register struct buf *dp;	register struct vsdev *vd;	register int s;	int unit = 0;#ifdef STDEBUG	ST_TRACK('t');#endif STDEBUG	vd = &vstapedev;	if ((sc->sc_flags & DEV_EOM) && !((sc->sc_flags & DEV_CSE) ||	    (dis_eot_st[unit] & DISEOT))) {		bp->b_resid = bp->b_bcount;		bp->b_error = ENOSPC;		bp->b_flags |= B_ERROR;		biodone(bp);		return;	}#ifdef	TM_NO_FIX	sc->sc_category_flags &= ~DEV_TPMARK;#else	if ((bp->b_flags&B_READ) && (bp->b_flags&B_RAWASYNC) && 	    ((sc->sc_category_flags&DEV_TPMARK) ||	    (sc->sc_flags&DEV_HARDERR))) {		bp->b_error = EIO;		bp->b_flags |= B_ERROR;		biodone(bp);		return;	}#endif	TM_NO_FIX	bp->av_forw = NULL;	/* 	 * If ST_NODEVICE is set, the device was opened	 * with FNDELAY, but the device didn't respond.	 * We'll try again to see if the device is here,	 * if it is not, return an error	 */	if (sc->sc_stflags & ST_NODEVICE) {	    DEV_UGH(sc->sc_device,unit,"offline");	    bp->b_resid = bp->b_bcount;	    bp->b_error = ENOSPC;	    bp->b_flags |= B_ERROR;	    biodone(bp);	    return;	}	um = stdinfo[unit]->ui_mi;	s = spl5();	dp = &stutab[unit];	if (dp->b_actf == NULL)		dp->b_actf = bp;	else		dp->b_actl->av_forw = bp;	dp->b_actl = bp;	if (dp->b_active == 0) {		dp->b_active = 1;		sc->sc_xstate = ST_NEXT;		sc->sc_xevent = ST_BEGIN;		/*		 * Call the routine that allocates the VAXSTAR 16K buffer		 * that the disk controller and tape controller share.		 * When the buffer is allocated to us (the tape driver)		 * st_start will be called from the allocation routine		 */		vd->vsd_action = VS_ALLOC;		vd->vsd_funcptr = st_start;		vs_bufctl(vd);	}	splx(s);#ifdef STDEBUG	ST_TRACK('T');#endif STDEBUG}/*  *//* * Interrupts come through here */stintr(){    register struct uba_ctlr *um = stdinfo[0]->ui_mi;    register struct st_softc *sc = &st_softc[0];    register struct buf *dp;    register struct buf *bp;    register struct nb1_regs *staddr = (struct nb1_regs *)qmem;    register struct nb_regs *stiaddr = (struct nb_regs *)nexus;    register struct vsbuf *vs;    register struct vsdev *vd;    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 sel_dly = 0;    int	arb_tries;    int cmdcnt;    int complete;    int	num_expected;    vs = &vsbuf;    vd = &vstapedev;    dp = &stutab[0];    bp = dp->b_actf;#ifdef STDEBUG	ST_TRACK('i');#endif STDEBUG    /*     * Check to make sure the tape owns the 16k hardware     * buffer before touching any device registers.  If     * the tape doesn't have the buffer, request it.     */    if(vs->vs_status != VS_ST) {	sc->sc_stflags &= ~ST_RETD_KEEP;	vd->vsd_action = VS_ALLOC;	vd->vsd_funcptr = stintr;	vs_bufctl(vd);#ifdef STDEBUG	ST_TRACK('A');#endif STDEBUG	return;    }#ifdef STDEBUG    printd6('T');    if (stdebug > 6) {	printd("stintr:\n");	stdumpregs();    }#endif STDEBUG    /*     * If a disconnect, give the buffer back.  We don't     * need to save any pointers because we only have     * one drive, and will take up where we left off     * when a reselect occurs.     */    if((staddr->scs_status & SCS_BSYERR) == SCS_BSYERR) {#ifdef STDEBUG	printd2("stintr: disconnecting...\n");#endif STDEBUG	sc->sc_selstat = ST_DISCONN;	staddr->scs_mode = 0;	i = staddr->scs_reset;	if(sc->sc_stflags & ST_RETD_KEEP) {	    sc->sc_stflags &= ~ST_RETD_KEEP;	    vd->vsd_action = VS_DEALLOC;	    vs_bufctl(vd);#ifdef STDEBUG	ST_TRACK('B');#endif STDEBUG	}	else {	    return(VS_DEALLOC);	}	return;    }    /*     * If ST_DISCONN,  check for reselect.     */    if(sc->sc_selstat == ST_DISCONN) {	if(((staddr->scs_curstat & (SCS_BSY|SCS_SEL|SCS_IO)) == (SCS_SEL|SCS_IO))) {	    sc->sc_selstat = ST_RESELECT;#ifdef STDEBUG	    ST_TRACK('G');	    printd2("stintr: reselecting...\n");#endif STDEBUG	    inicmd_tmp = SCS_INI_BSY;	    staddr->scs_inicmd = inicmd_tmp;	    STWAIT_WHILE(((staddr->scs_curstat & SCS_SEL) == SCS_SEL),10000,retval);	    if(retval >= 10000) {		mprintf("st0: device failed to reselect\n");		goto abort;	    }	    inicmd_tmp &= ~SCS_INI_BSY;	    staddr->scs_inicmd = inicmd_tmp;	    sc->sc_selstat = ST_SELECT;	}    }    /*     * The target controls the bus phase. We wait for REQ and BSY     * to be asserted on the bus before determining which phase

⌨️ 快捷键说明

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