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/ata_wdc.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: ata_wdc.c,v 1.53.2.3 2004/08/11 19:44:09 jmc Exp $     */
    2 
    3 /*
    4  * Copyright (c) 1998, 2001, 2003 Manuel Bouyer.
    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, 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, by Onno van der Linden and by Manuel Bouyer.
   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: ata_wdc.c,v 1.53.2.3 2004/08/11 19:44:09 jmc Exp $");
   70 
   71 #ifndef WDCDEBUG
   72 #define WDCDEBUG
   73 #endif /* WDCDEBUG */
   74 
   75 #include <sys/param.h>
   76 #include <sys/systm.h>
   77 #include <sys/kernel.h>
   78 #include <sys/file.h>
   79 #include <sys/stat.h>
   80 #include <sys/buf.h>
   81 #include <sys/malloc.h>
   82 #include <sys/device.h>
   83 #include <sys/disklabel.h>
   84 #include <sys/syslog.h>
   85 #include <sys/proc.h>
   86 
   87 #include <machine/intr.h>
   88 #include <machine/bus.h>
   89 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
   90 #define    bus_space_write_multi_stream_2    bus_space_write_multi_2
   91 #define    bus_space_write_multi_stream_4    bus_space_write_multi_4
   92 #define    bus_space_read_multi_stream_2    bus_space_read_multi_2
   93 #define    bus_space_read_multi_stream_4    bus_space_read_multi_4
   94 #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
   95 
   96 #include <dev/ata/atareg.h>
   97 #include <dev/ata/atavar.h>
   98 #include <dev/ic/wdcreg.h>
   99 #include <dev/ic/wdcvar.h>
  100 
  101 #define DEBUG_INTR   0x01
  102 #define DEBUG_XFERS  0x02
  103 #define DEBUG_STATUS 0x04
  104 #define DEBUG_FUNCS  0x08
  105 #define DEBUG_PROBE  0x10
  106 #ifdef WDCDEBUG
  107 extern int wdcdebug_wd_mask; /* inited in wd.c */
  108 #define WDCDEBUG_PRINT(args, level) \
  109         if (wdcdebug_wd_mask & (level)) \
  110                 printf args
  111 #else
  112 #define WDCDEBUG_PRINT(args, level)
  113 #endif
  114 
  115 #define ATA_DELAY 10000 /* 10s for a drive I/O */
  116 
  117 static int      wdc_ata_bio(struct ata_drive_datas*, struct ata_bio*);
  118 static void     wdc_ata_bio_start(struct wdc_channel *,struct ata_xfer *);
  119 static void     _wdc_ata_bio_start(struct wdc_channel *,struct ata_xfer *);
  120 static int      wdc_ata_bio_intr(struct wdc_channel *, struct ata_xfer *,
  121                                  int);
  122 static void     wdc_ata_bio_kill_xfer(struct wdc_channel *,
  123                                       struct ata_xfer *, int);
  124 static void     wdc_ata_bio_done(struct wdc_channel *, struct ata_xfer *); 
  125 static int      wdc_ata_err(struct ata_drive_datas *, struct ata_bio *);
  126 #define WDC_ATA_NOERR 0x00 /* Drive doesn't report an error */
  127 #define WDC_ATA_RECOV 0x01 /* There was a recovered error */
  128 #define WDC_ATA_ERR   0x02 /* Drive reports an error */
  129 static int      wdc_ata_addref(struct ata_drive_datas *);
  130 static void     wdc_ata_delref(struct ata_drive_datas *);
  131 static void     wdc_ata_kill_pending(struct ata_drive_datas *);
  132 
  133 const struct ata_bustype wdc_ata_bustype = {
  134         SCSIPI_BUSTYPE_ATA,
  135         wdc_ata_bio,
  136         wdc_reset_channel,
  137         wdc_exec_command,
  138         ata_get_params,
  139         wdc_ata_addref,
  140         wdc_ata_delref,
  141         wdc_ata_kill_pending,
  142 };
  143 
  144 /*
  145  * Convert a 32 bit command to a 48 bit command.
  146  */
  147 static __inline
  148 int to48(int cmd32)
  149 {
  150         switch (cmd32) {
  151         case WDCC_READ:
  152                 return WDCC_READ_EXT;
  153         case WDCC_WRITE:
  154                 return WDCC_WRITE_EXT;
  155         case WDCC_READMULTI:
  156                 return WDCC_READMULTI_EXT;
  157         case WDCC_WRITEMULTI:
  158                 return WDCC_WRITEMULTI_EXT;
  159         case WDCC_READDMA:
  160                 return WDCC_READDMA_EXT;
  161         case WDCC_WRITEDMA:
  162                 return WDCC_WRITEDMA_EXT;
  163         default:
  164                 panic("ata_wdc: illegal 32 bit command %d", cmd32);
  165                 /*NOTREACHED*/
  166         }
  167 }
  168 
  169 /*
  170  * Handle block I/O operation. Return WDC_COMPLETE, WDC_QUEUED, or
  171  * WDC_TRY_AGAIN. Must be called at splbio().
  172  */
  173 static int
  174 wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
  175 {
  176         struct ata_xfer *xfer;
  177         struct wdc_channel *chp = drvp->chnl_softc;
  178         struct wdc_softc *wdc = chp->ch_wdc;
  179 
  180         xfer = wdc_get_xfer(WDC_NOSLEEP);
  181         if (xfer == NULL)
  182                 return WDC_TRY_AGAIN;
  183         if (wdc->cap & WDC_CAPABILITY_NOIRQ)
  184                 ata_bio->flags |= ATA_POLL;
  185         if (ata_bio->flags & ATA_POLL)
  186                 xfer->c_flags |= C_POLL;
  187         if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
  188             (ata_bio->flags & ATA_SINGLE) == 0)
  189                 xfer->c_flags |= C_DMA;
  190         xfer->c_drive = drvp->drive;
  191         xfer->c_cmd = ata_bio;
  192         xfer->c_databuf = ata_bio->databuf;
  193         xfer->c_bcount = ata_bio->bcount;
  194         xfer->c_start = wdc_ata_bio_start;
  195         xfer->c_intr = wdc_ata_bio_intr;
  196         xfer->c_kill_xfer = wdc_ata_bio_kill_xfer;
  197         wdc_exec_xfer(chp, xfer);
  198         return (ata_bio->flags & ATA_ITSDONE) ? WDC_COMPLETE : WDC_QUEUED;
  199 }
  200 
  201 static void
  202 wdc_ata_bio_start(struct wdc_channel *chp, struct ata_xfer *xfer)
  203 {
  204         struct wdc_softc *wdc = chp->ch_wdc;
  205         struct ata_bio *ata_bio = xfer->c_cmd;
  206         struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
  207         int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
  208         char *errstring;
  209 
  210         WDCDEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
  211             wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive),
  212             DEBUG_XFERS);
  213 
  214         /* Do control operations specially. */
  215         if (__predict_false(drvp->state < READY)) {
  216                 /*
  217                  * Actually, we want to be careful not to mess with the control
  218                  * state if the device is currently busy, but we can assume
  219                  * that we never get to this point if that's the case.
  220                  */
  221                 /* If it's not a polled command, we need the kenrel thread */
  222                 if ((xfer->c_flags & C_POLL) == 0 &&
  223                     (chp->ch_flags & WDCF_TH_RUN) == 0) {
  224                         chp->ch_queue->queue_freeze++;
  225                         wakeup(&chp->ch_thread);
  226                         return;
  227                 }
  228                 /*
  229                  * disable interrupts, all commands here should be quick
  230                  * enouth to be able to poll, and we don't go here that often
  231                  */
  232                 bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
  233                     WDCTL_4BIT | WDCTL_IDS);
  234                 if (wdc->cap & WDC_CAPABILITY_SELECT)
  235                         wdc->select(chp, xfer->c_drive);
  236                 bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
  237                     WDSD_IBM | (xfer->c_drive << 4));
  238                 DELAY(10);
  239                 errstring = "wait";
  240                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
  241                         goto ctrltimeout;
  242                 wdccommandshort(chp, xfer->c_drive, WDCC_RECAL);
  243                 /* Wait for at last 400ns for status bit to be valid */
  244                 DELAY(1);
  245                 errstring = "recal";
  246                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
  247                         goto ctrltimeout;
  248                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
  249                         goto ctrlerror;
  250                 /* Don't try to set modes if controller can't be adjusted */
  251                 if ((wdc->cap & WDC_CAPABILITY_MODE) == 0)
  252                         goto geometry;
  253                 /* Also don't try if the drive didn't report its mode */
  254                 if ((drvp->drive_flags & DRIVE_MODE) == 0)
  255                         goto geometry;
  256                 wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
  257                     0x08 | drvp->PIO_mode, WDSF_SET_MODE);
  258                 errstring = "piomode";
  259                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
  260                         goto ctrltimeout;
  261                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
  262                         goto ctrlerror;
  263                 if (drvp->drive_flags & DRIVE_UDMA) {
  264                         wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
  265                             0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
  266                 } else if (drvp->drive_flags & DRIVE_DMA) {
  267                         wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
  268                             0x20 | drvp->DMA_mode, WDSF_SET_MODE);
  269                 } else {
  270                         goto geometry;
  271                 }       
  272                 errstring = "dmamode";
  273                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
  274                         goto ctrltimeout;
  275                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
  276                         goto ctrlerror;
  277 geometry:
  278                 if (ata_bio->flags & ATA_LBA)
  279                         goto multimode;
  280                 wdccommand(chp, xfer->c_drive, WDCC_IDP,
  281                     ata_bio->lp->d_ncylinders,
  282                     ata_bio->lp->d_ntracks - 1, 0, ata_bio->lp->d_nsectors,
  283                     (ata_bio->lp->d_type == DTYPE_ST506) ?
  284                         ata_bio->lp->d_precompcyl / 4 : 0);
  285                 errstring = "geometry";
  286                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
  287                         goto ctrltimeout;
  288                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
  289                         goto ctrlerror;
  290 multimode:
  291                 if (ata_bio->multi == 1)
  292                         goto ready;
  293                 wdccommand(chp, xfer->c_drive, WDCC_SETMULTI, 0, 0, 0,
  294                     ata_bio->multi, 0);
  295                 errstring = "setmulti";
  296                 if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
  297                         goto ctrltimeout;
  298                 if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
  299                         goto ctrlerror;
  300 ready:
  301                 drvp->state = READY;
  302                 /*
  303                  * The drive is usable now
  304                  */
  305                 bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
  306                     WDCTL_4BIT);
  307                 delay(10); /* some drives need a little delay here */
  308         }
  309 
  310         _wdc_ata_bio_start(chp, xfer);
  311         return;
  312 ctrltimeout:
  313         printf("%s:%d:%d: %s timed out\n",
  314             wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive,
  315             errstring);
  316         ata_bio->error = TIMEOUT;
  317         goto ctrldone;
  318 ctrlerror:
  319         printf("%s:%d:%d: %s ",
  320             wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive,
  321             errstring);
  322         if (chp->ch_status & WDCS_DWF) {
  323                 printf("drive fault\n");
  324                 ata_bio->error = ERR_DF;
  325         } else {
  326                 printf("error (%x)\n", chp->ch_error);
  327                 ata_bio->r_error = chp->ch_error;
  328                 ata_bio->error = ERROR;
  329         }
  330 ctrldone:
  331         drvp->state = 0;
  332         wdc_ata_bio_done(chp, xfer);
  333         bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
  334         return;
  335 }
  336 
  337 static void
  338 _wdc_ata_bio_start(struct wdc_channel *chp, struct ata_xfer *xfer)
  339 {
  340         struct wdc_softc *wdc = chp->ch_wdc;
  341         struct ata_bio *ata_bio = xfer->c_cmd;
  342         struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
  343         int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
  344         u_int16_t cyl;
  345         u_int8_t head, sect, cmd = 0;
  346         int nblks;
  347         int dma_flags = 0;
  348 
  349         WDCDEBUG_PRINT(("_wdc_ata_bio_start %s:%d:%d\n",
  350             wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive),
  351             DEBUG_INTR | DEBUG_XFERS);
  352 
  353         if (xfer->c_flags & C_DMA) {
  354                 if (drvp->n_xfers <= NXFER)
  355                         drvp->n_xfers++;
  356                 dma_flags = (ata_bio->flags & ATA_READ) ?  WDC_DMA_READ : 0;
  357                 if (ata_bio->flags & ATA_LBA48)
  358                         dma_flags |= WDC_DMA_LBA48;
  359         }
  360 again:
  361         /*
  362          *
  363          * When starting a multi-sector transfer, or doing single-sector
  364          * transfers...
  365          */
  366         if (xfer->c_skip == 0 || (ata_bio->flags & ATA_SINGLE) != 0) {
  367                 if (ata_bio->flags & ATA_SINGLE)
  368                         nblks = 1;
  369                 else 
  370                         nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
  371                 /* Check for bad sectors and adjust transfer, if necessary. */
  372                 if ((ata_bio->lp->d_flags & D_BADSECT) != 0) {
  373                         long blkdiff;
  374                         int i;
  375                         for (i = 0; (blkdiff = ata_bio->badsect[i]) != -1;
  376                             i++) {
  377                                 blkdiff -= ata_bio->blkno;
  378                                 if (blkdiff < 0)
  379                                         continue;
  380                                 if (blkdiff == 0) {
  381                                         /* Replace current block of transfer. */
  382                                         ata_bio->blkno =
  383                                             ata_bio->lp->d_secperunit -
  384                                             ata_bio->lp->d_nsectors - i - 1;
  385                                 }
  386                                 if (blkdiff < nblks) {
  387                                         /* Bad block inside transfer. */
  388                                         ata_bio->flags |= ATA_SINGLE;
  389                                         nblks = 1;
  390                                 }
  391                                 break;
  392                         }
  393                 /* Transfer is okay now. */
  394                 }
  395                 if (ata_bio->flags & ATA_LBA48) {
  396                         sect = 0;
  397                         cyl =  0;
  398                         head = 0;
  399                 } else if (ata_bio->flags & ATA_LBA) {
  400                         sect = (ata_bio->blkno >> 0) & 0xff;
  401                         cyl = (ata_bio->blkno >> 8) & 0xffff;
  402                         head = (ata_bio->blkno >> 24) & 0x0f;
  403                         head |= WDSD_LBA;
  404                 } else {
  405                         int blkno = ata_bio->blkno;
  406                         sect = blkno % ata_bio->lp->d_nsectors;
  407                         sect++;    /* Sectors begin with 1, not 0. */
  408                         blkno /= ata_bio->lp->d_nsectors;
  409                         head = blkno % ata_bio->lp->d_ntracks;
  410                         blkno /= ata_bio->lp->d_ntracks;
  411                         cyl = blkno;
  412                         head |= WDSD_CHS;
  413                 }
  414                 if (xfer->c_flags & C_DMA) {
  415                         ata_bio->nblks = nblks;
  416                         ata_bio->nbytes = xfer->c_bcount;
  417                         cmd = (ata_bio->flags & ATA_READ) ?
  418                             WDCC_READDMA : WDCC_WRITEDMA;
  419                         /* Init the DMA channel. */
  420                         if ((*wdc->dma_init)(wdc->dma_arg,
  421                             chp->ch_channel, xfer->c_drive,
  422                             (char *)xfer->c_databuf + xfer->c_skip, 
  423                             ata_bio->nbytes, dma_flags) != 0) {
  424                                 ata_bio->error = ERR_DMA;
  425                                 ata_bio->r_error = 0;
  426                                 wdc_ata_bio_done(chp, xfer);
  427                                 return;
  428                         }
  429                         /* Initiate command */
  430                         if (wdc->cap & WDC_CAPABILITY_SELECT)
  431                                 wdc->select(chp, xfer->c_drive);
  432                         bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
  433                             0, WDSD_IBM | (xfer->c_drive << 4));
  434                         switch(wdc_wait_for_ready(chp, ATA_DELAY, wait_flags)) {
  435                         case WDCWAIT_OK:
  436                                 break;  
  437                         case WDCWAIT_TOUT:
  438                                 goto timeout;
  439                         case WDCWAIT_THR:
  440                                 return;
  441                         }
  442                         if (ata_bio->flags & ATA_LBA48) {
  443                             wdccommandext(chp, xfer->c_drive, to48(cmd),
  444                                 (u_int64_t)ata_bio->blkno, nblks);
  445                         } else {
  446                             wdccommand(chp, xfer->c_drive, cmd, cyl,
  447                                 head, sect, nblks, 0);
  448                         }
  449                         /* start the DMA channel */
  450                         (*wdc->dma_start)(wdc->dma_arg,
  451                             chp->ch_channel, xfer->c_drive);
  452                         chp->ch_flags |= WDCF_DMA_WAIT;
  453                         /* start timeout machinery */
  454                         if ((xfer->c_flags & C_POLL) == 0)
  455                                 callout_reset(&chp->ch_callout,
  456                                     ATA_DELAY / 1000 * hz, wdctimeout, chp);
  457                         /* wait for irq */
  458                         goto intr;
  459                 } /* else not DMA */
  460                 ata_bio->nblks = min(nblks, ata_bio->multi);
  461                 ata_bio->nbytes = ata_bio->nblks * ata_bio->lp->d_secsize;
  462                 KASSERT(nblks == 1 || (ata_bio->flags & ATA_SINGLE) == 0);
  463                 if (ata_bio->nblks > 1) {
  464                         cmd = (ata_bio->flags & ATA_READ) ?
  465                             WDCC_READMULTI : WDCC_WRITEMULTI;
  466                 } else {
  467                         cmd = (ata_bio->flags & ATA_READ) ?
  468                             WDCC_READ : WDCC_WRITE;
  469                 }
  470                 /* Initiate command! */
  471                 if (wdc->cap & WDC_CAPABILITY_SELECT)
  472                         wdc->select(chp, xfer->c_drive);
  473                 bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
  474                     WDSD_IBM | (xfer->c_drive << 4));
  475                 switch(wdc_wait_for_ready(chp, ATA_DELAY, wait_flags)) {
  476                 case WDCWAIT_OK:
  477                         break;
  478                 case WDCWAIT_TOUT:
  479                         goto timeout;
  480                 case WDCWAIT_THR:
  481                         return;
  482                 }
  483                 if (ata_bio->flags & ATA_LBA48) {
  484                     wdccommandext(chp, xfer->c_drive, to48(cmd),
  485                         (u_int64_t) ata_bio->blkno, nblks);
  486                 } else {
  487                     wdccommand(chp, xfer->c_drive, cmd, cyl,
  488                         head, sect, nblks,
  489                         (ata_bio->lp->d_type == DTYPE_ST506) ?
  490                         ata_bio->lp->d_precompcyl / 4 : 0);
  491                 }
  492                 /* start timeout machinery */
  493                 if ((xfer->c_flags & C_POLL) == 0)
  494                         callout_reset(&chp->ch_callout,
  495                             ATA_DELAY / 1000 * hz, wdctimeout, chp);
  496         } else if (ata_bio->nblks > 1) {
  497                 /* The number of blocks in the last stretch may be smaller. */
  498                 nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
  499                 if (ata_bio->nblks > nblks) {
  500                 ata_bio->nblks = nblks;
  501                 ata_bio->nbytes = xfer->c_bcount;
  502                 }
  503         }
  504         /* If this was a write and not using DMA, push the data. */
  505         if ((ata_bio->flags & ATA_READ) == 0) {
  506                 /*
  507                  * we have to busy-wait here, we can't rely on running in
  508                  * thread context.
  509                  */
  510                 if (wdc_wait_for_drq(chp, ATA_DELAY, AT_POLL) != 0) {
  511                         printf("%s:%d:%d: timeout waiting for DRQ, "
  512                             "st=0x%02x, err=0x%02x\n",
  513                             wdc->sc_dev.dv_xname, chp->ch_channel,
  514                             xfer->c_drive, chp->ch_status, chp->ch_error);
  515                         if (wdc_ata_err(drvp, ata_bio) != WDC_ATA_ERR)
  516                                 ata_bio->error = TIMEOUT;
  517                         wdc_ata_bio_done(chp, xfer);
  518                         return;
  519                 }
  520                 if (wdc_ata_err(drvp, ata_bio) == WDC_ATA_ERR) {
  521                         wdc_ata_bio_done(chp, xfer);
  522                         return;
  523                 }
  524                 if ((wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)) {
  525                         if (drvp->drive_flags & DRIVE_CAP32) {
  526                                 bus_space_write_multi_4(chp->data32iot,
  527                                     chp->data32ioh, 0,
  528                                     (u_int32_t *)((char *)xfer->c_databuf +
  529                                                   xfer->c_skip),
  530                                     ata_bio->nbytes >> 2);
  531                         } else {
  532                                 bus_space_write_multi_2(chp->cmd_iot,
  533                                     chp->cmd_iohs[wd_data], 0,
  534                                     (u_int16_t *)((char *)xfer->c_databuf +
  535                                                   xfer->c_skip),
  536                                     ata_bio->nbytes >> 1);
  537                         }
  538                 } else {
  539                         if (drvp->drive_flags & DRIVE_CAP32) {
  540                                 bus_space_write_multi_stream_4(chp->data32iot,
  541                                     chp->data32ioh, 0,
  542                                     (u_int32_t *)((char *)xfer->c_databuf +
  543                                                   xfer->c_skip),
  544                                     ata_bio->nbytes >> 2);
  545                         } else {
  546                                 bus_space_write_multi_stream_2(chp->cmd_iot,
  547                                     chp->cmd_iohs[wd_data], 0,
  548                                     (u_int16_t *)((char *)xfer->c_databuf +
  549                                                   xfer->c_skip),
  550                                     ata_bio->nbytes >> 1);
  551                         }
  552                 }
  553         }
  554 
  555 intr:   /* Wait for IRQ (either real or polled) */
  556         if ((ata_bio->flags & ATA_POLL) == 0) {
  557                 chp->ch_flags |= WDCF_IRQ_WAIT;
  558         } else {
  559                 /* Wait for at last 400ns for status bit to be valid */
  560                 delay(1);
  561                 if (chp->ch_flags & WDCF_DMA_WAIT) {
  562                         wdc_dmawait(chp, xfer, ATA_DELAY);
  563                         chp->ch_flags &= ~WDCF_DMA_WAIT;
  564                 }
  565                 wdc_ata_bio_intr(chp, xfer, 0);
  566                 if ((ata_bio->flags & ATA_ITSDONE) == 0)
  567                         goto again;
  568         }
  569         return;
  570 timeout:
  571         printf("%s:%d:%d: not ready, st=0x%02x, err=0x%02x\n",
  572             wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive,
  573             chp->ch_status, chp->ch_error);
  574         if (wdc_ata_err(drvp, ata_bio) != WDC_ATA_ERR)
  575                 ata_bio->error = TIMEOUT;
  576         wdc_ata_bio_done(chp, xfer);
  577         return;
  578 }
  579 
  580 static int
  581 wdc_ata_bio_intr(struct wdc_channel *chp, struct ata_xfer *xfer, int irq)
  582 {
  583         struct wdc_softc *wdc = chp->ch_wdc;
  584         struct ata_bio *ata_bio = xfer->c_cmd;
  585         struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
  586         int drv_err;
  587 
  588         WDCDEBUG_PRINT(("wdc_ata_bio_intr %s:%d:%d\n",
  589             wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive),
  590             DEBUG_INTR | DEBUG_XFERS);
  591 
  592 
  593         /* Is it not a transfer, but a control operation? */
  594         if (drvp->state < READY) {
  595                 printf("%s:%d:%d: bad state %d in wdc_ata_bio_intr\n",
  596                     wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive,
  597                     drvp->state);
  598                 panic("wdc_ata_bio_intr: bad state");
  599         }
  600 
  601         /*
  602          * if we missed an interrupt in a PIO transfer, reset and restart.
  603          * Don't try to continue transfer, we may have missed cycles.
  604          */
  605         if ((xfer->c_flags & (C_TIMEOU | C_DMA)) == C_TIMEOU) {
  606                 ata_bio->error = TIMEOUT;
  607                 wdc_ata_bio_done(chp, xfer);
  608                 return 1;
  609         }
  610 
  611         /* Ack interrupt done by wdc_wait_for_unbusy */
  612         if (wdc_wait_for_unbusy(chp, (irq == 0) ? ATA_DELAY : 0, AT_POLL) < 0) {
  613                 if (irq && (xfer->c_flags & C_TIMEOU) == 0)
  614                         return 0; /* IRQ was not for us */
  615                 printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
  616                     wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive,
  617                     xfer->c_bcount, xfer->c_skip);
  618                 /* if we were using DMA, flag a DMA error */
  619                 if (xfer->c_flags & C_DMA) {
  620                         ata_dmaerr(drvp,
  621                             (xfer->c_flags & C_POLL) ? AT_POLL : 0);
  622                 }
  623                 ata_bio->error = TIMEOUT;
  624                 wdc_ata_bio_done(chp, xfer);
  625                 return 1;
  626         }
  627         if (wdc->cap & WDC_CAPABILITY_IRQACK)
  628                 wdc->irqack(chp);
  629         
  630         drv_err = wdc_ata_err(drvp, ata_bio);
  631 
  632         /* If we were using DMA, Turn off the DMA channel and check for error */
  633         if (xfer->c_flags & C_DMA) {
  634                 if (ata_bio->flags & ATA_POLL) {
  635                         /*
  636                          * IDE drives deassert WDCS_BSY before transfer is
  637                          * complete when using DMA. Polling for DRQ to deassert
  638                          * is not enough DRQ is not required to be
  639                          * asserted for DMA transfers, so poll for DRDY.
  640                          */
  641                         if (wdcwait(chp, WDCS_DRDY | WDCS_DRQ, WDCS_DRDY,
  642                             ATA_DELAY, ATA_POLL) == WDCWAIT_TOUT) {
  643                                 printf("%s:%d:%d: polled transfer timed out "
  644                                     "(st=0x%x)\n", wdc->sc_dev.dv_xname,
  645                                     chp->ch_channel, xfer->c_drive,
  646                                     chp->ch_status);
  647                                 ata_bio->error = TIMEOUT;
  648                                 drv_err = WDC_ATA_ERR;
  649                         }
  650                 }
  651                 if (wdc->dma_status != 0) {
  652                         if (drv_err != WDC_ATA_ERR) {
  653                                 ata_bio->error = ERR_DMA;
  654                                 drv_err = WDC_ATA_ERR;
  655                         }
  656                 }
  657                 if (chp->ch_status & WDCS_DRQ) {
  658                         if (drv_err != WDC_ATA_ERR) {
  659                                 printf("%s:%d:%d: intr with DRQ (st=0x%x)\n",
  660                                     wdc->sc_dev.dv_xname, chp->ch_channel,
  661                                     xfer->c_drive, chp->ch_status);
  662                                 ata_bio->error = TIMEOUT;
  663                                 drv_err = WDC_ATA_ERR;
  664                         }
  665                 }
  666                 if (drv_err != WDC_ATA_ERR)
  667                         goto end;
  668                 ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0);
  669         }
  670 
  671         /* if we had an error, end */
  672         if (drv_err == WDC_ATA_ERR) {
  673                 wdc_ata_bio_done(chp, xfer);
  674                 return 1;
  675         }
  676 
  677         /* If this was a read and not using DMA, fetch the data. */
  678         if ((ata_bio->flags & ATA_READ) != 0) {
  679                 if ((chp->ch_status & WDCS_DRQ) != WDCS_DRQ) {
  680                         printf("%s:%d:%d: read intr before drq\n",
  681                             wdc->sc_dev.dv_xname, chp->ch_channel,
  682                             xfer->c_drive);
  683                         ata_bio->error = TIMEOUT;
  684                         wdc_ata_bio_done(chp, xfer);
  685                         return 1;
  686                 }
  687                 if ((wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)) {
  688                         if (drvp->drive_flags & DRIVE_CAP32) {
  689                                 bus_space_read_multi_4(chp->data32iot,
  690                                     chp->data32ioh, 0,
  691                                     (u_int32_t *)((char *)xfer->c_databuf +
  692                                                   xfer->c_skip),
  693                                     ata_bio->nbytes >> 2);
  694                         } else {
  695                                 bus_space_read_multi_2(chp->cmd_iot,
  696                                     chp->cmd_iohs[wd_data], 0,
  697                                     (u_int16_t *)((char *)xfer->c_databuf +
  698                                                   xfer->c_skip),
  699                                     ata_bio->nbytes >> 1);
  700                         }
  701                 } else {
  702                         if (drvp->drive_flags & DRIVE_CAP32) {
  703                                 bus_space_read_multi_stream_4(chp->data32iot,
  704                                     chp->data32ioh, 0,
  705                                     (u_int32_t *)((char *)xfer->c_databuf +
  706                                                   xfer->c_skip),
  707                                     ata_bio->nbytes >> 2);
  708                         } else {
  709                                 bus_space_read_multi_stream_2(chp->cmd_iot,
  710                                     chp->cmd_iohs[wd_data], 0,
  711                                     (u_int16_t *)((char *)xfer->c_databuf +
  712                                                   xfer->c_skip),
  713                                     ata_bio->nbytes >> 1);
  714                         }
  715                 }
  716         }
  717 
  718 end:
  719         ata_bio->blkno += ata_bio->nblks;
  720         ata_bio->blkdone += ata_bio->nblks;
  721         xfer->c_skip += ata_bio->nbytes;
  722         xfer->c_bcount -= ata_bio->nbytes;
  723         /* See if this transfer is complete. */
  724         if (xfer->c_bcount > 0) {
  725                 if ((ata_bio->flags & ATA_POLL) == 0) {
  726                         /* Start the next operation */
  727                         _wdc_ata_bio_start(chp, xfer);
  728                 } else {
  729                         /* Let _wdc_ata_bio_start do the loop */
  730                         return 1;
  731                 }
  732         } else { /* Done with this transfer */
  733                 ata_bio->error = NOERROR;
  734                 wdc_ata_bio_done(chp, xfer);
  735         }
  736         return 1;
  737 }
  738 
  739 static void
  740 wdc_ata_kill_pending(struct ata_drive_datas *drvp)
  741 {
  742         struct wdc_channel *chp = drvp->chnl_softc;
  743 
  744         wdc_kill_pending(chp);
  745 }
  746 
  747 static void
  748 wdc_ata_bio_kill_xfer(struct wdc_channel *chp, struct ata_xfer *xfer,
  749     int reason)
  750 {
  751         struct ata_bio *ata_bio = xfer->c_cmd;
  752         int drive = xfer->c_drive;
  753 
  754         callout_stop(&chp->ch_callout);
  755         /* remove this command from xfer queue */
  756         wdc_free_xfer(chp, xfer);
  757 
  758         ata_bio->flags |= ATA_ITSDONE;
  759         switch (reason) {
  760         case KILL_GONE:
  761                 ata_bio->error = ERR_NODEV;
  762                 break;
  763         case KILL_RESET:
  764                 ata_bio->error = ERR_RESET;
  765                 break;
  766         default:
  767                 printf("wdc_ata_bio_kill_xfer: unknown reason %d\n",
  768                     reason);
  769                 panic("wdc_ata_bio_kill_xfer");
  770         }
  771         ata_bio->r_error = WDCE_ABRT;
  772         WDCDEBUG_PRINT(("wdc_ata_done: drv_done\n"), DEBUG_XFERS);
  773         (*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc);
  774 }
  775 
  776 static void
  777 wdc_ata_bio_done(struct wdc_channel *chp, struct ata_xfer *xfer)
  778 {
  779         struct wdc_softc *wdc = chp->ch_wdc;
  780         struct ata_bio *ata_bio = xfer->c_cmd;
  781         int drive = xfer->c_drive;
  782 
  783         WDCDEBUG_PRINT(("wdc_ata_bio_done %s:%d:%d: flags 0x%x\n",
  784             wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive, 
  785             (u_int)xfer->c_flags),
  786             DEBUG_XFERS);
  787 
  788         callout_stop(&chp->ch_callout);
  789 
  790         /* feed back residual bcount to our caller */
  791         ata_bio->bcount = xfer->c_bcount;
  792 
  793         /* remove this command from xfer queue */
  794         wdc_free_xfer(chp, xfer);
  795 
  796         ata_bio->flags |= ATA_ITSDONE;
  797         WDCDEBUG_PRINT(("wdc_ata_done: drv_done\n"), DEBUG_XFERS);
  798         (*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc);
  799         WDCDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n",
  800             chp->ch_flags), DEBUG_XFERS);
  801         wdcstart(chp);
  802 }
  803 
  804 static int
  805 wdc_ata_err(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
  806 {
  807         struct wdc_channel *chp = drvp->chnl_softc;
  808         ata_bio->error = 0;
  809         if (chp->ch_status & WDCS_BSY) {
  810                 ata_bio->error = TIMEOUT;
  811                 return WDC_ATA_ERR;
  812         }
  813 
  814         if (chp->ch_status & WDCS_DWF) {
  815                 ata_bio->error = ERR_DF;
  816                 return WDC_ATA_ERR;
  817         }
  818 
  819         if (chp->ch_status & WDCS_ERR) {
  820                 ata_bio->error = ERROR;
  821                 ata_bio->r_error = chp->ch_error;
  822                 if (drvp->drive_flags & DRIVE_UDMA &&
  823                     (ata_bio->r_error & WDCE_CRC)) {
  824                         /*
  825                          * Record the CRC error, to avoid downgrading to
  826                          * multiword DMA
  827                          */
  828                         drvp->drive_flags |= DRIVE_DMAERR;
  829                 }
  830                 if (ata_bio->r_error & (WDCE_BBK | WDCE_UNC | WDCE_IDNF |
  831                     WDCE_ABRT | WDCE_TK0NF | WDCE_AMNF))
  832                         return WDC_ATA_ERR;
  833                 return WDC_ATA_NOERR;
  834         }
  835 
  836         if (chp->ch_status & WDCS_CORR)
  837                 ata_bio->flags |= ATA_CORR;
  838         return WDC_ATA_NOERR;
  839 }
  840 
  841 static int
  842 wdc_ata_addref(struct ata_drive_datas *drvp)
  843 {
  844         struct wdc_channel *chp = drvp->chnl_softc;
  845 
  846         return (wdc_addref(chp));
  847 }
  848 
  849 static void
  850 wdc_ata_delref(struct ata_drive_datas *drvp)
  851 {
  852         struct wdc_channel *chp = drvp->chnl_softc;
  853 
  854         wdc_delref(chp);
  855 }

Cache object: be41b4cdd8ed55b450a02a5b5f423194


[ 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.