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

          Line data    Source code
       1             : /*      $OpenBSD: ata_wdc.c,v 1.51 2017/12/30 20:46:59 guenther Exp $   */
       2             : /*      $NetBSD: ata_wdc.c,v 1.21 1999/08/09 09:43:11 bouyer Exp $      */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1998, 2001 Manuel Bouyer.
       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             : /*-
      30             :  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      31             :  * All rights reserved.
      32             :  *
      33             :  * This code is derived from software contributed to The NetBSD Foundation
      34             :  * by Charles M. Hannum, by Onno van der Linden and by Manuel Bouyer.
      35             :  *
      36             :  * Redistribution and use in source and binary forms, with or without
      37             :  * modification, are permitted provided that the following conditions
      38             :  * are met:
      39             :  * 1. Redistributions of source code must retain the above copyright
      40             :  *    notice, this list of conditions and the following disclaimer.
      41             :  * 2. Redistributions in binary form must reproduce the above copyright
      42             :  *    notice, this list of conditions and the following disclaimer in the
      43             :  *    documentation and/or other materials provided with the distribution.
      44             :  *
      45             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      46             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      47             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      48             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      49             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      50             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      51             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      52             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      53             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      54             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      55             :  * POSSIBILITY OF SUCH DAMAGE.
      56             :  */
      57             : 
      58             : #include <sys/param.h>
      59             : #include <sys/systm.h>
      60             : #include <sys/kernel.h>
      61             : #include <sys/stat.h>
      62             : #include <sys/buf.h>
      63             : #include <sys/malloc.h>
      64             : #include <sys/device.h>
      65             : #include <sys/disklabel.h>
      66             : #include <sys/disk.h>
      67             : #include <sys/syslog.h>
      68             : 
      69             : #include <machine/intr.h>
      70             : #include <machine/bus.h>
      71             : 
      72             : #include <dev/ata/atavar.h>
      73             : #include <dev/ic/wdcreg.h>
      74             : #include <dev/ic/wdcvar.h>
      75             : #include <dev/ata/wdvar.h>
      76             : 
      77             : #ifdef HIBERNATE
      78             : #include <sys/hibernate.h>
      79             : #endif
      80             : 
      81             : #define DEBUG_INTR   0x01
      82             : #define DEBUG_XFERS  0x02
      83             : #define DEBUG_STATUS 0x04
      84             : #define DEBUG_FUNCS  0x08
      85             : #define DEBUG_PROBE  0x10
      86             : 
      87             : #ifdef WDCDEBUG
      88             : #ifndef WDCDEBUG_WD_MASK
      89             : #define WDCDEBUG_WD_MASK 0x00
      90             : #endif
      91             : int wdcdebug_wd_mask = WDCDEBUG_WD_MASK;
      92             : #define WDCDEBUG_PRINT(args, level) do {        \
      93             :         if ((wdcdebug_wd_mask & (level)) != 0)      \
      94             :                 printf args;                    \
      95             : } while (0)
      96             : #else
      97             : #define WDCDEBUG_PRINT(args, level)
      98             : #endif
      99             : 
     100             : #define ATA_DELAY 45000 /* 45s for a drive I/O */
     101             : 
     102             : void  wdc_ata_bio_start(struct channel_softc *, struct wdc_xfer *);
     103             : void  _wdc_ata_bio_start(struct channel_softc *, struct wdc_xfer *);
     104             : int   wdc_ata_bio_intr(struct channel_softc *, struct wdc_xfer *, int);
     105             : void  wdc_ata_bio_kill_xfer(struct channel_softc *, struct wdc_xfer *);
     106             : void  wdc_ata_bio_done(struct channel_softc *, struct wdc_xfer *);
     107             : int   wdc_ata_ctrl_intr(struct channel_softc *, struct wdc_xfer *, int);
     108             : int   wdc_ata_err(struct ata_drive_datas *, struct ata_bio *);
     109             : #define WDC_ATA_NOERR 0x00 /* Drive doesn't report an error */
     110             : #define WDC_ATA_RECOV 0x01 /* There was a recovered error */
     111             : #define WDC_ATA_ERR   0x02 /* Drive reports an error */
     112             : 
     113             : #ifdef HIBERNATE
     114             : int
     115           0 : wd_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size, int op, void *page)
     116             : {
     117             :         struct {
     118             :                 struct wd_softc wd;
     119             :                 struct wdc_xfer xfer;
     120             :                 struct channel_softc chp;
     121             :                 daddr_t poffset;
     122             :                 size_t psize;
     123           0 :         } *my = page;
     124           0 :         struct wd_softc *real_wd, *wd = &my->wd;
     125           0 :         struct wdc_xfer *xfer = &my->xfer;
     126           0 :         struct channel_softc *chp = &my->chp;
     127             :         struct ata_bio *ata_bio;
     128             :         extern struct cfdriver wd_cd;
     129             : 
     130             :         /* early call for initialization */
     131           0 :         if (op == HIB_INIT) {
     132           0 :                 my->poffset = blkno;
     133           0 :                 my->psize = size;
     134           0 :                 return(0);
     135             :         }
     136             : 
     137           0 :         real_wd = (struct wd_softc *)disk_lookup(&wd_cd, DISKUNIT(dev));
     138           0 :         if (real_wd == NULL)
     139           0 :                 return (ENODEV);
     140             : 
     141           0 :         if (op == HIB_DONE) {
     142           0 :                 struct wdc_softc *wdc = chp->wdc;
     143           0 :                 config_suspend(&wdc->sc_dev, DVACT_RESUME);
     144             :                 return (0);
     145             :         }
     146             : 
     147           0 :         if (blkno > my->psize)
     148           0 :                 return (E2BIG);
     149           0 :         blkno += my->poffset;
     150             : 
     151             :         /*
     152             :          * Craft a fake set of softc and related structures
     153             :          * which we think the driver modifies.  Some of these will
     154             :          * have pointers which reach to unsafe places, but..
     155             :          */
     156           0 :         bcopy(real_wd->drvp->chnl_softc, &my->chp, sizeof my->chp);
     157           0 :         chp->ch_drive[0].chnl_softc = chp;
     158           0 :         chp->ch_drive[1].chnl_softc = chp;
     159             : 
     160           0 :         bcopy(real_wd, &my->wd, sizeof my->wd);
     161           0 :         ata_bio = &wd->sc_wdc_bio;
     162           0 :         ata_bio->wd = wd;            /* fixup ata_bio->wd */
     163           0 :         wd->drvp = &chp->ch_drive[real_wd->drvp->drive];
     164             : 
     165             :         /* Fill the request and submit it */
     166           0 :         wd->sc_wdc_bio.blkno = blkno;
     167           0 :         wd->sc_wdc_bio.flags = ATA_POLL | ATA_LBA48;
     168           0 :         if (op == HIB_R)
     169           0 :                 wd->sc_wdc_bio.flags |= ATA_READ;
     170           0 :         wd->sc_wdc_bio.bcount = size;
     171           0 :         wd->sc_wdc_bio.databuf = (caddr_t)addr;
     172           0 :         wd->sc_wdc_bio.wd = wd;
     173             : 
     174           0 :         bzero(&my->xfer, sizeof my->xfer);
     175           0 :         xfer->c_flags |= C_PRIVATEXFER;      /* Our xfer is totally private */
     176           0 :         xfer->c_flags |= C_POLL;
     177           0 :         xfer->drive = wd->drvp->drive;
     178           0 :         xfer->cmd = ata_bio;
     179           0 :         xfer->databuf = ata_bio->databuf;
     180           0 :         xfer->c_bcount = ata_bio->bcount;
     181           0 :         xfer->c_start = wdc_ata_bio_start;
     182           0 :         xfer->c_intr = wdc_ata_bio_intr;
     183           0 :         xfer->c_kill_xfer = wdc_ata_bio_kill_xfer;
     184           0 :         wdc_exec_xfer(chp, xfer);
     185           0 :         return (ata_bio->flags & ATA_ITSDONE) ? 0 : EIO;
     186           0 : }
     187             : #endif /* HIBERNATE */
     188             : 
     189             : /*
     190             :  * Handle block I/O operation. Return WDC_COMPLETE, WDC_QUEUED, or
     191             :  * WDC_TRY_AGAIN. Must be called at splbio().
     192             :  */
     193             : int
     194           0 : wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
     195             : {
     196             :         struct wdc_xfer *xfer;
     197           0 :         struct channel_softc *chp = drvp->chnl_softc;
     198             : 
     199           0 :         xfer = wdc_get_xfer(WDC_NOSLEEP);
     200           0 :         if (xfer == NULL)
     201           0 :                 return WDC_TRY_AGAIN;
     202           0 :         if (ata_bio->flags & ATA_POLL)
     203           0 :                 xfer->c_flags |= C_POLL;
     204           0 :         if (!(ata_bio->flags & ATA_POLL) &&
     205           0 :             (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
     206           0 :             (ata_bio->flags & ATA_SINGLE) == 0 &&
     207           0 :             (ata_bio->bcount > 512 ||
     208           0 :             (chp->wdc->quirks & WDC_QUIRK_NOSHORTDMA) == 0))
     209           0 :                 xfer->c_flags |= C_DMA;
     210           0 :         xfer->drive = drvp->drive;
     211           0 :         xfer->cmd = ata_bio;
     212           0 :         xfer->databuf = ata_bio->databuf;
     213           0 :         xfer->c_bcount = ata_bio->bcount;
     214           0 :         xfer->c_start = wdc_ata_bio_start;
     215           0 :         xfer->c_intr = wdc_ata_bio_intr;
     216           0 :         xfer->c_kill_xfer = wdc_ata_bio_kill_xfer;
     217           0 :         wdc_exec_xfer(chp, xfer);
     218           0 :         return (ata_bio->flags & ATA_ITSDONE) ? WDC_COMPLETE : WDC_QUEUED;
     219           0 : }
     220             : 
     221             : void
     222           0 : wdc_ata_bio_start(struct channel_softc *chp, struct wdc_xfer *xfer)
     223             : {
     224           0 :         struct ata_bio *ata_bio = xfer->cmd;
     225             :         WDCDEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
     226             :             chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
     227             :             DEBUG_XFERS);
     228             : 
     229             :         /* start timeout machinery */
     230           0 :         if ((ata_bio->flags & ATA_POLL) == 0)
     231           0 :                 timeout_add_msec(&chp->ch_timo, ATA_DELAY);
     232           0 :         _wdc_ata_bio_start(chp, xfer);
     233           0 : }
     234             : 
     235             : void
     236           0 : _wdc_ata_bio_start(struct channel_softc *chp, struct wdc_xfer *xfer)
     237             : {
     238           0 :         struct ata_bio *ata_bio = xfer->cmd;
     239           0 :         struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
     240             :         u_int16_t cyl;
     241             :         u_int8_t head, sect, cmd = 0;
     242             :         int nblks;
     243             :         int ata_delay;
     244             :         int error, dma_flags = 0;
     245             : 
     246             :         WDCDEBUG_PRINT(("_wdc_ata_bio_start %s:%d:%d\n",
     247             :             chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
     248             :             DEBUG_INTR | DEBUG_XFERS);
     249             :         /* Do control operations specially. */
     250           0 :         if (drvp->state < READY) {
     251             :                 /*
     252             :                  * Actually, we want to be careful not to mess with the control
     253             :                  * state if the device is currently busy, but we can assume
     254             :                  * that we never get to this point if that's the case.
     255             :                  */
     256             :                 /* at this point, we should only be in RECAL state */
     257           0 :                 if (drvp->state != RECAL) {
     258           0 :                         printf("%s:%d:%d: bad state %d in _wdc_ata_bio_start\n",
     259           0 :                             chp->wdc->sc_dev.dv_xname, chp->channel,
     260           0 :                             xfer->drive, drvp->state);
     261           0 :                         panic("_wdc_ata_bio_start: bad state");
     262             :                 }
     263           0 :                 xfer->c_intr = wdc_ata_ctrl_intr;
     264           0 :                 wdc_set_drive(chp, xfer->drive);
     265           0 :                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY) != 0)
     266             :                         goto timeout;
     267           0 :                 wdccommandshort(chp, xfer->drive, WDCC_RECAL);
     268           0 :                 drvp->state = RECAL_WAIT;
     269           0 :                 if ((ata_bio->flags & ATA_POLL) == 0) {
     270           0 :                         chp->ch_flags |= WDCF_IRQ_WAIT;
     271           0 :                 } else {
     272             :                         /* Wait for at last 400ns for status bit to be valid */
     273           0 :                         DELAY(1);
     274           0 :                         wdc_ata_ctrl_intr(chp, xfer, 0);
     275             :                 }
     276           0 :                 return;
     277             :         }
     278             : 
     279           0 :         if (xfer->c_flags & C_DMA) {
     280           0 :                 if (drvp->n_xfers <= NXFER)
     281           0 :                         drvp->n_xfers++;
     282           0 :                 dma_flags = (ata_bio->flags & ATA_READ) ?  WDC_DMA_READ : 0;
     283           0 :                 if (ata_bio->flags & ATA_LBA48)
     284           0 :                         dma_flags |= WDC_DMA_LBA48;
     285             :         }
     286           0 :         if (ata_bio->flags & ATA_SINGLE)
     287             :                 ata_delay = ATA_DELAY;
     288             :         else
     289             :                 ata_delay = ATA_DELAY;
     290             : again:
     291             :         /*
     292             :          *
     293             :          * When starting a multi-sector transfer, or doing single-sector
     294             :          * transfers...
     295             :          */
     296           0 :         if (xfer->c_skip == 0 || (ata_bio->flags & ATA_SINGLE) != 0) {
     297           0 :                 if (ata_bio->flags & ATA_SINGLE)
     298           0 :                         nblks = 1;
     299             :                 else
     300           0 :                         nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
     301           0 :                 if (ata_bio->flags & ATA_LBA) {
     302           0 :                         sect = (ata_bio->blkno >> 0) & 0xff;
     303           0 :                         cyl = (ata_bio->blkno >> 8) & 0xffff;
     304           0 :                         head = (ata_bio->blkno >> 24) & 0x0f;
     305           0 :                         head |= WDSD_LBA;
     306           0 :                 } else {
     307           0 :                         int blkno = ata_bio->blkno;
     308           0 :                         sect = blkno % ata_bio->lp->d_nsectors;
     309           0 :                         sect++;    /* Sectors begin with 1, not 0. */
     310           0 :                         blkno /= ata_bio->lp->d_nsectors;
     311           0 :                         head = blkno % ata_bio->lp->d_ntracks;
     312           0 :                         blkno /= ata_bio->lp->d_ntracks;
     313           0 :                         cyl = blkno;
     314           0 :                         head |= WDSD_CHS;
     315             :                 }
     316           0 :                 if (xfer->c_flags & C_DMA) {
     317           0 :                         ata_bio->nblks = nblks;
     318           0 :                         ata_bio->nbytes = xfer->c_bcount;
     319           0 :                         if (ata_bio->flags & ATA_LBA48)
     320           0 :                                 cmd = (ata_bio->flags & ATA_READ) ?
     321             :                                     WDCC_READDMA_EXT : WDCC_WRITEDMA_EXT;
     322             :                         else
     323           0 :                                 cmd = (ata_bio->flags & ATA_READ) ?
     324             :                                     WDCC_READDMA : WDCC_WRITEDMA;
     325             :                         /* Init the DMA channel. */
     326           0 :                         error = (*chp->wdc->dma_init)(chp->wdc->dma_arg,
     327           0 :                             chp->channel, xfer->drive,
     328           0 :                             (char *)xfer->databuf + xfer->c_skip,
     329           0 :                             ata_bio->nbytes, dma_flags);
     330           0 :                         if (error) {
     331           0 :                                 if (error == EINVAL) {
     332             :                                         /*
     333             :                                          * We can't do DMA on this transfer
     334             :                                          * for some reason.  Fall back to
     335             :                                          * PIO.
     336             :                                          */
     337           0 :                                         xfer->c_flags &= ~C_DMA;
     338             :                                         error = 0;
     339           0 :                                         goto do_pio;
     340             :                                 }
     341           0 :                                 ata_bio->error = ERR_DMA;
     342           0 :                                 ata_bio->r_error = 0;
     343           0 :                                 wdc_ata_bio_done(chp, xfer);
     344           0 :                                 return;
     345             :                         }
     346             :                         /* Initiate command */
     347           0 :                         wdc_set_drive(chp, xfer->drive);
     348           0 :                         if (wait_for_ready(chp, ata_delay) < 0)
     349             :                                 goto timeout;
     350             : 
     351             :                         /* start the DMA channel (before) */
     352           0 :                         if (chp->ch_flags & WDCF_DMA_BEFORE_CMD)
     353           0 :                                 (*chp->wdc->dma_start)(chp->wdc->dma_arg,
     354           0 :                                     chp->channel, xfer->drive);
     355             : 
     356           0 :                         if (ata_bio->flags & ATA_LBA48) {
     357           0 :                                 wdccommandext(chp, xfer->drive, cmd,
     358           0 :                                     (u_int64_t)ata_bio->blkno, nblks);
     359           0 :                         } else {
     360           0 :                                 wdccommand(chp, xfer->drive, cmd, cyl,
     361           0 :                                     head, sect, nblks, 0);
     362             :                         }
     363             : 
     364             :                         /* start the DMA channel (after) */
     365           0 :                         if ((chp->ch_flags & WDCF_DMA_BEFORE_CMD) == 0)
     366           0 :                                 (*chp->wdc->dma_start)(chp->wdc->dma_arg,
     367           0 :                                     chp->channel, xfer->drive);
     368             : 
     369           0 :                         chp->ch_flags |= WDCF_DMA_WAIT;
     370             :                         /* wait for irq */
     371           0 :                         goto intr;
     372             :                 } /* else not DMA */
     373             :  do_pio:
     374           0 :                 ata_bio->nblks = min(nblks, ata_bio->multi);
     375           0 :                 ata_bio->nbytes = ata_bio->nblks * ata_bio->lp->d_secsize;
     376           0 :                 KASSERT(nblks == 1 || (ata_bio->flags & ATA_SINGLE) == 0);
     377           0 :                 if (ata_bio->nblks > 1) {
     378           0 :                         if (ata_bio->flags & ATA_LBA48)
     379           0 :                                 cmd = (ata_bio->flags & ATA_READ) ?
     380             :                                     WDCC_READMULTI_EXT : WDCC_WRITEMULTI_EXT;
     381             :                         else
     382           0 :                                 cmd = (ata_bio->flags & ATA_READ) ?
     383             :                                     WDCC_READMULTI : WDCC_WRITEMULTI;
     384             :                 } else {
     385           0 :                         if (ata_bio->flags & ATA_LBA48)
     386           0 :                                 cmd = (ata_bio->flags & ATA_READ) ?
     387             :                                     WDCC_READ_EXT : WDCC_WRITE_EXT;
     388             :                         else
     389           0 :                                 cmd = (ata_bio->flags & ATA_READ) ?
     390             :                                     WDCC_READ : WDCC_WRITE;
     391             :                 }
     392             :                 /* Initiate command! */
     393           0 :                 wdc_set_drive(chp, xfer->drive);
     394           0 :                 if (wait_for_ready(chp, ata_delay) < 0)
     395             :                         goto timeout;
     396           0 :                 if (ata_bio->flags & ATA_LBA48) {
     397           0 :                         wdccommandext(chp, xfer->drive, cmd,
     398           0 :                             (u_int64_t)ata_bio->blkno, nblks);
     399           0 :                 } else {
     400           0 :                         wdccommand(chp, xfer->drive, cmd, cyl,
     401           0 :                             head, sect, nblks, 0);
     402             :                 }
     403           0 :         } else if (ata_bio->nblks > 1) {
     404             :                 /* The number of blocks in the last stretch may be smaller. */
     405           0 :                 nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
     406           0 :                 if (ata_bio->nblks > nblks) {
     407           0 :                         ata_bio->nblks = nblks;
     408           0 :                         ata_bio->nbytes = xfer->c_bcount;
     409           0 :                 }
     410             :         }
     411             :         /* If this was a write and not using DMA, push the data. */
     412           0 :         if ((ata_bio->flags & ATA_READ) == 0) {
     413           0 :                 if (wait_for_drq(chp, ata_delay) != 0) {
     414           0 :                         printf("%s:%d:%d: timeout waiting for DRQ, "
     415             :                             "st=0x%b, err=0x%02x\n",
     416           0 :                             chp->wdc->sc_dev.dv_xname, chp->channel,
     417           0 :                             xfer->drive, chp->ch_status, WDCS_BITS,
     418           0 :                             chp->ch_error);
     419           0 :                         if (wdc_ata_err(drvp, ata_bio) != WDC_ATA_ERR)
     420           0 :                                 ata_bio->error = TIMEOUT;
     421           0 :                         wdc_ata_bio_done(chp, xfer);
     422           0 :                         return;
     423             :                 }
     424           0 :                 if (wdc_ata_err(drvp, ata_bio) == WDC_ATA_ERR) {
     425           0 :                         wdc_ata_bio_done(chp, xfer);
     426           0 :                         return;
     427             :                 }
     428           0 :                 wdc_output_bytes(drvp, (char *)xfer->databuf + xfer->c_skip,
     429           0 :                     ata_bio->nbytes);
     430           0 :         }
     431             : 
     432             : intr:   /* Wait for IRQ (either real or polled) */
     433           0 :         if ((ata_bio->flags & ATA_POLL) == 0) {
     434           0 :                 chp->ch_flags |= WDCF_IRQ_WAIT;
     435           0 :         } else {
     436             :                 /* Wait for at last 400ns for status bit to be valid */
     437           0 :                 delay(1);
     438           0 :                 if (chp->ch_flags & WDCF_DMA_WAIT) {
     439           0 :                         wdc_dmawait(chp, xfer, ATA_DELAY);
     440           0 :                         chp->ch_flags &= ~WDCF_DMA_WAIT;
     441           0 :                 }
     442           0 :                 wdc_ata_bio_intr(chp, xfer, 0);
     443           0 :                 if ((ata_bio->flags & ATA_ITSDONE) == 0)
     444           0 :                         goto again;
     445             :         }
     446           0 :         return;
     447             : timeout:
     448           0 :         if (chp->ch_status == 0xff)
     449           0 :                 return;
     450           0 :         printf("%s:%d:%d: not ready, st=0x%b, err=0x%02x\n",
     451           0 :             chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
     452           0 :             chp->ch_status, WDCS_BITS, chp->ch_error);
     453           0 :         if (wdc_ata_err(drvp, ata_bio) != WDC_ATA_ERR)
     454           0 :                 ata_bio->error = TIMEOUT;
     455           0 :         wdc_ata_bio_done(chp, xfer);
     456           0 :         return;
     457           0 : }
     458             : 
     459             : int
     460           0 : wdc_ata_bio_intr(struct channel_softc *chp, struct wdc_xfer *xfer, int irq)
     461             : {
     462           0 :         struct ata_bio *ata_bio = xfer->cmd;
     463           0 :         struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
     464             :         int drv_err;
     465             : 
     466             :         WDCDEBUG_PRINT(("wdc_ata_bio_intr %s:%d:%d\n",
     467             :             chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
     468             :             DEBUG_INTR | DEBUG_XFERS);
     469             : 
     470             : 
     471             :         /* Is it not a transfer, but a control operation? */
     472           0 :         if (drvp->state < READY) {
     473           0 :                 printf("%s:%d:%d: bad state %d in wdc_ata_bio_intr\n",
     474           0 :                     chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
     475             :                     drvp->state);
     476           0 :                 panic("wdc_ata_bio_intr: bad state");
     477             :         }
     478             : 
     479             :         /*
     480             :          * reset on timeout. This will cause extra resets in the case
     481             :          * of occasional lost interrupts
     482             :          */
     483           0 :         if (xfer->c_flags & C_TIMEOU)
     484             :                 goto timeout;
     485             : 
     486             :         /* Ack interrupt done by wait_for_unbusy */
     487           0 :         if (wait_for_unbusy(chp,
     488           0 :             (irq == 0) ? ATA_DELAY : 0) < 0) {
     489           0 :                 if (irq)
     490           0 :                         return 0; /* IRQ was not for us */
     491           0 :                 printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
     492           0 :                     chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
     493           0 :                     xfer->c_bcount, xfer->c_skip);
     494             : 
     495           0 :                 goto timeout;
     496             :         }
     497           0 :         if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
     498           0 :                 chp->wdc->irqack(chp);
     499             : 
     500           0 :         drv_err = wdc_ata_err(drvp, ata_bio);
     501             : 
     502           0 :         if (xfer->c_flags & C_DMA) {
     503           0 :                 if (chp->wdc->dma_status != 0) {
     504           0 :                         if (drv_err != WDC_ATA_ERR) {
     505           0 :                                 ata_bio->error = ERR_DMA;
     506             :                                 drv_err = WDC_ATA_ERR;
     507           0 :                         }
     508             :                 }
     509           0 :                 if (chp->ch_status & WDCS_DRQ) {
     510           0 :                         if (drv_err != WDC_ATA_ERR) {
     511           0 :                                 printf("%s:%d:%d: intr with DRQ (st=0x%b)\n",
     512           0 :                                     chp->wdc->sc_dev.dv_xname, chp->channel,
     513           0 :                                     xfer->drive, chp->ch_status, WDCS_BITS);
     514           0 :                                 ata_bio->error = TIMEOUT;
     515             :                                 drv_err = WDC_ATA_ERR;
     516           0 :                         }
     517             :                 }
     518           0 :                 if (drv_err != WDC_ATA_ERR)
     519             :                         goto end;
     520           0 :                 ata_dmaerr(drvp);
     521           0 :         }
     522             : 
     523             :         /* if we had an error, end */
     524           0 :         if (drv_err == WDC_ATA_ERR) {
     525           0 :                 wdc_ata_bio_done(chp, xfer);
     526           0 :                 return 1;
     527             :         }
     528             : 
     529             :         /* If this was a read and not using DMA, fetch the data. */
     530           0 :         if ((ata_bio->flags & ATA_READ) != 0) {
     531           0 :                 if ((chp->ch_status & WDCS_DRQ) != WDCS_DRQ) {
     532           0 :                         printf("%s:%d:%d: read intr before drq\n",
     533           0 :                             chp->wdc->sc_dev.dv_xname, chp->channel,
     534           0 :                             xfer->drive);
     535           0 :                         ata_bio->error = TIMEOUT;
     536           0 :                         wdc_ata_bio_done(chp, xfer);
     537           0 :                         return 1;
     538             :                 }
     539           0 :                 wdc_input_bytes(drvp, (char *)xfer->databuf + xfer->c_skip,
     540           0 :                     ata_bio->nbytes);
     541           0 :         }
     542             : end:
     543           0 :         ata_bio->blkno += ata_bio->nblks;
     544           0 :         ata_bio->blkdone += ata_bio->nblks;
     545           0 :         xfer->c_skip += ata_bio->nbytes;
     546           0 :         xfer->c_bcount -= ata_bio->nbytes;
     547             :         /* See if this transfer is complete. */
     548           0 :         if (xfer->c_bcount > 0) {
     549           0 :                 if ((ata_bio->flags & ATA_POLL) == 0) {
     550             :                         /* Start the next operation */
     551           0 :                         _wdc_ata_bio_start(chp, xfer);
     552             :                 } else {
     553             :                         /* Let _wdc_ata_bio_start do the loop */
     554           0 :                         return 1;
     555             :                 }
     556           0 :         } else { /* Done with this transfer */
     557           0 :                 ata_bio->error = NOERROR;
     558           0 :                 wdc_ata_bio_done(chp, xfer);
     559             :         }
     560           0 :         return 1;
     561             : 
     562             : timeout:
     563           0 :         if (xfer->c_flags & C_DMA)
     564           0 :                 ata_dmaerr(drvp);
     565             : 
     566           0 :         ata_bio->error = TIMEOUT;
     567           0 :         wdc_ata_bio_done(chp, xfer);
     568           0 :         return 1;
     569           0 : }
     570             : 
     571             : void
     572           0 : wdc_ata_bio_kill_xfer(struct channel_softc *chp, struct wdc_xfer *xfer)
     573             : {
     574           0 :         struct ata_bio *ata_bio = xfer->cmd;
     575             : 
     576           0 :         timeout_del(&chp->ch_timo);
     577             :         /* remove this command from xfer queue */
     578           0 :         wdc_free_xfer(chp, xfer);
     579             : 
     580           0 :         ata_bio->flags |= ATA_ITSDONE;
     581           0 :         ata_bio->error = ERR_NODEV;
     582           0 :         ata_bio->r_error = WDCE_ABRT;
     583           0 :         if ((ata_bio->flags & ATA_POLL) == 0) {
     584             :                 WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);
     585           0 :                 wddone(ata_bio->wd);
     586           0 :         }
     587           0 : }
     588             : 
     589             : void
     590           0 : wdc_ata_bio_done(struct channel_softc *chp, struct wdc_xfer *xfer)
     591             : {
     592           0 :         struct ata_bio *ata_bio = xfer->cmd;
     593             : 
     594             :         WDCDEBUG_PRINT(("wdc_ata_bio_done %s:%d:%d: flags 0x%x\n",
     595             :             chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
     596             :             (u_int)xfer->c_flags),
     597             :             DEBUG_XFERS);
     598             : 
     599           0 :         if ((xfer->c_flags & C_PRIVATEXFER) == 0)
     600           0 :                 timeout_del(&chp->ch_timo);
     601             : 
     602             :         /* feed back residual bcount to our caller */
     603           0 :         ata_bio->bcount = xfer->c_bcount;
     604             : 
     605             :         /* remove this command from xfer queue */
     606           0 :         wdc_free_xfer(chp, xfer);
     607             : 
     608           0 :         ata_bio->flags |= ATA_ITSDONE;
     609           0 :         if ((ata_bio->flags & ATA_POLL) == 0) {
     610             :                 WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);
     611           0 :                 wddone(ata_bio->wd);
     612           0 :         }
     613             :         WDCDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n",
     614             :             chp->ch_flags), DEBUG_XFERS);
     615           0 :         wdcstart(chp);
     616           0 : }
     617             : 
     618             : /*
     619             :  * Implement operations needed before read/write.
     620             :  */
     621             : int
     622           0 : wdc_ata_ctrl_intr(struct channel_softc *chp, struct wdc_xfer *xfer, int irq)
     623             : {
     624           0 :         struct ata_bio *ata_bio = xfer->cmd;
     625           0 :         struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
     626             :         char *errstring = NULL;
     627           0 :         int delay = (irq == 0) ? ATA_DELAY : 0;
     628             : 
     629             :         WDCDEBUG_PRINT(("wdc_ata_ctrl_intr: state %d\n", drvp->state),
     630             :             DEBUG_FUNCS);
     631             : 
     632             : again:
     633           0 :         switch (drvp->state) {
     634             :         case RECAL:    /* Should not be in this state here */
     635           0 :                 panic("wdc_ata_ctrl_intr: state==RECAL");
     636             :                 break;
     637             : 
     638             :         case RECAL_WAIT:
     639             :                 errstring = "recal";
     640           0 :                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
     641             :                         goto timeout;
     642           0 :                 if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
     643           0 :                         chp->wdc->irqack(chp);
     644           0 :                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
     645             :                         goto error;
     646             :         /* FALLTHROUGH */
     647             : 
     648             :         case PIOMODE:
     649             :                 /* Don't try to set modes if controller can't be adjusted */
     650           0 :                 if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)
     651             :                         goto geometry;
     652             :                 /* Also don't try if the drive didn't report its mode */
     653           0 :                 if ((drvp->drive_flags & DRIVE_MODE) == 0)
     654             :                         goto geometry;
     655             :                 /* SET FEATURES 0x08 is only for PIO mode > 2 */
     656           0 :                 if (drvp->PIO_mode <= 2)
     657             :                         goto geometry;
     658           0 :                 wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
     659           0 :                     0x08 | drvp->PIO_mode, WDSF_SET_MODE);
     660           0 :                 drvp->state = PIOMODE_WAIT;
     661           0 :                 break;
     662             : 
     663             :         case PIOMODE_WAIT:
     664             :                 errstring = "piomode";
     665           0 :                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
     666             :                         goto timeout;
     667           0 :                 if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
     668           0 :                         chp->wdc->irqack(chp);
     669           0 :                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
     670             :                         goto error;
     671             :         /* FALLTHROUGH */
     672             : 
     673             :         case DMAMODE:
     674           0 :                 if (drvp->drive_flags & DRIVE_UDMA) {
     675           0 :                         wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
     676           0 :                             0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
     677           0 :                 } else if (drvp->drive_flags & DRIVE_DMA) {
     678           0 :                         wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
     679           0 :                             0x20 | drvp->DMA_mode, WDSF_SET_MODE);
     680             :                 } else {
     681             :                         goto geometry;
     682             :                 }
     683           0 :                 drvp->state = DMAMODE_WAIT;
     684           0 :                 break;
     685             :         case DMAMODE_WAIT:
     686             :                 errstring = "dmamode";
     687           0 :                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
     688             :                         goto timeout;
     689           0 :                 if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
     690           0 :                         chp->wdc->irqack(chp);
     691           0 :                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
     692             :                         goto error;
     693             :         /* FALLTHROUGH */
     694             : 
     695             :         case GEOMETRY:
     696             :         geometry:
     697           0 :                 if (ata_bio->flags & ATA_LBA)
     698             :                         goto multimode;
     699           0 :                 wdccommand(chp, xfer->drive, WDCC_IDP,
     700           0 :                     ata_bio->lp->d_ncylinders,
     701           0 :                     ata_bio->lp->d_ntracks - 1, 0, ata_bio->lp->d_nsectors, 0);
     702           0 :                 drvp->state = GEOMETRY_WAIT;
     703           0 :                 break;
     704             : 
     705             :         case GEOMETRY_WAIT:
     706             :                 errstring = "geometry";
     707           0 :                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
     708             :                         goto timeout;
     709           0 :                 if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
     710           0 :                         chp->wdc->irqack(chp);
     711           0 :                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
     712             :                         goto error;
     713             :                 /* FALLTHROUGH */
     714             : 
     715             :         case MULTIMODE:
     716             :         multimode:
     717           0 :                 if (ata_bio->multi == 1)
     718             :                         goto ready;
     719           0 :                 wdccommand(chp, xfer->drive, WDCC_SETMULTI, 0, 0, 0,
     720           0 :                     ata_bio->multi, 0);
     721           0 :                 drvp->state = MULTIMODE_WAIT;
     722           0 :                 break;
     723             : 
     724             :         case MULTIMODE_WAIT:
     725             :                 errstring = "setmulti";
     726           0 :                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
     727             :                         goto timeout;
     728           0 :                 if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
     729           0 :                         chp->wdc->irqack(chp);
     730           0 :                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
     731             :                         goto error;
     732             :                 /* FALLTHROUGH */
     733             : 
     734             :         case READY:
     735             :         ready:
     736           0 :                 drvp->state = READY;
     737             :                 /*
     738             :                  * The drive is usable now
     739             :                  */
     740           0 :                 xfer->c_intr = wdc_ata_bio_intr;
     741           0 :                 _wdc_ata_bio_start(chp, xfer);
     742           0 :                 return 1;
     743             :         }
     744             : 
     745           0 :         if ((ata_bio->flags & ATA_POLL) == 0) {
     746           0 :                 chp->ch_flags |= WDCF_IRQ_WAIT;
     747             :         } else {
     748           0 :                 goto again;
     749             :         }
     750           0 :         return 1;
     751             : 
     752             : timeout:
     753           0 :         if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
     754           0 :                 return 0; /* IRQ was not for us */
     755             :         }
     756           0 :         printf("%s:%d:%d: %s timed out\n",
     757           0 :             chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, errstring);
     758           0 :         ata_bio->error = TIMEOUT;
     759           0 :         drvp->state = 0;
     760           0 :         wdc_ata_bio_done(chp, xfer);
     761           0 :         return 0;
     762             : error:
     763           0 :         printf("%s:%d:%d: %s ",
     764           0 :             chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
     765             :             errstring);
     766           0 :         if (chp->ch_status & WDCS_DWF) {
     767           0 :                 printf("drive fault\n");
     768           0 :                 ata_bio->error = ERR_DF;
     769           0 :         } else {
     770           0 :                 printf("error (%x)\n", chp->ch_error);
     771           0 :                 ata_bio->r_error = chp->ch_error;
     772           0 :                 ata_bio->error = ERROR;
     773             :         }
     774           0 :         drvp->state = 0;
     775           0 :         wdc_ata_bio_done(chp, xfer);
     776           0 :         return 1;
     777           0 : }
     778             : 
     779             : int
     780           0 : wdc_ata_err(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
     781             : {
     782           0 :         struct channel_softc *chp = drvp->chnl_softc;
     783           0 :         ata_bio->error = 0;
     784             : 
     785           0 :         if (chp->ch_status == 0xff) {
     786           0 :                 ata_bio->error = ERR_NODEV;
     787           0 :                 return WDC_ATA_ERR;
     788             :         }
     789           0 :         if (chp->ch_status & WDCS_BSY) {
     790           0 :                 ata_bio->error = TIMEOUT;
     791           0 :                 return WDC_ATA_ERR;
     792             :         }
     793             : 
     794           0 :         if (chp->ch_status & WDCS_DWF) {
     795           0 :                 ata_bio->error = ERR_DF;
     796           0 :                 return WDC_ATA_ERR;
     797             :         }
     798             : 
     799           0 :         if (chp->ch_status & WDCS_ERR) {
     800           0 :                 ata_bio->error = ERROR;
     801           0 :                 ata_bio->r_error = chp->ch_error;
     802           0 :                 if (drvp->drive_flags & DRIVE_UDMA &&
     803           0 :                     (ata_bio->r_error & WDCE_CRC)) {
     804             :                         /*
     805             :                          * Record the CRC error, to avoid downgrading to
     806             :                          * multiword DMA
     807             :                          */
     808           0 :                         drvp->drive_flags |= DRIVE_DMAERR;
     809           0 :                 }
     810           0 :                 if (ata_bio->r_error & (WDCE_BBK | WDCE_UNC | WDCE_IDNF |
     811             :                     WDCE_ABRT | WDCE_TK0NF | WDCE_AMNF))
     812           0 :                         return WDC_ATA_ERR;
     813           0 :                 return WDC_ATA_NOERR;
     814             :         }
     815             : 
     816           0 :         if (chp->ch_status & WDCS_CORR)
     817           0 :                 ata_bio->flags |= ATA_CORR;
     818           0 :         return WDC_ATA_NOERR;
     819           0 : }
     820             : 
     821             : #if 0
     822             : int
     823             : wdc_ata_addref(drvp)
     824             :         struct ata_drive_datas *drvp;
     825             : {
     826             :         struct channel_softc *chp = drvp->chnl_softc;
     827             : 
     828             :         return (wdc_addref(chp));
     829             : }
     830             : 
     831             : void
     832             : wdc_ata_delref(drvp)
     833             :         struct ata_drive_datas *drvp;
     834             : {
     835             :         struct channel_softc *chp = drvp->chnl_softc;
     836             : 
     837             :         wdc_delref(chp);
     838             : }
     839             : #endif

Generated by: LCOV version 1.13