📄 rk.c
字号:
#ifndef lintstatic char *sccsid = "@(#)rk.c 4.1 ULTRIX 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1984, 1986 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * rk.c 6.1 07/29/83 * * Modification history * * RK711/RK07 disk driver * * 26-July-89 - Alan Frechette * Conditionalize out the dump code. * * 11-Oct-84 - Stephen Reilly * * Derived from 4.2BSD labeled: rk.c 6.1 83/07/29. * Implemented the new partition table scheme. -001 * * 30-Nov-84 - Stephen Reilly * * Fixed up an error message. -002 * * 11-Mar-85 - Pete Keilty * * Fixed rkintr() do handle drive coming on line or going off line. * Removed check for vv in rkopen() because of bug per steve r. * request. Will be looked into in the future. -003 * * 24-Sep-85 - Stephen Reilly * * Added new ioctl request that will return the default * partition table. -004 * * 18-Mar-86 - jaw * * br/cvec changed to NOT use registers. * * 9-Apr-86 - Paul Shaughnessy * * Added partial dump code support, and removed common dump code. * * 16-Apr-86 - ricky palmer * * Added new DEVIOCGET ioctl request code along with * soft and hard error counters. V2.0 * * 22-May-86 - Paul Shaughnessy * * Added saving of the u_area to the partial dump code. * * 13-Jun-86 - jaw * * Fix to uba reset and drivers. * * 11-Jul-86 - ricky palmer * * Added adpt and nexus fields to DEVIOCGET code. * * 26-Aug-86 - rsp (Ricky Palmer) * * Cleaned up devioctl code to (1) zero out devget structure * upon entry and (2) use strlen instead of fixed storage * for bcopy's. * * 04-Dec-86 - pmk * Changed mprintf's to log just on entry. */#include "rk.h"#if defined(BINARY) || NHK > 0#ifdef RKDEBUGint rkpip; /* DEBUG */int rknosval; /* DEBUG */int rkdebug;#endif RKDEBUG#ifdef RKBDEBUGint rkbdebug;#endif RKBDEBUG#ifdef RKDEBUGint rktrb[1000];int *rktrp = rktrb;#define trace(a,b) { *rktrp++ = *(int *)a; *rktrp++ = (int)b; \ if(rktrp > &rktrb[998]) rktrp = rktrb; }#endif RKDEBUG#include "../h/dump.h"#include "../data/rk_data.c"#define MASKREG(reg) ((reg)&0xffff)short rktypes[] = { RK_CDT, 0 };int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr();u_short rkstd[] = { 0777440, 0 };struct uba_driver hkdriver = { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 };struct rkst { short nsect; short ntrak; short nspc; short ncyl; struct size *sizes;} rkst[] = { NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes,};u_char rk_offset[16] = { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800, RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0 };#define b_cylin b_resid#ifdef INTRLVEdaddr_t dkblock();#endif INTRLVEint rkwstart, rkwatch();rkprobe(reg) caddr_t reg;{#ifdef lint rkintr(0);#endif ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; DELAY(10); ((struct rkdevice *)reg)->rkcs1 = RK_CDT; return (sizeof (struct rkdevice));}rkslave(ui, reg) struct uba_device *ui; caddr_t reg;{ register struct rkdevice *rkaddr = (struct rkdevice *)reg; register struct rk_softc *sc = &rk_softc[ui->ui_ctlr]; sc->sc_offline[ui->ui_unit] = 1; ui->ui_type = 0; rkaddr->rkcs1 = RK_CCLR; rkaddr->rkcs2 = ui->ui_slave; rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; rkwait(rkaddr); DELAY(50); if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) { rkaddr->rkcs1 = RK_CCLR; return (0); } if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) { ui->ui_type = 1; rkaddr->rkcs1 = RK_CCLR; } return (1);}rkattach(ui) register struct uba_device *ui;{ register struct rk_softc *sc = &rk_softc[ui->ui_ctlr]; if (rkwstart == 0) { timeout(rkwatch, (caddr_t)0, hz); rkwstart++; } rkip[ui->ui_ctlr][ui->ui_slave] = ui; sc->sc_ndrive++; rkcyl[ui->ui_unit] = -1; ui->ui_flags = 0; if (ui->ui_dk >= 0) { dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); bcopy(DEV_RK07,sc->sc_device[ui->ui_unit], strlen(DEV_RK07)); sc->sc_softcnt[ui->ui_unit] = 0; sc->sc_hardcnt[ui->ui_unit] = 0; }}rkopen(dev, flag) dev_t dev; int flag;{ register int unit = minor(dev) >> 3; register struct uba_device *ui; register struct rk_softc *sc; struct uba_ctlr *um; register struct rkdevice *rkaddr; register int i; /* 001 */ int rkstrategy(); /* 001 */ if (unit >= nNRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0) { return (ENXIO); } um = ui->ui_mi; /* 001 */ rkaddr = (struct rkdevice *)um->um_addr; sc = &rk_softc[ui->ui_ctlr]; sc->sc_flags[ui->ui_unit] = 0; sc->sc_category_flags[ui->ui_unit] = 0; rkaddr->rkcs1 = RK_CCLR; rkaddr->rkcs2 = ui->ui_unit; rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_SELECT|RK_GO; rkwait(rkaddr); i = rkaddr->rkds; if (!(i & RKDS_DRDY)) { sc->sc_flags[ui->ui_unit] |= DEV_OFFLINE; } if (i & RKDS_WRL) { sc->sc_flags[ui->ui_unit] |= DEV_WRTLCK; } rkaddr->rkcs1 = rktypes[ui->ui_type] | RK_DCLR|RK_GO; rkwait(rkaddr); /* * See if we need to read in the partition table from the disk. * The conditions we will have to read from the disk is if the * partition table valid bit has not been set or the volume * is invalid. */ /* * Assume that the default values before trying to * see if the partition tables are on the pack. The * reason that we do this is that the strategy routine * is used to read in the superblock but uses the * partition info. So we must first assume the * default values. */ if((sc->sc_flags[ui->ui_unit] & DEV_OFFLINE) || (rk_part[unit].pt_valid == 0)) { int nspc = rkst[ui->ui_type].nspc; for( i = 0; i <= 7; i++ ) { rk_part[unit].pt_part[i].pi_nblocks = rkst[ui->ui_type].sizes[i].nblocks; rk_part[unit].pt_part[i].pi_blkoff = rkst[ui->ui_type].sizes[i].cyloff * nspc; } rk_part[unit].pt_valid = PT_VALID; /*001 Validate the pt*/ /* * Default partition are now set. Call rsblk to set * the driver's partition tables, if any exists, from * the "a" partition superblock */ rsblk( rkstrategy, dev, &rk_part[unit] ); } return (0);}rkstrategy(bp) register struct buf *bp;{ register int unit = dkunit(bp); register struct uba_device *ui = rkdinfo[unit]; register struct rkst *st; register struct pt *pt; /* 001 */ register struct rk_softc *sc = &rk_softc[ui->ui_ctlr]; struct buf *dp; int xunit = minor(bp->b_dev) & 07; long bn, sz; int s; sz = (bp->b_bcount+511) >> 9; if (unit >= nNRK) goto bad; if (ui == 0 || ui->ui_alive == 0) goto bad; st = &rkst[ui->ui_type]; /* * Get partition table for the pack */ pt = &rk_part[unit]; if ( rk_part[unit].pt_valid != PT_VALID ) panic("rkstrategy: invalid partition table "); if (bp->b_blkno < 0 || (bn = dkblock(bp))+sz > pt->pt_part[xunit].pi_nblocks) { /* 001 */ sc->sc_flags[ui->ui_unit] |= DEV_EOM; goto bad; } bp->b_cylin = bn/st->nspc + pt->pt_part[xunit].pi_blkoff / st->nspc; s = spl5();#ifdef RKDEBUG trace("stra",bp);#endif RKDEBUG dp = &rkutab[ui->ui_unit]; disksort(dp, bp); if (dp->b_active == 0) {#ifdef RKDEBUG trace("!act",dp);#endif RKDEBUG (void) rkustart(ui); bp = &ui->ui_mi->um_tab; if (bp->b_actf && bp->b_active == 0) (void) rkstart(ui->ui_mi); } splx(s); return;bad: bp->b_flags |= B_ERROR; if (sc->sc_flags[ui->ui_unit] & DEV_EOM) { bp->b_error = ENOSPC; } iodone(bp); return;}rkustart(ui) register struct uba_device *ui;{ register struct buf *bp, *dp; register struct uba_ctlr *um; register struct rkdevice *rkaddr; register struct rk_softc *sc; if (ui == 0) return; dk_busy &= ~(1<<ui->ui_dk); dp = &rkutab[ui->ui_unit]; um = ui->ui_mi; sc = &rk_softc[um->um_ctlr];#ifdef RKDEBUG trace("ustr",dp);#endif RKDEBUG rkaddr = (struct rkdevice *)um->um_addr; if (um->um_tab.b_active) { sc->sc_softas |= 1<<ui->ui_slave;#ifdef RKDEBUG trace("umac",sc->sc_softas);#endif RKDEBUG return; } if ((bp = dp->b_actf) == NULL) {#ifdef RKDEBUG trace("!bp",0);#endif RKDEBUG return; } rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR; rkaddr->rkcs2 = ui->ui_slave; rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; rkwait(rkaddr); if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) { /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ struct rkst *st = &rkst[ui->ui_type]; struct buf *bbp = &brkbuf[ui->ui_unit]; rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO; ui->ui_flags = 1; bbp->b_flags = B_READ|B_BUSY; bbp->b_dev = bp->b_dev; bbp->b_bcount = 512; bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit]; bbp->b_blkno = st->ncyl*st->nspc - st->nsect; bbp->b_cylin = st->ncyl - 1; dp->b_actf = bbp; bbp->av_forw = bp; bp = bbp; rkwait(rkaddr); } if (dp->b_active) goto done; dp->b_active = 1;#ifdef RKDEBUG trace("dpac",1);#endif RKDEBUG if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY) goto done; if (sc->sc_ndrive == 1) goto done; if (bp->b_cylin == rkcyl[ui->ui_unit]) goto done; rkaddr->rkcyl = bp->b_cylin; rkcyl[ui->ui_unit] = bp->b_cylin; rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;#ifdef RKDEBUG trace("seek",bp->b_cylin);#endif RKDEBUG if (ui->ui_dk >= 0) { dk_busy |= 1<<ui->ui_dk; dk_seek[ui->ui_dk]++; } goto out;done: if (dp->b_active != 2) {#ifdef RKDEBUG trace("!=2",dp->b_active);#endif RKDEBUG 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;#ifdef RKDEBUG trace("!nul",um->um_tab.b_actl);#endif RKDEBUG } um->um_tab.b_actl = dp; dp->b_active = 2; }out: return;}rkstart(um) register struct uba_ctlr *um;{ register struct buf *bp, *dp; register struct uba_device *ui; register struct rkdevice *rkaddr; struct rkst *st; daddr_t bn; int sn, tn, cmd;loop: if ((dp = um->um_tab.b_actf) == NULL) {#ifdef RKDEBUG trace("nodp",um);#endif RKDEBUG return; } if ((bp = dp->b_actf) == NULL) {#ifdef RKDEBUG trace("nobp",dp);#endif RKDEBUG um->um_tab.b_actf = dp->b_forw; goto loop; } um->um_tab.b_active++; ui = rkdinfo[dkunit(bp)]; bn = dkblock(bp);#ifdef RKDEBUG trace("star",dp);#endif RKDEBUG st = &rkst[ui->ui_type]; sn = bn%st->nspc; tn = sn/st->nsect; sn %= st->nsect; rkaddr = (struct rkdevice *)ui->ui_addr;retry: rkaddr->rkcs1 = RK_CCLR; rkaddr->rkcs2 = ui->ui_slave; rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; rkwait(rkaddr); if ((rkaddr->rkds&RKDS_SVAL) == 0) {#ifdef RKDEBUG rknosval++;#endif RKDEBUG goto nosval; } if (rkaddr->rkds&RKDS_PIP) {#ifdef RKDEBUG rkpip++;#endif RKDEBUG goto retry; } if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { mprintf("rk%d: not ready\n", dkunit(bp)); if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; rkwait(rkaddr); rkaddr->rkcs1 = RK_CCLR; rkwait(rkaddr); um->um_tab.b_active = 0; um->um_tab.b_errcnt = 0; dp->b_actf = bp->av_forw; dp->b_active = 0; bp->b_flags |= B_ERROR; iodone(bp); goto loop; } mprintf(" (came back!)\n"); }nosval: rkaddr->rkcyl = bp->b_cylin; rkcyl[ui->ui_unit] = bp->b_cylin; rkaddr->rkda = (tn << 8) + sn; rkaddr->rkwc = -bp->b_bcount / sizeof (short); if (bp->b_flags & B_READ) cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO; else cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO; um->um_cmd = cmd; (void) ubago(ui);}rkdgo(um) register struct uba_ctlr *um;{ register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; um->um_tab.b_active = 2; /* should now be 2 */ rkaddr->rkba = um->um_ubinfo; rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);#ifdef RKDEBUG trace("rkgo",um);#endif RKDEBUG}rkintr(rk11) int rk11;{ register struct uba_ctlr *um = rkminfo[rk11]; register struct uba_device *ui; register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; register struct buf *bp, *dp; register struct rk_softc *sc = &rk_softc[um->um_ctlr]; int unit; int as = (rkaddr->rkatt >> 8) | sc->sc_softas; sc->sc_wticks = 0; sc->sc_softas = 0;#ifdef RKDEBUG trace("intr",um->um_tab.b_active);#endif RKDEBUG if (um->um_tab.b_active == 2 || sc->sc_recal) { um->um_tab.b_active = 1; dp = um->um_tab.b_actf; bp = dp->b_actf; ui = rkdinfo[dkunit(bp)]; dk_busy &= ~(1 << ui->ui_dk); if (bp->b_flags&B_BAD) if (rkecc(ui, CONT)) return; if (rkaddr->rkcs1 & RK_CERR) { int recal; u_short ds = rkaddr->rkds; u_short cs2 = rkaddr->rkcs2; u_short er = rkaddr->rker;#ifdef RKDEBUG if (rkdebug) { printf("cs2=%b ds=%b er=%b\n", cs2, RKCS2_BITS, ds, RKDS_BITS, er, RKER_BITS); }#endif if (er & RKER_WLE) { bp->b_flags |= B_ERROR; sc->sc_flags[ui->ui_unit] |= DEV_WRTLCK; } else if (++um->um_tab.b_errcnt > 28 || ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) {hard: harderr(bp, "rk"); sc->sc_hardcnt[ui->ui_unit]++; sc->sc_flags[ui->ui_unit] |= DEV_HARDERR; mprintf("%s: unit#:%d hard err blk#:%d \ rkcs1:%x rkwc:%x rkba:%x rkda:%x rkcs2:%x \ rkds:%x rker:%x rkatt:%x rkdc:%x rkdb:%x \ rkmr1:%x rkec1:%x rkec2:%x rkmr2:%x \ rkmr3:%x\n", sc->sc_device[ui->ui_unit], ui->ui_unit, bp->b_blkno, MASKREG(rkaddr->rkcs1), MASKREG(rkaddr->rkwc), MASKREG(rkaddr->rkba), MASKREG(rkaddr->rkda),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -