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

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

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

CVSweb