📄 tm.c
字号:
#/* * TM tape driver */#include "../h/param.h"#include "../h/buf.h"#include "../h/dir.h"#include "../h/conf.h"#include "../h/file.h"#include "../h/user.h"struct device { int tmer; int tmcs; int tmbc; char *tmba; int tmdb; int tmrd;};struct buf tmtab;struct buf ctmbuf;struct buf rtmbuf;char t_flags[8];char t_openf[8];daddr_t t_blkno[8];daddr_t t_nxrec[8];#define TMADDR ((struct device *)0172520)#define GO 01#define RCOM 02#define WCOM 04#define WEOF 06#define NOP 0100#define SFORW 010#define SREV 012#define WIRG 014#define REW 016#define DENS 060000 /* 9-channel */#define IENABLE 0100#define CRDY 0200#define GAPSD 010000#define TUR 1#define HARD 0102200 /* ILC, EOT, NXM */#define RLE 0100#define EOF 0040000#define WL 04#define SSEEK 1#define SIO 2#define SCOM 3#define T_WRITTEN 1tmopen(dev, flag){ register unit, ds; unit = minor(dev) & 0177; if (t_openf[unit]) { u.u_error = ENXIO; return; } t_blkno[unit] = 0; t_nxrec[unit] = 65535; t_flags[unit] = 0; tmtab.b_flags |= B_TAPE; ds = tcommand(dev, NOP); if ((ds&TUR)==0) { printf("mt%d off line\n",unit); u.u_error = ENXIO; } if (flag && ds&WL) { printf("mt%d needs write ring\n",unit); u.u_error = ENXIO; } if (u.u_error==0) t_openf[unit]++;}tmclose(dev, flag)dev_t dev;int flag;{ if ( flag == FWRITE || ((flag&FWRITE) && (t_flags[minor(dev)&0177]&T_WRITTEN))) { tcommand(dev, WEOF); tcommand(dev, WEOF); tcommand(dev, SREV); } if ((minor(dev)&0200) == 0) tcommand(dev, REW); t_openf[minor(dev)&077] = 0;}tcommand(dev, com){ register struct buf *bp; bp = &ctmbuf; spl5(); while (bp->b_flags&B_BUSY) { bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO); } bp->b_flags = B_BUSY|B_READ; spl0(); bp->b_dev = dev; bp->b_resid = com; bp->b_blkno = 0; tmstrategy(bp); iowait(bp); if (bp->b_flags&B_WANTED) wakeup((caddr_t)bp); bp->b_flags = 0; return(bp->b_resid);}tmstrategy(bp)register struct buf *bp;{ register daddr_t *p; if(bp->b_flags&B_PHYS) mapalloc(bp); if (bp != &ctmbuf) { p = &t_nxrec[minor(bp->b_dev)&0177]; if (*p <= bp->b_blkno) { if (*p < bp->b_blkno) { bp->b_flags |= B_ERROR; iodone(bp); return; } if (bp->b_flags&B_READ) { clrbuf(bp); bp->b_resid = 0; iodone(bp); return; } } if ((bp->b_flags&B_READ) == 0) { t_flags[minor(bp->b_dev)&0177] |= T_WRITTEN; *p = bp->b_blkno+1; } } bp->av_forw = 0; spl5(); if (tmtab.b_actf == NULL) tmtab.b_actf = bp; else tmtab.b_actl->av_forw = bp; tmtab.b_actl = bp; if (tmtab.b_active == NULL) tmstart(); spl0();}tmstart(){ register struct buf *bp; register int com; int unit; register daddr_t *blkno; loop: if ((bp = tmtab.b_actf) == 0) return; unit = minor(bp->b_dev)&0177; blkno = &t_blkno[unit]; if (t_openf[unit] < 0 || (TMADDR->tmcs & CRDY) == NULL) { bp->b_flags |= B_ERROR; goto next; } if (bp == &ctmbuf) { if (bp->b_resid == NOP) { bp->b_resid = TMADDR->tmer; goto next; } tmtab.b_active = SCOM; TMADDR->tmcs = DENS|bp->b_resid|GO| (unit<<8) | IENABLE; return; } com = (unit<<8) | ((bp->b_xmem & 03) << 4) | IENABLE|DENS; if (*blkno != bp->b_blkno) { tmtab.b_active = SSEEK; if (*blkno < bp->b_blkno) { com |= SFORW|GO; TMADDR->tmbc = *blkno - bp->b_blkno; } else { if (bp->b_blkno == 0) com |= REW|GO; else { com |= SREV|GO; TMADDR->tmbc = bp->b_blkno - *blkno; } } TMADDR->tmcs = com; return; } tmtab.b_active = SIO; TMADDR->tmbc = -bp->b_bcount; TMADDR->tmba = bp->b_un.b_addr; TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO: ((tmtab.b_errcnt)? WIRG|GO: WCOM|GO)); return;next: tmtab.b_actf = bp->av_forw; iodone(bp); goto loop;}tmintr(){ register struct buf *bp; register int unit; int state; if ((bp = tmtab.b_actf) == NULL) return; unit = minor(bp->b_dev)&0177; state = tmtab.b_active; tmtab.b_active = 0; if (TMADDR->tmcs < 0) { /* error bit */ while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */ if (TMADDR->tmer&EOF) { t_nxrec[unit] = bp->b_blkno; state = SCOM; TMADDR->tmbc = -bp->b_bcount; goto out; } if ((TMADDR->tmer&HARD) == 0 && TMADDR->tmer&RLE) { state = SIO; goto out; } if ((TMADDR->tmer&(HARD|EOF)) == NULL && state==SIO) { if (++tmtab.b_errcnt < 2) { t_blkno[unit]++; tmtab.b_active = 0; tmstart(); return; } } else if (t_openf[unit]>0 && bp!=&rtmbuf && (TMADDR->tmer&EOF)==0 ) { t_openf[unit] = -1; deverror(bp, TMADDR->tmer, 0); } bp->b_flags |= B_ERROR; state = SIO; }out: switch ( state ) { case SIO: t_blkno[unit] += (bp->b_bcount>>BSHIFT); case SCOM: tmtab.b_errcnt = 0; tmtab.b_actf = bp->av_forw; bp->b_resid = -TMADDR->tmbc; iodone(bp); break; case SSEEK: t_blkno[unit] = bp->b_blkno; break; default: return; } tmstart();}tmread(dev){ tmphys(dev); physio(tmstrategy, &rtmbuf, dev, B_READ);}tmwrite(dev){ tmphys(dev); physio(tmstrategy, &rtmbuf, dev, B_WRITE);}tmphys(dev){ register unit; daddr_t a; unit = minor(dev) & 0177; if(unit < 8) { a = u.u_offset >> 9; t_blkno[unit] = a; t_nxrec[unit] = a+1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -