📄 stc.c
字号:
case ST_RBL: case ST_TUR: break; case ST_WFM: sc->st_wfm.numoffmks2 = 0; /* max of 65536 file marks */ sc->st_wfm.numoffmks1 = LTOB(count,1); sc->st_wfm.numoffmks0 = LTOB(count,0); break; case ST_P_BSPACEF: count = -count; case ST_P_FSPACEF: cmd = ST_SPACE; sc->st_space.code = 1; sc->st_space.count2 = LTOB(count,2); sc->st_space.count1 = LTOB(count,1); sc->st_space.count0 = LTOB(count,0); break; case ST_P_BSPACER: count = -count; case ST_P_FSPACER: cmd = ST_SPACE; sc->st_space.code = 0; sc->st_space.count2 = LTOB(count,2); sc->st_space.count1 = LTOB(count,1); sc->st_space.count0 = LTOB(count,0); break; case ST_VFY: sc->st_vfy.fixed = 1; /* only records */ sc->st_vfy.bytcmp = 0; /* CRC verify only */ sc->st_vfy.verflen2 = LTOB(count,2); sc->st_vfy.verflen1 = LTOB(count,1); sc->st_vfy.verflen0 = LTOB(count,0); break; case ST_ERASE: sc->st_erase.longbit = 0; /* don't erase to end of tape */ break; case ST_UNLOAD: sc->st_load.load = 0; /* unload only for now */ sc->st_load.reten = 0; /* not used on MAYA */ break; case ST_RECDIAG: sc->st_recdiag.aloclen1 = 0; sc->st_recdiag.aloclen0 = ST_RECDIAG_LEN; break; case ST_SNDDIAG: return(ST_RET_ERR); break; case ST_MODSEL: case ST_P_CACHE: cmd = ST_MODSEL; sc->st_modsel.pll = 0x0e; sc->st_modsel.bufmode = 1; sc->st_modsel.rdeclen = 0x08; sc->st_modsel.vulen = 1;#ifdef STDEBUG sc->st_modsel.vu7 = st_direct_track_mode;#endif STDEBUG sc->st_modsel.notimo = 1; sc->st_modsel.nof = st_max_numof_fills; break; case ST_P_NOCACHE: cmd = ST_MODSEL; sc->st_modsel.pll = 0x0e; sc->st_modsel.bufmode = 0; sc->st_modsel.rdeclen = 0x08; sc->st_modsel.vulen = 1; sc->st_modsel.nof = 0; break; case ST_TRKSEL: return(ST_RET_ERR); break; case ST_RESUNIT: case ST_RELUNIT:#ifdef STDEBUG printd("st_bldpkt: unimplemented command 0x%x\n", cmd);#endif STDEBUG return (ST_RET_ERR); break; default:#ifdef STDEBUG printd("st_bldpkt: unknown command = 0x%x\n", cmd);#endif STDEBUG return (ST_RET_ERR); break; } /* The only unit on the VAXSTAR is logical unit zero. * * st_read is used here to get to the fields in the * structure for all commands. */ sc->st_read.lun = 0; sc->st_read.link = 0; sc->st_read.flag = 0; sc->st_read.mbz = 0; sc->st_opcode = cmd; return(ST_SUCCESS);}/**/st_start(){ register struct nb1_regs *staddr = (struct nb1_regs *)qmem; register struct nb_regs *stiaddr = (struct nb_regs *)nexus; register struct buf *bp; register struct buf *dp; register struct st_softc *sc; register struct vsdev *vd; struct uba_ctlr *um; struct uba_device *ui; 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; int fuz; /* return value from a call to fuzzy() */ int ret; /* return value from various routines */ int sp_ret; int i, tmpstflags, tmpresid, tmpstat; short count; u_char *byteptr; vd = &vstapedev; um = stdinfo[0]->ui_mi; dp = &stutab[0]; sc = &st_softc[0]; bp = dp->b_actf; /* * st_start is one big state machine. The states are kept * in the st_softc structure. The state variables that * are used in this state machine are: * * sc->sc_xstate used to dispatch to major states * sc->sc_xevent used to dispatch to minor (sub)states */ for (;;) { /* forever */#ifdef STDEBUG printd2("st_start: state = %s, event = %s\n", trace_xstate[sc->sc_xstate], trace_event[sc->sc_xevent]);#endif STDEBUG switch(sc->sc_xstate) {/**/ case ST_NEXT: switch(sc->sc_xevent) { case ST_CONT: /* * Remove the completed request from the queue, * return the buffer, return. We will be called * back from vs_bufctl() when the vaxstar buffer * is allocated to us. */ bp = dp->b_actf; dp->b_actf = bp->av_forw; bp->b_resid = sc->sc_resid;#ifdef STDEBUG printd1("resid = %d\n", bp->b_resid);#endif STDEBUG sc->sc_flags |= DEV_DONE; biodone(bp); sc->sc_xevent = ST_BEGIN; st_retries = 0; /* * The comand has ended, reset the timer to zero */ sc->sc_ticks = 0; if(dp->b_actf == NULL) { dp->b_active = 0;#ifdef STDEBUG ST_TRACK('@');#endif STDEBUG return(VS_DEALLOC); } else {#ifdef STDEBUG ST_TRACK('#');#endif STDEBUG vd->vsd_funcptr = st_start; return(VS_WANTBACK); } break; case ST_BEGIN: sc->sc_stflags &= ~ST_MAPPED; if ((bp = dp->b_actf) == NULL) { dp->b_active = 0;#ifdef STDEBUG ST_TRACK('$');#endif STDEBUG return(VS_DEALLOC); } if((sc->sc_flags & DEV_EOM) && !((sc->sc_flags & DEV_CSE) || (dis_eot_st[0] & DISEOT))) { bp->b_resid = bp->b_bcount; bp->b_error = ENOSPC; bp->b_flags |= B_ERROR; sc->sc_xevent = ST_CONT; break; }#ifdef TM_NO_FIX if((sc->sc_category_flags & DEV_TPMARK) && (bp->b_flags & B_READ)) { bp->b_resid = 0; bp->b_error = EIO; bp->b_flags |= B_ERROR; sc->sc_xevent = ST_CONT; break; }#endif TM_NO_FIX 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; sc->sc_xevent = ST_CONT; break; } /* log progress */ sc->sc_progress = time; if (bp == &cstbuf[0]) { /* * execute control operation with the specified count */ if (bp->b_command == ST_REWIND) { um->um_tab.b_active = SREW; sc->sc_flags &= ~DEV_EOM; } else { um->um_tab.b_active = SCOM; } sc->sc_xstate = ST_SP_START; sc->sc_xevent = ST_CONT; break; } /* * If it's not a control operation, it must be * data. */ sc->sc_xstate = ST_RW_START; sc->sc_xevent = ST_CONT; break; default: ;#ifdef STDEBUG printd("st_start: ST_NEXT: state = %s, event = %s\n", trace_xstate[sc->sc_xstate], trace_event[sc->sc_xevent]);#endif STDEBUG } break;/* */ case ST_SP_START: if (sc->st_opcode != ST_RQSNS) { sc->sc_flags &= ~DEV_WRITTEN; } /* * The write to b_resid has to follow the * read of b_command. This is because both * b_command and b_resid are the same field * (overloaded). The write to b_resid destroys * the data in b_command. This is a black * hole waiting to be fallen into! */ sc->sc_curcmd = bp->b_command; bp->b_resid = 0; st_bldpkt(sc, sc->sc_curcmd, bp->b_bcount); switch (fuz = st_scsistart()) { case ST_SUCCESS: sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; case ST_RET_ERR: /* * If this command was issued from stopen, don't * do the ST_RQSNS if it fails */ if (!(st_from_open)) { st_bldpkt(sc, ST_RQSNS, 0); if(st_scsistart() == ST_SUCCESS) {#ifdef STDEBUG if (stdebug > 1) { stprintsense(); }#endif STDEBUG switch (sp_ret = sterror(sc)) { case ST_SUCCESS: sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; case ST_RETRY: sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; if ((st_retries < 3 ) && (sc->st_opcode != ST_TUR)) { sc->sc_xevent = ST_BEGIN; st_retries++; } else { bp->b_flags |= B_ERROR; sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; } break; case ST_FATAL: if((sc->sc_flags & DEV_EOM) && !((sc->sc_flags & DEV_CSE) || (dis_eot_st[0] & DISEOT))) { bp->b_error = ENOSPC; } bp->b_flags |= B_ERROR; sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; default:#ifdef STDEBUG printd("st_start: ST_SP_CONT: unknown sp_ret = 0x%x\n", sp_ret);#endif STDEBUG bp->b_flags = B_ERROR; sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } if((sc->st_opcode == ST_RQSNS) || (sc->st_opcode == ST_SPACE)) { sc->sc_xevent = ST_CONT; } break; } else { sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } } else { sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } break; case ST_IP: sc->sc_xstate = ST_SP_CONT;#ifdef STDEBUG ST_TRACK('%');#endif STDEBUG sc->sc_stflags |= ST_RETD_KEEP; return(VS_KEEP); break; default:#ifdef STDEBUG printd("st_start: ST_SP_START: return value = 0x%x\n", fuz);#endif STDEBUG bp->b_flags = B_ERROR; sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } break; /* */ case ST_SP_CONT: /* * If this command is a ST_RQSNS, look at the * status bytes and determine what to do next, * otherwise process as ususal. */ if (sc->st_opcode != ST_RQSNS) { if (sc->sc_stflags == ST_NORMAL) { sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } if (sc->sc_stflags & ST_NEED_SENSE) { st_bldpkt(sc, ST_RQSNS, 0); if(st_scsistart() == ST_SUCCESS) {#ifdef STDEBUG if (stdebug > 1) { stprintsense(); }#endif STDEBUG switch (sp_ret = sterror(sc)) { case ST_SUCCESS:#ifndef TM_NO_FIX if ((sc->sc_category_flags & DEV_TPMARK) && ((sc->sc_curcmd == ST_P_FSPACER) || (sc->sc_curcmd == ST_P_BSPACER))) bp->b_flags |= B_ERROR;#endif TM_NO_FIX sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; case ST_RETRY: sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; if ((st_retries < 3 ) && (sc->st_opcode != ST_TUR)) { sc->sc_xevent = ST_BEGIN; st_retries++; } else { bp->b_flags |= B_ERROR; sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; } break; case ST_FATAL: bp->b_flags |= B_ERROR; sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; default:#ifdef STDEBUG printd("st_start: ST_SP_CONT: unknown sp_ret = 0x%x\n", sp_ret);#endif STDEBUG bp->b_flags = B_ERROR; sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } if((sc->st_opcode == ST_RQSNS) || (sc->st_opcode == ST_SPACE)) { sc->sc_xevent = ST_CONT; } break; } else { sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } } else { if ((sc->sc_stflags & ST_ENCR_ERR) == ST_ENCR_ERR) { bp->b_flags |= B_ERROR; sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } else { sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } } }#ifdef STDEBUG if (stdebug > 1) { stprintsense(); }#endif STDEBUG sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break;/**/ case ST_RW_START: /* * If bytecount is too large, throw out the transfer */ if (bp->b_bcount > 16384) { mprintf("st0: buffer too large\n"); DEV_UGH(sc->sc_device,0,"buffer too large"); bp->b_flags |= B_ERROR; sc->sc_xstate = ST_NEXT; sc->sc_xevent = ST_CONT; break; } if (bp->b_flags & B_READ) { sc->sc_curcmd = ST_READ; st_bldpkt(sc, sc->sc_curcmd, bp->b_bcount); sc->sc_xstate = ST_R_STDMA; } else { sc->sc_curcmd = ST_WRITE; st_bldpkt(sc, sc->sc_curcmd, bp->b_bcount); sc->sc_xstate = ST_W_STDMA; } break;/**/ case ST_R_COPY: /* Copy the data from the 16K buffer to memo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -