LCOV - code coverage report
Current view: top level - dev/ata - wd.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 502 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13