Annotation of 43BSDTahoe/sys/tahoestand/vd.c, revision 1.1

1.1     ! root        1: /*     vd.c    7.10    88/06/14        */
        !             2: 
        !             3: /*
        !             4:  * Stand alone driver for the VDDC/SMDE controller 
        !             5:  */
        !             6: #include "../machine/mtpr.h"
        !             7: 
        !             8: #include "param.h"
        !             9: #include "inode.h"
        !            10: #include "fs.h"
        !            11: #include "buf.h"
        !            12: #include "disklabel.h"
        !            13: #include "saio.h"
        !            14: 
        !            15: #include "../tahoevba/vdreg.h"
        !            16: #include "../tahoevba/vbaparam.h"
        !            17: 
        !            18: #define        COMPAT_42       1
        !            19: 
        !            20: #define NVD            4               /* controllers */
        !            21: #define        NDRIVE          8               /* drives per controller */
        !            22: 
        !            23: #define        VDADDR(ctlr)    ((struct vddevice *)vdaddrs[ctlr])
        !            24: long   vdaddrs[NVD] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300 };
        !            25: 
        !            26: u_char vdinit[NVD];                    /* controller initialized */
        !            27: u_char vdtype[NVD];                    /* controller type */
        !            28: u_char dkconfigured[NVD][NDRIVE];      /* unit configured */
        !            29: u_char dkflags[NVD][NDRIVE];           /* unit flags */
        !            30: 
        !            31: static struct disklabel dklabel[NVD][NDRIVE];  /* pack label */
        !            32: static struct mdcb mdcb;
        !            33: static struct dcb dcb;
        !            34: static char lbuf[DEV_BSIZE];
        !            35: 
        !            36: vdopen(io)
        !            37:        register struct iob *io;
        !            38: {
        !            39:        register int ctlr = io->i_ctlr;
        !            40:        register struct dkinfo *dk;
        !            41:        register struct disklabel *lp, *dlp;
        !            42:        int error;
        !            43: 
        !            44:        if ((u_int)io->i_adapt)
        !            45:                return (EADAPT);
        !            46:        if ((u_int)ctlr >= NVD)
        !            47:                return (ECTLR);
        !            48:        if (!vdinit[ctlr] && (error = vdreset_ctlr(ctlr, io->i_unit)))
        !            49:                return (error);
        !            50:        lp = &dklabel[io->i_ctlr][io->i_unit];
        !            51:        if (!dkconfigured[io->i_ctlr][io->i_unit]) {
        !            52:                struct iob tio;
        !            53: 
        !            54:                /*
        !            55:                 * Read in the pack label.
        !            56:                 */
        !            57:                lp->d_secsize = 1024;
        !            58:                lp->d_nsectors = 72;
        !            59:                lp->d_ntracks = 24;
        !            60:                lp->d_ncylinders = 711;
        !            61:                lp->d_secpercyl = 72*24;
        !            62:                if (!vdreset_drive(io))
        !            63:                        return (ENXIO);
        !            64:                tio = *io;
        !            65:                tio.i_bn = LABELSECTOR;
        !            66:                tio.i_ma = lbuf;
        !            67:                tio.i_cc = DEV_BSIZE;
        !            68:                tio.i_flgs |= F_RDDATA;
        !            69:                if (vdstrategy(&tio, READ) != DEV_BSIZE)
        !            70:                        return (ERDLAB);
        !            71:                dlp = (struct disklabel *)(lbuf + LABELOFFSET);
        !            72:                if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC)
        !            73: #ifdef COMPAT_42
        !            74:                {
        !            75:                        printf("dk%d: unlabeled\n", io->i_unit);
        !            76:                        if (error = vdmaptype(io))
        !            77:                                return (error);
        !            78:                }
        !            79: #else
        !            80:                        return (EUNLAB);
        !            81: #endif
        !            82:                else {
        !            83:                        *lp = *dlp;
        !            84:                        if (!vdreset_drive(io))
        !            85:                                return (ENXIO);
        !            86:                }
        !            87:                dkconfigured[io->i_ctlr][io->i_unit] = 1;
        !            88:        }
        !            89:        if (io->i_part < 0 || io->i_part >= lp->d_npartitions ||
        !            90:            lp->d_partitions[io->i_part].p_size == 0)
        !            91:                return (EPART);
        !            92:        io->i_boff =
        !            93:            (lp->d_partitions[io->i_part].p_offset * lp->d_secsize) / DEV_BSIZE;
        !            94:        return (0);
        !            95: }
        !            96: 
        !            97: /*
        !            98:  * Reset and initialize the controller.
        !            99:  */
        !           100: vdreset_ctlr(ctlr, unit)
        !           101:        register int ctlr, unit;
        !           102: {
        !           103:        register int i;
        !           104:        register struct vddevice *vdaddr = VDADDR(ctlr);
        !           105: 
        !           106:        if (badaddr(vdaddr, 2)) {
        !           107:                printf("vd%d: %x: invalid csr\n", ctlr, vdaddr);
        !           108:                return (ENXIO);
        !           109:        }
        !           110:        /* probe further to find what kind of controller it is */
        !           111:        vdaddr->vdreset = 0xffffffff;
        !           112:        DELAY(1000000);
        !           113:        if (vdaddr->vdreset != 0xffffffff) {
        !           114:                vdtype[ctlr] = VDTYPE_VDDC;
        !           115:                DELAY(1000000);
        !           116:        } else {
        !           117:                vdtype[ctlr] = VDTYPE_SMDE;
        !           118:                vdaddr->vdrstclr = 0;
        !           119:                DELAY(3000000);
        !           120:                vdaddr->vdcsr =  0;
        !           121:                vdaddr->vdtcf_mdcb = AM_ENPDA;
        !           122:                vdaddr->vdtcf_dcb = AM_ENPDA;
        !           123:                vdaddr->vdtcf_trail = AM_ENPDA;
        !           124:                vdaddr->vdtcf_data = AM_ENPDA;
        !           125:                vdaddr->vdccf = CCF_SEN | CCF_DER | CCF_STS |
        !           126:                    XMD_32BIT | BSZ_16WRD |
        !           127:                    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
        !           128:        }
        !           129:        if (!vdcmd(ctlr, 0, VDOP_INIT, 10) ||
        !           130:            !vdcmd(ctlr, 0, VDOP_DIAG, 10)) {
        !           131:                vderror(unit, dcb.opcode == VDOP_INIT ? "init" : "diag", &dcb);
        !           132:                return (EIO);
        !           133:        }
        !           134:        vdinit[ctlr] = 1;
        !           135:        for (i = NDRIVE - 1; i >= 0; i--)
        !           136:                dkconfigured[ctlr][i] = 0;
        !           137:        return (0);
        !           138: }
        !           139: 
        !           140: /*
        !           141:  * Reset and configure a drive's parameters.
        !           142:  */
        !           143: vdreset_drive(io)
        !           144:        register struct iob *io;
        !           145: {
        !           146:        register int ctlr = io->i_ctlr, slave = io->i_unit;
        !           147:        register struct disklabel *lp = &dklabel[io->i_ctlr][io->i_unit];
        !           148:        register struct vddevice *vdaddr = VDADDR(ctlr);
        !           149:        int pass = 0, type = vdtype[ctlr], error;
        !           150:        int devflags = dkflags[ctlr][slave];            /* starts with 0 */
        !           151: 
        !           152: again:
        !           153:        dcb.opcode = VDOP_CONFIG;               /* command */
        !           154:        dcb.intflg = DCBINT_NONE;
        !           155:        dcb.nxtdcb = (struct dcb *)0;   /* end of chain */
        !           156:        dcb.operrsta = 0;
        !           157:        dcb.devselect = slave | devflags;
        !           158:        dcb.trail.rstrail.ncyl = lp->d_ncylinders;
        !           159:        dcb.trail.rstrail.nsurfaces = lp->d_ntracks;
        !           160:        if (type == VDTYPE_SMDE) {
        !           161:                dcb.trailcnt = sizeof (struct treset) / sizeof (long);
        !           162:                dcb.trail.rstrail.nsectors = lp->d_nsectors;
        !           163:                dcb.trail.rstrail.slip_sec = lp->d_trackskew;
        !           164:                dcb.trail.rstrail.recovery = VDRF_NORMAL;
        !           165:        } else
        !           166:                dcb.trailcnt = 2;       /* XXX */
        !           167:        mdcb.mdcb_head = &dcb;
        !           168:        mdcb.mdcb_status = 0;
        !           169:        VDGO(vdaddr, (u_long)&mdcb, type);
        !           170:        if (!vdpoll(vdaddr, &dcb, 10, type)) {
        !           171:                if (pass++ != 0) {
        !           172:                        printf(" during drive configuration.\n");
        !           173:                        return (0);
        !           174:                }
        !           175:                VDRESET(vdaddr, type);
        !           176:                if (error = vdreset_ctlr(ctlr, io->i_unit))
        !           177:                        return (error);
        !           178:                goto again;
        !           179:        }
        !           180:        if ((dcb.operrsta & VDERR_HARD) == 0) {         /* success */
        !           181:                dkflags[ctlr][slave] = devflags;
        !           182:                return (1);
        !           183:        }
        !           184:        if (devflags == 0) {
        !           185:                devflags = VD_ESDI;
        !           186:                goto again;
        !           187:        }
        !           188:        if (type == VDTYPE_SMDE && (vdaddr->vdstatus[slave] & STA_US) == 0) {
        !           189:                printf("dk%d: nonexistent drive\n", io->i_unit);
        !           190:                return (0);
        !           191:        }
        !           192:        if ((dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0) {
        !           193:                vderror(io->i_unit, "config", &dcb);
        !           194:                return (0);
        !           195:        }
        !           196:        devflags = 0;
        !           197:        if (pass++)                     /* give up */
        !           198:                return (0);
        !           199:        /*
        !           200:         * Try to spin up drive with remote command.
        !           201:         */
        !           202:        if (!vdcmd(ctlr, 0, VDOP_START, 62)) {
        !           203:                vderror(io->i_unit, "start", &dcb);
        !           204:                return (0);
        !           205:        }
        !           206:        DELAY(62000000);
        !           207:        goto again;
        !           208: }
        !           209: 
        !           210: vdcmd(ctlr, unit, cmd, time)
        !           211:        register int ctlr;
        !           212:        int unit, cmd, time;
        !           213: {
        !           214:        register struct vddevice *vdaddr = VDADDR(ctlr);
        !           215: 
        !           216:        dcb.opcode = cmd;
        !           217:        dcb.intflg = DCBINT_NONE;
        !           218:        dcb.nxtdcb = (struct dcb *)0;   /* end of chain */
        !           219:        dcb.operrsta  = 0;
        !           220:        dcb.devselect = unit | dkflags[ctlr][unit];
        !           221:        dcb.trailcnt = 0;
        !           222:        mdcb.mdcb_head = &dcb;
        !           223:        mdcb.mdcb_status = 0;
        !           224:        VDGO(vdaddr, (u_long)&mdcb, vdtype[ctlr]);
        !           225:        if (!vdpoll(vdaddr, &dcb, time, vdtype[ctlr]))
        !           226:                _stop(" during initialization operation.\n");
        !           227:        return ((dcb.operrsta & VDERR_HARD) == 0);
        !           228: }
        !           229: 
        !           230: vdstrategy(io, cmd)
        !           231:        register struct iob *io;
        !           232:        int cmd;
        !           233: {
        !           234:        register struct disklabel *lp;
        !           235:        int ctlr, cn, tn, sn, slave, retries = 0;
        !           236:        daddr_t bn;
        !           237:        struct vddevice *vdaddr;
        !           238: 
        !           239:        if (io->i_cc == 0 || io->i_cc > 65535) {
        !           240:                printf("dk%d: invalid transfer size %d\n", io->i_unit,
        !           241:                    io->i_cc);
        !           242:                io->i_error = EIO;
        !           243:                return (-1);
        !           244:        }
        !           245:        lp = &dklabel[io->i_ctlr][io->i_unit];
        !           246:        bn = io->i_bn * (DEV_BSIZE / lp->d_secsize);
        !           247:        cn = bn / lp->d_secpercyl;
        !           248:        sn = bn % lp->d_secpercyl;
        !           249:        tn = sn / lp->d_nsectors;
        !           250:        sn = sn % lp->d_nsectors;
        !           251: 
        !           252: top:
        !           253:        dcb.opcode = (cmd == READ ? VDOP_RD : VDOP_WD);
        !           254:        dcb.intflg = DCBINT_NONE;
        !           255:        dcb.nxtdcb = (struct dcb *)0;   /* end of chain */
        !           256:        dcb.operrsta  = 0;
        !           257:        ctlr = io->i_ctlr;
        !           258:        slave = io->i_unit;
        !           259:        dcb.devselect = slave | dkflags[ctlr][slave];
        !           260:        dcb.trailcnt = sizeof (struct trrw) / sizeof (int);
        !           261:        dcb.trail.rwtrail.memadr = (u_long)io->i_ma; 
        !           262:        dcb.trail.rwtrail.wcount = (io->i_cc + 1) / sizeof (short);
        !           263:        dcb.trail.rwtrail.disk.cylinder = cn;
        !           264:        dcb.trail.rwtrail.disk.track = tn;
        !           265:        dcb.trail.rwtrail.disk.sector = sn;
        !           266:        mdcb.mdcb_head = &dcb;
        !           267:        mdcb.mdcb_status = 0;
        !           268:        vdaddr = VDADDR(ctlr);
        !           269:        VDGO(vdaddr, (u_long)&mdcb, vdtype[ctlr]);
        !           270:        if (!vdpoll(vdaddr, &dcb, 60, vdtype[ctlr]))
        !           271:                _stop(" during i/o operation.\n");
        !           272:        if (dcb.operrsta & VDERR_HARD) {
        !           273:                if (retries++ == 0 && vdreset_ctlr(ctlr, io->i_unit) == 0 &&
        !           274:                    vdreset_drive(io))
        !           275:                        goto top;
        !           276:                vderror(io->i_unit, cmd == READ ? "read" : "write", &dcb);
        !           277:                io->i_error = EIO;
        !           278:                return (-1);
        !           279:        }
        !           280:        mtpr(PADC, 0);
        !           281:        return (io->i_cc);
        !           282: }
        !           283: 
        !           284: vderror(unit, cmd, dcb)
        !           285:        int unit;
        !           286:        char *cmd;
        !           287:        struct dcb *dcb;
        !           288: {
        !           289: 
        !           290:        printf("dk%d: %s error; status %b", unit, cmd,
        !           291:            dcb->operrsta, VDERRBITS);
        !           292:        if (dcb->err_code)
        !           293:                printf(", code %x", dcb->err_code);
        !           294:        printf("\n");
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * Poll controller until operation
        !           299:  * completes or timeout expires.
        !           300:  */
        !           301: vdpoll(vdaddr, dcb, t, type)
        !           302:        register struct vddevice *vdaddr;
        !           303:        register struct dcb *dcb;
        !           304:        register int t, type;
        !           305: {
        !           306: 
        !           307:        t *= 1000;
        !           308:        for (;;) {
        !           309:                uncache(&dcb->operrsta);
        !           310:                if (dcb->operrsta & (DCBS_DONE|DCBS_ABORT))
        !           311:                        break;
        !           312:                if (--t <= 0) {
        !           313:                        printf("vd: controller timeout");
        !           314:                        VDABORT(vdaddr, type);
        !           315:                        DELAY(30000);
        !           316:                        uncache(&dcb->operrsta);
        !           317:                        return (0);
        !           318:                }
        !           319:                DELAY(1000);
        !           320:        }
        !           321:        if (type == VDTYPE_SMDE) {
        !           322:                for (;;) {
        !           323:                        uncache(&vdaddr->vdcsr);
        !           324:                        if ((vdaddr->vdcsr & CS_GO) == 0)
        !           325:                                break;
        !           326:                        DELAY(50);
        !           327:                }
        !           328:                DELAY(300);
        !           329:                uncache(&dcb->err_code);
        !           330:        }
        !           331:        DELAY(200);
        !           332:        uncache(&dcb->operrsta);
        !           333:        return (1);
        !           334: }
        !           335: 
        !           336: #ifdef COMPAT_42
        !           337: struct dkcompat {
        !           338:        int     nsectors;               /* sectors per track */
        !           339:        int     ntracks;                /* tracks per cylinder */
        !           340:        int     ncylinders;             /* cylinders per drive */
        !           341:        int     secsize;                /* sector size */
        !           342: #define        NPART   2
        !           343:        int     poff[NPART];            /* [a+b] for bootstrapping */
        !           344: } dkcompat[] = {
        !           345:        { 64, 20,  842,  512, 0, 61440 },       /* 2361a eagle */
        !           346:        { 48, 24,  711,  512, 0, 61056 },       /* xsd */
        !           347:        { 44, 20,  842,  512, 0, 52800 },       /* eagle */
        !           348:        { 64, 10,  823,  512, 0, 38400 },       /* fuji 360 */
        !           349:        { 32, 24,  711,  512, 0, 40704 },       /* xfd */
        !           350:        { 32, 19,  823,  512, 0, 40128 },       /* smd */
        !           351:        { 32, 10,  823,  512, 0, 19200 },       /* fsd */
        !           352:        { 18, 15, 1224, 1024, 0, 21600 },       /* mxd */
        !           353: };
        !           354: #define        NDKCOMPAT       (sizeof (dkcompat) / sizeof (dkcompat[0]))
        !           355: 
        !           356: /*
        !           357:  * Identify and configure drive from above table
        !           358:  * by trying to read the last sector until a description
        !           359:  * is found for which we're successful.
        !           360:  */
        !           361: vdmaptype(io)
        !           362:        struct iob *io;
        !           363: {
        !           364:        register struct disklabel *lp = &dklabel[io->i_ctlr][io->i_unit];
        !           365:        register struct dkcompat *dp;
        !           366:        int i, ctlr, slave, type;
        !           367:        struct vddevice *vdaddr;
        !           368: 
        !           369:        ctlr = io->i_ctlr;
        !           370:        slave = io->i_unit;
        !           371:        vdaddr = VDADDR(ctlr);
        !           372:        type = vdtype[ctlr];
        !           373:        for (dp = dkcompat; dp < &dkcompat[NDKCOMPAT]; dp++) {
        !           374:                if (type == VDTYPE_VDDC && dp->nsectors != 32)
        !           375:                        continue;
        !           376:                lp->d_nsectors = dp->nsectors;
        !           377:                lp->d_ntracks = dp->ntracks;
        !           378:                lp->d_ncylinders = dp->ncylinders;
        !           379:                lp->d_secsize = dp->secsize;
        !           380:                if (!vdreset_drive(io))         /* set drive parameters */
        !           381:                        return (EIO);
        !           382:                dcb.opcode = VDOP_RD;
        !           383:                dcb.intflg = DCBINT_NONE;
        !           384:                dcb.nxtdcb = (struct dcb *)0;   /* end of chain */
        !           385:                dcb.devselect = slave | dkflags[ctlr][slave];
        !           386:                dcb.operrsta = 0;
        !           387:                dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
        !           388:                dcb.trail.rwtrail.memadr = (u_long)lbuf; 
        !           389:                dcb.trail.rwtrail.wcount = lp->d_secsize / sizeof (short);
        !           390:                dcb.trail.rwtrail.disk.cylinder = dp->ncylinders - 2;
        !           391:                dcb.trail.rwtrail.disk.track = dp->ntracks - 1;
        !           392:                dcb.trail.rwtrail.disk.sector = dp->nsectors - 1;
        !           393:                mdcb.mdcb_head = &dcb;
        !           394:                mdcb.mdcb_status = 0;
        !           395:                VDGO(vdaddr, (u_long)&mdcb, type);
        !           396:                if (!vdpoll(vdaddr, &dcb, 60, type))
        !           397:                        _stop(" during i/o operation.\n");
        !           398:                if (dcb.operrsta & VDERR_HARD)
        !           399:                        continue;
        !           400:                /* simulate necessary parts of disk label */
        !           401:                lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
        !           402:                lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
        !           403:                lp->d_npartitions = NPART;
        !           404:                for (i = 0; i < NPART; i++) {
        !           405:                        lp->d_partitions[i].p_offset = dp->poff[i];
        !           406:                        lp->d_partitions[i].p_size =
        !           407:                            lp->d_secperunit - dp->poff[i];
        !           408:                }
        !           409:                return (0);
        !           410:        }
        !           411:        printf("dk%d: unknown drive type\n", io->i_unit);
        !           412:        return (ENXIO);
        !           413: }
        !           414: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.