📄 rk.c
字号:
MASKREG(rkaddr->rkcs2), MASKREG(rkaddr->rkds), MASKREG(rkaddr->rker), MASKREG(rkaddr->rkatt), MASKREG(rkaddr->rkcyl), MASKREG(rkaddr->rkdb), MASKREG(rkaddr->rkmr1), MASKREG(rkaddr->rkec1), MASKREG(rkaddr->rkec2), MASKREG(rkaddr->rkmr2), MASKREG(rkaddr->rkmr3)); bp->b_flags |= B_ERROR; sc->sc_recal = 0; } else if (er & RKER_BSE) { if (rkecc(ui, BSE)) return; else goto hard; } else { if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) { if (rkecc(ui, ECC)) return; } else um->um_tab.b_active = 0; } if (cs2&RKCS2_MDS) { rkaddr->rkcs2 = RKCS2_SCLR; goto retry; } recal = 0; if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || (um->um_tab.b_errcnt&07) == 4) recal = 1; rkaddr->rkcs1 = RK_CCLR; rkaddr->rkcs2 = ui->ui_slave; rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; rkwait(rkaddr); if (recal && um->um_tab.b_active == 0) { rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO; rkcyl[ui->ui_unit] = -1; sc->sc_recal = 0; goto nextrecal; } }retry: switch (sc->sc_recal) { case 1: rkaddr->rkcyl = bp->b_cylin; rkcyl[ui->ui_unit] = bp->b_cylin; rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; goto nextrecal; case 2: if (um->um_tab.b_errcnt < 16 || (bp->b_flags&B_READ) == 0) goto donerecal; rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO; /* fall into ... */ nextrecal: sc->sc_recal++; rkwait(rkaddr); um->um_tab.b_active = 1; return; donerecal: case 3: sc->sc_recal = 0; um->um_tab.b_active = 0; break; } ubadone(um); if (um->um_tab.b_active) { um->um_tab.b_active = 0; um->um_tab.b_errcnt = 0; um->um_tab.b_actf = dp->b_forw; dp->b_active = 0; dp->b_errcnt = 0; dp->b_actf = bp->av_forw;#ifdef RKDEBUG trace("done",dp); trace(&um->um_tab.b_actf,dp->b_actf);#endif RKDEBUG bp->b_resid = -rkaddr->rkwc * sizeof(short); iodone(bp); if (dp->b_actf) rkustart(ui); } as &= ~(1<<ui->ui_slave); }#ifdef RKDEBUG trace("as =",as); /* 003 */#endif RKDEBUG for (unit = 0; as; unit++) /* 003 */ if (as & (1<<unit)) { /* 003 */ as &= ~(1<<unit); /* 003 */ ui = rkip[rk11][unit]; /* 003 */ if (ui) { /* 003 */ rkaddr->rkcs1 = RK_CCLR; /* 003 */ rkaddr->rkcs2 = unit; /* 003 */ rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_SELECT|RK_GO; rkwait(rkaddr); /* 003 */ if (rkaddr->rkds & RKDS_DRDY) { /* 003 */ if (sc->sc_offline[ui->ui_unit]) { /* 003 */#ifdef RKDEBUG trace("rdy",unit); /* 003 */#endif RKDEBUG rkaddr->rkcs1 = rktypes[ui->ui_type]| RK_DCLR|RK_GO; rkwait(rkaddr); /* 003 */ sc->sc_offline[ui->ui_unit] = 0; /* 003 */ }#ifdef RKDEBUG trace("ui =",rkip[rk11][unit]); /* 003 */#endif RKDEBUG rkustart(rkip[rk11][unit]); /* 003 */ } else {#ifdef RKDEBUG trace("!rdy",unit); /* 003 */#endif RKDEBUG rkaddr->rkcs1 = rktypes[ui->ui_type]| RK_DCLR|RK_GO; rkwait(rkaddr); /* 003 */ sc->sc_flags[ui->ui_unit] |= DEV_OFFLINE; sc->sc_offline[ui->ui_unit] = 1; /* 003 */ dp = &rkutab[unit]; /* 003 */ bp = dp->b_actf; /* 003 */ if (dp->b_active) { /* 003 */ dp->b_active = 0; /* 003 */ bp->b_flags |= B_ERROR; /* 003 */ dp->b_actf = bp->av_forw; /* 003 */ iodone(bp); /* 003 */ if (dp->b_actf) rkustart(rkip[rk11][unit]); /* 003 */ } } } else { mprintf("intr on unit %d ?",unit); /* 003 */ rkaddr->rkcs1 = RK_CCLR; /* 003 */ rkaddr->rkcs2 = unit; /* 003 */ rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; /* 003 */ rkwait(rkaddr); /* 003 */ } } if (um->um_tab.b_actf && um->um_tab.b_active == 0) rkstart(um); if (((rkaddr->rkcs1) & RK_IE) == 0) rkaddr->rkcs1 = RK_IE;}rkwait(addr) register struct rkdevice *addr;{ while ((addr->rkcs1 & RK_CRDY) == 0) ;}rkread(dev, uio) register dev_t dev; register struct uio *uio;{ register int unit = minor(dev) >> 3; return (physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys, uio));}rkwrite(dev, uio) register dev_t dev; register struct uio *uio;{ register int unit = minor(dev) >> 3; return (physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys, uio));}/*ARGSUSED*/rkioctl(dev, cmd, data, flag) dev_t dev; int cmd; caddr_t data; int flag;{ register int unit = minor(dev) >> 3; register struct uba_device *ui = rkdinfo[unit]; register struct pt *pt = (struct pt *)data; register struct rk_softc *sc = &rk_softc[ui->ui_ctlr]; struct dkop *dkop; struct dkget *dkget; struct devget *devget; register int i; int error; int nspc; switch (cmd) { case DKIOCHDR: /* do header read/write */ break; case DIOCGETPT: /* 001 get partition table info */ /* * Do a structure copy into the user's data area */ *pt = rk_part[unit]; break; case DIOCDGTPT: /* 004 Return default partition table */ /* * Get number of sector per cyliinder */ nspc = rkst[ui->ui_type].nspc; /* * Get and store the default block count and offset */ for( i = 0; i <= 7; i++ ) { pt->pt_part[i].pi_nblocks = rkst[ui->ui_type].sizes[i].nblocks; pt->pt_part[i].pi_blkoff = rkst[ui->ui_type].sizes[i].cyloff * nspc; } break; case DIOCSETPT: /* 001 set the driver partition tables */ /* * Only super users can set the pack's partition * table */ if ( !suser() ) return(EACCES); /* * Before we set the new partition tables make sure * that it will no corrupt any of the kernel data * structures */ if ( ( error = ptcmp( dev, &rk_part[unit], pt ) ) != 0 ) return(error); /* * Using the user's data to set the partition table * for the pack */ rk_part[unit] = *pt; /* * See if we need to update the superblock of the * "a" partition of this disk */ ssblk(dev,pt); /* * Just make sure that we set the valid bit */ rk_part[unit].pt_valid = PT_VALID; break; case DKIOCDOP: /* Disk operation */ if ( !suser() ) return(EACCES); break; case DKIOCGET: /* Get disk status */ break; case DEVIOCGET: /* Device status */ devget = (struct devget *)data; bzero(devget,sizeof(struct devget)); devget->category = DEV_DISK; /* Disk */ devget->bus = DEV_UB; /* Unibus */ bcopy(DEV_RK711,devget->interface, strlen(DEV_RK711)); /* RK711 */ bcopy(sc->sc_device[ui->ui_unit], devget->device, strlen(sc->sc_device[ui->ui_unit])); /* RK?? */ devget->adpt_num = ui->ui_adpt; /* which adapter*/ devget->nexus_num = ui->ui_nexus; /* which nexus */ devget->bus_num = ui->ui_ubanum; /* which UBA */ devget->ctlr_num = ui->ui_ctlr; /* which RK711 */ devget->slave_num = ui->ui_slave; /* which plug */ bcopy(ui->ui_driver->ud_dname, devget->dev_name, strlen(ui->ui_driver->ud_dname)); /* Ultrix "rk" */ devget->unit_num = unit; /* which rk?? */ devget->soft_count = sc->sc_softcnt[ui->ui_unit]; /* soft er. cnt.*/ devget->hard_count = sc->sc_hardcnt[ui->ui_unit]; /* hard er. cnt.*/ devget->stat = sc->sc_flags[ui->ui_unit]; /* status */ devget->category_stat = DEV_DISKPART; /* which prtn. */ break; default: return (ENXIO); } return(0);}rkecc(ui, flag) register struct uba_device *ui;{ register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; register struct buf *bp = rkutab[ui->ui_unit].b_actf; register struct uba_ctlr *um = ui->ui_mi; register struct rkst *st; struct uba_regs *ubp = ui->ui_hd->uh_uba; caddr_t addr; int reg, npf, o, cmd, ubaddr; int bn, cn, tn, sn; if (flag == CONT) npf = bp->b_error; else npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount); reg = btop(um->um_ubinfo&0x3ffff) + npf; o = (int)bp->b_un.b_addr & PGOFSET; bn = dkblock(bp); st = &rkst[ui->ui_type]; cn = bp->b_cylin; sn = bn%st->nspc + npf; tn = sn/st->nsect; sn %= st->nsect; cn += tn/st->ntrak; tn %= st->ntrak; ubapurge(um); switch (flag) { case ECC: { register int i; int bit, byte, mask; npf--; reg--; mprintf("rk%d%c: soft ecc sn#:%d cyl:%d trk:%d sect:%d\n", dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf, rk->rkcyl, (rk->rkda >> 8) & 0xff, rk->rkda & 0xff); mask = rk->rkec2; i = rk->rkec1 - 1; /* -1 makes 0 origin */ bit = i&07; i = (i&~07)>>3; byte = i + o; while(i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11){ struct pte pte; pte = ubp->uba_map[reg + btop(byte)]; addr = ptob(pte.pg_pfnum)+ (byte & PGOFSET); putmemc(addr, getmemc(addr)^(mask<<bit)); byte++; i++; bit -= 8; } if (rk->rkwc == 0) { um->um_tab.b_active = 0; return (0); } npf++; reg++; break; } case BSE:#ifdef RKBDEBUG if (rkbdebug) printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);#endif if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0) return(0); bp->b_flags |= B_BAD; bp->b_error = npf + 1; bn = st->ncyl*st->nspc - st->nsect - 1 - bn; cn = bn/st->nspc; sn = bn%st->nspc; tn = sn/st->nsect; sn %= st->nsect;#ifdef RKBDEBUG if (rkbdebug) printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);#endif rk->rkwc = -(512 / sizeof (short)); break; case CONT:#ifdef RKBDEBUG if (rkbdebug) printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);#endif bp->b_flags &= ~B_BAD; rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short)); if (rk->rkwc == 0) return (0); break; } rk->rkcs1 = RK_CCLR; rk->rkcs2 = ui->ui_slave; rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; rkwait(rk); rk->rkcyl = cn; rk->rkda = (tn << 8) | sn; ubaddr = (int)ptob(reg) + o; rk->rkba = ubaddr; cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO; cmd |= (ubaddr >> 8) & 0x300; cmd |= rktypes[ui->ui_type]; rk->rkcs1 = cmd; um->um_tab.b_active = 2; /* continuing */ um->um_tab.b_errcnt = 0; /* error has been corrected */ return (1);}rkreset(uban) int uban;{ register struct uba_ctlr *um; register struct uba_device *ui; register rk11, unit; struct rk_softc *sc; for (rk11 = 0; rk11 < nNHK; rk11++) { if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || um->um_alive == 0) continue; printf(" hk%d", rk11); sc = &rk_softc[um->um_ctlr]; um->um_tab.b_active = 0; um->um_tab.b_actf = um->um_tab.b_actl = 0; sc->sc_recal = 0; sc->sc_wticks = 0; if (um->um_ubinfo) { printf("<%d>", (um->um_ubinfo>>28)&0xf); um->um_ubinfo = 0; } for (unit = 0; unit < nNRK; unit++) { if ((ui = rkdinfo[unit]) == 0) continue; if (ui->ui_alive == 0 || ui->ui_mi != um) continue; rkutab[unit].b_active = 0; (void) rkustart(ui); } (void) rkstart(um); }}rkwatch(){ register struct uba_ctlr *um; register rk11, unit; register struct rk_softc *sc; timeout(rkwatch, (caddr_t)0, hz); for (rk11 = 0; rk11 < nNHK; rk11++) { um = rkminfo[rk11]; if (um == 0 || um->um_alive == 0) continue; sc = &rk_softc[rk11]; if (um->um_tab.b_active == 0) { for (unit = 0; unit < nNRK; unit++) if (rkutab[unit].b_active && rkdinfo[unit]->ui_mi == um) goto active; sc->sc_wticks = 0; continue; }active: sc->sc_wticks++; if (sc->sc_wticks >= 30) { sc->sc_wticks = 0; printf("hk%d: lost interrupt\n", rk11); ubareset(um->um_ubanum); } }}#define DBSIZE 20rkdump(dev, dumpinfo) dev_t dev; /* dump device */ struct dumpinfo dumpinfo; /* dump info */{#ifdef notdef struct rkdevice *rkaddr; char *start; char *start_tmp; int blk, unit; register struct uba_regs *uba; register struct uba_device *ui; register short *rp; struct rkst *st; int ubatype; unit = minor(dev) >> 3; if (unit >= nNRK) return (ENXIO);#define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) ui = phys(struct uba_device *, rkdinfo[unit]); if (ui->ui_alive == 0) return (ENXIO); uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; ubatype = phys(struct uba_hd *, ui->ui_hd)->uba_type; ubainit(uba,ubatype); rkaddr = (struct rkdevice *)ui->ui_physaddr; start = start_tmp = 0; rkaddr->rkcs1 = RK_CCLR; rkaddr->rkcs2 = unit; rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; rkwait(rkaddr); if ((rkaddr->rkds & RKDS_VV) == 0) { rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO; rkwait(rkaddr); } st = &rkst[ui->ui_type]; /* * If a full dump is being performed, then this loop * will dump all of core. If a partial dump is being * performed, then as much of core as possible will be * dumped, leaving room for the u_area and error logger * buffer. Please note that dumpsys predetermined what * type of dump will be performed. */ while ((dumpinfo.size_to_dump > 0) || (dumpinfo.partial_dump)) { register struct pte *io; register int i; int cn, sn, tn; daddr_t bn; blk = dumpinfo.size_to_dump > DBSIZE ? DBSIZE : dumpinfo.size_to_dump; io = uba->uba_map; for (i = 0; i < blk; i++) *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; *(int *)io = 0; bn = dumplo + btop(start_tmp); cn = bn/st->nspc + dumpinfo.blkoffs / st->nspc; sn = bn%st->nspc; tn = sn/st->nsect; sn = sn%st->nsect; rkaddr->rkcyl = cn; rp = (short *) &rkaddr->rkda; *rp = (tn << 8) + sn; *--rp = 0; *--rp = -blk*NBPG / sizeof (short); *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE; rkwait(rkaddr); if (rkaddr->rkcs1 & RK_CERR) return (EIO); start += blk*NBPG; start_tmp += blk*NBPG; dumpinfo.size_to_dump -= blk; if ((dumpinfo.size_to_dump <= 0) && (dumpinfo.partial_dump)) { /* * If a partial dump is being performed.... */ /* Set size_to_dump to the number of pages to dump */ dumpinfo.size_to_dump = dumpinfo.pdump[NUM_TO_DUMP-dumpinfo.partial_dump].num_blks; /* Set start to starting address */ start = 0; start += dumpinfo.pdump[NUM_TO_DUMP-dumpinfo.partial_dump].start_addr; dumpinfo.partial_dump--; } } return (0);#endif notdef}rksize(dev) register dev_t dev;{ register int unit = minor(dev) >> 3; register struct uba_device *ui; register struct rkst *st; if (unit >= nNRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0) return (-1); /* * Sanity check 001 */ if ( rk_part[unit].pt_valid != PT_VALID ) panic("rksize: invalid partition table "); return (rk_part[unit].pt_part[minor(dev) & 07].pi_nblocks); /* 001 */}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -