?? rl.c
字號:
/* * RL disk driver * Reworked to handle RL01/RL02 * R.A.Mason Oct.1980 * Intended to eventually handle overlapped seeks */#include "../h/param.h"#include "../h/buf.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/systm.h"#define DK_N 1struct device { int rlcs; int rlba; int rlda; int rlmp;};#define RLADDR ((struct device *)0174400)#define NPDISK 4#define NLDISK 1 /* no subdivision into logical disks */#define RLCYLSZ 10240#define RLSECSZ 256#define RL01SIZE 10240#define RL02SIZE 20480/* rlcs bits */#define DRDY 0000001#define GETSTAT 0000004#define SEEK 0000006#define RDHDR 0000010#define WCOM 0000012#define RCOM 0000014#define IENABLE 0000100#define CRDY 0000200#define DS 0001400#define OPI 0002000#define CRC 0004000#define DLT 0010000#define NXM 0020000#define DE 0040000#define ERROR 0100000#define ACCESS_ERROR (NXM|DLT|CRC|OPI)/* rlda bits - during seek */#define SEEKLO 0000001#define SEEKHI 0000005/* - during get status */#define GS 0000002#define RST 0000010#define RESET (RST|GS|01)#define STAT (GS|01)/* status bits */#define HO 0000020#define DT 0000200#define VC 0001000#define WL 0020000struct buf rltab;struct buf rrlbuf;struct rl{ int status; /* drive status */ int headp; /* location of heads */ struct buf *iop; /* current transfer on drive */ int errcnt; /* error count on drive */ int com; /* read or write command word */ int chn; /* cylinder and head number */ unsigned int bleft; /* bytes left to be transferred */ unsigned int bpart; /* number of bytes transferred */ int sn; /* sector number */ union { int w[2]; long l; } addr; /* address of memory for transfer */} rl[NPDISK];/* Bit sets for drive status */#define RL01 01#define RL02 02#define HEADKNOWN 010rlopen(dev,rw)dev_t dev;{ register struct rl *rlp; register struct device *rp; int drive,status; drive = minor(dev); if(drive >= NPDISK) { u.u_error = ENXIO; return; } rlp = &rl[drive]; rp = RLADDR; spl5(); while((rp->rlcs & CRDY) == 0); rp->rlda = STAT; rp->rlcs = (drive << 8) | GETSTAT; while((rp->rlcs & CRDY) == 0); status = rp->rlmp; rp->rlda = RESET; rp->rlcs = (drive << 8) | GETSTAT; while((rp->rlcs & CRDY) == 0); spl0(); if((status&HO) == 0) { u.u_error = ENXIO; return; } if(rw && (status&WL)) { u.u_error = EROFS; return; } if(status&DT) rlp->status |= RL02; else rlp->status |= RL01;}rlclose(dev)dev_t dev;{ register struct rl *rlp; rlp = &rl[minor(dev)]; /* will do something on next rework */}rlstrategy(bp)register struct buf *bp;{ register struct rl *rlp; int drive,dsize;#ifdef UNIBMAP if(bp->b_flags&B_PHYS) mapalloc(bp);#endif UNIBMAP drive = minor(bp->b_dev); rlp = &rl[drive]; dsize = 0; if(rlp->status&RL01) dsize = RL01SIZE; else if(rlp->status&RL02) dsize = RL02SIZE; if(bp->b_blkno >= dsize) { if((bp->b_blkno == dsize) && (bp->b_flags&B_READ)) bp->b_resid = bp->b_bcount; else { bp->b_flags |= B_ERROR; bp->b_error = ENXIO; } iodone(bp); return; } bp->av_forw = NULL; spl5(); if(rltab.b_actf == NULL) rltab.b_actf = bp; else rltab.b_actl->av_forw = bp; rltab.b_actl = bp; if(rltab.b_active == NULL) rlstart(); spl0();}rlstart(){ register struct buf *bp; register struct rl *rlp; int drive; if((bp = rltab.b_actf) == NULL) return; rltab.b_active++; drive = minor(bp->b_dev); rlp = &rl[drive]; rlp->iop = bp; rlp->chn = bp->b_blkno/20; rlp->sn = (bp->b_blkno%20) << 1; rlp->bleft = bp->b_bcount; rlp->addr.w[0] = bp->b_xmem & 3; rlp->addr.w[1] = (int)bp->b_un.b_addr; rlp->com = (drive << 8) | IENABLE; if(bp->b_flags & B_READ) rlp->com |= RCOM; else rlp->com |= WCOM; rlio(drive);}rlintr(){ register struct buf *bp; register struct device *rp; register struct rl *rlp; int drive,status; rp = RLADDR; drive = (rp->rlcs&DS) >> 8; rlp = &rl[drive]; if(rlp->iop == NULL) {/* logstray(rp); */ return; } bp = rlp->iop;#ifdef INSTRM dk_busy &= ~(1<<DK_N);#endif INSTRM if(rp->rlcs&ERROR) { if(rp->rlcs&ACCESS_ERROR) { if(rlp->errcnt > 2) deverror(bp, rp->rlcs, rp->rlda); } if(rp->rlcs&DE) { rp->rlda = STAT; rp->rlcs = (drive << 8) | GETSTAT; while((rp->rlcs & CRDY) == 0); status = rp->rlmp; if(rlp->errcnt > 2) deverror(bp, status, rp->rlda); rp->rlda = RESET; rp->rlcs = (drive << 8) | GETSTAT; while((rp->rlcs & CRDY) == 0); if(status&DT) /* drive type */ rlp->status |= RL02; else rlp->status |= RL01; if(status&VC) { /* volume check */ rlstart(); return; } } if(++rlp->errcnt <= 10) { rlp->status &= ~HEADKNOWN; rlstart(); return; } else { bp->b_flags |= B_ERROR; rlp->bpart = rlp->bleft; } } if((rlp->bleft -= rlp->bpart) > 0) { rlp->addr.l += rlp->bpart; rlp->sn = 0; rlp->chn++; rlio(drive); return; } rlp->iop = NULL; rlp->errcnt = 0; rltab.b_active = NULL; rltab.b_actf = bp->av_forw; bp->b_resid = 0; iodone(bp); rlstart();}rlio(dn)int dn;{ register struct device *rp; register struct rl *rlp; int dif,head; rp = RLADDR; rlp = &rl[dn];#ifdef INSTRM dk_busy |= 1<<DK_N; dk_numb[DK_N] += 1; dk_wds[DK_N] += (rlp->bpart>>6);#endif INSTRM if((rlp->status&HEADKNOWN) == 0) { rp->rlcs = (dn << 8) | RDHDR; while((rp->rlcs&CRDY) == 0); rlp->headp = ((unsigned)(rp->rlmp&0177700)) >> 6; rlp->status |= HEADKNOWN; } dif = (rlp->headp >> 1) - (rlp->chn >>1); head = (rlp->chn & 1) << 4; if(dif < 0) rp->rlda = (-dif<<7) | SEEKHI | head; else rp->rlda = (dif<< 7) | SEEKLO | head; rp->rlcs = (dn << 8) | SEEK; rlp->headp = rlp->chn; if(rlp->bleft < (rlp->bpart = RLCYLSZ - (rlp->sn * RLSECSZ))) rlp->bpart = rlp->bleft; while((rp->rlcs&CRDY) == 0); rp->rlda = (rlp->chn << 6) | rlp->sn; rp->rlba = rlp->addr.w[1]; rp->rlmp = -(rlp->bpart >> 1); rp->rlcs = rlp->com | rlp->addr.w[0] << 4;}rlread(dev){ physio(rlstrategy, &rrlbuf, dev, B_READ);}rlwrite(dev){ physio(rlstrategy, &rrlbuf, dev, B_WRITE);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -