[BACK]Return to hd.c CVS log [TXT][DIR] Up to [local] / sys / arch / hp300 / dev

Annotation of sys/arch/hp300/dev/hd.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: hd.c,v 1.53 2007/06/21 20:23:07 miod Exp $    */
        !             2: /*     $NetBSD: rd.c,v 1.33 1997/07/10 18:14:08 kleink Exp $   */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1996, 1997 Jason R. Thorpe.  All rights reserved.
        !             6:  * Copyright (c) 1988 University of Utah.
        !             7:  * Copyright (c) 1982, 1990, 1993
        !             8:  *     The Regents of the University of California.  All rights reserved.
        !             9:  *
        !            10:  * This code is derived from software contributed to Berkeley by
        !            11:  * the Systems Programming Group of the University of Utah Computer
        !            12:  * Science Department.
        !            13:  *
        !            14:  * Redistribution and use in source and binary forms, with or without
        !            15:  * modification, are permitted provided that the following conditions
        !            16:  * are met:
        !            17:  * 1. Redistributions of source code must retain the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer.
        !            19:  * 2. Redistributions in binary form must reproduce the above copyright
        !            20:  *    notice, this list of conditions and the following disclaimer in the
        !            21:  *    documentation and/or other materials provided with the distribution.
        !            22:  * 3. Neither the name of the University nor the names of its contributors
        !            23:  *    may be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  *
        !            38:  * from: Utah $Hdr: rd.c 1.44 92/12/26$
        !            39:  *
        !            40:  *     @(#)rd.c        8.2 (Berkeley) 5/19/94
        !            41:  */
        !            42:
        !            43: /*
        !            44:  * CS80/SS80 disk driver
        !            45:  */
        !            46:
        !            47: #include <sys/param.h>
        !            48: #include <sys/systm.h>
        !            49: #include <sys/buf.h>
        !            50: #include <sys/conf.h>
        !            51: #include <sys/device.h>
        !            52: #include <sys/disk.h>
        !            53: #include <sys/disklabel.h>
        !            54: #include <sys/fcntl.h>
        !            55: #include <sys/ioctl.h>
        !            56: #include <sys/kernel.h>
        !            57: #include <sys/proc.h>
        !            58: #include <sys/stat.h>
        !            59: #include <sys/syslog.h>
        !            60:
        !            61: #include <ufs/ffs/fs.h>                        /* for BBSIZE and SBSIZE */
        !            62:
        !            63: #include <hp300/dev/hpibvar.h>
        !            64:
        !            65: #include <hp300/dev/hdreg.h>
        !            66: #include <hp300/dev/hdvar.h>
        !            67:
        !            68: #ifdef USELEDS
        !            69: #include <hp300/hp300/leds.h>
        !            70: #endif
        !            71:
        !            72: #ifndef        HDRETRY
        !            73: #define        HDRETRY         5
        !            74: #endif
        !            75:
        !            76: #ifndef        HDWAITC
        !            77: #define HDWAITC                1       /* min time for timeout in seconds */
        !            78: #endif
        !            79:
        !            80: int    hderrthresh = HDRETRY - 1;      /* when to start reporting errors */
        !            81:
        !            82: #ifdef DEBUG
        !            83: /* error message tables */
        !            84: const char *err_reject[16] = {
        !            85:        NULL,
        !            86:        NULL,
        !            87:        "channel parity error",         /* 0x2000 */
        !            88:        NULL,
        !            89:        NULL,
        !            90:        "illegal opcode",               /* 0x0400 */
        !            91:        "module addressing",            /* 0x0200 */
        !            92:        "address bounds",               /* 0x0100 */
        !            93:        "parameter bounds",             /* 0x0080 */
        !            94:        "illegal parameter",            /* 0x0040 */
        !            95:        "message sequence",             /* 0x0020 */
        !            96:        NULL,
        !            97:        "message length",               /* 0x0008 */
        !            98:        NULL,
        !            99:        NULL,
        !           100:        NULL
        !           101: };
        !           102:
        !           103: const char *err_fault[16] = {
        !           104:        NULL,
        !           105:        "cross unit",                   /* 0x4000 */
        !           106:        NULL,
        !           107:        "controller fault",             /* 0x1000 */
        !           108:        NULL,
        !           109:        NULL,
        !           110:        "unit fault",                   /* 0x0200 */
        !           111:        NULL,
        !           112:        "diagnostic result",            /* 0x0080 */
        !           113:        NULL,
        !           114:        "operator release request",     /* 0x0020 */
        !           115:        "diagnostic release request",   /* 0x0010 */
        !           116:        "internal maintenance release request", /* 0x0008 */
        !           117:        NULL,
        !           118:        "power fail",                   /* 0x0002 */
        !           119:        "retransmit"                    /* 0x0001 */
        !           120: };
        !           121:
        !           122: const char *err_access[16] = {
        !           123:        "illegal parallel operation",   /* 0x8000 */
        !           124:        "uninitialized media",          /* 0x4000 */
        !           125:        "no spares available",          /* 0x2000 */
        !           126:        "not ready",                    /* 0x1000 */
        !           127:        "write protect",                /* 0x0800 */
        !           128:        "no data found",                /* 0x0400 */
        !           129:        NULL,
        !           130:        NULL,
        !           131:        "unrecoverable data overflow",  /* 0x0080 */
        !           132:        "unrecoverable data",           /* 0x0040 */
        !           133:        NULL,
        !           134:        "end of file",                  /* 0x0010 */
        !           135:        "end of volume",                /* 0x0008 */
        !           136:        NULL,
        !           137:        NULL,
        !           138:        NULL
        !           139: };
        !           140:
        !           141: const char *err_info[16] = {
        !           142:        "operator release request",     /* 0x8000 */
        !           143:        "diagnostic release request",   /* 0x4000 */
        !           144:        "internal maintenance release request", /* 0x2000 */
        !           145:        "media wear",                   /* 0x1000 */
        !           146:        "latency induced",              /* 0x0800 */
        !           147:        NULL,
        !           148:        NULL,
        !           149:        "auto sparing invoked",         /* 0x0100 */
        !           150:        NULL,
        !           151:        "recoverable data overflow",    /* 0x0040 */
        !           152:        "marginal data",                /* 0x0020 */
        !           153:        "recoverable data",             /* 0x0010 */
        !           154:        NULL,
        !           155:        "maintenance track overflow",   /* 0x0004 */
        !           156:        NULL,
        !           157:        NULL
        !           158: };
        !           159:
        !           160: #define HDB_FOLLOW     0x01
        !           161: #define HDB_STATUS     0x02
        !           162: #define HDB_IDENT      0x04
        !           163: #define HDB_IO         0x08
        !           164: #define HDB_ASYNC      0x10
        !           165: #define HDB_ERROR      0x80
        !           166: int    hddebug = HDB_ERROR | HDB_IDENT;
        !           167: #endif
        !           168:
        !           169: /*
        !           170:  * Misc. HW description, indexed by sc_type.
        !           171:  * Nothing really critical here, could do without it.
        !           172:  */
        !           173: const struct hdidentinfo hdidentinfo[] = {
        !           174:        { HD7946AID,    0,      "7945A",        NHD7945ABPT,
        !           175:          NHD7945ATRK,  968,     108416 },
        !           176:
        !           177:        { HD9134DID,    1,      "9134D",        NHD9134DBPT,
        !           178:          NHD9134DTRK,  303,      29088 },
        !           179:
        !           180:        { HD9134LID,    1,      "9122S",        NHD9122SBPT,
        !           181:          NHD9122STRK,  77,        1232 },
        !           182:
        !           183:        { HD7912PID,    0,      "7912P",        NHD7912PBPT,
        !           184:          NHD7912PTRK,  572,     128128 },
        !           185:
        !           186:        { HD7914PID,    0,      "7914P",        NHD7914PBPT,
        !           187:          NHD7914PTRK,  1152,    258048 },
        !           188:
        !           189:        { HD7958AID,    0,      "7958A",        NHD7958ABPT,
        !           190:          NHD7958ATRK,  1013,    255276 },
        !           191:
        !           192:        { HD7957AID,    0,      "7957A",        NHD7957ABPT,
        !           193:          NHD7957ATRK,  1036,    159544 },
        !           194:
        !           195:        { HD7933HID,    0,      "7933H",        NHD7933HBPT,
        !           196:          NHD7933HTRK,  1321,    789958 },
        !           197:
        !           198:        { HD9134LID,    1,      "9134L",        NHD9134LBPT,
        !           199:          NHD9134LTRK,  973,      77840 },
        !           200:
        !           201:        { HD7936HID,    0,      "7936H",        NHD7936HBPT,
        !           202:          NHD7936HTRK,  698,     600978 },
        !           203:
        !           204:        { HD7937HID,    0,      "7937H",        NHD7937HBPT,
        !           205:          NHD7937HTRK,  698,    1116102 },
        !           206:
        !           207:        { HD7914CTID,   0,      "7914CT",       NHD7914PBPT,
        !           208:          NHD7914PTRK,  1152,    258048 },
        !           209:
        !           210:        { HD7946AID,    0,      "7946A",        NHD7945ABPT,
        !           211:          NHD7945ATRK,  968,     108416 },
        !           212:
        !           213:        { HD9134LID,    1,      "9122D",        NHD9122SBPT,
        !           214:          NHD9122STRK,  77,        1232 },
        !           215:
        !           216:        { HD7957BID,    0,      "7957B",        NHD7957BBPT,
        !           217:          NHD7957BTRK,  1269,    159894 },
        !           218:
        !           219:        { HD7958BID,    0,      "7958B",        NHD7958BBPT,
        !           220:          NHD7958BTRK,  786,     297108 },
        !           221:
        !           222:        { HD7959BID,    0,      "7959B",        NHD7959BBPT,
        !           223:          NHD7959BTRK,  1572,    594216 },
        !           224:
        !           225:        { HD2200AID,    0,      "2200A",        NHD2200ABPT,
        !           226:          NHD2200ATRK,  1449,    654948 },
        !           227:
        !           228:        { HD2203AID,    0,      "2203A",        NHD2203ABPT,
        !           229:          NHD2203ATRK,  1449,   1309896 }
        !           230: };
        !           231: const int numhdidentinfo = sizeof(hdidentinfo) / sizeof(hdidentinfo[0]);
        !           232:
        !           233: bdev_decl(hd);
        !           234: cdev_decl(hd);
        !           235:
        !           236: int    hdident(struct device *, struct hd_softc *,
        !           237:            struct hpibbus_attach_args *);
        !           238: void   hdreset(int, int, int);
        !           239: void   hdustart(struct hd_softc *);
        !           240: void   hdgetdisklabel(dev_t, struct hd_softc *, struct disklabel *, int);
        !           241: void   hdrestart(void *);
        !           242: struct buf *hdfinish(struct hd_softc *, struct buf *);
        !           243:
        !           244: void   hdstart(void *);
        !           245: void   hdinterrupt(void *);
        !           246: void   hdgo(void *);
        !           247: int    hdstatus(struct hd_softc *);
        !           248: int    hderror(int);
        !           249: #ifdef DEBUG
        !           250: void   hdprinterr(const char *, short, const char **);
        !           251: #endif
        !           252:
        !           253: int    hdmatch(struct device *, void *, void *);
        !           254: void   hdattach(struct device *, struct device *, void *);
        !           255:
        !           256: struct cfattach hd_ca = {
        !           257:        sizeof(struct hd_softc), hdmatch, hdattach
        !           258: };
        !           259:
        !           260: struct cfdriver hd_cd = {
        !           261:        NULL, "hd", DV_DISK
        !           262: };
        !           263:
        !           264: #define        hdlock(rs)      disk_lock(&(rs)->sc_dkdev)
        !           265: #define        hdunlock(rs)    disk_unlock(&(rs)->sc_dkdev)
        !           266: #define        hdlookup(unit)  (struct hd_softc *)device_lookup(&hd_cd, (unit))
        !           267:
        !           268: int
        !           269: hdmatch(parent, match, aux)
        !           270:        struct device *parent;
        !           271:        void *match, *aux;
        !           272: {
        !           273:        struct hpibbus_attach_args *ha = aux;
        !           274:
        !           275:        return (hdident(parent, NULL, ha));
        !           276: }
        !           277:
        !           278: void
        !           279: hdattach(parent, self, aux)
        !           280:        struct device *parent, *self;
        !           281:        void *aux;
        !           282: {
        !           283:        struct hd_softc *sc = (struct hd_softc *)self;
        !           284:        struct hpibbus_attach_args *ha = aux;
        !           285:
        !           286:        if (hdident(parent, sc, ha) == 0) {
        !           287:                printf("\n%s: didn't respond to describe command!\n",
        !           288:                    sc->sc_dev.dv_xname);
        !           289:                return;
        !           290:        }
        !           291:
        !           292:        /*
        !           293:         * Initialize and attach the disk structure.
        !           294:         */
        !           295:        bzero(&sc->sc_dkdev, sizeof(sc->sc_dkdev));
        !           296:        sc->sc_dkdev.dk_name = sc->sc_dev.dv_xname;
        !           297:        disk_attach(&sc->sc_dkdev);
        !           298:
        !           299:        sc->sc_slave = ha->ha_slave;
        !           300:        sc->sc_punit = ha->ha_punit;
        !           301:
        !           302:        /* Initialize the hpib job queue entry */
        !           303:        sc->sc_hq.hq_softc = sc;
        !           304:        sc->sc_hq.hq_slave = sc->sc_slave;
        !           305:        sc->sc_hq.hq_start = hdstart;
        !           306:        sc->sc_hq.hq_go = hdgo;
        !           307:        sc->sc_hq.hq_intr = hdinterrupt;
        !           308:
        !           309: #ifdef DEBUG
        !           310:        /* always report errors */
        !           311:        if (hddebug & HDB_ERROR)
        !           312:                hderrthresh = 0;
        !           313: #endif
        !           314:
        !           315:        /* Initialize timeout structure */
        !           316:        timeout_set(&sc->sc_timeout, hdrestart, sc);
        !           317: }
        !           318:
        !           319: int
        !           320: hdident(parent, sc, ha)
        !           321:        struct device *parent;
        !           322:        struct hd_softc *sc;
        !           323:        struct hpibbus_attach_args *ha;
        !           324: {
        !           325:        struct cs80_describe desc;
        !           326:        u_char stat, cmd[3];
        !           327:        char name[7];
        !           328:        int i, id, n, ctlr, slave;
        !           329:
        !           330:        ctlr = parent->dv_unit;
        !           331:        slave = ha->ha_slave;
        !           332:
        !           333:        /* Verify that we have a CS80 device. */
        !           334:        if ((ha->ha_id & 0x200) == 0)
        !           335:                return (0);
        !           336:
        !           337:        /* Is it one of the disks we support? */
        !           338:        for (id = 0; id < numhdidentinfo; id++)
        !           339:                if (ha->ha_id == hdidentinfo[id].ri_hwid &&
        !           340:                    ha->ha_punit <= hdidentinfo[id].ri_maxunum)
        !           341:                        break;
        !           342:        if (id == numhdidentinfo)
        !           343:                return (0);
        !           344:
        !           345:        /*
        !           346:         * Reset device and collect description
        !           347:         */
        !           348:        bzero(&desc, sizeof(desc));
        !           349:        stat = 0;
        !           350:        hdreset(ctlr, slave, ha->ha_punit);
        !           351:        cmd[0] = C_SUNIT(ha->ha_punit);
        !           352:        cmd[1] = C_SVOL(0);
        !           353:        cmd[2] = C_DESC;
        !           354:        hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd));
        !           355:        hpibrecv(ctlr, slave, C_EXEC, &desc, sizeof(desc));
        !           356:        hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
        !           357:
        !           358:        if (desc.d_name == 0 && stat != 0)
        !           359:                return (0);
        !           360:
        !           361:        /*
        !           362:         * If we're just probing for the device, that's all the
        !           363:         * work we need to do.
        !           364:         */
        !           365:        if (sc == NULL)
        !           366:                return (1);
        !           367:
        !           368:        bzero(name, sizeof(name));
        !           369:        n = desc.d_name;
        !           370:        for (i = 5; i >= 0; i--) {
        !           371:                name[i] = (n & 0xf) + '0';
        !           372:                n >>= 4;
        !           373:        }
        !           374:
        !           375: #ifdef DEBUG
        !           376:        if (hddebug & HDB_IDENT) {
        !           377:                printf(": stat %d name: %x ('%s')\n", stat, desc.d_name, name);
        !           378:                printf("  iuw %x, maxxfr %d, ctype %d\n",
        !           379:                    desc.d_iuw, desc.d_cmaxxfr, desc.d_ctype);
        !           380:                printf("  utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",
        !           381:                    desc.d_utype, desc.d_sectsize,
        !           382:                    desc.d_blkbuf, desc.d_burstsize, desc.d_blocktime);
        !           383:                printf("  avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",
        !           384:                    desc.d_uavexfr, desc.d_retry, desc.d_access,
        !           385:                    desc.d_maxint, desc.d_fvbyte, desc.d_rvbyte);
        !           386:                printf("  maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",
        !           387:                    desc.d_maxcyl, desc.d_maxhead, desc.d_maxsect,
        !           388:                    desc.d_maxvsectl, desc.d_interleave);
        !           389:                printf("%s:", sc->sc_dev.dv_xname);
        !           390:        }
        !           391: #endif
        !           392:
        !           393:        /*
        !           394:         * Take care of a couple of anomalies:
        !           395:         * 1. 7945A and 7946A both return same HW id
        !           396:         * 2. 9122S and 9134D both return same HW id
        !           397:         * 3. 9122D and 9134L both return same HW id
        !           398:         */
        !           399:        switch (ha->ha_id) {
        !           400:        case HD7946AID:
        !           401:                if (bcmp(name, "079450", 6) == 0)
        !           402:                        id = HD7945A;
        !           403:                else
        !           404:                        id = HD7946A;
        !           405:                break;
        !           406:
        !           407:        case HD9134LID:
        !           408:                if (bcmp(name, "091340", 6) == 0)
        !           409:                        id = HD9134L;
        !           410:                else
        !           411:                        id = HD9122D;
        !           412:                break;
        !           413:
        !           414:        case HD9134DID:
        !           415:                if (bcmp(name, "091220", 6) == 0)
        !           416:                        id = HD9122S;
        !           417:                else
        !           418:                        id = HD9134D;
        !           419:                break;
        !           420:        }
        !           421:
        !           422:        sc->sc_type = id;
        !           423:
        !           424:        /*
        !           425:         * XXX We use DEV_BSIZE instead of the sector size value pulled
        !           426:         * XXX off the driver because all of this code assumes 512 byte
        !           427:         * XXX blocks.  ICK!
        !           428:         */
        !           429:        printf(": %s\n", hdidentinfo[id].ri_desc);
        !           430:        printf("%s: %luMB, %lu cyl, %lu head, %lu sec, %lu bytes/sec, %lu sec total\n",
        !           431:            sc->sc_dev.dv_xname,
        !           432:            hdidentinfo[id].ri_nblocks / (1048576 / DEV_BSIZE),
        !           433:            hdidentinfo[id].ri_ncyl, hdidentinfo[id].ri_ntpc,
        !           434:            hdidentinfo[id].ri_nbpt, DEV_BSIZE, hdidentinfo[id].ri_nblocks);
        !           435:
        !           436:        return (1);
        !           437: }
        !           438:
        !           439: void
        !           440: hdreset(ctlr, slave, punit)
        !           441:        int ctlr, slave, punit;
        !           442: {
        !           443:        struct  hd_ssmcmd ssmc;
        !           444:        struct  hd_srcmd src;
        !           445:        struct  hd_clearcmd clear;
        !           446:        u_char stat;
        !           447:
        !           448:        bzero(&clear, sizeof(clear));
        !           449:        clear.c_unit = C_SUNIT(punit);
        !           450:        clear.c_cmd = C_CLEAR;
        !           451:        hpibsend(ctlr, slave, C_TCMD, &clear, sizeof(clear));
        !           452:        hpibswait(ctlr, slave);
        !           453:        hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
        !           454:
        !           455:        bzero(&src, sizeof(src));
        !           456:        src.c_unit = C_SUNIT(HDCTLR);
        !           457:        src.c_nop = C_NOP;
        !           458:        src.c_cmd = C_SREL;
        !           459:        src.c_param = C_REL;
        !           460:        hpibsend(ctlr, slave, C_CMD, &src, sizeof(src));
        !           461:        hpibswait(ctlr, slave);
        !           462:        hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
        !           463:
        !           464:        bzero(&ssmc, sizeof(ssmc));
        !           465:        ssmc.c_unit = C_SUNIT(punit);
        !           466:        ssmc.c_cmd = C_SSM;
        !           467:        ssmc.c_refm = REF_MASK;
        !           468:        ssmc.c_fefm = FEF_MASK;
        !           469:        ssmc.c_aefm = AEF_MASK;
        !           470:        ssmc.c_iefm = IEF_MASK;
        !           471:        hpibsend(ctlr, slave, C_CMD, &ssmc, sizeof(ssmc));
        !           472:        hpibswait(ctlr, slave);
        !           473:        hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
        !           474: }
        !           475:
        !           476: /*
        !           477:  * Read or construct a disklabel
        !           478:  */
        !           479: void
        !           480: hdgetdisklabel(dev, rs, lp, spoofonly)
        !           481:        dev_t dev;
        !           482:        struct hd_softc *rs;
        !           483:        struct disklabel *lp;
        !           484:        int spoofonly;
        !           485: {
        !           486:        char *errstring;
        !           487:
        !           488:        bzero(lp, sizeof(struct disklabel));
        !           489:
        !           490:        /*
        !           491:         * Create a default disk label based on geometry.
        !           492:         * This will get overridden if there is a real label on the disk.
        !           493:         */
        !           494:        lp->d_secsize = DEV_BSIZE;
        !           495:        lp->d_ntracks = hdidentinfo[rs->sc_type].ri_ntpc;
        !           496:        lp->d_nsectors = hdidentinfo[rs->sc_type].ri_nbpt;
        !           497:        lp->d_ncylinders = hdidentinfo[rs->sc_type].ri_ncyl;
        !           498:        lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
        !           499:        if (lp->d_secpercyl == 0) {
        !           500:                lp->d_secpercyl = 100;
        !           501:                /* as long as it's not 0 - readdisklabel divides by it */
        !           502:        }
        !           503:
        !           504:        lp->d_type = DTYPE_HPIB;
        !           505:        strncpy(lp->d_typename, hdidentinfo[rs->sc_type].ri_desc,
        !           506:            sizeof(lp->d_typename));
        !           507:        strncpy(lp->d_packname, "fictitious", sizeof lp->d_packname);
        !           508:
        !           509:        DL_SETDSIZE(lp, hdidentinfo[rs->sc_type].ri_nblocks);
        !           510:        lp->d_rpm = 3600;
        !           511:        lp->d_interleave = 1;
        !           512:        lp->d_flags = 0;
        !           513:        lp->d_version = 1;
        !           514:
        !           515:        /* XXX - these values for BBSIZE and SBSIZE assume ffs */
        !           516:        lp->d_bbsize = BBSIZE;
        !           517:        lp->d_sbsize = SBSIZE;
        !           518:
        !           519:        lp->d_magic = DISKMAGIC;
        !           520:        lp->d_magic2 = DISKMAGIC;
        !           521:        lp->d_checksum = dkcksum(lp);
        !           522:
        !           523:        /*
        !           524:         * Now try to read the disklabel
        !           525:         */
        !           526:        errstring = readdisklabel(DISKLABELDEV(dev), hdstrategy, lp,
        !           527:            spoofonly);
        !           528:        if (errstring) {
        !           529:                /* printf("%s: %s\n", rs->sc_dev.dv_xname, errstring); */
        !           530:                return;
        !           531:        }
        !           532: }
        !           533:
        !           534: int
        !           535: hdopen(dev, flags, mode, p)
        !           536:        dev_t dev;
        !           537:        int flags, mode;
        !           538:        struct proc *p;
        !           539: {
        !           540:        int unit = DISKUNIT(dev);
        !           541:        struct hd_softc *rs;
        !           542:        int mask, part;
        !           543:        int error;
        !           544:
        !           545:        rs = hdlookup(unit);
        !           546:        if (rs == NULL)
        !           547:                return (ENXIO);
        !           548:
        !           549:        if ((error = hdlock(rs)) != 0) {
        !           550:                device_unref(&rs->sc_dev);
        !           551:                return (error);
        !           552:        }
        !           553:
        !           554:        /*
        !           555:         * On first open, get label and partition info.
        !           556:         * We may block reading the label, so be careful
        !           557:         * to stop any other opens.
        !           558:         */
        !           559:        if (rs->sc_dkdev.dk_openmask == 0) {
        !           560:                rs->sc_flags |= HDF_OPENING;
        !           561:                hdgetdisklabel(dev, rs, rs->sc_dkdev.dk_label, 0);
        !           562:                rs->sc_flags &= ~HDF_OPENING;
        !           563:        }
        !           564:
        !           565:        part = DISKPART(dev);
        !           566:        mask = 1 << part;
        !           567:
        !           568:        /* Check that the partition exists. */
        !           569:        if (part != RAW_PART &&
        !           570:            (part > rs->sc_dkdev.dk_label->d_npartitions ||
        !           571:             rs->sc_dkdev.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
        !           572:                error = ENXIO;
        !           573:                goto out;
        !           574:        }
        !           575:
        !           576:        /* Ensure only one open at a time. */
        !           577:        switch (mode) {
        !           578:        case S_IFCHR:
        !           579:                rs->sc_dkdev.dk_copenmask |= mask;
        !           580:                break;
        !           581:        case S_IFBLK:
        !           582:                rs->sc_dkdev.dk_bopenmask |= mask;
        !           583:                break;
        !           584:        }
        !           585:        rs->sc_dkdev.dk_openmask =
        !           586:            rs->sc_dkdev.dk_copenmask | rs->sc_dkdev.dk_bopenmask;
        !           587:
        !           588:        error = 0;
        !           589: out:
        !           590:        hdunlock(rs);
        !           591:        device_unref(&rs->sc_dev);
        !           592:        return (error);
        !           593: }
        !           594:
        !           595: int
        !           596: hdclose(dev, flag, mode, p)
        !           597:        dev_t dev;
        !           598:        int flag, mode;
        !           599:        struct proc *p;
        !           600: {
        !           601:        int unit = DISKUNIT(dev);
        !           602:        struct hd_softc *rs;
        !           603:        struct disk *dk;
        !           604:        int mask, s;
        !           605:        int error;
        !           606:
        !           607:        rs = hdlookup(unit);
        !           608:        if (rs == NULL)
        !           609:                return (ENXIO);
        !           610:
        !           611:        if ((error = hdlock(rs)) != 0) {
        !           612:                device_unref(&rs->sc_dev);
        !           613:                return (error);
        !           614:        }
        !           615:
        !           616:        mask = 1 << DISKPART(dev);
        !           617:        dk = &rs->sc_dkdev;
        !           618:        switch (mode) {
        !           619:        case S_IFCHR:
        !           620:                dk->dk_copenmask &= ~mask;
        !           621:                break;
        !           622:        case S_IFBLK:
        !           623:                dk->dk_bopenmask &= ~mask;
        !           624:                break;
        !           625:        }
        !           626:        dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
        !           627:
        !           628:        /*
        !           629:         * On last close, we wait for all activity to cease since
        !           630:         * the label/parition info will become invalid.
        !           631:         * Note we don't have to about other closes since we know
        !           632:         * we are the last one.
        !           633:         */
        !           634:        if (dk->dk_openmask == 0) {
        !           635:                rs->sc_flags |= HDF_CLOSING;
        !           636:                s = splbio();
        !           637:                while (rs->sc_tab.b_active) {
        !           638:                        rs->sc_flags |= HDF_WANTED;
        !           639:                        tsleep((caddr_t)&rs->sc_tab, PRIBIO, "hdclose", 0);
        !           640:                }
        !           641:                splx(s);
        !           642:                rs->sc_flags &= ~(HDF_CLOSING);
        !           643:        }
        !           644:
        !           645:        hdunlock(rs);
        !           646:        device_unref(&rs->sc_dev);
        !           647:        return (0);
        !           648: }
        !           649:
        !           650: void
        !           651: hdstrategy(bp)
        !           652:        struct buf *bp;
        !           653: {
        !           654:        int unit = DISKUNIT(bp->b_dev);
        !           655:        struct hd_softc *rs;
        !           656:        struct buf *dp;
        !           657:        struct disklabel *lp;
        !           658:        int s;
        !           659:
        !           660:        rs = hdlookup(unit);
        !           661:        if (rs == NULL) {
        !           662:                bp->b_error = ENXIO;
        !           663:                goto bad;
        !           664:        }
        !           665:
        !           666: #ifdef DEBUG
        !           667:        if (hddebug & HDB_FOLLOW)
        !           668:                printf("hdstrategy(%x): dev %x, bn %x, bcount %lx, %c\n",
        !           669:                       bp, bp->b_dev, bp->b_blkno, bp->b_bcount,
        !           670:                       (bp->b_flags & B_READ) ? 'R' : 'W');
        !           671: #endif
        !           672:
        !           673:        lp = rs->sc_dkdev.dk_label;
        !           674:
        !           675:        /*
        !           676:         * If it's a null transfer, return immediately
        !           677:         */
        !           678:        if (bp->b_bcount == 0)
        !           679:                goto done;
        !           680:
        !           681:        /*
        !           682:         * The transfer must be a whole number of blocks.
        !           683:         */
        !           684:        if ((bp->b_bcount % lp->d_secsize) != 0) {
        !           685:                bp->b_error = EINVAL;
        !           686:                goto bad;
        !           687:        }
        !           688:
        !           689:        /*
        !           690:         * Do bounds checking, adjust transfer. if error, process;
        !           691:         * If end of partition, just return.
        !           692:         */
        !           693:        if (bounds_check_with_label(bp, lp,
        !           694:            (rs->sc_flags & HDF_WLABEL) != 0) <= 0)
        !           695:                        goto done;
        !           696:
        !           697:        s = splbio();
        !           698:        dp = &rs->sc_tab;
        !           699:        disksort(dp, bp);
        !           700:        if (dp->b_active == 0) {
        !           701:                dp->b_active = 1;
        !           702:                hdustart(rs);
        !           703:        }
        !           704:        splx(s);
        !           705:
        !           706:        device_unref(&rs->sc_dev);
        !           707:        return;
        !           708: bad:
        !           709:        bp->b_flags |= B_ERROR;
        !           710: done:
        !           711:        /*
        !           712:         * Correctly set the buf to indicate a completed xfer
        !           713:         */
        !           714:        bp->b_resid = bp->b_bcount;
        !           715:        s = splbio();
        !           716:        biodone(bp);
        !           717:        splx(s);
        !           718:        if (rs != NULL)
        !           719:                device_unref(&rs->sc_dev);
        !           720: }
        !           721:
        !           722: /*
        !           723:  * Called via timeout(9) when handling maintenance releases
        !           724:  */
        !           725: void
        !           726: hdrestart(arg)
        !           727:        void *arg;
        !           728: {
        !           729:        int s = splbio();
        !           730:        hdustart((struct hd_softc *)arg);
        !           731:        splx(s);
        !           732: }
        !           733:
        !           734: void
        !           735: hdustart(rs)
        !           736:        struct hd_softc *rs;
        !           737: {
        !           738:        struct buf *bp;
        !           739:
        !           740:        bp = rs->sc_tab.b_actf;
        !           741:        rs->sc_addr = bp->b_data;
        !           742:        rs->sc_resid = bp->b_bcount;
        !           743:        if (hpibreq(rs->sc_dev.dv_parent, &rs->sc_hq))
        !           744:                hdstart(rs);
        !           745: }
        !           746:
        !           747: struct buf *
        !           748: hdfinish(rs, bp)
        !           749:        struct hd_softc *rs;
        !           750:        struct buf *bp;
        !           751: {
        !           752:        struct buf *dp = &rs->sc_tab;
        !           753:        int s;
        !           754:
        !           755:        rs->sc_errcnt = 0;
        !           756:        dp->b_actf = bp->b_actf;
        !           757:        bp->b_resid = 0;
        !           758:        s = splbio();
        !           759:        biodone(bp);
        !           760:        splx(s);
        !           761:        hpibfree(rs->sc_dev.dv_parent, &rs->sc_hq);
        !           762:        if (dp->b_actf)
        !           763:                return (dp->b_actf);
        !           764:        dp->b_active = 0;
        !           765:        if (rs->sc_flags & HDF_WANTED) {
        !           766:                rs->sc_flags &= ~HDF_WANTED;
        !           767:                wakeup((caddr_t)dp);
        !           768:        }
        !           769:        return (NULL);
        !           770: }
        !           771:
        !           772: void
        !           773: hdstart(arg)
        !           774:        void *arg;
        !           775: {
        !           776:        struct hd_softc *rs = arg;
        !           777:        struct disklabel *lp;
        !           778:        struct buf *bp = rs->sc_tab.b_actf;
        !           779:        int ctlr, slave;
        !           780:        daddr64_t bn;
        !           781:
        !           782:        ctlr = rs->sc_dev.dv_parent->dv_unit;
        !           783:        slave = rs->sc_slave;
        !           784:
        !           785: again:
        !           786: #ifdef DEBUG
        !           787:        if (hddebug & HDB_FOLLOW)
        !           788:                printf("hdstart(%s): bp %p, %c\n", rs->sc_dev.dv_xname, bp,
        !           789:                       (bp->b_flags & B_READ) ? 'R' : 'W');
        !           790: #endif
        !           791:        lp = rs->sc_dkdev.dk_label;
        !           792:        bn = bp->b_blkno +
        !           793:            DL_GETPOFFSET(&lp->d_partitions[DISKPART(bp->b_dev)]);
        !           794:
        !           795:        rs->sc_flags |= HDF_SEEK;
        !           796:        rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
        !           797:        rs->sc_ioc.c_volume = C_SVOL(0);
        !           798:        rs->sc_ioc.c_saddr = C_SADDR;
        !           799:        rs->sc_ioc.c_hiaddr = 0;
        !           800:        rs->sc_ioc.c_addr = HDBTOS(bn);
        !           801:        rs->sc_ioc.c_nop2 = C_NOP;
        !           802:        rs->sc_ioc.c_slen = C_SLEN;
        !           803:        rs->sc_ioc.c_len = rs->sc_resid;
        !           804:        rs->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE;
        !           805: #ifdef DEBUG
        !           806:        if (hddebug & HDB_IO)
        !           807:                printf("hdstart: hpibsend(%x, %x, %x, %p, %x)\n",
        !           808:                       ctlr, slave, C_CMD,
        !           809:                       &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);
        !           810: #endif
        !           811:        if (hpibsend(ctlr, slave, C_CMD, &rs->sc_ioc.c_unit,
        !           812:                     sizeof(rs->sc_ioc)-2) == sizeof(rs->sc_ioc)-2) {
        !           813:
        !           814:                /* Instrumentation. */
        !           815:                disk_busy(&rs->sc_dkdev);
        !           816:                rs->sc_dkdev.dk_seek++;
        !           817:
        !           818: #ifdef DEBUG
        !           819:                if (hddebug & HDB_IO)
        !           820:                        printf("hdstart: hpibawait(%x)\n", ctlr);
        !           821: #endif
        !           822:                hpibawait(ctlr);
        !           823:                return;
        !           824:        }
        !           825:        /*
        !           826:         * Experience has shown that the hpibwait in this hpibsend will
        !           827:         * occasionally timeout.  It appears to occur mostly on old 7914
        !           828:         * drives with full maintenance tracks.  We should probably
        !           829:         * integrate this with the backoff code in hderror.
        !           830:         */
        !           831: #ifdef DEBUG
        !           832:        if (hddebug & HDB_ERROR)
        !           833:                printf("%s: hdstart: cmd %x adr %lx blk %d len %d ecnt %ld\n",
        !           834:                       rs->sc_dev.dv_xname, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
        !           835:                       bp->b_blkno, rs->sc_resid, rs->sc_errcnt);
        !           836:        rs->sc_stats.hdretries++;
        !           837: #endif
        !           838:        rs->sc_flags &= ~HDF_SEEK;
        !           839:        hdreset(rs->sc_dev.dv_parent->dv_unit, rs->sc_slave, rs->sc_punit);
        !           840:        if (rs->sc_errcnt++ < HDRETRY)
        !           841:                goto again;
        !           842:        printf("%s: hdstart err: err: cmd 0x%x sect %ld blk %d len %d\n",
        !           843:               rs->sc_dev.dv_xname, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
        !           844:               bp->b_blkno, rs->sc_resid);
        !           845:        bp->b_flags |= B_ERROR;
        !           846:        bp->b_error = EIO;
        !           847:        bp = hdfinish(rs, bp);
        !           848:        if (bp) {
        !           849:                rs->sc_addr = bp->b_data;
        !           850:                rs->sc_resid = bp->b_bcount;
        !           851:                if (hpibreq(rs->sc_dev.dv_parent, &rs->sc_hq))
        !           852:                        goto again;
        !           853:        }
        !           854: }
        !           855:
        !           856: void
        !           857: hdgo(arg)
        !           858:        void *arg;
        !           859: {
        !           860:        struct hd_softc *rs = arg;
        !           861:        struct buf *bp = rs->sc_tab.b_actf;
        !           862:        int rw, ctlr, slave;
        !           863:
        !           864:        ctlr = rs->sc_dev.dv_parent->dv_unit;
        !           865:        slave = rs->sc_slave;
        !           866:
        !           867:        rw = bp->b_flags & B_READ;
        !           868:
        !           869:        /* Instrumentation. */
        !           870:        disk_busy(&rs->sc_dkdev);
        !           871:
        !           872: #ifdef USELEDS
        !           873:        ledcontrol(0, 0, LED_DISK);
        !           874: #endif
        !           875:        hpibgo(ctlr, slave, C_EXEC, rs->sc_addr, rs->sc_resid, rw, rw != 0);
        !           876: }
        !           877:
        !           878: /* ARGSUSED */
        !           879: void
        !           880: hdinterrupt(arg)
        !           881:        void *arg;
        !           882: {
        !           883:        struct hd_softc *rs = arg;
        !           884:        int unit = rs->sc_dev.dv_unit;
        !           885:        struct buf *bp = rs->sc_tab.b_actf;
        !           886:        u_char stat = 13;       /* in case hpibrecv fails */
        !           887:        int rv, restart, ctlr, slave;
        !           888:
        !           889:        ctlr = rs->sc_dev.dv_parent->dv_unit;
        !           890:        slave = rs->sc_slave;
        !           891:
        !           892: #ifdef DEBUG
        !           893:        if (hddebug & HDB_FOLLOW)
        !           894:                printf("hdinterrupt(%d): bp %p, %c, flags %x\n", unit, bp,
        !           895:                       (bp->b_flags & B_READ) ? 'R' : 'W', rs->sc_flags);
        !           896:        if (bp == NULL) {
        !           897:                printf("%s: bp == NULL\n", rs->sc_dev.dv_xname);
        !           898:                return;
        !           899:        }
        !           900: #endif
        !           901:        disk_unbusy(&rs->sc_dkdev, (bp->b_bcount - bp->b_resid),
        !           902:            (bp->b_flags & B_READ));
        !           903:
        !           904:        if (rs->sc_flags & HDF_SEEK) {
        !           905:                rs->sc_flags &= ~HDF_SEEK;
        !           906:                if (hpibustart(ctlr))
        !           907:                        hdgo(rs);
        !           908:                return;
        !           909:        }
        !           910:        if ((rs->sc_flags & HDF_SWAIT) == 0) {
        !           911: #ifdef DEBUG
        !           912:                rs->sc_stats.hdpolltries++;
        !           913: #endif
        !           914:                if (hpibpptest(ctlr, slave) == 0) {
        !           915: #ifdef DEBUG
        !           916:                        rs->sc_stats.hdpollwaits++;
        !           917: #endif
        !           918:
        !           919:                        /* Instrumentation. */
        !           920:                        disk_busy(&rs->sc_dkdev);
        !           921:                        rs->sc_flags |= HDF_SWAIT;
        !           922:                        hpibawait(ctlr);
        !           923:                        return;
        !           924:                }
        !           925:        } else
        !           926:                rs->sc_flags &= ~HDF_SWAIT;
        !           927:        rv = hpibrecv(ctlr, slave, C_QSTAT, &stat, 1);
        !           928:        if (rv != 1 || stat) {
        !           929: #ifdef DEBUG
        !           930:                if (hddebug & HDB_ERROR)
        !           931:                        printf("hdinterrupt: recv failed or bad stat %d\n", stat);
        !           932: #endif
        !           933:                restart = hderror(unit);
        !           934: #ifdef DEBUG
        !           935:                rs->sc_stats.hdretries++;
        !           936: #endif
        !           937:                if (rs->sc_errcnt++ < HDRETRY) {
        !           938:                        if (restart)
        !           939:                                hdstart(rs);
        !           940:                        return;
        !           941:                }
        !           942:                bp->b_flags |= B_ERROR;
        !           943:                bp->b_error = EIO;
        !           944:        }
        !           945:        if (hdfinish(rs, bp))
        !           946:                hdustart(rs);
        !           947: }
        !           948:
        !           949: int
        !           950: hdstatus(rs)
        !           951:        struct hd_softc *rs;
        !           952: {
        !           953:        int c, s;
        !           954:        u_char stat;
        !           955:        int rv;
        !           956:
        !           957:        c = rs->sc_dev.dv_parent->dv_unit;
        !           958:        s = rs->sc_slave;
        !           959:        rs->sc_rsc.c_unit = C_SUNIT(rs->sc_punit);
        !           960:        rs->sc_rsc.c_sram = C_SRAM;
        !           961:        rs->sc_rsc.c_ram = C_RAM;
        !           962:        rs->sc_rsc.c_cmd = C_STATUS;
        !           963:        bzero((caddr_t)&rs->sc_stat, sizeof(rs->sc_stat));
        !           964:        rv = hpibsend(c, s, C_CMD, &rs->sc_rsc, sizeof(rs->sc_rsc));
        !           965:        if (rv != sizeof(rs->sc_rsc)) {
        !           966: #ifdef DEBUG
        !           967:                if (hddebug & HDB_STATUS)
        !           968:                        printf("hdstatus: send C_CMD failed %d != %d\n",
        !           969:                               rv, sizeof(rs->sc_rsc));
        !           970: #endif
        !           971:                return(1);
        !           972:        }
        !           973:        rv = hpibrecv(c, s, C_EXEC, &rs->sc_stat, sizeof(rs->sc_stat));
        !           974:        if (rv != sizeof(rs->sc_stat)) {
        !           975: #ifdef DEBUG
        !           976:                if (hddebug & HDB_STATUS)
        !           977:                        printf("hdstatus: send C_EXEC failed %d != %d\n",
        !           978:                               rv, sizeof(rs->sc_stat));
        !           979: #endif
        !           980:                return(1);
        !           981:        }
        !           982:        rv = hpibrecv(c, s, C_QSTAT, &stat, 1);
        !           983:        if (rv != 1 || stat) {
        !           984: #ifdef DEBUG
        !           985:                if (hddebug & HDB_STATUS)
        !           986:                        printf("hdstatus: recv failed %d or bad stat %d\n",
        !           987:                               rv, stat);
        !           988: #endif
        !           989:                return(1);
        !           990:        }
        !           991:        return(0);
        !           992: }
        !           993:
        !           994: /*
        !           995:  * Deal with errors.
        !           996:  * Returns 1 if request should be restarted,
        !           997:  * 0 if we should just quietly give up.
        !           998:  */
        !           999: int
        !          1000: hderror(unit)
        !          1001:        int unit;
        !          1002: {
        !          1003:        struct hd_softc *rs = hd_cd.cd_devs[unit];
        !          1004:        struct hd_stat *sp;
        !          1005:        struct buf *bp;
        !          1006:        daddr64_t hwbn, pbn;
        !          1007:
        !          1008:        if (hdstatus(rs)) {
        !          1009: #ifdef DEBUG
        !          1010:                printf("%s: couldn't get status\n", rs->sc_dev.dv_xname);
        !          1011: #endif
        !          1012:                hdreset(rs->sc_dev.dv_parent->dv_unit,
        !          1013:                    rs->sc_slave, rs->sc_punit);
        !          1014:                return(1);
        !          1015:        }
        !          1016:        sp = &rs->sc_stat;
        !          1017:        if (sp->c_fef & FEF_REXMT)
        !          1018:                return(1);
        !          1019:        if (sp->c_fef & FEF_PF) {
        !          1020:                hdreset(rs->sc_dev.dv_parent->dv_unit,
        !          1021:                    rs->sc_slave, rs->sc_punit);
        !          1022:                return(1);
        !          1023:        }
        !          1024:        /*
        !          1025:         * Unit requests release for internal maintenance.
        !          1026:         * We just delay a while and try again later.  Use exponentially
        !          1027:         * increasing backoff a la ethernet drivers since we don't really
        !          1028:         * know how long the maintenance will take.  With HDWAITC and
        !          1029:         * HDRETRY as defined, the range is 1 to 32 seconds.
        !          1030:         */
        !          1031:        if (sp->c_fef & FEF_IMR) {
        !          1032:                int hdtimo = HDWAITC << rs->sc_errcnt;
        !          1033: #ifdef DEBUG
        !          1034:                printf("%s: internal maintenance, %d second timeout\n",
        !          1035:                       rs->sc_dev.dv_xname, hdtimo);
        !          1036:                rs->sc_stats.hdtimeouts++;
        !          1037: #endif
        !          1038:                hpibfree(rs->sc_dev.dv_parent, &rs->sc_hq);
        !          1039:                timeout_add(&rs->sc_timeout, hdtimo * hz);
        !          1040:                return(0);
        !          1041:        }
        !          1042:        /*
        !          1043:         * Only report error if we have reached the error reporting
        !          1044:         * threshold.  By default, this will only report after the
        !          1045:         * retry limit has been exceeded.
        !          1046:         */
        !          1047:        if (rs->sc_errcnt < hderrthresh)
        !          1048:                return(1);
        !          1049:
        !          1050:        /*
        !          1051:         * First conjure up the block number at which the error occurred.
        !          1052:         * Note that not all errors report a block number, in that case
        !          1053:         * we just use b_blkno.
        !          1054:         */
        !          1055:        bp = rs->sc_tab.b_actf;
        !          1056:        pbn = DL_GETPOFFSET(&rs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)]);
        !          1057:        if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
        !          1058:            (sp->c_ief & IEF_RRMASK)) {
        !          1059:                hwbn = HDBTOS(pbn + bp->b_blkno);
        !          1060:                pbn = bp->b_blkno;
        !          1061:        } else {
        !          1062:                hwbn = sp->c_blk;
        !          1063:                pbn = HDSTOB(hwbn) - pbn;
        !          1064:        }
        !          1065:
        !          1066:        diskerr(bp, hd_cd.cd_name, "hard error", LOG_PRINTF,
        !          1067:            pbn - bp->b_blkno, rs->sc_dkdev.dk_label);
        !          1068:        printf("\n%s%c: ", rs->sc_dev.dv_xname, 'a' + DISKPART(bp->b_dev));
        !          1069:
        !          1070: #ifdef DEBUG
        !          1071:        if (hddebug & HDB_ERROR) {
        !          1072:                /* status info */
        !          1073:                printf("volume: %d, unit: %d\n",
        !          1074:                       (sp->c_vu>>4)&0xF, sp->c_vu&0xF);
        !          1075:                hdprinterr("reject", sp->c_ref, err_reject);
        !          1076:                hdprinterr("fault", sp->c_fef, err_fault);
        !          1077:                hdprinterr("access", sp->c_aef, err_access);
        !          1078:                hdprinterr("info", sp->c_ief, err_info);
        !          1079:                printf("    block: %d, P1-P10: ", hwbn);
        !          1080:                printf("0x%04x", *(u_int *)&sp->c_raw[0]);
        !          1081:                printf("%04x", *(u_int *)&sp->c_raw[4]);
        !          1082:                printf("%02x\n", *(u_short *)&sp->c_raw[8]);
        !          1083:                /* command */
        !          1084:                printf("    ioc: ");
        !          1085:                printf("0x%x", *(u_int *)&rs->sc_ioc.c_pad);
        !          1086:                printf("0x%x", *(u_short *)&rs->sc_ioc.c_hiaddr);
        !          1087:                printf("0x%x", *(u_int *)&rs->sc_ioc.c_addr);
        !          1088:                printf("0x%x", *(u_short *)&rs->sc_ioc.c_nop2);
        !          1089:                printf("0x%x", *(u_int *)&rs->sc_ioc.c_len);
        !          1090:                printf("0x%x\n", *(u_short *)&rs->sc_ioc.c_cmd);
        !          1091:        } else
        !          1092: #endif
        !          1093:        {
        !          1094:                printf("v%d u%d, R0x%x F0x%x A0x%x I0x%x",
        !          1095:                    (sp->c_vu>>4)&0xF, sp->c_vu&0xF,
        !          1096:                    sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief);
        !          1097:                printf(" P1-P10: 0x%04x%04x%02x\n",
        !          1098:                    *(u_int *)&sp->c_raw[0], *(u_int *)&sp->c_raw[4],
        !          1099:                    *(u_short *)&sp->c_raw[8]);
        !          1100:        }
        !          1101:        return (1);
        !          1102: }
        !          1103:
        !          1104: int
        !          1105: hdread(dev, uio, flags)
        !          1106:        dev_t dev;
        !          1107:        struct uio *uio;
        !          1108:        int flags;
        !          1109: {
        !          1110:
        !          1111:        return (physio(hdstrategy, NULL, dev, B_READ, minphys, uio));
        !          1112: }
        !          1113:
        !          1114: int
        !          1115: hdwrite(dev, uio, flags)
        !          1116:        dev_t dev;
        !          1117:        struct uio *uio;
        !          1118:        int flags;
        !          1119: {
        !          1120:
        !          1121:        return (physio(hdstrategy, NULL, dev, B_WRITE, minphys, uio));
        !          1122: }
        !          1123:
        !          1124: int
        !          1125: hdioctl(dev, cmd, data, flag, p)
        !          1126:        dev_t dev;
        !          1127:        u_long cmd;
        !          1128:        caddr_t data;
        !          1129:        int flag;
        !          1130:        struct proc *p;
        !          1131: {
        !          1132:        int unit = DISKUNIT(dev);
        !          1133:        struct hd_softc *sc;
        !          1134:        int error = 0;
        !          1135:
        !          1136:        sc = hdlookup(unit);
        !          1137:        if (sc == NULL)
        !          1138:                return (ENXIO);
        !          1139:
        !          1140:        switch (cmd) {
        !          1141:        case DIOCGPDINFO:
        !          1142:                hdgetdisklabel(dev, sc, (struct disklabel *)data, 1);
        !          1143:                goto exit;
        !          1144:
        !          1145:        case DIOCGDINFO:
        !          1146:                *(struct disklabel *)data = *sc->sc_dkdev.dk_label;
        !          1147:                goto exit;
        !          1148:
        !          1149:        case DIOCGPART:
        !          1150:                ((struct partinfo *)data)->disklab = sc->sc_dkdev.dk_label;
        !          1151:                ((struct partinfo *)data)->part =
        !          1152:                        &sc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
        !          1153:                goto exit;
        !          1154:
        !          1155:        case DIOCWLABEL:
        !          1156:                if ((flag & FWRITE) == 0) {
        !          1157:                        error = EBADF;
        !          1158:                        goto exit;
        !          1159:                }
        !          1160:                if (*(int *)data)
        !          1161:                        sc->sc_flags |= HDF_WLABEL;
        !          1162:                else
        !          1163:                        sc->sc_flags &= ~HDF_WLABEL;
        !          1164:                goto exit;
        !          1165:
        !          1166:        case DIOCWDINFO:
        !          1167:        case DIOCSDINFO:
        !          1168:                if ((flag & FWRITE) == 0) {
        !          1169:                        error = EBADF;
        !          1170:                        goto exit;
        !          1171:                }
        !          1172:
        !          1173:                if ((error = hdlock(sc)) != 0)
        !          1174:                        goto exit;
        !          1175:                sc->sc_flags |= HDF_WLABEL;
        !          1176:
        !          1177:                error = setdisklabel(sc->sc_dkdev.dk_label,
        !          1178:                    (struct disklabel *)data, /* sc->sc_dkdev.dk_openmask */ 0);
        !          1179:                if (error == 0) {
        !          1180:                        if (cmd == DIOCWDINFO)
        !          1181:                                error = writedisklabel(DISKLABELDEV(dev),
        !          1182:                                    hdstrategy, sc->sc_dkdev.dk_label);
        !          1183:                }
        !          1184:
        !          1185:                sc->sc_flags &= ~HDF_WLABEL;
        !          1186:                hdunlock(sc);
        !          1187:                goto exit;
        !          1188:
        !          1189:        default:
        !          1190:                error = EINVAL;
        !          1191:                break;
        !          1192:        }
        !          1193:
        !          1194: exit:
        !          1195:        device_unref(&sc->sc_dev);
        !          1196:        return (error);
        !          1197: }
        !          1198:
        !          1199: daddr64_t
        !          1200: hdsize(dev)
        !          1201:        dev_t dev;
        !          1202: {
        !          1203:        struct hd_softc *rs;
        !          1204:        int unit = DISKUNIT(dev);
        !          1205:        int part, omask;
        !          1206:        int size;
        !          1207:
        !          1208:        rs = hdlookup(unit);
        !          1209:        if (rs == NULL)
        !          1210:                return (-1);
        !          1211:
        !          1212:        part = DISKPART(dev);
        !          1213:        omask = rs->sc_dkdev.dk_openmask & (1 << part);
        !          1214:
        !          1215:        /*
        !          1216:         * We get called very early on (via swapconf)
        !          1217:         * without the device being open so we may need
        !          1218:         * to handle it here.
        !          1219:         */
        !          1220:        if (omask == 0 && hdopen(dev, FREAD | FWRITE, S_IFBLK, NULL) != 0) {
        !          1221:                size = -1;
        !          1222:                goto out;
        !          1223:        }
        !          1224:
        !          1225:        if (rs->sc_dkdev.dk_label->d_partitions[part].p_fstype != FS_SWAP)
        !          1226:                size = -1;
        !          1227:        else
        !          1228:                size = DL_GETPSIZE(&rs->sc_dkdev.dk_label->d_partitions[part]) *
        !          1229:                    (rs->sc_dkdev.dk_label->d_secsize / DEV_BSIZE);
        !          1230:
        !          1231:        if (hdclose(dev, FREAD | FWRITE, S_IFBLK, NULL) != 0)
        !          1232:                size = -1;
        !          1233:
        !          1234: out:
        !          1235:        device_unref(&rs->sc_dev);
        !          1236:        return (size);
        !          1237: }
        !          1238:
        !          1239: #ifdef DEBUG
        !          1240: void
        !          1241: hdprinterr(str, err, tab)
        !          1242:        const char *str;
        !          1243:        short err;
        !          1244:        const char **tab;
        !          1245: {
        !          1246:        int i;
        !          1247:        int printed;
        !          1248:
        !          1249:        if (err == 0)
        !          1250:                return;
        !          1251:        printf("    %s error %d field:", str, err);
        !          1252:        printed = 0;
        !          1253:        for (i = 0; i < 16; i++)
        !          1254:                if (err & (0x8000 >> i))
        !          1255:                        printf("%s%s", printed++ ? " + " : " ", tab[i]);
        !          1256:        printf("\n");
        !          1257: }
        !          1258: #endif
        !          1259:
        !          1260: static int hddoingadump;       /* simple mutex */
        !          1261:
        !          1262: /*
        !          1263:  * Non-interrupt driven, non-dma dump routine.
        !          1264:  */
        !          1265: int
        !          1266: hddump(dev, blkno, va, size)
        !          1267:        dev_t dev;
        !          1268:        daddr64_t blkno;
        !          1269:        caddr_t va;
        !          1270:        size_t size;
        !          1271: {
        !          1272:        int sectorsize;         /* size of a disk sector */
        !          1273:        daddr64_t nsects;       /* number of sectors in partition */
        !          1274:        daddr64_t sectoff;      /* sector offset of partition */
        !          1275:        int totwrt;             /* total number of sectors left to write */
        !          1276:        int nwrt;               /* current number of sectors to write */
        !          1277:        int unit, part;
        !          1278:        int ctlr, slave;
        !          1279:        struct hd_softc *rs;
        !          1280:        struct disklabel *lp;
        !          1281:        char stat;
        !          1282:
        !          1283:        /* Check for recursive dump; if so, punt. */
        !          1284:        if (hddoingadump)
        !          1285:                return (EFAULT);
        !          1286:        hddoingadump = 1;
        !          1287:
        !          1288:        /* Decompose unit and partition. */
        !          1289:        unit = DISKUNIT(dev);
        !          1290:        part = DISKPART(dev);
        !          1291:
        !          1292:        /* Make sure dump device is ok. */
        !          1293:        rs = hdlookup(unit);
        !          1294:        if (rs == NULL)
        !          1295:                return (ENXIO);
        !          1296:        device_unref(&rs->sc_dev);
        !          1297:
        !          1298:        ctlr = rs->sc_dev.dv_parent->dv_unit;
        !          1299:        slave = rs->sc_slave;
        !          1300:
        !          1301:        /*
        !          1302:         * Convert to disk sectors.  Request must be a multiple of size.
        !          1303:         */
        !          1304:        lp = rs->sc_dkdev.dk_label;
        !          1305:        sectorsize = lp->d_secsize;
        !          1306:        if ((size % sectorsize) != 0)
        !          1307:                return (EFAULT);
        !          1308:        totwrt = size / sectorsize;
        !          1309:        blkno = dbtob(blkno) / sectorsize;      /* blkno in DEV_BSIZE units */
        !          1310:
        !          1311:        nsects = DL_GETPSIZE(&lp->d_partitions[part]);
        !          1312:        sectoff = DL_GETPOFFSET(&lp->d_partitions[part]);
        !          1313:
        !          1314:        /* Check transfer bounds against partition size. */
        !          1315:        if ((blkno < 0) || (blkno + totwrt) > nsects)
        !          1316:                return (EINVAL);
        !          1317:
        !          1318:        /* Offset block number to start of partition. */
        !          1319:        blkno += sectoff;
        !          1320:
        !          1321:        while (totwrt > 0) {
        !          1322:                nwrt = totwrt;          /* XXX */
        !          1323: #ifndef HD_DUMP_NOT_TRUSTED
        !          1324:                /*
        !          1325:                 * Fill out and send HPIB command.
        !          1326:                 */
        !          1327:                rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);
        !          1328:                rs->sc_ioc.c_volume = C_SVOL(0);
        !          1329:                rs->sc_ioc.c_saddr = C_SADDR;
        !          1330:                rs->sc_ioc.c_hiaddr = 0;
        !          1331:                rs->sc_ioc.c_addr = HDBTOS(blkno);
        !          1332:                rs->sc_ioc.c_nop2 = C_NOP;
        !          1333:                rs->sc_ioc.c_slen = C_SLEN;
        !          1334:                rs->sc_ioc.c_len = nwrt * sectorsize;
        !          1335:                rs->sc_ioc.c_cmd = C_WRITE;
        !          1336:                hpibsend(ctlr, slave, C_CMD, &rs->sc_ioc.c_unit,
        !          1337:                    sizeof(rs->sc_ioc)-2);
        !          1338:                if (hpibswait(ctlr, slave))
        !          1339:                        return (EIO);
        !          1340:
        !          1341:                /*
        !          1342:                 * Send the data.
        !          1343:                 */
        !          1344:                hpibsend(ctlr, slave, C_EXEC, va, nwrt * sectorsize);
        !          1345:                (void) hpibswait(ctlr, slave);
        !          1346:                hpibrecv(ctlr, slave, C_QSTAT, &stat, 1);
        !          1347:                if (stat)
        !          1348:                        return (EIO);
        !          1349: #else /* HD_DUMP_NOT_TRUSTED */
        !          1350:                /* Let's just talk about this first... */
        !          1351:                printf("%s: dump addr %p, blk %d\n", sc->sc_dev.dv_xname,
        !          1352:                    va, blkno);
        !          1353:                delay(500 * 1000);      /* half a second */
        !          1354: #endif /* HD_DUMP_NOT_TRUSTED */
        !          1355:
        !          1356:                /* update block count */
        !          1357:                totwrt -= nwrt;
        !          1358:                blkno += nwrt;
        !          1359:                va += sectorsize * nwrt;
        !          1360:        }
        !          1361:        hddoingadump = 0;
        !          1362:        return (0);
        !          1363: }

CVSweb