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

📄 stc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	case SCS_MESSO:#ifdef STDEBUG	    printd2("stintr: SCS_MESSO:\n");#endif STDEBUG	    sc->sc_prevpha = sc->sc_fstate;	    sc->sc_fstate = ST_MESSO_PHA;	    sc->sc_stflags = 0;	    /*	     * Send the Identify message	     */	    if(staddr->scs_curstat & SCS_REQ) {		staddr->scs_outdata = ST_ID_DIS;		inicmd_tmp |= (SCS_INI_ENOUT | SCS_INI_ATN);		staddr->scs_inicmd = inicmd_tmp;		DELAY(2);		inicmd_tmp &= ~SCS_INI_ATN;		staddr->scs_inicmd = inicmd_tmp;		inicmd_tmp |= SCS_INI_ACK;		staddr->scs_inicmd = inicmd_tmp;		STWAIT_WHILE((staddr->scs_curstat & SCS_REQ),100000,retval);		if(retval >= 100000) {#ifdef STDEBUG		printd("stintr: SCS_MESSO: SCS_REQ failed to set\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('X');#endif STDEBUG		    goto abort;		}		inicmd_tmp &= ~SCS_INI_ACK;		staddr->scs_inicmd = inicmd_tmp;		if (staddr->scs_status & SCS_PARERR) {#ifdef STDEBUG		printd("stintr: SCS_MESSO: parity error\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('Y');#endif STDEBUG		    goto abort;		}	    }	    break;	case SCS_MESSI:#ifdef STDEBUG	    printd2("stintr: SCS_MESSI:\n");#endif STDEBUG	    sc->sc_prevpha = sc->sc_fstate;	    sc->sc_fstate = ST_MESSI_PHA;	    sc->sc_message = staddr->scs_curdata;	    inicmd_tmp |= SCS_INI_ACK;	    staddr->scs_inicmd = inicmd_tmp;	    STWAIT_WHILE(((staddr->scs_curstat & SCS_REQ) == SCS_REQ),1000000,retval);	    if(retval >= 1000000) {#ifdef STDEBUG	    printd("stintr: SCS_MESSI: SCS_REQ failed to clear\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('Z');#endif STDEBUG		goto abort;	    }	    inicmd_tmp &= ~SCS_INI_ACK;	    staddr->scs_inicmd = inicmd_tmp;	    switch (sc->sc_message) {		case ST_CMDCPT:		    /*		     * The command has completed, release the bus.		     */		    /* disable interrupts */		    stiaddr->nb_int_msk &= ~SCS_INT_TAPE;		    inicmd_tmp = 0;		    staddr->scs_inicmd = 0;		    staddr->scs_mode = 0;		    staddr->scs_tarcmd = 0;		    staddr->scs_selena = 0;		    /*		     * clear SCS_PARERR, SCS_INTREQ, and SCS_BSYERR 		     * in mode reg, and return 		     */		    /*		     * clear any pending interrupts		     */		    stiaddr->nb_int_reqclr = SCS_INT_TAPE;		    i = staddr->scs_reset;		    sc->sc_selstat = ST_IDLE;		    sc->sc_fstate = 0;		    /*		     * Call st_start to complete the transfer		     */		    sc->sc_stflags &= ~ST_DID_DMA;		    st_start();		    complete++;		    break;					case ST_SDP:		    if (sc->sc_prevpha == ST_DATAO_PHA) {			stiaddr->nb_hltcod = 0;		    	sc->sc_savcnt = (short)staddr->scd_cnt - 1;			sc->sc_stflags |= ST_WAS_DISCON;		    }/*		    else {			sc->sc_savcnt = 0;		    }*/		    if (sc->sc_prevpha == ST_DATAI_PHA) {			sc->sc_stflags |= ST_WAS_DISCON;			stiaddr->nb_hltcod = 0;			sc->sc_savcnt = (short)staddr->scd_cnt;			/* Fix for rev 45 TZK50 */			if (sc->sc_savcnt == 0)			    sc->sc_stflags |= ST_COPY_DONE;			    /*			     * Map the user page tables to my page tables (mpte)			     */			    if ((cpu == C_VAXSTAR) && cvs_exmode_on)				stv = (char *)cvseddbmem + 0x10000;			    else				stv = (char *)&staddr->nb_ddb[0];			    if ((bp->b_flags & B_PHYS) == 0) {				bufp = (char *)bp->b_un.b_addr;			    }			    else {				/*				 * Map to user space				 */				v = btop(bp->b_un.b_addr);				o = (int)bp->b_un.b_addr & PGOFSET;				npf = btoc(bp->b_bcount + o);				rp = (bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc;				if (bp->b_flags & B_UAREA) {				    pte = &rp->p_addr[v];				}				else if (bp->b_flags & B_PAGET) {				    pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];				}				else {				    pte = vtopte(rp, v);				}				bufp = (char *)ST_bufmap + o;				mpte = (struct pte *)stbufmap;				for (i = 0; i < npf; i++) {				    if (pte->pg_pfnum == 0)				    panic("st0: zero pfn in pte");				    *(int *)mpte++ = pte++->pg_pfnum | PG_V | PG_KW;				    mtpr(TBIS, (char *) ST_bufmap + (i * NBPG));				}				*(int *)mpte = 0;				mtpr(TBIS, (char *) ST_bufmap + (i * NBPG));			    }			    sc->sc_stflags |= ST_MAPPED;			    sc->sc_savstv = (long)stv;			    sc->sc_savbufp = (long)bufp;			/*			 * This is a quick way to subtract the the number of			 * bytes not transfered before the disconnect, from			 * the total number of bytes to transfer.  The result			 * is the number of bytes that need to be transfered.			 * sc->sc_savcnt is in two's complement form.			 */			bufp = bufp + ((short)bp->b_bcount - sc->sc_bcount);#ifdef STDEBUG				printd1("stintr: count = 0x%x\n",			    (((short)sc->sc_bcount + sc->sc_savcnt) & 0xffff));#endif STDEBUG			bcopy (stv, bufp,			    (((short)sc->sc_bcount + sc->sc_savcnt) & 0xffff));#ifdef STDEBUG			if (stdebug > 5) {			    int j;			    char *tmpstv;			    tmpstv = stv;			    printd("b_bcount = %d, bytes to read = %d\n",				bp->b_bcount,				(((short)bp->b_bcount + sc->sc_savcnt) & 0xffff));			    for (j = 0; j < (((short)bp->b_bcount + sc->sc_savcnt) & 0xffff); j++) {				printd("%c", *tmpstv++);			    }			    printd("\n");			}#endif STDEBUG		    }#ifdef STDEBUG		    printd1("stintr: save data pointers, scd_cnt = 0x%x\n",			sc->sc_savcnt);#endif STDEBUG		    break;		case ST_DISCON:#ifdef STDEBUG		    printd2("stintr: disconnect message\n");#endif STDEBUG		    staddr->scs_mode = (SCS_MONBSY|SCS_PARCK|SCS_INTPAR);#ifdef STDEBUG	ST_TRACK('4');#endif STDEBUG		    sc->sc_stflags |= ST_RETD_KEEP;		    return(VS_KEEP);		    break;					case ST_ID_NODIS:#ifdef STDEBUG		    printd2("stintr: identify message\n");#endif STDEBUG		    break;		case ST_ID_DIS:#ifdef STDEBUG		    printd2("stintr: identify w/disconnect message\n");#endif STDEBUG		    break;		default:#ifdef STDEBUG		    printd("stintr: MESSI: message = 0x%x\n", sc->sc_message);#endif STDEBUG#ifdef STDEBUG	ST_TRACK('5');#endif STDEBUG		    goto abort;	    }	    break;	default:	    ;#ifdef STDEBUG	    mprintf("st0: unknown phase = 0x%x\n",		staddr->scs_status & SCS_PHA_MSK);#endif STDEBUG	}    } /* end of do loop */    while (complete == 0);    /*     * If a VS_KEEP was returned, at command completion we     * need to call vs_bufctl with either VS_DEALLOC, or     * VS_WANTBACK.  If we haven't returned a VS_KEEP,     * we just return VS_DEALLOC or VS_WANTBACK.     */    if (sc->sc_stflags & ST_RETD_KEEP) {	sc->sc_stflags &= ~ST_RETD_KEEP;	if (dp->b_actf == NULL) {	    vd->vsd_action = VS_DEALLOC;	}	else {	    vd->vsd_funcptr = st_start;	    vd->vsd_action = VS_WANTBACK;	}	vs_bufctl(vd);    }    else {	if (dp->b_actf == NULL) {	    return(VS_DEALLOC);	}	else {	    vd->vsd_funcptr = st_start;	    return(VS_WANTBACK);	}    }    return;abort:    /*     * Too much is wrong, we cannot recover.  The transfer will be      * aborted by setting sc_xstate to ST_ERR and sc_xevent to ST_RESET.     * st_start will be called to rundown the request queue, marking     * each buffer with B_ERROR, and call st_reset to reset the     * SCSI bus.     */#ifdef STDEBUG    printd ("stintr: ST_ABORT: fevent = 0x%x\n", sc->sc_fevent);    stdumpregs();#endif STDEBUG    mprintf("st0: aborting transfer\n");    sc->sc_stflags |= ST_ENCR_ERR;    sc->sc_xstate = ST_ERR;    sc->sc_xevent = ST_RESET;    st_start(sc);    if (dp->b_actf != NULL) {	printf("st0: stintr: queue not empty after reset");    }    /*     * If a VS_KEEP was returned, at command completion we     * need to call vs_bufctl with either VS_DEALLOC, or     * VS_WANTBACK.  If we haven't returned a VS_KEEP,     * we just return VS_DEALLOC or VS_WANTBACK.     */    if (sc->sc_stflags & ST_RETD_KEEP) {	sc->sc_stflags &= ~ST_RETD_KEEP;	vd->vsd_action = VS_DEALLOC;	vs_bufctl(vd);    }    else {	return(VS_DEALLOC);    }}/*  */stread(dev, uio)	register dev_t dev;	register struct uio *uio;{	register int unit = 0;	return (physio(ststrategy, &rstbuf[unit], dev, B_READ,		minphys, uio));}/*  */stwrite(dev, uio)	register dev_t dev;	register struct uio *uio;{	register int unit = 0;	return (physio(ststrategy, &rstbuf[unit], dev, B_WRITE,		minphys, uio));}/*  */stioctl(dev, cmd, data, flag)	dev_t dev;	register int cmd;	caddr_t data;	int flag;{	register struct uba_device *ui = stdinfo[0];	register struct st_softc *sc = &st_softc[UNIT(dev)];	register struct buf *bp = &cstbuf[UNIT(dev)];	register int callcount;	register int fcount;	struct mtop *mtop;	struct mtget *mtget;	struct devget *devget;	int unit = 0;	/* we depend of the values and order of the MT codes here */	static stops[] = { ST_WFM,ST_P_FSPACEF,ST_P_BSPACEF,ST_P_FSPACER,			   ST_P_BSPACER,ST_REWIND,ST_UNLOAD,ST_P_CACHE,			   ST_P_NOCACHE,ST_RQSNS };	switch (cmd) {	case MTIOCTOP:				/* tape operation */		/* 		 * 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");		    return(ENXIO);		}		mtop = (struct mtop *)data;		switch (mtop->mt_op) {		case MTWEOF:			callcount = 1;			fcount = mtop->mt_count;			break;		case MTFSF: case MTBSF:			callcount = 1;			fcount = mtop->mt_count;			break;		case MTFSR: case MTBSR:			callcount = 1;			fcount = mtop->mt_count;			break;		case MTREW: case MTOFFL:			sc->sc_flags &= ~DEV_EOM;			callcount = 1;			fcount = 1;			break;		case MTNOP:			return(0);		case MTCACHE:		case MTNOCACHE:			return(ENXIO);		case MTCSE:#ifndef	TM_NO_FIX			sc->sc_category_flags &= ~DEV_TPMARK;#endif	TM_NO_FIX			sc->sc_flags |= DEV_CSE;			return(0);		case MTCLX: case MTCLS:			return(0);		case MTENAEOT:			dis_eot_st[unit] = 0;			return(0);		case MTDISEOT:			dis_eot_st[unit] = DISEOT;			sc->sc_flags &= ~DEV_EOM;			return(0);		default:			return (ENXIO);		}		if (callcount <= 0 || fcount <= 0)			return (EINVAL);		while (--callcount >= 0) {			stcommand(dev, stops[mtop->mt_op], fcount);			if (bp->b_flags & B_ERROR)				break;		}		return (geterror(bp));	case MTIOCGET:				/* tape status */		mtget = (struct mtget *)data;		mtget->mt_dsreg = 0;		mtget->mt_erreg = 0;		mtget->mt_resid = sc->sc_resid;		mtget->mt_type = MT_ISST;		break;	case DEVIOCGET: 			/* device status */		devget = (struct devget *)data;		bzero(devget,sizeof(struct devget));		devget->category = DEV_TAPE;		devget->bus = DEV_NB;		bcopy(DEV_VS_TAPE,devget->interface,strlen(DEV_VS_TAPE));		bcopy(DEV_TK50,devget->device,strlen(DEV_TK50));		devget->adpt_num = 0;		devget->nexus_num = 0;		devget->bus_num = 0;		devget->ctlr_num = 0;		devget->slave_num = 0;		bcopy("st", devget->dev_name, 3);		devget->unit_num = 0;		devget->soft_count = sc->sc_softcnt;		devget->hard_count = sc->sc_hardcnt;		devget->stat = sc->sc_flags;		devget->category_stat = (sc->sc_category_flags | DEV_6666BPI);		break;	default:		return (ENXIO);	}	return (0);}/*  */stdump(){}/*  *//* * Build a packet that is then passed one byte at a time * to the SCSI device. */st_bldpkt(sc, cmd, count)register struct st_softc *sc;long	cmd;long	count;{	u_char *byteptr;	int i;	/*	 * Get a byte address of the begining of sc->st_cmd space,	 * and clear the data space	 */	byteptr = (u_char *)&sc->st_command;	for (i=0; i < ST_MAX_CMD_LEN; i++)		*byteptr++ = 0;#ifdef STDEBUG	if (sc->sc_flags & DEV_CSE) {	printd1("st_bldpkt: command = 0x%x\n", cmd);	}#endif STDEBUG	/* build the comand packet */	switch (cmd) {		case ST_READ:		case ST_WRITE:		case ST_RBD:			sc->st_read.fixed = 0;	/* only records */			sc->st_read.xferlen2 = LTOB(count,2);			sc->st_read.xferlen1 = LTOB(count,1);			sc->st_read.xferlen0 = LTOB(count,0);			break;		case ST_RQSNS:			sc->st_rqsns.alclen = ST_RQSNS_LEN;			break;		case ST_MODSNS:			sc->st_modsns.alclen = ST_MODSNS_LEN;			break;		case ST_INQ:			sc->st_rqsns.alclen = ST_INQ_LEN;			break;		case ST_REWIND:

⌨️ 快捷键说明

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