📄 stc.c
字号:
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 + -