📄 tmscp.c
字号:
* serious exception on the next command. */ tms->tms_serex = 2; } /* * The tmscp spec states that controllers do not have to * report the number of records or files skipped. So on * reposition commands we go strictly by cmd status. */ if (mp->mscp_opcode != (M_OP_REPOS|M_OP_END)) bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; else bp->b_resid = 0; tms->tms_resid = bp->b_resid; iodone(bp); break; case M_OP_GTUNT|M_OP_END:# ifdef DEBUG printd("tmscprsp: GTUNT end packet status = 0%o\n",st); printd("tmscprsp: unit %d mediaid %x %c%c %c%c%c%d %x %x t=%d\n" ,mp->mscp_unit, mp->mscp_mediaid ,F_to_C(mp,4),F_to_C(mp,3),F_to_C(mp,2) ,F_to_C(mp,1),F_to_C(mp,0) ,mp->mscp_mediaid & 0x7f ,mp->mscp_unitid.val[0] ,mp->mscp_unitid.val[1] ,mp->mscp_format);# endif tms->tms_type = mp->mscp_mediaid; tms->tms_fmtmenu = mp->mscp_fmtmenu; tms->tms_unitflgs = mp->mscp_unitflgs; break; default: printf("tmscp unknown packet\n"); tmserror(um, (struct mslg *)mp); } /* end switch mp->mscp_opcode */}/* * Give a meaningful error when the mscp_status field returns an error code. */errinfo(st) int st; /* the status code */{ switch(st) { case M_ST_ICMD: printf("invalid command\n"); break; case M_ST_ABRTD: printf("command aborted\n"); break; case M_ST_OFFLN: printf("unit offline\n"); break; case M_ST_WRTPR: printf("unit write protected\n"); break; case M_ST_COMP: printf("compare error\n"); break; case M_ST_DATA: printf("data error\n"); break; case M_ST_HSTBF: printf("host buffer access error\n"); break; case M_ST_CNTLR: printf("controller error\n"); break; case M_ST_DRIVE: printf("drive error\n"); break; case M_ST_FMTER: printf("formatter error\n"); break; case M_ST_BOT: printf("BOT encountered\n"); break; case M_ST_TAPEM: printf("tape mark encountered\n"); break; case M_ST_RDTRN: printf("record data truncated\n"); break; case M_ST_PLOST: printf("position lost\n"); break; case M_ST_SEX: printf("serious exception\n"); break; case M_ST_LED: printf("LEOT detected\n"); break; }}/* * Manage buffers and perform block mode read and write operations. */tmscpstrategy (bp) register struct buf *bp;{ register struct uba_device *ui; register struct uba_ctlr *um; register struct buf *dp; register int unit = TMSUNIT(bp->b_dev); int s; if (unit >= NTMS) {# ifdef DEBUG printd ("tmscpstrategy: bad unit # %d\n",unit);# endif bp->b_flags |= B_ERROR; iodone(bp); return; } ui = tmsdinfo[unit]; um = ui->ui_mi; if (ui == 0 || ui->ui_alive == 0) { bp->b_flags |= B_ERROR; iodone(bp); return; } s = spl5(); /* * Link the buffer onto the drive queue */ dp = &tmsutab[ui->ui_unit]; if (dp->b_actf == 0) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; bp->av_forw = 0; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (um->um_tab.b_actf == NULL) um->um_tab.b_actf = dp; else um->um_tab.b_actl->b_forw = dp; um->um_tab.b_actl = dp; dp->b_active = 1; } /* * If the controller is not active, start it. */ if (um->um_tab.b_active == 0) {# if defined(VAX750) if (cpu == VAX_750 && tmscpwtab[um->um_ctlr].av_forw == &tmscpwtab[um->um_ctlr]) { if (um->um_ubinfo != 0) log(TMS_PRI, "tmscpstrategy: ubinfo 0x%x\n", um->um_ubinfo); else um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); }# endif# ifdef DEBUG printd10("tmscpstrategy: Controller not active, starting it\n");# endif (void) tmscpstart(um); } splx(s); return;}#define DBSIZE 32#define ca_Rspdsc ca_rspdsc[0]#define ca_Cmddsc ca_rspdsc[1]#define tmscp_Rsp tmscp_rsp[0]#define tmscp_Cmd tmscp_cmd[0]struct tmscp tmscpd[NTMSCP];tmscpdump(dev) dev_t dev;{ struct tmscpdevice *tmscpaddr; struct tmscp *tmscp_ubaddr; char *start; int num, blk, unit; register struct uba_regs *uba; register struct uba_device *ui; register struct tmscp *tmscpp; register struct pte *io; register int i; unit = minor(dev) & 03; if (unit >= NTMS) return (ENXIO);# define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) ui = phys(struct uba_device *, tmsdinfo[unit]); if (ui->ui_alive == 0) return (ENXIO); uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; ubainit(uba); tmscpaddr = (struct tmscpdevice *)ui->ui_physaddr; DELAY(2000000); tmscpp = phys(struct tmscp *, &tmscpd[ui->ui_ctlr]); num = btoc(sizeof(struct tmscp)) + 1; io = &uba->uba_map[NUBMREG-num]; for(i = 0; i<num; i++) *(int *)io++ = UBAMR_MRV|(btop(tmscpp)+i); tmscp_ubaddr = (struct tmscp *)(((int)tmscpp & PGOFSET)|((NUBMREG-num)<<9)); tmscpaddr->tmscpip = 0; while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0) if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); tmscpaddr->tmscpsa = TMSCP_ERR; while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0) if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); tmscpaddr->tmscpsa = (short)&tmscp_ubaddr->tmscp_ca.ca_ringbase; while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0) if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16); while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0) if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT); tmscpaddr->tmscpsa = TMSCP_GO; tmscpp->tmscp_ca.ca_Rspdsc = (long)&tmscp_ubaddr->tmscp_Rsp.mscp_cmdref; tmscpp->tmscp_ca.ca_Cmddsc = (long)&tmscp_ubaddr->tmscp_Cmd.mscp_cmdref; tmscpp->tmscp_Cmd.mscp_header.tmscp_vcid = 1; /* for tape */ tmscpp->tmscp_Cmd.mscp_cntflgs = 0; tmscpp->tmscp_Cmd.mscp_version = 0; if (tmscpcmd(M_OP_STCON, tmscpp, tmscpaddr) == 0) { return(EFAULT); } tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; if (tmscpcmd(M_OP_ONLIN, tmscpp, tmscpaddr) == 0) { return(EFAULT); } num = maxfree; start = 0; while (num > 0) { blk = num > DBSIZE ? DBSIZE : num; io = uba->uba_map; for (i = 0; i < blk; i++) *(int *)io++ = (btop(start)+i) | UBAMR_MRV; *(int *)io = 0; tmscpp->tmscp_Cmd.mscp_lbn = btop(start); tmscpp->tmscp_Cmd.mscp_unit = ui->ui_slave; tmscpp->tmscp_Cmd.mscp_bytecnt = blk*NBPG;# ifdef MVAX if( cpu == MVAX_I ) tmscpp->tmscp_Cmd.mscp_buffer = (long) start; else# endif MVAX tmscpp->tmscp_Cmd.mscp_buffer = 0; if (tmscpcmd(M_OP_WRITE, tmscpp, tmscpaddr) == 0) return(EIO); start += blk*NBPG; num -= blk; } return (0);}/* * Perform a standalone tmscp command. This routine is only used by tmscpdump. */tmscpcmd(op, tmscpp, tmscpaddr) int op; register struct tmscp *tmscpp; struct tmscpdevice *tmscpaddr;{ int i; tmscpp->tmscp_Cmd.mscp_opcode = op; tmscpp->tmscp_Rsp.mscp_header.tmscp_msglen = mscp_msglen; tmscpp->tmscp_Cmd.mscp_header.tmscp_msglen = mscp_msglen; tmscpp->tmscp_ca.ca_Rspdsc |= TMSCP_OWN|TMSCP_INT; tmscpp->tmscp_ca.ca_Cmddsc |= TMSCP_OWN|TMSCP_INT; if (tmscpaddr->tmscpsa&TMSCP_ERR) printf("tmscp fatal error (0%o)\n", tmscpaddr->tmscpsa&0xffff); i = tmscpaddr->tmscpip;#ifdef lint i = i;#endif for (;;) { if (tmscpp->tmscp_ca.ca_cmdint) tmscpp->tmscp_ca.ca_cmdint = 0; if (tmscpp->tmscp_ca.ca_rspint) break; } tmscpp->tmscp_ca.ca_rspint = 0; if (tmscpp->tmscp_Rsp.mscp_opcode != (op|M_OP_END) || (tmscpp->tmscp_Rsp.mscp_status&M_ST_MASK) != M_ST_SUCC) { printf("error: com %d opc 0x%x stat 0x%x\ndump ", op, tmscpp->tmscp_Rsp.mscp_opcode, tmscpp->tmscp_Rsp.mscp_status); return(0); } return(1);}/* * Catch ioctl commands, and call the "command" routine to do them. *//* ARGSUSED */tmscpioctl(dev, cmd, data, flag) dev_t dev; int cmd; caddr_t data; int flag;{ register struct buf *bp = &ctmscpbuf[TMSCPCTLR(dev)]; register callcount; /* number of times to call cmd routine */ register struct uba_device *ui; register struct tms_info *tms; int fcount; /* number of files (or records) to space */ int error = 0; register struct mtop *mtop; /* mag tape cmd op to perform */ register struct mtget *mtget; /* mag tape struct to get info in */ /* we depend of the values and order of the TMS ioctl codes here */ static tmsops[] = {TMS_WRITM,TMS_FSF,TMS_BSF,TMS_FSR,TMS_BSR,TMS_REW,TMS_OFFL,TMS_SENSE, TMS_CACHE,TMS_NOCACHE}; switch (cmd) { case MTIOCTOP: /* tape operation */ mtop = (struct mtop *)data; switch (mtop->mt_op) { case MTWEOF: callcount = mtop->mt_count; fcount = 1; break; case MTFSF: case MTBSF: case MTFSR: case MTBSR: callcount = 1; fcount = mtop->mt_count; break; case MTREW: case MTOFFL: case MTNOP: case MTCACHE: case MTNOCACHE: callcount = 1; fcount = 1; /* wait for this rewind */ break; default: return (ENXIO); } /* end switch mtop->mt_op */ if (callcount <= 0 || fcount <= 0) return (EINVAL); while (--callcount >= 0) { tmscpcommand(dev, tmsops[mtop->mt_op], fcount); if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && bp->b_resid) return (EIO); if (bp->b_flags & B_ERROR) /* like hitting BOT */ break; } if (bp->b_flags&B_ERROR) if ((error = bp->b_error)==0) return (EIO); return (error); case MTIOCGET: /* * Return status info associated with the particular UNIT. */ ui = tmsdinfo[TMSUNIT(dev)]; tms = &tms_info[ui->ui_unit]; mtget = (struct mtget *)data; mtget->mt_type = MT_ISTMSCP; mtget->mt_dsreg = tms->tms_flags << 8; mtget->mt_dsreg |= tms->tms_endcode; mtget->mt_erreg = tms->tms_status; mtget->mt_resid = tms->tms_resid; break; default: return (ENXIO); } return (0);}/* * Reset (for raw mode use only). */tmscpreset (uban) int uban;{ register struct uba_ctlr *um; register struct uba_device *ui; register struct buf *bp, *dp; register int unit; struct buf *nbp; int d; for (d = 0; d < NTMSCP; d++) { if ((um = tmscpminfo[d]) == 0 || um->um_ubanum != uban || um->um_alive == 0) continue; printf(" tmscp%d", d); um->um_tab.b_active = 0; um->um_tab.b_actf = um->um_tab.b_actl = 0; tmscp_softc[d].sc_state = S_IDLE; tmscp_softc[d].sc_mapped = 0; for (unit = 0; unit < NTMS; unit++) { if ((ui = tmsdinfo[unit]) == 0) continue; if (ui->ui_alive == 0 || ui->ui_mi != um) continue; tmsutab[unit].b_active = 0; tmsutab[unit].b_qsize = 0; } for (bp = tmscpwtab[d].av_forw; bp != &tmscpwtab[d]; bp = nbp) { nbp = bp->av_forw; bp->b_ubinfo = 0; /* * Link the buffer onto the drive queue */ dp = &tmsutab[TMSUNIT(bp->b_dev)]; if (dp->b_actf == 0) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; bp->av_forw = 0; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (um->um_tab.b_actf == NULL) um->um_tab.b_actf = dp; else um->um_tab.b_actl->b_forw = dp; um->um_tab.b_actl = dp; dp->b_active = 1; } } (void)tmscpinit(d); }}/* * Process an error log message * * Only minimal decoding is done, only "useful" * information is printed. Eventually should * send message to an error logger. */tmserror(um, mp) register struct uba_ctlr *um; register struct mslg *mp;{ register i;# ifdef DEBUG printd("tmserror:\n");# endif if(!(mp->mslg_flags & (M_LF_SUCC | M_LF_CONT))) log(TMS_PRI, "tmscp%d: %s error, ", um->um_ctlr, mp->mslg_flags & ( M_LF_SUCC | M_LF_CONT ) ? "soft" : "hard"); switch (mp->mslg_format) { case M_FM_CNTERR: log(TMS_PRI, "controller error, event 0%o\n", mp->mslg_event); break; case M_FM_BUSADDR: log(TMS_PRI, "host memory access error, event 0%o, addr 0%o\n", mp->mslg_event, mp->mslg_busaddr); break; case M_FM_TAPETRN: log(TMS_PRI, "tape transfer error, unit %d, grp 0x%x, event 0%o\n", mp->mslg_unit, mp->mslg_group, mp->mslg_event); break; case M_FM_STIERR: log(TMS_PRI, "STI error, unit %d, event 0%o\n", mp->mslg_unit, mp->mslg_event);#ifdef notdef /* too painful to do with log() */ for(i = 0; i < 62;i++) mprintf("\t0x%x",mp->mslg_stiunsucc[i] & 0xff); mprintf("\n");#endif break; case M_FM_STIDEL: log(TMS_PRI, "STI Drive Error Log, unit %d, event 0%o\n", mp->mslg_unit, mp->mslg_event); break; case M_FM_STIFEL: log(TMS_PRI, "STI Formatter Error Log, unit %d, event 0%o\n", mp->mslg_unit, mp->mslg_event); break; default: log(TMS_PRI, "unknown error, unit %d, format 0%o, event 0%o\n", mp->mslg_unit, mp->mslg_format, mp->mslg_event); } if (tmscperror) { register long *p = (long *)mp; for (i = 0; i < mp->mslg_header.tmscp_msglen; i += sizeof(*p)) printf("%x ", *p++); printf("\n"); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -