[BACK]Return to ata_wdc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / ata

Annotation of src/sys/dev/ata/ata_wdc.c, Revision 1.21.2.1

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

CVSweb <webmaster@jp.NetBSD.org>