The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ata/wd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: wd.c,v 1.274.2.14 2007/10/15 23:11:38 riz Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *      notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *      notice, this list of conditions and the following disclaimer in the
   13  *      documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *      must display the following acknowledgement:
   16  *  This product includes software developed by Manuel Bouyer.
   17  * 4. The name of the author may not be used to endorse or promote products
   18  *      derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*-
   33  * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
   34  * All rights reserved.
   35  *
   36  * This code is derived from software contributed to The NetBSD Foundation
   37  * by Charles M. Hannum and by Onno van der Linden.
   38  *
   39  * Redistribution and use in source and binary forms, with or without
   40  * modification, are permitted provided that the following conditions
   41  * are met:
   42  * 1. Redistributions of source code must retain the above copyright
   43  *    notice, this list of conditions and the following disclaimer.
   44  * 2. Redistributions in binary form must reproduce the above copyright
   45  *    notice, this list of conditions and the following disclaimer in the
   46  *    documentation and/or other materials provided with the distribution.
   47  * 3. All advertising materials mentioning features or use of this software
   48  *    must display the following acknowledgement:
   49  *        This product includes software developed by the NetBSD
   50  *        Foundation, Inc. and its contributors.
   51  * 4. Neither the name of The NetBSD Foundation nor the names of its
   52  *    contributors may be used to endorse or promote products derived
   53  *    from this software without specific prior written permission.
   54  *
   55  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   56  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   57  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   58  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   59  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   60  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   61  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   62  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   63  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   64  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   65  * POSSIBILITY OF SUCH DAMAGE.
   66  */
   67 
   68 #include <sys/cdefs.h>
   69 __KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.274.2.14 2007/10/15 23:11:38 riz Exp $");
   70 
   71 #ifndef WDCDEBUG
   72 #define WDCDEBUG
   73 #endif /* WDCDEBUG */
   74 
   75 #include "rnd.h"
   76 
   77 #include <sys/param.h>
   78 #include <sys/systm.h>
   79 #include <sys/kernel.h>
   80 #include <sys/conf.h>
   81 #include <sys/file.h>
   82 #include <sys/stat.h>
   83 #include <sys/ioctl.h>
   84 #include <sys/buf.h>
   85 #include <sys/uio.h>
   86 #include <sys/malloc.h>
   87 #include <sys/device.h>
   88 #include <sys/disklabel.h>
   89 #include <sys/disk.h>
   90 #include <sys/syslog.h>
   91 #include <sys/proc.h>
   92 #include <sys/vnode.h>
   93 #if NRND > 0
   94 #include <sys/rnd.h>
   95 #endif
   96 
   97 #include <machine/intr.h>
   98 #include <machine/bus.h>
   99 
  100 #include <dev/ata/atareg.h>
  101 #include <dev/ata/atavar.h>
  102 #include <dev/ata/wdvar.h>
  103 #include <dev/ic/wdcreg.h>
  104 #include <sys/ataio.h>
  105 #include "locators.h"
  106 
  107 #define LBA48_THRESHOLD         (0xfffffff)     /* 128GB / DEV_BSIZE */
  108 
  109 #define WDIORETRIES_SINGLE 4    /* number of retries before single-sector */
  110 #define WDIORETRIES     5       /* number of retries before giving up */
  111 #define RECOVERYTIME hz/2       /* time to wait before retrying a cmd */
  112 
  113 #define WDUNIT(dev)             DISKUNIT(dev)
  114 #define WDPART(dev)             DISKPART(dev)
  115 #define WDMINOR(unit, part)     DISKMINOR(unit, part)
  116 #define MAKEWDDEV(maj, unit, part)      MAKEDISKDEV(maj, unit, part)
  117 
  118 #define WDLABELDEV(dev) (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART))
  119 
  120 #define DEBUG_INTR   0x01
  121 #define DEBUG_XFERS  0x02
  122 #define DEBUG_STATUS 0x04
  123 #define DEBUG_FUNCS  0x08
  124 #define DEBUG_PROBE  0x10
  125 #ifdef WDCDEBUG
  126 int wdcdebug_wd_mask = 0x0; 
  127 #define WDCDEBUG_PRINT(args, level) \
  128         if (wdcdebug_wd_mask & (level)) \
  129                 printf args
  130 #else
  131 #define WDCDEBUG_PRINT(args, level)
  132 #endif
  133 
  134 int     wdprobe(struct device *, struct cfdata *, void *);
  135 void    wdattach(struct device *, struct device *, void *);
  136 int     wddetach(struct device *, int);
  137 int     wdactivate(struct device *, enum devact);
  138 int     wdprint(void *, char *);
  139 void    wdperror(const struct wd_softc *);
  140 
  141 CFATTACH_DECL(wd, sizeof(struct wd_softc),
  142     wdprobe, wdattach, wddetach, wdactivate);
  143 
  144 extern struct cfdriver wd_cd;
  145 
  146 dev_type_open(wdopen);
  147 dev_type_close(wdclose);
  148 dev_type_read(wdread);
  149 dev_type_write(wdwrite);
  150 dev_type_ioctl(wdioctl);
  151 dev_type_strategy(wdstrategy);
  152 dev_type_dump(wddump);
  153 dev_type_size(wdsize);
  154 
  155 const struct bdevsw wd_bdevsw = {
  156         wdopen, wdclose, wdstrategy, wdioctl, wddump, wdsize, D_DISK
  157 };
  158 
  159 const struct cdevsw wd_cdevsw = {
  160         wdopen, wdclose, wdread, wdwrite, wdioctl,
  161         nostop, notty, nopoll, nommap, nokqfilter, D_DISK
  162 };
  163 
  164 /*
  165  * Glue necessary to hook WDCIOCCOMMAND into physio
  166  */
  167 
  168 struct wd_ioctl {
  169         LIST_ENTRY(wd_ioctl) wi_list;
  170         struct buf wi_bp;
  171         struct uio wi_uio;
  172         struct iovec wi_iov;
  173         atareq_t wi_atareq;
  174         struct wd_softc *wi_softc;
  175 };
  176 
  177 LIST_HEAD(, wd_ioctl) wi_head;
  178 
  179 struct  wd_ioctl *wi_find(struct buf *);
  180 void    wi_free(struct wd_ioctl *);
  181 struct  wd_ioctl *wi_get(void);
  182 void    wdioctlstrategy(struct buf *);
  183 
  184 void  wdgetdefaultlabel(struct wd_softc *, struct disklabel *);
  185 void  wdgetdisklabel(struct wd_softc *);
  186 void  wdstart(void *);
  187 void  __wdstart(struct wd_softc*, struct buf *);
  188 void  wdrestart(void *);
  189 void  wddone(void *);
  190 int   wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *);
  191 int   wd_flushcache(struct wd_softc *, int);
  192 void  wd_shutdown(void *);
  193 
  194 int   wd_getcache(struct wd_softc *, int *);
  195 int   wd_setcache(struct wd_softc *, int);
  196 
  197 struct dkdriver wddkdriver = { wdstrategy };
  198 
  199 #ifdef HAS_BAD144_HANDLING
  200 static void bad144intern(struct wd_softc *);
  201 #endif
  202 
  203 #define WD_QUIRK_SPLIT_MOD15_WRITE      0x0001  /* must split certain writes */
  204 #define WD_QUIRK_FORCE_LBA48            0x0002  /* must use LBA48 commands */
  205 
  206 /*
  207  * Quirk table for IDE drives.  Put more-specific matches first, since
  208  * a simple globbing routine is used for matching.
  209  */
  210 static const struct wd_quirk {
  211         const char *wdq_match;          /* inquiry pattern to match */
  212         int wdq_quirks;                 /* drive quirks */
  213 } wd_quirk_table[] = {
  214         /*
  215          * Some Seagate S-ATA drives have a PHY which can get confused
  216          * with the way data is packetized by some S-ATA controllers.
  217          *
  218          * The work-around is to split in two any write transfer whose
  219          * sector count % 15 == 1 (assuming 512 byte sectors).
  220          *
  221          * XXX This is an incomplete list.  There are at least a couple
  222          * XXX more model numbers.  If you have trouble with such transfers
  223          * XXX (8K is the most common) on Seagate S-ATA drives, please
  224          * XXX notify thorpej@NetBSD.org.
  225          */
  226         { "ST3120023AS",
  227           WD_QUIRK_SPLIT_MOD15_WRITE },
  228         { "ST380023AS",
  229           WD_QUIRK_SPLIT_MOD15_WRITE },
  230 
  231         /*
  232          * This seagate drive seems to have issue addressing sector 0xfffffff
  233          * (aka LBA48_THRESHOLD) in LBA mode. The workaround is to force
  234          * LBA48
  235          */
  236         { "ST3160021A*",
  237           WD_QUIRK_FORCE_LBA48 },
  238         { "ST3160811A*",
  239           WD_QUIRK_FORCE_LBA48 },
  240         { "ST3160812A*",
  241           WD_QUIRK_FORCE_LBA48 },
  242         { "ST3160023A*",
  243           WD_QUIRK_FORCE_LBA48 },
  244         { "ST3160827A*",
  245           WD_QUIRK_FORCE_LBA48 },
  246         /* Attempt to catch all seagate drives larger than 200GB */
  247         { "ST3[2-9][0-9][0-9][0-9][0-9][0-9][A-Z]*",
  248           WD_QUIRK_FORCE_LBA48 },
  249         { NULL,
  250           0 }
  251 };
  252 
  253 static const struct wd_quirk *
  254 wd_lookup_quirks(const char *name)
  255 {
  256         const struct wd_quirk *wdq;
  257         const char *estr;
  258 
  259         for (wdq = wd_quirk_table; wdq->wdq_match != NULL; wdq++) {
  260                 /*
  261                  * We only want exact matches (which include matches
  262                  * against globbing characters).
  263                  */
  264                 if (pmatch(name, wdq->wdq_match, &estr) == 2)
  265                         return (wdq);
  266         }
  267         return (NULL);
  268 }
  269 
  270 int
  271 wdprobe(struct device *parent, struct cfdata *match, void *aux)
  272 {
  273         struct ata_device *adev = aux;
  274 
  275         if (adev == NULL)
  276                 return 0;
  277         if (adev->adev_bustype->bustype_type != SCSIPI_BUSTYPE_ATA)
  278                 return 0;
  279 
  280         if (match->cf_loc[ATA_HLCF_DRIVE] != ATA_HLCF_DRIVE_DEFAULT &&
  281             match->cf_loc[ATA_HLCF_DRIVE] != adev->adev_drv_data->drive)
  282                 return 0;
  283         return 1;
  284 }
  285 
  286 void
  287 wdattach(struct device *parent, struct device *self, void *aux)
  288 {
  289         struct wd_softc *wd = (void *)self;
  290         struct ata_device *adev= aux;
  291         int i, blank;
  292         char buf[41], pbuf[9], c, *p, *q;
  293         const struct wd_quirk *wdq;
  294         WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
  295 
  296         lockinit(&wd->sc_lock, PRIBIO | PCATCH, "wdlock", 0, 0);
  297 
  298         callout_init(&wd->sc_restart_ch);
  299         bufq_alloc(&wd->sc_q, BUFQ_DISK_DEFAULT_STRAT()|BUFQ_SORT_RAWBLOCK);
  300         SLIST_INIT(&wd->sc_bslist);
  301 
  302         wd->atabus = adev->adev_bustype;
  303         wd->openings = adev->adev_openings;
  304         wd->drvp = adev->adev_drv_data;
  305 
  306         wd->drvp->drv_done = wddone;
  307         wd->drvp->drv_softc = &wd->sc_dev;
  308 
  309         aprint_naive("\n");
  310 
  311         /* read our drive info */
  312         if (wd_get_params(wd, AT_WAIT, &wd->sc_params) != 0) {
  313                 aprint_error("\n%s: IDENTIFY failed\n", wd->sc_dev.dv_xname);
  314                 return;
  315         }
  316 
  317         for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0;
  318             i < sizeof(wd->sc_params.atap_model); i++) {
  319                 c = *p++;
  320                 if (c == '\0')
  321                         break;
  322                 if (c != ' ') {
  323                         if (blank) {
  324                                 *q++ = ' ';
  325                                 blank = 0;
  326                         }
  327                         *q++ = c;
  328                 } else
  329                         blank = 1;
  330         }
  331         *q++ = '\0';
  332 
  333         aprint_normal(": <%s>\n", buf);
  334 
  335         wdq = wd_lookup_quirks(buf);
  336         if (wdq != NULL)
  337                 wd->sc_quirks = wdq->wdq_quirks;
  338 
  339         if ((wd->sc_params.atap_multi & 0xff) > 1) {
  340                 wd->sc_multi = wd->sc_params.atap_multi & 0xff;
  341         } else {
  342                 wd->sc_multi = 1;
  343         }
  344 
  345         aprint_normal("%s: drive supports %d-sector PIO transfers,",
  346             wd->sc_dev.dv_xname, wd->sc_multi);
  347 
  348         /* 48-bit LBA addressing */
  349         if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0)
  350                 wd->sc_flags |= WDF_LBA48;
  351 
  352         /* Prior to ATA-4, LBA was optional. */
  353         if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0)
  354                 wd->sc_flags |= WDF_LBA;
  355 #if 0
  356         /* ATA-4 requires LBA. */
  357         if (wd->sc_params.atap_ataversion != 0xffff &&
  358             wd->sc_params.atap_ataversion >= WDC_VER_ATA4)
  359                 wd->sc_flags |= WDF_LBA;
  360 #endif
  361 
  362         if ((wd->sc_flags & WDF_LBA48) != 0) {
  363                 aprint_normal(" LBA48 addressing\n");
  364                 wd->sc_capacity =
  365                     ((u_int64_t) wd->sc_params.__reserved6[11] << 48) |
  366                     ((u_int64_t) wd->sc_params.__reserved6[10] << 32) |
  367                     ((u_int64_t) wd->sc_params.__reserved6[9]  << 16) |
  368                     ((u_int64_t) wd->sc_params.__reserved6[8]  << 0);
  369         } else if ((wd->sc_flags & WDF_LBA) != 0) {
  370                 aprint_normal(" LBA addressing\n");
  371                 wd->sc_capacity =
  372                     (wd->sc_params.atap_capacity[1] << 16) |
  373                     wd->sc_params.atap_capacity[0];
  374         } else {
  375                 aprint_normal(" chs addressing\n");
  376                 wd->sc_capacity =
  377                     wd->sc_params.atap_cylinders *
  378                     wd->sc_params.atap_heads *
  379                     wd->sc_params.atap_sectors;
  380         }
  381         format_bytes(pbuf, sizeof(pbuf), wd->sc_capacity * DEV_BSIZE);
  382         aprint_normal("%s: %s, %d cyl, %d head, %d sec, "
  383             "%d bytes/sect x %llu sectors\n",
  384             self->dv_xname, pbuf,
  385             (wd->sc_flags & WDF_LBA) ? (int)(wd->sc_capacity /
  386                 (wd->sc_params.atap_heads * wd->sc_params.atap_sectors)) :
  387                 wd->sc_params.atap_cylinders,
  388             wd->sc_params.atap_heads, wd->sc_params.atap_sectors,
  389             DEV_BSIZE, (unsigned long long)wd->sc_capacity);
  390 
  391         WDCDEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n",
  392             self->dv_xname, wd->sc_params.atap_dmatiming_mimi,
  393             wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE);
  394         /*
  395          * Initialize and attach the disk structure.
  396          */
  397         wd->sc_dk.dk_driver = &wddkdriver;
  398         wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
  399         disk_attach(&wd->sc_dk);
  400         wd->sc_wdc_bio.lp = wd->sc_dk.dk_label;
  401         wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd);
  402         if (wd->sc_sdhook == NULL)
  403                 aprint_error("%s: WARNING: unable to establish shutdown hook\n",
  404                     wd->sc_dev.dv_xname);
  405 #if NRND > 0
  406         rnd_attach_source(&wd->rnd_source, wd->sc_dev.dv_xname,
  407                           RND_TYPE_DISK, 0);
  408 #endif
  409 }
  410 
  411 int
  412 wdactivate(struct device *self, enum devact act)
  413 {
  414         int rv = 0;
  415 
  416         switch (act) {
  417         case DVACT_ACTIVATE:
  418                 rv = EOPNOTSUPP;
  419                 break;
  420 
  421         case DVACT_DEACTIVATE:
  422                 /*
  423                  * Nothing to do; we key off the device's DVF_ACTIVATE.
  424                  */
  425                 break;
  426         }
  427         return (rv);
  428 }
  429 
  430 int
  431 wddetach(struct device *self, int flags)
  432 {
  433         struct wd_softc *sc = (struct wd_softc *)self;
  434         struct buf *bp;
  435         int s, bmaj, cmaj, i, mn;
  436 
  437         /* locate the major number */
  438         bmaj = bdevsw_lookup_major(&wd_bdevsw);
  439         cmaj = cdevsw_lookup_major(&wd_cdevsw);
  440 
  441         s = splbio();
  442 
  443         /* Kill off any queued buffers. */
  444         while ((bp = BUFQ_GET(&sc->sc_q)) != NULL) {
  445                 bp->b_error = EIO;
  446                 bp->b_flags |= B_ERROR;
  447                 bp->b_resid = bp->b_bcount;
  448                 biodone(bp);
  449         }
  450 
  451         bufq_free(&sc->sc_q);
  452 
  453         splx(s);
  454 
  455         /* Nuke the vnodes for any open instances. */
  456         for (i = 0; i < MAXPARTITIONS; i++) {
  457                 mn = WDMINOR(self->dv_unit, i);
  458                 vdevgone(bmaj, mn, mn, VBLK);
  459                 vdevgone(cmaj, mn, mn, VCHR);
  460         }
  461 
  462         /* Detach disk. */
  463         disk_detach(&sc->sc_dk);
  464 
  465         /* Clean out the bad sector list */
  466         while (!SLIST_EMPTY(&sc->sc_bslist)) {
  467                 void *head = SLIST_FIRST(&sc->sc_bslist);
  468                 SLIST_REMOVE_HEAD(&sc->sc_bslist, dbs_next);
  469                 free(head, M_TEMP);
  470         }
  471         sc->sc_bscount = 0;
  472 
  473         /* Get rid of the shutdown hook. */
  474         if (sc->sc_sdhook != NULL)
  475                 shutdownhook_disestablish(sc->sc_sdhook);
  476 
  477 #if NRND > 0
  478         /* Unhook the entropy source. */
  479         rnd_detach_source(&sc->rnd_source);
  480 #endif
  481 
  482         lockmgr(&sc->sc_lock, LK_DRAIN, NULL);
  483 
  484         return (0);
  485 }
  486 
  487 /*
  488  * Read/write routine for a buffer.  Validates the arguments and schedules the
  489  * transfer.  Does not wait for the transfer to complete.
  490  */
  491 void
  492 wdstrategy(struct buf *bp)
  493 {
  494         struct wd_softc *wd = device_lookup(&wd_cd, WDUNIT(bp->b_dev));
  495         struct disklabel *lp = wd->sc_dk.dk_label;
  496         daddr_t blkno;
  497         int s;
  498 
  499         WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname),
  500             DEBUG_XFERS);
  501 
  502         /* Valid request?  */
  503         if (bp->b_blkno < 0 ||
  504             (bp->b_bcount % lp->d_secsize) != 0 ||
  505             (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) {
  506                 bp->b_error = EINVAL;
  507                 goto bad;
  508         }
  509 
  510         /* If device invalidated (e.g. media change, door open), error. */
  511         if ((wd->sc_flags & WDF_LOADED) == 0) {
  512                 bp->b_error = EIO;
  513                 goto bad;
  514         }
  515 
  516         /* If it's a null transfer, return immediately. */
  517         if (bp->b_bcount == 0)
  518                 goto done;
  519 
  520         /*
  521          * Do bounds checking, adjust transfer. if error, process.
  522          * If end of partition, just return.
  523          */
  524         if (WDPART(bp->b_dev) == RAW_PART) {
  525                 if (bounds_check_with_mediasize(bp, DEV_BSIZE,
  526                     wd->sc_capacity) <= 0)
  527                         goto done;
  528         } else {
  529                 if (bounds_check_with_label(&wd->sc_dk, bp,
  530                     (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
  531                         goto done;
  532         }
  533 
  534         /*
  535          * Now convert the block number to absolute and put it in
  536          * terms of the device's logical block size.
  537          */
  538         if (lp->d_secsize >= DEV_BSIZE)
  539                 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
  540         else
  541                 blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
  542 
  543         if (WDPART(bp->b_dev) != RAW_PART)
  544                 blkno += lp->d_partitions[WDPART(bp->b_dev)].p_offset;
  545 
  546         bp->b_rawblkno = blkno;
  547 
  548         /*
  549          * If the transfer about to be attempted contains only a block that
  550          * is known to be bad then return an error for the transfer without
  551          * even attempting to start a transfer up under the premis that we
  552          * will just end up doing more retries for a transfer that will end
  553          * up failing again.
  554          * XXX:SMP - mutex required to protect with DIOCBSFLUSH
  555          */
  556         if (__predict_false(!SLIST_EMPTY(&wd->sc_bslist))) {
  557                 struct disk_badsectors *dbs;
  558                 daddr_t maxblk = blkno + (bp->b_bcount >> DEV_BSHIFT) - 1;
  559 
  560                 SLIST_FOREACH(dbs, &wd->sc_bslist, dbs_next)
  561                         if ((dbs->dbs_min <= blkno && blkno <= dbs->dbs_max) ||
  562                             (dbs->dbs_min <= maxblk && maxblk <= dbs->dbs_max)){
  563                                 bp->b_error = EIO;
  564                                 goto bad;
  565                         }
  566         }
  567 
  568         /* Queue transfer on drive, activate drive and controller if idle. */
  569         s = splbio();
  570         BUFQ_PUT(&wd->sc_q, bp);
  571         wdstart(wd);
  572         splx(s);
  573         return;
  574 bad:
  575         bp->b_flags |= B_ERROR;
  576 done:
  577         /* Toss transfer; we're done early. */
  578         bp->b_resid = bp->b_bcount;
  579         biodone(bp);
  580 }
  581 
  582 /*
  583  * Queue a drive for I/O.
  584  */
  585 void
  586 wdstart(void *arg)
  587 {
  588         struct wd_softc *wd = arg;
  589         struct buf *bp = NULL;
  590 
  591         WDCDEBUG_PRINT(("wdstart %s\n", wd->sc_dev.dv_xname),
  592             DEBUG_XFERS);
  593         while (wd->openings > 0) {
  594 
  595                 /* Is there a buf for us ? */
  596                 if ((bp = BUFQ_GET(&wd->sc_q)) == NULL)
  597                         return;
  598 
  599                 /*
  600                  * Make the command. First lock the device
  601                  */
  602                 wd->openings--;
  603 
  604                 wd->retries = 0;
  605                 __wdstart(wd, bp);
  606         }
  607 }
  608 
  609 static void
  610 wd_split_mod15_write(struct buf *bp)
  611 {
  612         struct buf *obp = bp->b_private;
  613         struct wd_softc *sc = wd_cd.cd_devs[DISKUNIT(obp->b_dev)];
  614 
  615         if (__predict_false(bp->b_flags & B_ERROR) != 0) {
  616                 /*
  617                  * Propagate the error.  If this was the first half of
  618                  * the original transfer, make sure to account for that
  619                  * in the residual.
  620                  */
  621                 if (bp->b_data == obp->b_data)
  622                         bp->b_resid += bp->b_bcount;
  623                 goto done;
  624         }
  625 
  626         /*
  627          * If this was the second half of the transfer, we're all done!
  628          */
  629         if (bp->b_data != obp->b_data)
  630                 goto done;
  631 
  632         /*
  633          * Advance the pointer to the second half and issue that command
  634          * using the same opening.
  635          */
  636         bp->b_flags = obp->b_flags | B_CALL;
  637         bp->b_data += bp->b_bcount;
  638         bp->b_blkno += (bp->b_bcount / 512);
  639         bp->b_rawblkno += (bp->b_bcount / 512);
  640         __wdstart(sc, bp);
  641         return;
  642 
  643  done:
  644         obp->b_flags |= (bp->b_flags & (B_EINTR|B_ERROR));
  645         obp->b_error = bp->b_error;
  646         obp->b_resid = bp->b_resid;
  647         pool_put(&bufpool, bp);
  648         biodone(obp);
  649         sc->openings++;
  650         /* wddone() will call wdstart() */
  651 }
  652 
  653 void
  654 __wdstart(struct wd_softc *wd, struct buf *bp)
  655 {
  656 
  657         /*
  658          * Deal with the "split mod15 write" quirk.  We just divide the
  659          * transfer in two, doing the first half and then then second half
  660          * with the same command opening.
  661          *
  662          * Note we MUST do this here, because we can't let insertion
  663          * into the bufq cause the transfers to be re-merged.
  664          */
  665         if (__predict_false((wd->sc_quirks & WD_QUIRK_SPLIT_MOD15_WRITE) != 0 &&
  666                             (bp->b_flags & B_READ) == 0 &&
  667                             bp->b_bcount > 512 &&
  668                             ((bp->b_bcount / 512) % 15) == 1)) {
  669                 struct buf *nbp;
  670 
  671                 /* already at splbio */
  672                 nbp = pool_get(&bufpool, PR_NOWAIT);
  673                 if (__predict_false(nbp == NULL)) {
  674                         /* No memory -- fail the iop. */
  675                         bp->b_error = ENOMEM;
  676                         bp->b_flags |= B_ERROR;
  677                         bp->b_resid = bp->b_bcount;
  678                         biodone(bp);
  679                         wd->openings++;
  680                         return;
  681                 }
  682 
  683                 BUF_INIT(nbp);
  684                 nbp->b_error = 0;
  685                 nbp->b_proc = bp->b_proc;
  686                 nbp->b_vp = NULLVP;
  687                 nbp->b_dev = bp->b_dev;
  688 
  689                 nbp->b_bcount = bp->b_bcount / 2;
  690                 nbp->b_bufsize = bp->b_bcount / 2;
  691                 nbp->b_data = bp->b_data;
  692 
  693                 nbp->b_blkno = bp->b_blkno;
  694                 nbp->b_rawblkno = bp->b_rawblkno;
  695 
  696                 nbp->b_flags = bp->b_flags | B_CALL;
  697                 nbp->b_iodone = wd_split_mod15_write;
  698 
  699                 /* Put ptr to orig buf in b_private and use new buf */
  700                 nbp->b_private = bp;
  701 
  702                 BIO_COPYPRIO(nbp, bp);
  703 
  704                 bp = nbp;
  705         }
  706 
  707         wd->sc_wdc_bio.blkno = bp->b_rawblkno;
  708         wd->sc_wdc_bio.blkdone =0;
  709         wd->sc_bp = bp;
  710         /*
  711          * If we're retrying, retry in single-sector mode. This will give us
  712          * the sector number of the problem, and will eventually allow the
  713          * transfer to succeed.
  714          */
  715         if (wd->retries >= WDIORETRIES_SINGLE)
  716                 wd->sc_wdc_bio.flags = ATA_SINGLE;
  717         else
  718                 wd->sc_wdc_bio.flags = 0;
  719         if (wd->sc_flags & WDF_LBA48 &&
  720             (wd->sc_wdc_bio.blkno > LBA48_THRESHOLD ||
  721             (wd->sc_quirks & WD_QUIRK_FORCE_LBA48) != 0))
  722                 wd->sc_wdc_bio.flags |= ATA_LBA48;
  723         if (wd->sc_flags & WDF_LBA)
  724                 wd->sc_wdc_bio.flags |= ATA_LBA;
  725         if (bp->b_flags & B_READ)
  726                 wd->sc_wdc_bio.flags |= ATA_READ;
  727         wd->sc_wdc_bio.bcount = bp->b_bcount;
  728         wd->sc_wdc_bio.databuf = bp->b_data;
  729         /* Instrumentation. */
  730         disk_busy(&wd->sc_dk);
  731         switch (wd->atabus->ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
  732         case WDC_TRY_AGAIN:
  733                 callout_reset(&wd->sc_restart_ch, hz, wdrestart, wd);
  734                 break;
  735         case WDC_QUEUED:
  736         case WDC_COMPLETE:
  737                 break;
  738         default:
  739                 panic("__wdstart: bad return code from ata_bio()");
  740         }
  741 }
  742 
  743 void
  744 wddone(void *v)
  745 {
  746         struct wd_softc *wd = v;
  747         struct buf *bp = wd->sc_bp;
  748         const char *errmsg;
  749         int do_perror = 0;
  750         WDCDEBUG_PRINT(("wddone %s\n", wd->sc_dev.dv_xname),
  751             DEBUG_XFERS);
  752         int nblks;
  753 
  754         if (bp == NULL)
  755                 return;
  756         bp->b_resid = wd->sc_wdc_bio.bcount;
  757         switch (wd->sc_wdc_bio.error) {
  758         case ERR_DMA:
  759                 errmsg = "DMA error";
  760                 goto retry;
  761         case ERR_DF:
  762                 errmsg = "device fault";
  763                 goto retry;
  764         case TIMEOUT:
  765                 errmsg = "device timeout";
  766                 goto retry;
  767         case ERR_RESET:
  768                 errmsg = "channel reset";
  769                 goto retry2;
  770         case ERROR:
  771                 /* Don't care about media change bits */
  772                 if (wd->sc_wdc_bio.r_error != 0 &&
  773                     (wd->sc_wdc_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0)
  774                         goto noerror;
  775                 errmsg = "error";
  776                 do_perror = 1;
  777                 if (wd->sc_wdc_bio.r_error & WDCE_IDNF &&
  778                     (wd->sc_quirks & WD_QUIRK_FORCE_LBA48) == 0) {
  779                         nblks = wd->sc_wdc_bio.bcount /
  780                             wd->sc_dk.dk_label->d_secsize;
  781                         /*
  782                          * If we get a "id not found" when crossing the
  783                          * LBA48_THRESHOLD, and the drive is larger than
  784                          * 128GB, then we can assume the drive has the
  785                          * LBA48 bug and we switch to LBA48.
  786                          */
  787                         if (wd->sc_wdc_bio.blkno <= LBA48_THRESHOLD &&
  788                             wd->sc_wdc_bio.blkno + nblks > LBA48_THRESHOLD &&
  789                             wd->sc_capacity > LBA48_THRESHOLD + 1) {
  790                                 errmsg = "LBA48 bug";
  791                                 wd->sc_quirks |= WD_QUIRK_FORCE_LBA48;
  792                                 do_perror = 0;
  793                                 goto retry2;
  794                         }
  795                 }
  796 retry:          /* Just reset and retry. Can we do more ? */
  797                 wd->atabus->ata_reset_channel(wd->drvp, AT_RST_NOCMD);
  798 retry2:
  799                 diskerr(bp, "wd", errmsg, LOG_PRINTF,
  800                     wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label);
  801                 if (wd->retries < WDIORETRIES)
  802                         printf(", retrying");
  803                 printf("\n");
  804                 if (do_perror)
  805                         wdperror(wd);
  806                 if (wd->retries < WDIORETRIES) {
  807                         wd->retries++;
  808                         callout_reset(&wd->sc_restart_ch, RECOVERYTIME,
  809                             wdrestart, wd);
  810                         return;
  811                 }
  812 
  813                 /*
  814                  * Not all errors indicate a failed block but those that do,
  815                  * put the block on the bad-block list for the device.  Only
  816                  * do this for reads because the drive should do it for writes,
  817                  * itself, according to Manuel.
  818                  */
  819                 if ((bp->b_flags & B_READ) &&
  820                     ((wd->drvp->ata_vers >= 4 && wd->sc_wdc_bio.r_error & 64) ||
  821                      (wd->drvp->ata_vers < 4 && wd->sc_wdc_bio.r_error & 192))) {
  822                         struct disk_badsectors *dbs;
  823 
  824                         dbs = malloc(sizeof *dbs, M_TEMP, M_WAITOK);
  825                         dbs->dbs_min = bp->b_rawblkno;
  826                         dbs->dbs_max = dbs->dbs_min + (bp->b_bcount >> DEV_BSHIFT) - 1;
  827                         microtime(&dbs->dbs_failedat);
  828                         SLIST_INSERT_HEAD(&wd->sc_bslist, dbs, dbs_next);
  829                         wd->sc_bscount++;
  830                 }
  831 
  832                 bp->b_flags |= B_ERROR;
  833                 bp->b_error = EIO;
  834                 break;
  835         case NOERROR:
  836 noerror:        if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0)
  837                         printf("%s: soft error (corrected)\n",
  838                             wd->sc_dev.dv_xname);
  839                 break;
  840         case ERR_NODEV:
  841                 bp->b_flags |= B_ERROR;
  842                 bp->b_error = EIO;
  843                 break;
  844         }
  845         disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid),
  846             (bp->b_flags & B_READ));
  847 #if NRND > 0
  848         rnd_add_uint32(&wd->rnd_source, bp->b_blkno);
  849 #endif
  850         /* XXX Yuck, but we don't want to increment openings in this case */
  851         if (__predict_false((bp->b_flags & B_CALL) != 0 &&
  852                             bp->b_iodone == wd_split_mod15_write))
  853                 biodone(bp);
  854         else {
  855                 biodone(bp);
  856                 wd->openings++;
  857         }
  858         wdstart(wd);
  859 }
  860 
  861 void
  862 wdrestart(void *v)
  863 {
  864         struct wd_softc *wd = v;
  865         struct buf *bp = wd->sc_bp;
  866         int s;
  867         WDCDEBUG_PRINT(("wdrestart %s\n", wd->sc_dev.dv_xname),
  868             DEBUG_XFERS);
  869 
  870         s = splbio();
  871         __wdstart(v, bp);
  872         splx(s);
  873 }
  874 
  875 int
  876 wdread(dev_t dev, struct uio *uio, int flags)
  877 {
  878 
  879         WDCDEBUG_PRINT(("wdread\n"), DEBUG_XFERS);
  880         return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
  881 }
  882 
  883 int
  884 wdwrite(dev_t dev, struct uio *uio, int flags)
  885 {
  886 
  887         WDCDEBUG_PRINT(("wdwrite\n"), DEBUG_XFERS);
  888         return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
  889 }
  890 
  891 int
  892 wdopen(dev_t dev, int flag, int fmt, struct proc *p)
  893 {
  894         struct wd_softc *wd;
  895         int part, error;
  896 
  897         WDCDEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS);
  898         wd = device_lookup(&wd_cd, WDUNIT(dev));
  899         if (wd == NULL)
  900                 return (ENXIO);
  901 
  902         if ((wd->sc_dev.dv_flags & DVF_ACTIVE) == 0)
  903                 return (ENODEV);
  904 
  905         /*
  906          * If this is the first open of this device, add a reference
  907          * to the adapter.
  908          */
  909         if (wd->sc_dk.dk_openmask == 0 &&
  910             (error = wd->atabus->ata_addref(wd->drvp)) != 0)
  911                 return (error);
  912 
  913         if ((error = lockmgr(&wd->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
  914                 goto bad4;
  915 
  916         if (wd->sc_dk.dk_openmask != 0) {
  917                 /*
  918                  * If any partition is open, but the disk has been invalidated,
  919                  * disallow further opens.
  920                  */
  921                 if ((wd->sc_flags & WDF_LOADED) == 0) {
  922                         error = EIO;
  923                         goto bad3;
  924                 }
  925         } else {
  926                 if ((wd->sc_flags & WDF_LOADED) == 0) {
  927                         wd->sc_flags |= WDF_LOADED;
  928 
  929                         /* Load the physical device parameters. */
  930                         wd_get_params(wd, AT_WAIT, &wd->sc_params);
  931 
  932                         /* Load the partition info if not already loaded. */
  933                         wdgetdisklabel(wd);
  934                 }
  935         }
  936 
  937         part = WDPART(dev);
  938 
  939         /* Check that the partition exists. */
  940         if (part != RAW_PART &&
  941             (part >= wd->sc_dk.dk_label->d_npartitions ||
  942              wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
  943                 error = ENXIO;
  944                 goto bad;
  945         }
  946 
  947         /* Insure only one open at a time. */
  948         switch (fmt) {
  949         case S_IFCHR:
  950                 wd->sc_dk.dk_copenmask |= (1 << part);
  951                 break;
  952         case S_IFBLK:
  953                 wd->sc_dk.dk_bopenmask |= (1 << part);
  954                 break;
  955         }
  956         wd->sc_dk.dk_openmask =
  957             wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
  958 
  959         lockmgr(&wd->sc_lock, LK_RELEASE, NULL);
  960         return 0;
  961 
  962 bad:
  963         if (wd->sc_dk.dk_openmask == 0) {
  964         }
  965 
  966 bad3:
  967         lockmgr(&wd->sc_lock, LK_RELEASE, NULL);
  968 bad4:
  969         if (wd->sc_dk.dk_openmask == 0)
  970                 wd->atabus->ata_delref(wd->drvp);
  971         return error;
  972 }
  973 
  974 int
  975 wdclose(dev_t dev, int flag, int fmt, struct proc *p)
  976 {
  977         struct wd_softc *wd = device_lookup(&wd_cd, WDUNIT(dev));
  978         int part = WDPART(dev);
  979         int error;
  980 
  981         WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS);
  982         if ((error = lockmgr(&wd->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
  983                 return error;
  984 
  985         switch (fmt) {
  986         case S_IFCHR:
  987                 wd->sc_dk.dk_copenmask &= ~(1 << part);
  988                 break;
  989         case S_IFBLK:
  990                 wd->sc_dk.dk_bopenmask &= ~(1 << part);
  991                 break;
  992         }
  993         wd->sc_dk.dk_openmask =
  994             wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
  995 
  996         if (wd->sc_dk.dk_openmask == 0) {
  997                 wd_flushcache(wd, AT_WAIT);
  998                 /* XXXX Must wait for I/O to complete! */
  999 
 1000                 if (! (wd->sc_flags & WDF_KLABEL))
 1001                         wd->sc_flags &= ~WDF_LOADED;
 1002 
 1003                 wd->atabus->ata_delref(wd->drvp);
 1004         }
 1005 
 1006         lockmgr(&wd->sc_lock, LK_RELEASE, NULL);
 1007         return 0;
 1008 }
 1009 
 1010 void
 1011 wdgetdefaultlabel(struct wd_softc *wd, struct disklabel *lp)
 1012 {
 1013 
 1014         WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS);
 1015         memset(lp, 0, sizeof(struct disklabel));
 1016 
 1017         lp->d_secsize = DEV_BSIZE;
 1018         lp->d_ntracks = wd->sc_params.atap_heads;
 1019         lp->d_nsectors = wd->sc_params.atap_sectors;
 1020         lp->d_ncylinders = (wd->sc_flags & WDF_LBA) ? wd->sc_capacity /
 1021                 (wd->sc_params.atap_heads * wd->sc_params.atap_sectors) :
 1022                 wd->sc_params.atap_cylinders;
 1023         lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
 1024 
 1025         if (strcmp(wd->sc_params.atap_model, "ST506") == 0)
 1026                 lp->d_type = DTYPE_ST506;
 1027         else
 1028                 lp->d_type = DTYPE_ESDI;
 1029 
 1030         strncpy(lp->d_typename, wd->sc_params.atap_model, 16);
 1031         strncpy(lp->d_packname, "fictitious", 16);
 1032         if (wd->sc_capacity > UINT32_MAX)
 1033                 lp->d_secperunit = UINT32_MAX;
 1034         else
 1035                 lp->d_secperunit = wd->sc_capacity;
 1036         lp->d_rpm = 3600;
 1037         lp->d_interleave = 1;
 1038         lp->d_flags = 0;
 1039 
 1040         lp->d_partitions[RAW_PART].p_offset = 0;
 1041         lp->d_partitions[RAW_PART].p_size =
 1042             lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
 1043         lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
 1044         lp->d_npartitions = RAW_PART + 1;
 1045 
 1046         lp->d_magic = DISKMAGIC;
 1047         lp->d_magic2 = DISKMAGIC;
 1048         lp->d_checksum = dkcksum(lp);
 1049 }
 1050 
 1051 /*
 1052  * Fabricate a default disk label, and try to read the correct one.
 1053  */
 1054 void
 1055 wdgetdisklabel(struct wd_softc *wd)
 1056 {
 1057         struct disklabel *lp = wd->sc_dk.dk_label;
 1058         const char *errstring;
 1059 
 1060         WDCDEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS);
 1061 
 1062         memset(wd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
 1063 
 1064         wdgetdefaultlabel(wd, lp);
 1065 
 1066         wd->sc_badsect[0] = -1;
 1067 
 1068         if (wd->drvp->state > RESET)
 1069                 wd->drvp->drive_flags |= DRIVE_RESET;
 1070         errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
 1071             wdstrategy, lp, wd->sc_dk.dk_cpulabel);
 1072         if (errstring) {
 1073                 /*
 1074                  * This probably happened because the drive's default
 1075                  * geometry doesn't match the DOS geometry.  We
 1076                  * assume the DOS geometry is now in the label and try
 1077                  * again.  XXX This is a kluge.
 1078                  */
 1079                 if (wd->drvp->state > RESET)
 1080                         wd->drvp->drive_flags |= DRIVE_RESET;
 1081                 errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit,
 1082                     RAW_PART), wdstrategy, lp, wd->sc_dk.dk_cpulabel);
 1083         }
 1084         if (errstring) {
 1085                 printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);
 1086                 return;
 1087         }
 1088 
 1089         if (wd->drvp->state > RESET)
 1090                 wd->drvp->drive_flags |= DRIVE_RESET;
 1091 #ifdef HAS_BAD144_HANDLING
 1092         if ((lp->d_flags & D_BADSECT) != 0)
 1093                 bad144intern(wd);
 1094 #endif
 1095 }
 1096 
 1097 void
 1098 wdperror(const struct wd_softc *wd)
 1099 {
 1100         static const char *const errstr0_3[] = {"address mark not found",
 1101             "track 0 not found", "aborted command", "media change requested",
 1102             "id not found", "media changed", "uncorrectable data error",
 1103             "bad block detected"};
 1104         static const char *const errstr4_5[] = {
 1105             "obsolete (address mark not found)",
 1106             "no media/write protected", "aborted command",
 1107             "media change requested", "id not found", "media changed",
 1108             "uncorrectable data error", "interface CRC error"};
 1109         const char *const *errstr;
 1110         int i;
 1111         char *sep = "";
 1112 
 1113         const char *devname = wd->sc_dev.dv_xname;
 1114         struct ata_drive_datas *drvp = wd->drvp;
 1115         int errno = wd->sc_wdc_bio.r_error;
 1116 
 1117         if (drvp->ata_vers >= 4)
 1118                 errstr = errstr4_5;
 1119         else
 1120                 errstr = errstr0_3;
 1121 
 1122         printf("%s: (", devname);
 1123 
 1124         if (errno == 0)
 1125                 printf("error not notified");
 1126 
 1127         for (i = 0; i < 8; i++) {
 1128                 if (errno & (1 << i)) {
 1129                         printf("%s%s", sep, errstr[i]);
 1130                         sep = ", ";
 1131                 }
 1132         }
 1133         printf(")\n");
 1134 }
 1135 
 1136 int
 1137 wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p)
 1138 {
 1139         struct wd_softc *wd = device_lookup(&wd_cd, WDUNIT(dev));
 1140         int error = 0;
 1141 #ifdef __HAVE_OLD_DISKLABEL
 1142         struct disklabel *newlabel = NULL;
 1143 #endif
 1144 
 1145         WDCDEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS);
 1146 
 1147         if ((wd->sc_flags & WDF_LOADED) == 0)
 1148                 return EIO;
 1149 
 1150         switch (xfer) {
 1151 #ifdef HAS_BAD144_HANDLING
 1152         case DIOCSBAD:
 1153                 if ((flag & FWRITE) == 0)
 1154                         return EBADF;
 1155                 wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
 1156                 wd->sc_dk.dk_label->d_flags |= D_BADSECT;
 1157                 bad144intern(wd);
 1158                 return 0;
 1159 #endif
 1160 
 1161         case DIOCBSLIST :
 1162         {
 1163                 u_int32_t count, missing, skip;
 1164                 struct disk_badsecinfo dbsi;
 1165                 struct disk_badsectors *dbs;
 1166                 size_t available;
 1167                 caddr_t laddr;
 1168 
 1169                 dbsi = *(struct disk_badsecinfo *)addr;
 1170                 missing = wd->sc_bscount;
 1171                 count = 0;
 1172                 available = dbsi.dbsi_bufsize;
 1173                 skip = dbsi.dbsi_skip;
 1174                 laddr = dbsi.dbsi_buffer;
 1175 
 1176                 /*
 1177                  * We start this loop with the expectation that all of the
 1178                  * entries will be missed and decrement this counter each
 1179                  * time we either skip over one (already copied out) or
 1180                  * we actually copy it back to user space.  The structs
 1181                  * holding the bad sector information are copied directly
 1182                  * back to user space whilst the summary is returned via
 1183                  * the struct passed in via the ioctl.
 1184                  */
 1185                 SLIST_FOREACH(dbs, &wd->sc_bslist, dbs_next) {
 1186                         if (skip > 0) {
 1187                                 missing--;
 1188                                 skip--;
 1189                                 continue;
 1190                         }
 1191                         if (available < sizeof(*dbs))
 1192                                 break;
 1193                         available -= sizeof(*dbs);
 1194                         copyout(dbs, laddr, sizeof(*dbs));
 1195                         laddr += sizeof(*dbs);
 1196                         missing--;
 1197                         count++;
 1198                 }
 1199                 dbsi.dbsi_left = missing;
 1200                 dbsi.dbsi_copied = count;
 1201                 *(struct disk_badsecinfo *)addr = dbsi;
 1202                 return 0;
 1203         }
 1204 
 1205         case DIOCBSFLUSH :
 1206                 /* Clean out the bad sector list */
 1207                 while (!SLIST_EMPTY(&wd->sc_bslist)) {
 1208                         void *head = SLIST_FIRST(&wd->sc_bslist);
 1209                         SLIST_REMOVE_HEAD(&wd->sc_bslist, dbs_next);
 1210                         free(head, M_TEMP);
 1211                 }
 1212                 wd->sc_bscount = 0;
 1213                 return 0;
 1214 
 1215         case DIOCGDINFO:
 1216                 *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
 1217                 return 0;
 1218 #ifdef __HAVE_OLD_DISKLABEL
 1219         case ODIOCGDINFO:
 1220                 newlabel = malloc(sizeof *newlabel, M_TEMP, M_WAITOK);
 1221                 if (newlabel == NULL)
 1222                         return EIO;
 1223                 *newlabel = *(wd->sc_dk.dk_label);
 1224                 if (newlabel->d_npartitions <= OLDMAXPARTITIONS)
 1225                         memcpy(addr, newlabel, sizeof (struct olddisklabel));
 1226                 else
 1227                         error = ENOTTY;
 1228                 free(newlabel, M_TEMP);
 1229                 return error;
 1230 #endif
 1231 
 1232         case DIOCGPART:
 1233                 ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
 1234                 ((struct partinfo *)addr)->part =
 1235                     &wd->sc_dk.dk_label->d_partitions[WDPART(dev)];
 1236                 return 0;
 1237 
 1238         case DIOCWDINFO:
 1239         case DIOCSDINFO:
 1240 #ifdef __HAVE_OLD_DISKLABEL
 1241         case ODIOCWDINFO:
 1242         case ODIOCSDINFO:
 1243 #endif
 1244         {
 1245                 struct disklabel *lp;
 1246 
 1247                 if ((flag & FWRITE) == 0)
 1248                         return EBADF;
 1249 
 1250 #ifdef __HAVE_OLD_DISKLABEL
 1251                 if (xfer == ODIOCSDINFO || xfer == ODIOCWDINFO) {
 1252                         newlabel = malloc(sizeof *newlabel, M_TEMP, M_WAITOK);
 1253                         if (newlabel == NULL)
 1254                                 return EIO;
 1255                         memset(newlabel, 0, sizeof newlabel);
 1256                         memcpy(newlabel, addr, sizeof (struct olddisklabel));
 1257                         lp = newlabel;
 1258                 } else
 1259 #endif
 1260                 lp = (struct disklabel *)addr;
 1261 
 1262                 if ((error = lockmgr(&wd->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
 1263                         goto bad;
 1264                 wd->sc_flags |= WDF_LABELLING;
 1265 
 1266                 error = setdisklabel(wd->sc_dk.dk_label,
 1267                     lp, /*wd->sc_dk.dk_openmask : */0,
 1268                     wd->sc_dk.dk_cpulabel);
 1269                 if (error == 0) {
 1270                         if (wd->drvp->state > RESET)
 1271                                 wd->drvp->drive_flags |= DRIVE_RESET;
 1272                         if (xfer == DIOCWDINFO
 1273 #ifdef __HAVE_OLD_DISKLABEL
 1274                             || xfer == ODIOCWDINFO
 1275 #endif
 1276                             )
 1277                                 error = writedisklabel(WDLABELDEV(dev),
 1278                                     wdstrategy, wd->sc_dk.dk_label,
 1279                                     wd->sc_dk.dk_cpulabel);
 1280                 }
 1281 
 1282                 wd->sc_flags &= ~WDF_LABELLING;
 1283                 lockmgr(&wd->sc_lock, LK_RELEASE, NULL);
 1284 bad:
 1285 #ifdef __HAVE_OLD_DISKLABEL
 1286                 if (newlabel != NULL)
 1287                         free(newlabel, M_TEMP);
 1288 #endif
 1289                 return error;
 1290         }
 1291 
 1292         case DIOCKLABEL:
 1293                 if (*(int *)addr)
 1294                         wd->sc_flags |= WDF_KLABEL;
 1295                 else
 1296                         wd->sc_flags &= ~WDF_KLABEL;
 1297                 return 0;
 1298 
 1299         case DIOCWLABEL:
 1300                 if ((flag & FWRITE) == 0)
 1301                         return EBADF;
 1302                 if (*(int *)addr)
 1303                         wd->sc_flags |= WDF_WLABEL;
 1304                 else
 1305                         wd->sc_flags &= ~WDF_WLABEL;
 1306                 return 0;
 1307 
 1308         case DIOCGDEFLABEL:
 1309                 wdgetdefaultlabel(wd, (struct disklabel *)addr);
 1310                 return 0;
 1311 #ifdef __HAVE_OLD_DISKLABEL
 1312         case ODIOCGDEFLABEL:
 1313                 newlabel = malloc(sizeof *newlabel, M_TEMP, M_WAITOK);
 1314                 if (newlabel == NULL)
 1315                         return EIO;
 1316                 wdgetdefaultlabel(wd, newlabel);
 1317                 if (newlabel->d_npartitions <= OLDMAXPARTITIONS)
 1318                         memcpy(addr, &newlabel, sizeof (struct olddisklabel));
 1319                 else
 1320                         error = ENOTTY;
 1321                 free(newlabel, M_TEMP);
 1322                 return error;
 1323 #endif
 1324 
 1325 #ifdef notyet
 1326         case DIOCWFORMAT:
 1327                 if ((flag & FWRITE) == 0)
 1328                         return EBADF;
 1329                 {
 1330                 register struct format_op *fop;
 1331                 struct iovec aiov;
 1332                 struct uio auio;
 1333 
 1334                 fop = (struct format_op *)addr;
 1335                 aiov.iov_base = fop->df_buf;
 1336                 aiov.iov_len = fop->df_count;
 1337                 auio.uio_iov = &aiov;
 1338                 auio.uio_iovcnt = 1;
 1339                 auio.uio_resid = fop->df_count;
 1340                 auio.uio_segflg = 0;
 1341                 auio.uio_offset =
 1342                         fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
 1343                 auio.uio_procp = p;
 1344                 error = physio(wdformat, NULL, dev, B_WRITE, minphys,
 1345                     &auio);
 1346                 fop->df_count -= auio.uio_resid;
 1347                 fop->df_reg[0] = wdc->sc_status;
 1348                 fop->df_reg[1] = wdc->sc_error;
 1349                 return error;
 1350                 }
 1351 #endif
 1352         case DIOCGCACHE:
 1353                 return wd_getcache(wd, (int *)addr);
 1354 
 1355         case DIOCSCACHE:
 1356                 return wd_setcache(wd, *(int *)addr);
 1357 
 1358         case DIOCCACHESYNC:
 1359                 return wd_flushcache(wd, AT_WAIT);
 1360 
 1361         case ATAIOCCOMMAND:
 1362                 /*
 1363                  * Make sure this command is (relatively) safe first
 1364                  */
 1365                 if ((((atareq_t *) addr)->flags & ATACMD_READ) == 0 &&
 1366                     (flag & FWRITE) == 0)
 1367                         return (EBADF);
 1368                 {
 1369                 struct wd_ioctl *wi;
 1370                 atareq_t *atareq = (atareq_t *) addr;
 1371                 int error;
 1372 
 1373                 wi = wi_get();
 1374                 wi->wi_softc = wd;
 1375                 wi->wi_atareq = *atareq;
 1376 
 1377                 if (atareq->datalen && atareq->flags &
 1378                     (ATACMD_READ | ATACMD_WRITE)) {
 1379                         wi->wi_iov.iov_base = atareq->databuf;
 1380                         wi->wi_iov.iov_len = atareq->datalen;
 1381                         wi->wi_uio.uio_iov = &wi->wi_iov;
 1382                         wi->wi_uio.uio_iovcnt = 1;
 1383                         wi->wi_uio.uio_resid = atareq->datalen;
 1384                         wi->wi_uio.uio_offset = 0;
 1385                         wi->wi_uio.uio_segflg = UIO_USERSPACE;
 1386                         wi->wi_uio.uio_rw =
 1387                             (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE;
 1388                         wi->wi_uio.uio_procp = p;
 1389                         error = physio(wdioctlstrategy, &wi->wi_bp, dev,
 1390                             (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE,
 1391                             minphys, &wi->wi_uio);
 1392                 } else {
 1393                         /* No need to call physio if we don't have any
 1394                            user data */
 1395                         wi->wi_bp.b_flags = 0;
 1396                         wi->wi_bp.b_data = 0;
 1397                         wi->wi_bp.b_bcount = 0;
 1398                         wi->wi_bp.b_dev = 0;
 1399                         wi->wi_bp.b_proc = p;
 1400                         wdioctlstrategy(&wi->wi_bp);
 1401                         error = wi->wi_bp.b_error;
 1402                 }
 1403                 *atareq = wi->wi_atareq;
 1404                 wi_free(wi);
 1405                 return(error);
 1406                 }
 1407 
 1408         default:
 1409                 return ENOTTY;
 1410         }
 1411 
 1412 #ifdef DIAGNOSTIC
 1413         panic("wdioctl: impossible");
 1414 #endif
 1415 }
 1416 
 1417 #ifdef B_FORMAT
 1418 int
 1419 wdformat(struct buf *bp)
 1420 {
 1421 
 1422         bp->b_flags |= B_FORMAT;
 1423         return wdstrategy(bp);
 1424 }
 1425 #endif
 1426 
 1427 int
 1428 wdsize(dev_t dev)
 1429 {
 1430         struct wd_softc *wd;
 1431         int part, omask;
 1432         int size;
 1433 
 1434         WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS);
 1435 
 1436         wd = device_lookup(&wd_cd, WDUNIT(dev));
 1437         if (wd == NULL)
 1438                 return (-1);
 1439 
 1440         part = WDPART(dev);
 1441         omask = wd->sc_dk.dk_openmask & (1 << part);
 1442 
 1443         if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0)
 1444                 return (-1);
 1445         if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
 1446                 size = -1;
 1447         else
 1448                 size = wd->sc_dk.dk_label->d_partitions[part].p_size *
 1449                     (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
 1450         if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0)
 1451                 return (-1);
 1452         return (size);
 1453 }
 1454 
 1455 /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
 1456 static int wddoingadump = 0;
 1457 static int wddumprecalibrated = 0;
 1458 static int wddumpmulti = 1;
 1459 
 1460 /*
 1461  * Dump core after a system crash.
 1462  */
 1463 int
 1464 wddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
 1465 {
 1466         struct wd_softc *wd;    /* disk unit to do the I/O */
 1467         struct disklabel *lp;   /* disk's disklabel */
 1468         int part, err;
 1469         int nblks;      /* total number of sectors left to write */
 1470 
 1471         /* Check if recursive dump; if so, punt. */
 1472         if (wddoingadump)
 1473                 return EFAULT;
 1474         wddoingadump = 1;
 1475 
 1476         wd = device_lookup(&wd_cd, WDUNIT(dev));
 1477         if (wd == NULL)
 1478                 return (ENXIO);
 1479 
 1480         part = WDPART(dev);
 1481 
 1482         /* Convert to disk sectors.  Request must be a multiple of size. */
 1483         lp = wd->sc_dk.dk_label;
 1484         if ((size % lp->d_secsize) != 0)
 1485                 return EFAULT;
 1486         nblks = size / lp->d_secsize;
 1487         blkno = blkno / (lp->d_secsize / DEV_BSIZE);
 1488 
 1489         /* Check transfer bounds against partition size. */
 1490         if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
 1491                 return EINVAL;
 1492 
 1493         /* Offset block number to start of partition. */
 1494         blkno += lp->d_partitions[part].p_offset;
 1495 
 1496         /* Recalibrate, if first dump transfer. */
 1497         if (wddumprecalibrated == 0) {
 1498                 wddumpmulti = wd->sc_multi;
 1499                 wddumprecalibrated = 1;
 1500                 wd->atabus->ata_reset_channel(wd->drvp, AT_POLL | AT_RST_EMERG);
 1501                 wd->drvp->state = RESET;
 1502         }
 1503 
 1504         while (nblks > 0) {
 1505                 wd->sc_bp = NULL;
 1506                 wd->sc_wdc_bio.blkno = blkno;
 1507                 wd->sc_wdc_bio.flags = ATA_POLL;
 1508                 if (wd->sc_flags & WDF_LBA48 &&
 1509                     (blkno > LBA48_THRESHOLD ||
 1510                     (wd->sc_quirks & WD_QUIRK_FORCE_LBA48) != 0))
 1511                         wd->sc_wdc_bio.flags |= ATA_LBA48;
 1512                 if (wd->sc_flags & WDF_LBA)
 1513                         wd->sc_wdc_bio.flags |= ATA_LBA;
 1514                 wd->sc_wdc_bio.bcount =
 1515                         min(nblks, wddumpmulti) * lp->d_secsize;
 1516                 wd->sc_wdc_bio.databuf = va;
 1517 #ifndef WD_DUMP_NOT_TRUSTED
 1518                 switch (wd->atabus->ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
 1519                 case WDC_TRY_AGAIN:
 1520                         panic("wddump: try again");
 1521                         break;
 1522                 case WDC_QUEUED:
 1523                         panic("wddump: polled command has been queued");
 1524                         break;
 1525                 case WDC_COMPLETE:
 1526                         break;
 1527                 }
 1528                 switch(wd->sc_wdc_bio.error) {
 1529                 case TIMEOUT:
 1530                         printf("wddump: device timed out");
 1531                         err = EIO;
 1532                         break;
 1533                 case ERR_DF:
 1534                         printf("wddump: drive fault");
 1535                         err = EIO;
 1536                         break;
 1537                 case ERR_DMA:
 1538                         printf("wddump: DMA error");
 1539                         err = EIO;
 1540                         break;
 1541                 case ERROR:
 1542                         printf("wddump: ");
 1543                         wdperror(wd);
 1544                         err = EIO;
 1545                         break;
 1546                 case NOERROR:
 1547                         err = 0;
 1548                         break;
 1549                 default:
 1550                         panic("wddump: unknown error type");
 1551                 }
 1552                 if (err != 0) {
 1553                         printf("\n");
 1554                         return err;
 1555                 }
 1556 #else   /* WD_DUMP_NOT_TRUSTED */
 1557                 /* Let's just talk about this first... */
 1558                 printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
 1559                     unit, va, cylin, head, sector);
 1560                 delay(500 * 1000);      /* half a second */
 1561 #endif
 1562 
 1563                 /* update block count */
 1564                 nblks -= min(nblks, wddumpmulti);
 1565                 blkno += min(nblks, wddumpmulti);
 1566                 va += min(nblks, wddumpmulti) * lp->d_secsize;
 1567         }
 1568 
 1569         wddoingadump = 0;
 1570         return 0;
 1571 }
 1572 
 1573 #ifdef HAS_BAD144_HANDLING
 1574 /*
 1575  * Internalize the bad sector table.
 1576  */
 1577 void
 1578 bad144intern(struct wd_softc *wd)
 1579 {
 1580         struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
 1581         struct disklabel *lp = wd->sc_dk.dk_label;
 1582         int i = 0;
 1583 
 1584         WDCDEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS);
 1585 
 1586         for (; i < NBT_BAD; i++) {
 1587                 if (bt->bt_bad[i].bt_cyl == 0xffff)
 1588                         break;
 1589                 wd->sc_badsect[i] =
 1590                     bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
 1591                     (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
 1592                     (bt->bt_bad[i].bt_trksec & 0xff);
 1593         }
 1594         for (; i < NBT_BAD+1; i++)
 1595                 wd->sc_badsect[i] = -1;
 1596 }
 1597 #endif
 1598 
 1599 int
 1600 wd_get_params(struct wd_softc *wd, u_int8_t flags, struct ataparams *params)
 1601 {
 1602         switch (wd->atabus->ata_get_params(wd->drvp, flags, params)) {
 1603         case CMD_AGAIN:
 1604                 return 1;
 1605         case CMD_ERR:
 1606                 /*
 1607                  * We `know' there's a drive here; just assume it's old.
 1608                  * This geometry is only used to read the MBR and print a
 1609                  * (false) attach message.
 1610                  */
 1611                 strncpy(params->atap_model, "ST506",
 1612                     sizeof params->atap_model);
 1613                 params->atap_config = ATA_CFG_FIXED;
 1614                 params->atap_cylinders = 1024;
 1615                 params->atap_heads = 8;
 1616                 params->atap_sectors = 17;
 1617                 params->atap_multi = 1;
 1618                 params->atap_capabilities1 = params->atap_capabilities2 = 0;
 1619                 wd->drvp->ata_vers = -1; /* Mark it as pre-ATA */
 1620                 return 0;
 1621         case CMD_OK:
 1622                 return 0;
 1623         default:
 1624                 panic("wd_get_params: bad return code from ata_get_params");
 1625                 /* NOTREACHED */
 1626         }
 1627 }
 1628 
 1629 int
 1630 wd_getcache(struct wd_softc *wd, int *bitsp)
 1631 {
 1632         struct ataparams params;
 1633 
 1634         if (wd_get_params(wd, AT_WAIT, &params) != 0)
 1635                 return EIO;
 1636         if (params.atap_cmd_set1 == 0x0000 ||
 1637             params.atap_cmd_set1 == 0xffff ||
 1638             (params.atap_cmd_set1 & WDC_CMD1_CACHE) == 0) {
 1639                 *bitsp = 0;
 1640                 return 0;
 1641         }
 1642         *bitsp = DKCACHE_WCHANGE | DKCACHE_READ;
 1643         if (params.atap_cmd1_en & WDC_CMD1_CACHE)
 1644                 *bitsp |= DKCACHE_WRITE;
 1645 
 1646         return 0;
 1647 }
 1648 
 1649 int
 1650 wd_setcache(struct wd_softc *wd, int bits)
 1651 {
 1652         struct ataparams params;
 1653         struct wdc_command wdc_c;
 1654 
 1655         if (wd_get_params(wd, AT_WAIT, &params) != 0)
 1656                 return EIO;
 1657 
 1658         if (params.atap_cmd_set1 == 0x0000 ||
 1659             params.atap_cmd_set1 == 0xffff ||
 1660             (params.atap_cmd_set1 & WDC_CMD1_CACHE) == 0)
 1661                 return EOPNOTSUPP;
 1662 
 1663         if ((bits & DKCACHE_READ) == 0 ||
 1664             (bits & DKCACHE_SAVE) != 0)
 1665                 return EOPNOTSUPP;
 1666 
 1667         memset(&wdc_c, 0, sizeof(struct wdc_command));
 1668         wdc_c.r_command = SET_FEATURES;
 1669         wdc_c.r_st_bmask = 0;
 1670         wdc_c.r_st_pmask = 0;
 1671         wdc_c.timeout = 30000; /* 30s timeout */
 1672         wdc_c.flags = AT_WAIT;
 1673         if (bits & DKCACHE_WRITE)
 1674                 wdc_c.r_precomp = WDSF_WRITE_CACHE_EN;
 1675         else
 1676                 wdc_c.r_precomp = WDSF_WRITE_CACHE_DS;
 1677         if (wd->atabus->ata_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) {
 1678                 printf("%s: wd_setcache command not complete\n",
 1679                     wd->sc_dev.dv_xname);
 1680                 return EIO;
 1681         }
 1682         if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
 1683                 printf("%s: wd_setcache command error 0x%x\n",
 1684                     wd->sc_dev.dv_xname, wdc_c.flags);
 1685                 return EIO;
 1686         }
 1687         if (wdc_c.flags & ERR_NODEV)
 1688                 return ENODEV;
 1689         return 0;
 1690 }
 1691 
 1692 int
 1693 wd_flushcache(struct wd_softc *wd, int flags)
 1694 {
 1695         struct wdc_command wdc_c;
 1696 
 1697         if (wd->drvp->ata_vers < 4) /* WDCC_FLUSHCACHE is here since ATA-4 */
 1698                 return ENODEV;
 1699         memset(&wdc_c, 0, sizeof(struct wdc_command));
 1700         if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0 &&
 1701             (wd->sc_params.atap_cmd2_en & ATA_CMD2_FCE) != 0)
 1702                 wdc_c.r_command = WDCC_FLUSHCACHE_EXT;
 1703         else
 1704                 wdc_c.r_command = WDCC_FLUSHCACHE;
 1705         wdc_c.r_st_bmask = WDCS_DRDY;
 1706         wdc_c.r_st_pmask = WDCS_DRDY;
 1707         wdc_c.flags = flags;
 1708         wdc_c.timeout = 30000; /* 30s timeout */
 1709         if (wd->atabus->ata_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) {
 1710                 printf("%s: flush cache command didn't complete\n",
 1711                     wd->sc_dev.dv_xname);
 1712                 return EIO;
 1713         }
 1714         if (wdc_c.flags & ERR_NODEV)
 1715                 return ENODEV;
 1716         if (wdc_c.flags & AT_TIMEOU) {
 1717                 printf("%s: flush cache command timeout\n",
 1718                     wd->sc_dev.dv_xname);
 1719                 return EIO;
 1720         }
 1721         if (wdc_c.flags & AT_ERROR) {
 1722                 if (wdc_c.r_error == WDCE_ABRT) /* command not supported */
 1723                         return ENODEV;
 1724                 printf("%s: flush cache command: error 0x%x\n",
 1725                     wd->sc_dev.dv_xname, wdc_c.r_error);
 1726                 return EIO;
 1727         }
 1728         if (wdc_c.flags & AT_DF) {
 1729                 printf("%s: flush cache command: drive fault\n",
 1730                     wd->sc_dev.dv_xname);
 1731                 return EIO;
 1732         }
 1733         return 0;
 1734 }
 1735 
 1736 void
 1737 wd_shutdown(void *arg)
 1738 {
 1739         struct wd_softc *wd = arg;
 1740         wd_flushcache(wd, AT_POLL);
 1741 }
 1742 
 1743 /*
 1744  * Allocate space for a ioctl queue structure.  Mostly taken from
 1745  * scsipi_ioctl.c
 1746  */
 1747 struct wd_ioctl *
 1748 wi_get(void)
 1749 {
 1750         struct wd_ioctl *wi;
 1751         int s;
 1752 
 1753         wi = malloc(sizeof(struct wd_ioctl), M_TEMP, M_WAITOK|M_ZERO);
 1754         simple_lock_init(&wi->wi_bp.b_interlock);
 1755         s = splbio();
 1756         LIST_INSERT_HEAD(&wi_head, wi, wi_list);
 1757         splx(s);
 1758         return (wi);
 1759 }
 1760 
 1761 /*
 1762  * Free an ioctl structure and remove it from our list
 1763  */
 1764 
 1765 void
 1766 wi_free(struct wd_ioctl *wi)
 1767 {
 1768         int s;
 1769 
 1770         s = splbio();
 1771         LIST_REMOVE(wi, wi_list);
 1772         splx(s);
 1773         free(wi, M_TEMP);
 1774 }
 1775 
 1776 /*
 1777  * Find a wd_ioctl structure based on the struct buf.
 1778  */
 1779 
 1780 struct wd_ioctl *
 1781 wi_find(struct buf *bp)
 1782 {
 1783         struct wd_ioctl *wi;
 1784         int s;
 1785 
 1786         s = splbio();
 1787         for (wi = wi_head.lh_first; wi != 0; wi = wi->wi_list.le_next)
 1788                 if (bp == &wi->wi_bp)
 1789                         break;
 1790         splx(s);
 1791         return (wi);
 1792 }
 1793 
 1794 /*
 1795  * Ioctl pseudo strategy routine
 1796  *
 1797  * This is mostly stolen from scsipi_ioctl.c:scsistrategy().  What
 1798  * happens here is:
 1799  *
 1800  * - wdioctl() queues a wd_ioctl structure.
 1801  *
 1802  * - wdioctl() calls physio/wdioctlstrategy based on whether or not
 1803  *   user space I/O is required.  If physio() is called, physio() eventually
 1804  *   calls wdioctlstrategy().
 1805  *
 1806  * - In either case, wdioctlstrategy() calls wd->atabus->ata_exec_command()
 1807  *   to perform the actual command
 1808  *
 1809  * The reason for the use of the pseudo strategy routine is because
 1810  * when doing I/O to/from user space, physio _really_ wants to be in
 1811  * the loop.  We could put the entire buffer into the ioctl request
 1812  * structure, but that won't scale if we want to do things like download
 1813  * microcode.
 1814  */
 1815 
 1816 void
 1817 wdioctlstrategy(struct buf *bp)
 1818 {
 1819         struct wd_ioctl *wi;
 1820         struct wdc_command wdc_c;
 1821         int error = 0;
 1822 
 1823         wi = wi_find(bp);
 1824         if (wi == NULL) {
 1825                 printf("user_strat: No ioctl\n");
 1826                 error = EINVAL;
 1827                 goto bad;
 1828         }
 1829 
 1830         memset(&wdc_c, 0, sizeof(wdc_c));
 1831 
 1832         /*
 1833          * Abort if physio broke up the transfer
 1834          */
 1835 
 1836         if (bp->b_bcount != wi->wi_atareq.datalen) {
 1837                 printf("physio split wd ioctl request... cannot proceed\n");
 1838                 error = EIO;
 1839                 goto bad;
 1840         }
 1841 
 1842         /*
 1843          * Abort if we didn't get a buffer size that was a multiple of
 1844          * our sector size (or was larger than NBBY)
 1845          */
 1846 
 1847         if ((bp->b_bcount % wi->wi_softc->sc_dk.dk_label->d_secsize) != 0 ||
 1848             (bp->b_bcount / wi->wi_softc->sc_dk.dk_label->d_secsize) >=
 1849              (1 << NBBY)) {
 1850                 error = EINVAL;
 1851                 goto bad;
 1852         }
 1853 
 1854         /*
 1855          * Make sure a timeout was supplied in the ioctl request
 1856          */
 1857 
 1858         if (wi->wi_atareq.timeout == 0) {
 1859                 error = EINVAL;
 1860                 goto bad;
 1861         }
 1862 
 1863         if (wi->wi_atareq.flags & ATACMD_READ)
 1864                 wdc_c.flags |= AT_READ;
 1865         else if (wi->wi_atareq.flags & ATACMD_WRITE)
 1866                 wdc_c.flags |= AT_WRITE;
 1867 
 1868         if (wi->wi_atareq.flags & ATACMD_READREG)
 1869                 wdc_c.flags |= AT_READREG;
 1870 
 1871         wdc_c.flags |= AT_WAIT;
 1872 
 1873         wdc_c.timeout = wi->wi_atareq.timeout;
 1874         wdc_c.r_command = wi->wi_atareq.command;
 1875         wdc_c.r_head = wi->wi_atareq.head & 0x0f;
 1876         wdc_c.r_cyl = wi->wi_atareq.cylinder;
 1877         wdc_c.r_sector = wi->wi_atareq.sec_num;
 1878         wdc_c.r_count = wi->wi_atareq.sec_count;
 1879         wdc_c.r_precomp = wi->wi_atareq.features;
 1880         wdc_c.r_st_bmask = WDCS_DRDY;
 1881         wdc_c.r_st_pmask = WDCS_DRDY;
 1882         wdc_c.data = wi->wi_bp.b_data;
 1883         wdc_c.bcount = wi->wi_bp.b_bcount;
 1884 
 1885         if (wi->wi_softc->atabus->ata_exec_command(wi->wi_softc->drvp, &wdc_c)
 1886             != WDC_COMPLETE) {
 1887                 wi->wi_atareq.retsts = ATACMD_ERROR;
 1888                 goto bad;
 1889         }
 1890 
 1891         if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
 1892                 if (wdc_c.flags & AT_ERROR) {
 1893                         wi->wi_atareq.retsts = ATACMD_ERROR;
 1894                         wi->wi_atareq.error = wdc_c.r_error;
 1895                 } else if (wdc_c.flags & AT_DF)
 1896                         wi->wi_atareq.retsts = ATACMD_DF;
 1897                 else
 1898                         wi->wi_atareq.retsts = ATACMD_TIMEOUT;
 1899         } else {
 1900                 wi->wi_atareq.retsts = ATACMD_OK;
 1901                 if (wi->wi_atareq.flags & ATACMD_READREG) {
 1902                         wi->wi_atareq.head = wdc_c.r_head ;
 1903                         wi->wi_atareq.cylinder = wdc_c.r_cyl;
 1904                         wi->wi_atareq.sec_num = wdc_c.r_sector;
 1905                         wi->wi_atareq.sec_count = wdc_c.r_count;
 1906                         wi->wi_atareq.features = wdc_c.r_precomp;
 1907                         wi->wi_atareq.error = wdc_c.r_error;
 1908                 }
 1909         }
 1910 
 1911         bp->b_error = 0;
 1912         biodone(bp);
 1913         return;
 1914 bad:
 1915         bp->b_flags |= B_ERROR;
 1916         bp->b_error = error;
 1917         biodone(bp);
 1918 }

Cache object: 52145a1fc5234995cd5a7ea98649e7f6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.