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

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

unix.superglobalmegacorp.com

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