Annotation of 43BSDReno/sys/tahoestand/vd.c, revision 1.1.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.