[BACK]Return to wd.c CVS log [TXT][DIR] Up to [local] / sys / dev / ata

Annotation of sys/dev/ata/wd.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: wd.c,v 1.66 2007/06/20 18:15:46 deraadt Exp $ */
                      2: /*     $NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *     notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *     notice, this list of conditions and the following disclaimer in the
                     14:  *     documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *     must display the following acknowledgement:
                     17:  *  This product includes software developed by Manuel Bouyer.
                     18:  * 4. The name of the author may not be used to endorse or promote products
                     19:  *     derived from this software without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: /*-
                     34:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
                     35:  * All rights reserved.
                     36:  *
                     37:  * This code is derived from software contributed to The NetBSD Foundation
                     38:  * by Charles M. Hannum and by Onno van der Linden.
                     39:  *
                     40:  * Redistribution and use in source and binary forms, with or without
                     41:  * modification, are permitted provided that the following conditions
                     42:  * are met:
                     43:  * 1. Redistributions of source code must retain the above copyright
                     44:  *    notice, this list of conditions and the following disclaimer.
                     45:  * 2. Redistributions in binary form must reproduce the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer in the
                     47:  *    documentation and/or other materials provided with the distribution.
                     48:  * 3. All advertising materials mentioning features or use of this software
                     49:  *    must display the following acknowledgement:
                     50:  *        This product includes software developed by the NetBSD
                     51:  *        Foundation, Inc. and its contributors.
                     52:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     53:  *    contributors may be used to endorse or promote products derived
                     54:  *    from this software without specific prior written permission.
                     55:  *
                     56:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     57:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     58:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     59:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     60:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     61:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     62:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     63:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     64:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     65:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     66:  * POSSIBILITY OF SUCH DAMAGE.
                     67:  */
                     68:
                     69: #if 0
                     70: #include "rnd.h"
                     71: #endif
                     72:
                     73: #include <sys/param.h>
                     74: #include <sys/systm.h>
                     75: #include <sys/kernel.h>
                     76: #include <sys/conf.h>
                     77: #include <sys/file.h>
                     78: #include <sys/stat.h>
                     79: #include <sys/ioctl.h>
                     80: #include <sys/buf.h>
                     81: #include <sys/uio.h>
                     82: #include <sys/malloc.h>
                     83: #include <sys/device.h>
                     84: #include <sys/disklabel.h>
                     85: #include <sys/disk.h>
                     86: #include <sys/syslog.h>
                     87: #include <sys/proc.h>
                     88: #include <sys/vnode.h>
                     89:
                     90: #include <uvm/uvm_extern.h>
                     91:
                     92: #include <machine/intr.h>
                     93: #include <machine/bus.h>
                     94:
                     95: #include <dev/ata/atareg.h>
                     96: #include <dev/ata/atavar.h>
                     97: #include <dev/ata/wdvar.h>
                     98: #include <dev/ic/wdcreg.h>
                     99: #include <dev/ic/wdcvar.h>
                    100: #if 0
                    101: #include "locators.h"
                    102: #endif
                    103:
                    104: #define        LBA48_THRESHOLD         (0xfffffff)     /* 128GB / DEV_BSIZE */
                    105:
                    106: #define        WDIORETRIES_SINGLE 4    /* number of retries before single-sector */
                    107: #define        WDIORETRIES     5       /* number of retries before giving up */
                    108: #define        RECOVERYTIME hz/2       /* time to wait before retrying a cmd */
                    109:
                    110: #define DEBUG_INTR   0x01
                    111: #define DEBUG_XFERS  0x02
                    112: #define DEBUG_STATUS 0x04
                    113: #define DEBUG_FUNCS  0x08
                    114: #define DEBUG_PROBE  0x10
                    115: #ifdef WDCDEBUG
                    116: extern int wdcdebug_wd_mask; /* init'ed in ata_wdc.c */
                    117: #define WDCDEBUG_PRINT(args, level) do {       \
                    118:        if ((wdcdebug_wd_mask & (level)) != 0)  \
                    119:                printf args;                    \
                    120: } while (0)
                    121: #else
                    122: #define WDCDEBUG_PRINT(args, level)
                    123: #endif
                    124:
                    125: struct wd_softc {
                    126:        /* General disk infos */
                    127:        struct device sc_dev;
                    128:        struct disk sc_dk;
                    129:        struct buf sc_q;
                    130:        /* IDE disk soft states */
                    131:        struct ata_bio sc_wdc_bio; /* current transfer */
                    132:        struct buf *sc_bp; /* buf being transferred */
                    133:        struct ata_drive_datas *drvp; /* Our controller's infos */
                    134:        int openings;
                    135:        struct ataparams sc_params;/* drive characteristics found */
                    136:        int sc_flags;
                    137: #define WDF_LOCKED       0x01
                    138: #define WDF_WANTED       0x02
                    139: #define WDF_WLABEL       0x04 /* label is writable */
                    140: #define WDF_LABELLING    0x08 /* writing label */
                    141: /*
                    142:  * XXX Nothing resets this yet, but disk change sensing will when ATA-4 is
                    143:  * more fully implemented.
                    144:  */
                    145: #define WDF_LOADED     0x10 /* parameters loaded */
                    146: #define WDF_WAIT       0x20 /* waiting for resources */
                    147: #define WDF_LBA                0x40 /* using LBA mode */
                    148: #define WDF_LBA48      0x80 /* using 48-bit LBA mode */
                    149:
                    150:        u_int64_t sc_capacity;
                    151:        int cyl; /* actual drive parameters */
                    152:        int heads;
                    153:        int sectors;
                    154:        int retries; /* number of xfer retry */
                    155:        struct timeout sc_restart_timeout;
                    156:        void *sc_sdhook;
                    157: };
                    158:
                    159: #define sc_drive sc_wdc_bio.drive
                    160: #define sc_mode sc_wdc_bio.mode
                    161: #define sc_multi sc_wdc_bio.multi
                    162:
                    163: int    wdprobe(struct device *, void *, void *);
                    164: void   wdattach(struct device *, struct device *, void *);
                    165: int    wddetach(struct device *, int);
                    166: int    wdactivate(struct device *, enum devact);
                    167: int    wdprint(void *, char *);
                    168:
                    169: struct cfattach wd_ca = {
                    170:        sizeof(struct wd_softc), wdprobe, wdattach,
                    171:        wddetach, wdactivate
                    172: };
                    173:
                    174: struct cfdriver wd_cd = {
                    175:        NULL, "wd", DV_DISK
                    176: };
                    177:
                    178: void  wdgetdefaultlabel(struct wd_softc *, struct disklabel *);
                    179: void  wdgetdisklabel(dev_t dev, struct wd_softc *, struct disklabel *, int);
                    180: void  wdstrategy(struct buf *);
                    181: void  wdstart(void *);
                    182: void  __wdstart(struct wd_softc*, struct buf *);
                    183: void  wdrestart(void *);
                    184: int   wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *);
                    185: void  wd_flushcache(struct wd_softc *, int);
                    186: void  wd_shutdown(void *);
                    187:
                    188: struct dkdriver wddkdriver = { wdstrategy };
                    189:
                    190: /* XXX: these should go elsewhere */
                    191: cdev_decl(wd);
                    192: bdev_decl(wd);
                    193:
                    194: #define wdlock(wd)  disk_lock(&(wd)->sc_dk)
                    195: #define wdunlock(wd)  disk_unlock(&(wd)->sc_dk)
                    196: #define wdlookup(unit) (struct wd_softc *)device_lookup(&wd_cd, (unit))
                    197:
                    198:
                    199: int
                    200: wdprobe(struct device *parent, void *match_, void *aux)
                    201: {
                    202:        struct ata_atapi_attach *aa_link = aux;
                    203:        struct cfdata *match = match_;
                    204:
                    205:        if (aa_link == NULL)
                    206:                return 0;
                    207:        if (aa_link->aa_type != T_ATA)
                    208:                return 0;
                    209:
                    210:        if (match->cf_loc[0] != -1 &&
                    211:            match->cf_loc[0] != aa_link->aa_channel)
                    212:                return 0;
                    213:
                    214:        if (match->cf_loc[1] != -1 &&
                    215:            match->cf_loc[1] != aa_link->aa_drv_data->drive)
                    216:                return 0;
                    217:
                    218:        return 1;
                    219: }
                    220:
                    221: void
                    222: wdattach(struct device *parent, struct device *self, void *aux)
                    223: {
                    224:        struct wd_softc *wd = (void *)self;
                    225:        struct ata_atapi_attach *aa_link= aux;
                    226:        struct wdc_command wdc_c;
                    227:        int i, blank;
                    228:        char buf[41], c, *p, *q;
                    229:        WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
                    230:
                    231:        wd->openings = aa_link->aa_openings;
                    232:        wd->drvp = aa_link->aa_drv_data;
                    233:
                    234:        strlcpy(wd->drvp->drive_name, wd->sc_dev.dv_xname,
                    235:            sizeof(wd->drvp->drive_name));
                    236:        wd->drvp->cf_flags = wd->sc_dev.dv_cfdata->cf_flags;
                    237:
                    238:        if ((NERRS_MAX - 2) > 0)
                    239:                wd->drvp->n_dmaerrs = NERRS_MAX - 2;
                    240:        else
                    241:                wd->drvp->n_dmaerrs = 0;
                    242:
                    243:        /* read our drive info */
                    244:        if (wd_get_params(wd, at_poll, &wd->sc_params) != 0) {
                    245:                printf("%s: IDENTIFY failed\n", wd->sc_dev.dv_xname);
                    246:                return;
                    247:        }
                    248:
                    249:        for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0;
                    250:            i < sizeof(wd->sc_params.atap_model); i++) {
                    251:                c = *p++;
                    252:                if (c == '\0')
                    253:                        break;
                    254:                if (c != ' ') {
                    255:                        if (blank) {
                    256:                                *q++ = ' ';
                    257:                                blank = 0;
                    258:                        }
                    259:                        *q++ = c;
                    260:                } else
                    261:                        blank = 1;
                    262:                }
                    263:        *q++ = '\0';
                    264:
                    265:        printf(": <%s>\n", buf);
                    266:
                    267:        wdc_probe_caps(wd->drvp, &wd->sc_params);
                    268:        wdc_print_caps(wd->drvp);
                    269:
                    270:        if ((wd->sc_params.atap_multi & 0xff) > 1) {
                    271:                wd->sc_multi = wd->sc_params.atap_multi & 0xff;
                    272:        } else {
                    273:                wd->sc_multi = 1;
                    274:        }
                    275:
                    276:        printf("%s: %d-sector PIO,", wd->sc_dev.dv_xname, wd->sc_multi);
                    277:
                    278:        /* use 48-bit LBA if enabled */
                    279:        /* XXX: shall we use it if drive capacity < 137Gb? */
                    280:        if ((wd->sc_params.atap_cmd2_en & ATAPI_CMD2_48AD) != 0)
                    281:                wd->sc_flags |= WDF_LBA48;
                    282:
                    283:        /* Prior to ATA-4, LBA was optional. */
                    284:        if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0)
                    285:                wd->sc_flags |= WDF_LBA;
                    286: #if 0
                    287:        /* ATA-4 requires LBA. */
                    288:        if (wd->sc_params.atap_ataversion != 0xffff &&
                    289:            wd->sc_params.atap_ataversion >= WDC_VER_ATA4)
                    290:                wd->sc_flags |= WDF_LBA;
                    291: #endif
                    292:
                    293:        if ((wd->sc_flags & WDF_LBA48) != 0) {
                    294:                wd->sc_capacity =
                    295:                    (((u_int64_t)wd->sc_params.atap_max_lba[3] << 48) |
                    296:                     ((u_int64_t)wd->sc_params.atap_max_lba[2] << 32) |
                    297:                     ((u_int64_t)wd->sc_params.atap_max_lba[1] << 16) |
                    298:                      (u_int64_t)wd->sc_params.atap_max_lba[0]);
                    299:                printf(" LBA48, %lluMB, %llu sectors\n",
                    300:                    wd->sc_capacity / (1048576 / DEV_BSIZE),
                    301:                    wd->sc_capacity);
                    302:        } else if ((wd->sc_flags & WDF_LBA) != 0) {
                    303:                wd->sc_capacity =
                    304:                    (wd->sc_params.atap_capacity[1] << 16) |
                    305:                    wd->sc_params.atap_capacity[0];
                    306:                printf(" LBA, %lluMB, %llu sectors\n",
                    307:                    wd->sc_capacity / (1048576 / DEV_BSIZE),
                    308:                    wd->sc_capacity);
                    309:        } else {
                    310:                wd->sc_capacity =
                    311:                    wd->sc_params.atap_cylinders *
                    312:                    wd->sc_params.atap_heads *
                    313:                    wd->sc_params.atap_sectors;
                    314:                printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n",
                    315:                    wd->sc_capacity / (1048576 / DEV_BSIZE),
                    316:                    wd->sc_params.atap_cylinders,
                    317:                    wd->sc_params.atap_heads,
                    318:                    wd->sc_params.atap_sectors,
                    319:                    wd->sc_capacity);
                    320:        }
                    321:        WDCDEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n",
                    322:            self->dv_xname, wd->sc_params.atap_dmatiming_mimi,
                    323:            wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE);
                    324:
                    325:        /*
                    326:         * FREEZE LOCK the drive so malicous users can't lock it on us.
                    327:         * As there is no harm in issuing this to drives that don't
                    328:         * support the security feature set we just send it, and don't
                    329:         * bother checking if the drive sends a command abort to tell us it
                    330:         * doesn't support it.
                    331:         */
                    332:        bzero(&wdc_c, sizeof(struct wdc_command));
                    333:
                    334:        wdc_c.r_command = WDCC_SEC_FREEZE_LOCK;
                    335:        wdc_c.timeout = 1000;
                    336:        wdc_c.flags = at_poll;
                    337:        if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) {
                    338:                printf("%s: freeze lock command didn't complete\n",
                    339:                    wd->sc_dev.dv_xname);
                    340:        }
                    341:
                    342:        /*
                    343:         * Initialize and attach the disk structure.
                    344:         */
                    345:        wd->sc_dk.dk_driver = &wddkdriver;
                    346:        wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
                    347:        disk_attach(&wd->sc_dk);
                    348:        wd->sc_wdc_bio.lp = wd->sc_dk.dk_label;
                    349:        wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd);
                    350:        if (wd->sc_sdhook == NULL)
                    351:                printf("%s: WARNING: unable to establish shutdown hook\n",
                    352:                    wd->sc_dev.dv_xname);
                    353:        timeout_set(&wd->sc_restart_timeout, wdrestart, wd);
                    354: }
                    355:
                    356: int
                    357: wdactivate(struct device *self, enum devact act)
                    358: {
                    359:        int rv = 0;
                    360:
                    361:        switch (act) {
                    362:        case DVACT_ACTIVATE:
                    363:                break;
                    364:
                    365:        case DVACT_DEACTIVATE:
                    366:                /*
                    367:                * Nothing to do; we key off the device's DVF_ACTIVATE.
                    368:                */
                    369:                break;
                    370:        }
                    371:        return (rv);
                    372: }
                    373:
                    374: int
                    375: wddetach(struct device *self, int flags)
                    376: {
                    377:        struct wd_softc *sc = (struct wd_softc *)self;
                    378:        struct buf *dp, *bp;
                    379:        int s, bmaj, cmaj, mn;
                    380:
                    381:        /* Remove unprocessed buffers from queue */
                    382:        s = splbio();
                    383:        for (dp = &sc->sc_q; (bp = dp->b_actf) != NULL; ) {
                    384:                dp->b_actf = bp->b_actf;
                    385:                bp->b_error = ENXIO;
                    386:                bp->b_flags |= B_ERROR;
                    387:                biodone(bp);
                    388:        }
                    389:        splx(s);
                    390:
                    391:        /* Locate the lowest minor number to be detached. */
                    392:        mn = DISKMINOR(self->dv_unit, 0);
                    393:
                    394:        for (bmaj = 0; bmaj < nblkdev; bmaj++)
                    395:                if (bdevsw[bmaj].d_open == wdopen)
                    396:                        vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK);
                    397:        for (cmaj = 0; cmaj < nchrdev; cmaj++)
                    398:                if (cdevsw[cmaj].d_open == wdopen)
                    399:                        vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR);
                    400:
                    401:        /* Get rid of the shutdown hook. */
                    402:        if (sc->sc_sdhook != NULL)
                    403:                shutdownhook_disestablish(sc->sc_sdhook);
                    404:
                    405:        /* Detach disk. */
                    406:        disk_detach(&sc->sc_dk);
                    407:
                    408:        return (0);
                    409: }
                    410:
                    411: /*
                    412:  * Read/write routine for a buffer.  Validates the arguments and schedules the
                    413:  * transfer.  Does not wait for the transfer to complete.
                    414:  */
                    415: void
                    416: wdstrategy(struct buf *bp)
                    417: {
                    418:        struct wd_softc *wd;
                    419:        int s;
                    420:
                    421:        wd = wdlookup(DISKUNIT(bp->b_dev));
                    422:        if (wd == NULL) {
                    423:                bp->b_error = ENXIO;
                    424:                goto bad;
                    425:        }
                    426:
                    427:        WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname),
                    428:            DEBUG_XFERS);
                    429:
                    430:        /* Valid request?  */
                    431:        if (bp->b_blkno < 0 ||
                    432:            (bp->b_bcount % wd->sc_dk.dk_label->d_secsize) != 0 ||
                    433:            (bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
                    434:                bp->b_error = EINVAL;
                    435:                goto bad;
                    436:        }
                    437:
                    438:        /* If device invalidated (e.g. media change, door open), error. */
                    439:        if ((wd->sc_flags & WDF_LOADED) == 0) {
                    440:                bp->b_error = EIO;
                    441:                goto bad;
                    442:        }
                    443:
                    444:        /* If it's a null transfer, return immediately. */
                    445:        if (bp->b_bcount == 0)
                    446:                goto done;
                    447:
                    448:        /*
                    449:         * Do bounds checking, adjust transfer. if error, process.
                    450:         * If end of partition, just return.
                    451:         */
                    452:        if (DISKPART(bp->b_dev) != RAW_PART &&
                    453:            bounds_check_with_label(bp, wd->sc_dk.dk_label,
                    454:            (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
                    455:                goto done;
                    456:        /* Queue transfer on drive, activate drive and controller if idle. */
                    457:        s = splbio();
                    458:        disksort(&wd->sc_q, bp);
                    459:        wdstart(wd);
                    460:        splx(s);
                    461:        device_unref(&wd->sc_dev);
                    462:        return;
                    463: bad:
                    464:        bp->b_flags |= B_ERROR;
                    465: done:
                    466:        /* Toss transfer; we're done early. */
                    467:        bp->b_resid = bp->b_bcount;
                    468:        s = splbio();
                    469:        biodone(bp);
                    470:        splx(s);
                    471:        if (wd != NULL)
                    472:                device_unref(&wd->sc_dev);
                    473: }
                    474:
                    475: /*
                    476:  * Queue a drive for I/O.
                    477:  */
                    478: void
                    479: wdstart(void *arg)
                    480: {
                    481:        struct wd_softc *wd = arg;
                    482:        struct buf *dp, *bp = NULL;
                    483:
                    484:        WDCDEBUG_PRINT(("wdstart %s\n", wd->sc_dev.dv_xname),
                    485:            DEBUG_XFERS);
                    486:        while (wd->openings > 0) {
                    487:
                    488:                /* Is there a buf for us ? */
                    489:                dp = &wd->sc_q;
                    490:                if ((bp = dp->b_actf) == NULL)  /* yes, an assign */
                    491:                        return;
                    492:                dp->b_actf = bp->b_actf;
                    493:
                    494:                /*
                    495:                 * Make the command. First lock the device
                    496:                 */
                    497:                wd->openings--;
                    498:
                    499:                wd->retries = 0;
                    500:                __wdstart(wd, bp);
                    501:        }
                    502: }
                    503:
                    504: void
                    505: __wdstart(struct wd_softc *wd, struct buf *bp)
                    506: {
                    507:        daddr64_t nblks;
                    508:
                    509:        wd->sc_wdc_bio.blkno = bp->b_blkno +
                    510:            DL_GETPOFFSET(&wd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]);
                    511:        wd->sc_wdc_bio.blkno /= (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
                    512:        wd->sc_wdc_bio.blkdone =0;
                    513:        wd->sc_bp = bp;
                    514:        /*
                    515:         * If we're retrying, retry in single-sector mode. This will give us
                    516:         * the sector number of the problem, and will eventually allow the
                    517:         * transfer to succeed.
                    518:         */
                    519:        if (wd->sc_multi == 1 || wd->retries >= WDIORETRIES_SINGLE)
                    520:                wd->sc_wdc_bio.flags = ATA_SINGLE;
                    521:        else
                    522:                wd->sc_wdc_bio.flags = 0;
                    523:        nblks = bp->b_bcount / wd->sc_dk.dk_label->d_secsize;
                    524:        if ((wd->sc_flags & WDF_LBA48) &&
                    525:            /* use LBA48 only if really need */
                    526:            ((wd->sc_wdc_bio.blkno + nblks - 1 > LBA48_THRESHOLD) ||
                    527:             (nblks > 0xff)))
                    528:                wd->sc_wdc_bio.flags |= ATA_LBA48;
                    529:        if (wd->sc_flags & WDF_LBA)
                    530:                wd->sc_wdc_bio.flags |= ATA_LBA;
                    531:        if (bp->b_flags & B_READ)
                    532:                wd->sc_wdc_bio.flags |= ATA_READ;
                    533:        wd->sc_wdc_bio.bcount = bp->b_bcount;
                    534:        wd->sc_wdc_bio.databuf = bp->b_data;
                    535:        wd->sc_wdc_bio.wd = wd;
                    536:        /* Instrumentation. */
                    537:        disk_busy(&wd->sc_dk);
                    538:        switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
                    539:        case WDC_TRY_AGAIN:
                    540:                timeout_add(&wd->sc_restart_timeout, hz);
                    541:                break;
                    542:        case WDC_QUEUED:
                    543:                break;
                    544:        case WDC_COMPLETE:
                    545:                /*
                    546:                 * This code is never executed because we never set
                    547:                 * the ATA_POLL flag above
                    548:                 */
                    549: #if 0
                    550:                if (wd->sc_wdc_bio.flags & ATA_POLL)
                    551:                        wddone(wd);
                    552: #endif
                    553:                break;
                    554:        default:
                    555:                panic("__wdstart: bad return code from wdc_ata_bio()");
                    556:        }
                    557: }
                    558:
                    559: void
                    560: wddone(void *v)
                    561: {
                    562:        struct wd_softc *wd = v;
                    563:        struct buf *bp = wd->sc_bp;
                    564:        char buf[256], *errbuf = buf;
                    565:        WDCDEBUG_PRINT(("wddone %s\n", wd->sc_dev.dv_xname),
                    566:            DEBUG_XFERS);
                    567:
                    568:        bp->b_resid = wd->sc_wdc_bio.bcount;
                    569:        errbuf[0] = '\0';
                    570:        switch (wd->sc_wdc_bio.error) {
                    571:        case ERR_NODEV:
                    572:                bp->b_flags |= B_ERROR;
                    573:                bp->b_error = ENXIO;
                    574:                break;
                    575:        case ERR_DMA:
                    576:                errbuf = "DMA error";
                    577:                goto retry;
                    578:        case ERR_DF:
                    579:                errbuf = "device fault";
                    580:                goto retry;
                    581:        case TIMEOUT:
                    582:                errbuf = "device timeout";
                    583:                goto retry;
                    584:        case ERROR:
                    585:                /* Don't care about media change bits */
                    586:                if (wd->sc_wdc_bio.r_error != 0 &&
                    587:                    (wd->sc_wdc_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0)
                    588:                        goto noerror;
                    589:                ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf,
                    590:                    sizeof buf);
                    591: retry:
                    592:                /* Just reset and retry. Can we do more ? */
                    593:                wdc_reset_channel(wd->drvp);
                    594:                diskerr(bp, "wd", errbuf, LOG_PRINTF,
                    595:                    wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label);
                    596:                if (wd->retries++ < WDIORETRIES) {
                    597:                        printf(", retrying\n");
                    598:                        timeout_add(&wd->sc_restart_timeout, RECOVERYTIME);
                    599:                        return;
                    600:                }
                    601:                printf("\n");
                    602:                bp->b_flags |= B_ERROR;
                    603:                bp->b_error = EIO;
                    604:                break;
                    605:        case NOERROR:
                    606: noerror:       if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0)
                    607:                        printf("%s: soft error (corrected)\n",
                    608:                            wd->sc_dev.dv_xname);
                    609:        }
                    610:        disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid),
                    611:            (bp->b_flags & B_READ));
                    612:        biodone(bp);
                    613:        wd->openings++;
                    614:        wdstart(wd);
                    615: }
                    616:
                    617: void
                    618: wdrestart(void *v)
                    619: {
                    620:        struct wd_softc *wd = v;
                    621:        struct buf *bp = wd->sc_bp;
                    622:        int s;
                    623:        WDCDEBUG_PRINT(("wdrestart %s\n", wd->sc_dev.dv_xname),
                    624:            DEBUG_XFERS);
                    625:
                    626:        s = splbio();
                    627:        disk_unbusy(&wd->sc_dk, 0, (bp->b_flags & B_READ));
                    628:        __wdstart(v, bp);
                    629:        splx(s);
                    630: }
                    631:
                    632: int
                    633: wdread(dev_t dev, struct uio *uio, int flags)
                    634: {
                    635:
                    636:        WDCDEBUG_PRINT(("wdread\n"), DEBUG_XFERS);
                    637:        return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
                    638: }
                    639:
                    640: int
                    641: wdwrite(dev_t dev, struct uio *uio, int flags)
                    642: {
                    643:
                    644:        WDCDEBUG_PRINT(("wdwrite\n"), DEBUG_XFERS);
                    645:        return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
                    646: }
                    647:
                    648: int
                    649: wdopen(dev_t dev, int flag, int fmt, struct proc *p)
                    650: {
                    651:        struct wd_softc *wd;
                    652:        int unit, part;
                    653:        int error;
                    654:
                    655:        WDCDEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS);
                    656:
                    657:        unit = DISKUNIT(dev);
                    658:        wd = wdlookup(unit);
                    659:        if (wd == NULL)
                    660:                return ENXIO;
                    661:
                    662:        /*
                    663:         * If this is the first open of this device, add a reference
                    664:         * to the adapter.
                    665:         */
                    666:        if ((error = wdlock(wd)) != 0)
                    667:                goto bad4;
                    668:
                    669:        if (wd->sc_dk.dk_openmask != 0) {
                    670:                /*
                    671:                 * If any partition is open, but the disk has been invalidated,
                    672:                 * disallow further opens.
                    673:                 */
                    674:                if ((wd->sc_flags & WDF_LOADED) == 0) {
                    675:                        error = EIO;
                    676:                        goto bad3;
                    677:                }
                    678:        } else {
                    679:                if ((wd->sc_flags & WDF_LOADED) == 0) {
                    680:                        wd->sc_flags |= WDF_LOADED;
                    681:
                    682:                        /* Load the physical device parameters. */
                    683:                        wd_get_params(wd, AT_WAIT, &wd->sc_params);
                    684:
                    685:                        /* Load the partition info if not already loaded. */
                    686:                        wdgetdisklabel(dev, wd, wd->sc_dk.dk_label, 0);
                    687:                }
                    688:        }
                    689:
                    690:        part = DISKPART(dev);
                    691:
                    692:        /* Check that the partition exists. */
                    693:        if (part != RAW_PART &&
                    694:            (part >= wd->sc_dk.dk_label->d_npartitions ||
                    695:             wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
                    696:                error = ENXIO;
                    697:                goto bad;
                    698:        }
                    699:
                    700:        /* Insure only one open at a time. */
                    701:        switch (fmt) {
                    702:        case S_IFCHR:
                    703:                wd->sc_dk.dk_copenmask |= (1 << part);
                    704:                break;
                    705:        case S_IFBLK:
                    706:                wd->sc_dk.dk_bopenmask |= (1 << part);
                    707:                break;
                    708:        }
                    709:        wd->sc_dk.dk_openmask =
                    710:            wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
                    711:
                    712:        wdunlock(wd);
                    713:        device_unref(&wd->sc_dev);
                    714:        return 0;
                    715:
                    716: bad:
                    717:        if (wd->sc_dk.dk_openmask == 0) {
                    718:        }
                    719:
                    720: bad3:
                    721:        wdunlock(wd);
                    722: bad4:
                    723:        device_unref(&wd->sc_dev);
                    724:        return error;
                    725: }
                    726:
                    727: int
                    728: wdclose(dev_t dev, int flag, int fmt, struct proc *p)
                    729: {
                    730:        struct wd_softc *wd;
                    731:        int part = DISKPART(dev);
                    732:        int error = 0;
                    733:
                    734:        wd = wdlookup(DISKUNIT(dev));
                    735:        if (wd == NULL)
                    736:                return ENXIO;
                    737:
                    738:        WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS);
                    739:        if ((error = wdlock(wd)) != 0)
                    740:                goto exit;
                    741:
                    742:        switch (fmt) {
                    743:        case S_IFCHR:
                    744:                wd->sc_dk.dk_copenmask &= ~(1 << part);
                    745:                break;
                    746:        case S_IFBLK:
                    747:                wd->sc_dk.dk_bopenmask &= ~(1 << part);
                    748:                break;
                    749:        }
                    750:        wd->sc_dk.dk_openmask =
                    751:            wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
                    752:
                    753:        if (wd->sc_dk.dk_openmask == 0) {
                    754:                wd_flushcache(wd, 0);
                    755:                /* XXXX Must wait for I/O to complete! */
                    756:        }
                    757:
                    758:        wdunlock(wd);
                    759:
                    760:  exit:
                    761:        device_unref(&wd->sc_dev);
                    762:        return (error);
                    763: }
                    764:
                    765: void
                    766: wdgetdefaultlabel(struct wd_softc *wd, struct disklabel *lp)
                    767: {
                    768:        WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS);
                    769:        bzero(lp, sizeof(struct disklabel));
                    770:
                    771:        lp->d_secsize = DEV_BSIZE;
                    772:        DL_SETDSIZE(lp, wd->sc_capacity);
                    773:        lp->d_ntracks = wd->sc_params.atap_heads;
                    774:        lp->d_nsectors = wd->sc_params.atap_sectors;
                    775:        lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
                    776:        lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl;
                    777:        if (wd->drvp->ata_vers == -1) {
                    778:                lp->d_type = DTYPE_ST506;
                    779:                strncpy(lp->d_typename, "ST506/MFM/RLL", sizeof lp->d_typename);
                    780:        } else {
                    781:                lp->d_type = DTYPE_ESDI;
                    782:                strncpy(lp->d_typename, "ESDI/IDE disk", sizeof lp->d_typename);
                    783:        }
                    784:        /* XXX - user viscopy() like sd.c */
                    785:        strncpy(lp->d_packname, wd->sc_params.atap_model, sizeof lp->d_packname);
                    786:        lp->d_rpm = 3600;
                    787:        lp->d_interleave = 1;
                    788:        lp->d_flags = 0;
                    789:        lp->d_version = 1;
                    790:
                    791:        lp->d_magic = DISKMAGIC;
                    792:        lp->d_magic2 = DISKMAGIC;
                    793:        lp->d_checksum = dkcksum(lp);
                    794: }
                    795:
                    796: /*
                    797:  * Fabricate a default disk label, and try to read the correct one.
                    798:  */
                    799: void
                    800: wdgetdisklabel(dev_t dev, struct wd_softc *wd, struct disklabel *lp,
                    801:     int spoofonly)
                    802: {
                    803:        char *errstring;
                    804:
                    805:        WDCDEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS);
                    806:
                    807:        wdgetdefaultlabel(wd, lp);
                    808:
                    809:        if (wd->drvp->state > RECAL)
                    810:                wd->drvp->drive_flags |= DRIVE_RESET;
                    811:        errstring = readdisklabel(DISKLABELDEV(dev), wdstrategy, lp,
                    812:            spoofonly);
                    813:        if (wd->drvp->state > RECAL)
                    814:                wd->drvp->drive_flags |= DRIVE_RESET;
                    815:        if (errstring) {
                    816:                /*printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);*/
                    817:        }
                    818: }
                    819:
                    820: int
                    821: wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p)
                    822: {
                    823:        struct wd_softc *wd;
                    824:        struct disklabel *lp;
                    825:        int error = 0;
                    826:
                    827:        WDCDEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS);
                    828:
                    829:        wd = wdlookup(DISKUNIT(dev));
                    830:        if (wd == NULL)
                    831:                return ENXIO;
                    832:
                    833:        if ((wd->sc_flags & WDF_LOADED) == 0) {
                    834:                error = EIO;
                    835:                goto exit;
                    836:        }
                    837:
                    838:        switch (xfer) {
                    839:        case DIOCRLDINFO:
                    840:                lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
                    841:                wdgetdisklabel(dev, wd, lp, 0);
                    842:                bcopy(lp, wd->sc_dk.dk_label, sizeof(*lp));
                    843:                free(lp, M_TEMP);
                    844:                goto exit;
                    845:
                    846:        case DIOCGPDINFO:
                    847:                wdgetdisklabel(dev, wd, (struct disklabel *)addr, 1);
                    848:                goto exit;
                    849:
                    850:        case DIOCGDINFO:
                    851:                *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
                    852:                goto exit;
                    853:
                    854:        case DIOCGPART:
                    855:                ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
                    856:                ((struct partinfo *)addr)->part =
                    857:                    &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)];
                    858:                goto exit;
                    859:
                    860:        case DIOCWDINFO:
                    861:        case DIOCSDINFO:
                    862:                if ((flag & FWRITE) == 0) {
                    863:                        error = EBADF;
                    864:                        goto exit;
                    865:                }
                    866:
                    867:                if ((error = wdlock(wd)) != 0)
                    868:                        goto exit;
                    869:                wd->sc_flags |= WDF_LABELLING;
                    870:
                    871:                error = setdisklabel(wd->sc_dk.dk_label,
                    872:                    (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0);
                    873:                if (error == 0) {
                    874:                        if (wd->drvp->state > RECAL)
                    875:                                wd->drvp->drive_flags |= DRIVE_RESET;
                    876:                        if (xfer == DIOCWDINFO)
                    877:                                error = writedisklabel(DISKLABELDEV(dev),
                    878:                                    wdstrategy, wd->sc_dk.dk_label);
                    879:                }
                    880:
                    881:                wd->sc_flags &= ~WDF_LABELLING;
                    882:                wdunlock(wd);
                    883:                goto exit;
                    884:
                    885:        case DIOCWLABEL:
                    886:                if ((flag & FWRITE) == 0) {
                    887:                        error = EBADF;
                    888:                        goto exit;
                    889:                }
                    890:
                    891:                if (*(int *)addr)
                    892:                        wd->sc_flags |= WDF_WLABEL;
                    893:                else
                    894:                        wd->sc_flags &= ~WDF_WLABEL;
                    895:                goto exit;
                    896:
                    897: #ifdef notyet
                    898:        case DIOCWFORMAT:
                    899:                if ((flag & FWRITE) == 0)
                    900:                        return EBADF;
                    901:                {
                    902:                struct format_op *fop;
                    903:                struct iovec aiov;
                    904:                struct uio auio;
                    905:
                    906:                fop = (struct format_op *)addr;
                    907:                aiov.iov_base = fop->df_buf;
                    908:                aiov.iov_len = fop->df_count;
                    909:                auio.uio_iov = &aiov;
                    910:                auio.uio_iovcnt = 1;
                    911:                auio.uio_resid = fop->df_count;
                    912:                auio.uio_segflg = 0;
                    913:                auio.uio_offset =
                    914:                        fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
                    915:                auio.uio_procp = p;
                    916:                error = physio(wdformat, NULL, dev, B_WRITE, minphys,
                    917:                    &auio);
                    918:                fop->df_count -= auio.uio_resid;
                    919:                fop->df_reg[0] = wdc->sc_status;
                    920:                fop->df_reg[1] = wdc->sc_error;
                    921:                goto exit;
                    922:                }
                    923: #endif
                    924:
                    925:        default:
                    926:                error = wdc_ioctl(wd->drvp, xfer, addr, flag, p);
                    927:                goto exit;
                    928:        }
                    929:
                    930: #ifdef DIAGNOSTIC
                    931:        panic("wdioctl: impossible");
                    932: #endif
                    933:
                    934:  exit:
                    935:        device_unref(&wd->sc_dev);
                    936:        return (error);
                    937: }
                    938:
                    939: #ifdef B_FORMAT
                    940: int
                    941: wdformat(struct buf *bp)
                    942: {
                    943:
                    944:        bp->b_flags |= B_FORMAT;
                    945:        return wdstrategy(bp);
                    946: }
                    947: #endif
                    948:
                    949: daddr64_t
                    950: wdsize(dev_t dev)
                    951: {
                    952:        struct wd_softc *wd;
                    953:        int part, omask;
                    954:        int64_t size;
                    955:
                    956:        WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS);
                    957:
                    958:        wd = wdlookup(DISKUNIT(dev));
                    959:        if (wd == NULL)
                    960:                return (-1);
                    961:
                    962:        part = DISKPART(dev);
                    963:        omask = wd->sc_dk.dk_openmask & (1 << part);
                    964:
                    965:        if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) {
                    966:                size = -1;
                    967:                goto exit;
                    968:        }
                    969:
                    970:        size = DL_GETPSIZE(&wd->sc_dk.dk_label->d_partitions[part]) *
                    971:            (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
                    972:        if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0)
                    973:                size = -1;
                    974:
                    975:  exit:
                    976:        device_unref(&wd->sc_dev);
                    977:        return (size);
                    978: }
                    979:
                    980: /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
                    981: static int wddoingadump = 0;
                    982: static int wddumprecalibrated = 0;
                    983: static int wddumpmulti = 1;
                    984:
                    985: /*
                    986:  * Dump core after a system crash.
                    987:  */
                    988: int
                    989: wddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
                    990: {
                    991:        struct wd_softc *wd;    /* disk unit to do the I/O */
                    992:        struct disklabel *lp;   /* disk's disklabel */
                    993:        int unit, part;
                    994:        int nblks;      /* total number of sectors left to write */
                    995:        int err;
                    996:        char errbuf[256];
                    997:
                    998:        /* Check if recursive dump; if so, punt. */
                    999:        if (wddoingadump)
                   1000:                return EFAULT;
                   1001:        wddoingadump = 1;
                   1002:
                   1003:        unit = DISKUNIT(dev);
                   1004:        wd = wdlookup(unit);
                   1005:        if (wd == NULL)
                   1006:                return ENXIO;
                   1007:
                   1008:        part = DISKPART(dev);
                   1009:
                   1010:        /* Make sure it was initialized. */
                   1011:        if (wd->drvp->state < READY)
                   1012:                return ENXIO;
                   1013:
                   1014:        /* Convert to disk sectors.  Request must be a multiple of size. */
                   1015:        lp = wd->sc_dk.dk_label;
                   1016:        if ((size % lp->d_secsize) != 0)
                   1017:                return EFAULT;
                   1018:        nblks = size / lp->d_secsize;
                   1019:        blkno = blkno / (lp->d_secsize / DEV_BSIZE);
                   1020:
                   1021:        /* Check transfer bounds against partition size. */
                   1022:        if ((blkno < 0) || ((blkno + nblks) > DL_GETPSIZE(&lp->d_partitions[part])))
                   1023:                return EINVAL;
                   1024:
                   1025:        /* Offset block number to start of partition. */
                   1026:        blkno += DL_GETPOFFSET(&lp->d_partitions[part]);
                   1027:
                   1028:        /* Recalibrate, if first dump transfer. */
                   1029:        if (wddumprecalibrated == 0) {
                   1030:                wddumpmulti = wd->sc_multi;
                   1031:                wddumprecalibrated = 1;
                   1032:                wd->drvp->state = RECAL;
                   1033:        }
                   1034:
                   1035:        while (nblks > 0) {
                   1036: again:
                   1037:                wd->sc_wdc_bio.blkno = blkno;
                   1038:                wd->sc_wdc_bio.flags = ATA_POLL;
                   1039:                if (wddumpmulti == 1)
                   1040:                        wd->sc_wdc_bio.flags |= ATA_SINGLE;
                   1041:                if (wd->sc_flags & WDF_LBA48)
                   1042:                        wd->sc_wdc_bio.flags |= ATA_LBA48;
                   1043:                if (wd->sc_flags & WDF_LBA)
                   1044:                        wd->sc_wdc_bio.flags |= ATA_LBA;
                   1045:                wd->sc_wdc_bio.bcount =
                   1046:                        min(nblks, wddumpmulti) * lp->d_secsize;
                   1047:                wd->sc_wdc_bio.databuf = va;
                   1048:                wd->sc_wdc_bio.wd = wd;
                   1049: #ifndef WD_DUMP_NOT_TRUSTED
                   1050:                switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
                   1051:                case WDC_TRY_AGAIN:
                   1052:                        panic("wddump: try again");
                   1053:                        break;
                   1054:                case WDC_QUEUED:
                   1055:                        panic("wddump: polled command has been queued");
                   1056:                        break;
                   1057:                case WDC_COMPLETE:
                   1058:                        break;
                   1059:                }
                   1060:                switch(wd->sc_wdc_bio.error) {
                   1061:                case TIMEOUT:
                   1062:                        printf("wddump: device timed out");
                   1063:                        err = EIO;
                   1064:                        break;
                   1065:                case ERR_DF:
                   1066:                        printf("wddump: drive fault");
                   1067:                        err = EIO;
                   1068:                        break;
                   1069:                case ERR_DMA:
                   1070:                        printf("wddump: DMA error");
                   1071:                        err = EIO;
                   1072:                        break;
                   1073:                case ERROR:
                   1074:                        errbuf[0] = '\0';
                   1075:                        ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf,
                   1076:                            sizeof errbuf);
                   1077:                        printf("wddump: %s", errbuf);
                   1078:                        err = EIO;
                   1079:                        break;
                   1080:                case NOERROR:
                   1081:                        err = 0;
                   1082:                        break;
                   1083:                default:
                   1084:                        panic("wddump: unknown error type");
                   1085:                }
                   1086:                if (err != 0) {
                   1087:                        if (wddumpmulti != 1) {
                   1088:                                wddumpmulti = 1; /* retry in single-sector */
                   1089:                                printf(", retrying\n");
                   1090:                                goto again;
                   1091:                        }
                   1092:                        printf("\n");
                   1093:                        return err;
                   1094:                }
                   1095: #else  /* WD_DUMP_NOT_TRUSTED */
                   1096:                /* Let's just talk about this first... */
                   1097:                printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
                   1098:                    unit, va, cylin, head, sector);
                   1099:                delay(500 * 1000);      /* half a second */
                   1100: #endif
                   1101:
                   1102:                /* update block count */
                   1103:                nblks -= min(nblks, wddumpmulti);
                   1104:                blkno += min(nblks, wddumpmulti);
                   1105:                va += min(nblks, wddumpmulti) * lp->d_secsize;
                   1106:        }
                   1107:
                   1108:        wddoingadump = 0;
                   1109:        return 0;
                   1110: }
                   1111:
                   1112: int
                   1113: wd_get_params(struct wd_softc *wd, u_int8_t flags, struct ataparams *params)
                   1114: {
                   1115:        switch (ata_get_params(wd->drvp, flags, params)) {
                   1116:        case CMD_AGAIN:
                   1117:                return 1;
                   1118:        case CMD_ERR:
                   1119:                /* If we already have drive parameters, reuse them. */
                   1120:                if (wd->sc_params.atap_cylinders != 0) {
                   1121:                        if (params != &wd->sc_params)
                   1122:                                bcopy(&wd->sc_params, params,
                   1123:                                    sizeof(struct ataparams));
                   1124:                        return 0;
                   1125:                }
                   1126:                /*
                   1127:                 * We `know' there's a drive here; just assume it's old.
                   1128:                 * This geometry is only used to read the MBR and print a
                   1129:                 * (false) attach message.
                   1130:                 */
                   1131:                bzero(params, sizeof(struct ataparams));
                   1132:                strncpy(params->atap_model, "ST506",
                   1133:                    sizeof params->atap_model);
                   1134:                params->atap_config = ATA_CFG_FIXED;
                   1135:                params->atap_cylinders = 1024;
                   1136:                params->atap_heads = 8;
                   1137:                params->atap_sectors = 17;
                   1138:                params->atap_multi = 1;
                   1139:                params->atap_capabilities1 = params->atap_capabilities2 = 0;
                   1140:                wd->drvp->ata_vers = -1; /* Mark it as pre-ATA */
                   1141:                return 0;
                   1142:        case CMD_OK:
                   1143:                return 0;
                   1144:        default:
                   1145:                panic("wd_get_params: bad return code from ata_get_params");
                   1146:                /* NOTREACHED */
                   1147:        }
                   1148: }
                   1149:
                   1150: void
                   1151: wd_flushcache(struct wd_softc *wd, int flags)
                   1152: {
                   1153:        struct wdc_command wdc_c;
                   1154:
                   1155:        if (wd->drvp->ata_vers < 4) /* WDCC_FLUSHCACHE is here since ATA-4 */
                   1156:                return;
                   1157:        bzero(&wdc_c, sizeof(struct wdc_command));
                   1158:        wdc_c.r_command = (wd->sc_flags & WDF_LBA48 ? WDCC_FLUSHCACHE_EXT :
                   1159:            WDCC_FLUSHCACHE);
                   1160:        wdc_c.r_st_bmask = WDCS_DRDY;
                   1161:        wdc_c.r_st_pmask = WDCS_DRDY;
                   1162:        if (flags != 0) {
                   1163:                wdc_c.flags = AT_POLL;
                   1164:        } else {
                   1165:                wdc_c.flags = AT_WAIT;
                   1166:        }
                   1167:        wdc_c.timeout = 30000; /* 30s timeout */
                   1168:        if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) {
                   1169:                printf("%s: flush cache command didn't complete\n",
                   1170:                    wd->sc_dev.dv_xname);
                   1171:        }
                   1172:        if (wdc_c.flags & AT_TIMEOU) {
                   1173:                printf("%s: flush cache command timeout\n",
                   1174:                    wd->sc_dev.dv_xname);
                   1175:        }
                   1176:        if (wdc_c.flags & AT_DF) {
                   1177:                printf("%s: flush cache command: drive fault\n",
                   1178:                    wd->sc_dev.dv_xname);
                   1179:        }
                   1180:        /*
                   1181:         * Ignore error register, it shouldn't report anything else
                   1182:         * than COMMAND ABORTED, which means the device doesn't support
                   1183:         * flush cache
                   1184:         */
                   1185: }
                   1186:
                   1187: void
                   1188: wd_shutdown(void *arg)
                   1189: {
                   1190:        struct wd_softc *wd = arg;
                   1191:        wd_flushcache(wd, AT_POLL);
                   1192: }

CVSweb