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

Annotation of src/sys/dev/scsipi/atapi_wdc.c, Revision 1.138.4.1

1.138.4.1! thorpej     1: /*     $NetBSD: atapi_wdc.c,v 1.138 2020/04/13 10:49:34 jdolecek Exp $ */
1.2       bouyer      2:
                      3: /*
1.47      bouyer      4:  * Copyright (c) 1998, 2001 Manuel Bouyer.
1.2       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:  *
1.35      bouyer     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     17:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1.92      perry      18:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1.35      bouyer     19:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     20:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     21:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     22:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     23:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     24:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.2       bouyer     25:  */
1.44      lukem      26:
                     27: #include <sys/cdefs.h>
1.138.4.1! thorpej    28: __KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.138 2020/04/13 10:49:34 jdolecek Exp $");
1.2       bouyer     29:
1.86      thorpej    30: #ifndef ATADEBUG
                     31: #define ATADEBUG
                     32: #endif /* ATADEBUG */
1.2       bouyer     33:
                     34: #include <sys/param.h>
                     35: #include <sys/systm.h>
                     36: #include <sys/kernel.h>
                     37: #include <sys/file.h>
                     38: #include <sys/stat.h>
                     39: #include <sys/buf.h>
                     40: #include <sys/malloc.h>
                     41: #include <sys/device.h>
                     42: #include <sys/syslog.h>
                     43: #include <sys/proc.h>
1.39      mycroft    44: #include <sys/dvdio.h>
1.2       bouyer     45:
1.105     ad         46: #include <sys/intr.h>
                     47: #include <sys/bus.h>
1.2       bouyer     48:
                     49: #ifndef __BUS_SPACE_HAS_STREAM_METHODS
1.65      thorpej    50: #define        bus_space_write_multi_stream_2  bus_space_write_multi_2
                     51: #define        bus_space_write_multi_stream_4  bus_space_write_multi_4
                     52: #define        bus_space_read_multi_stream_2   bus_space_read_multi_2
                     53: #define        bus_space_read_multi_stream_4   bus_space_read_multi_4
1.2       bouyer     54: #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
                     55:
1.101     itohy      56: #include <dev/ata/ataconf.h>
1.2       bouyer     57: #include <dev/ata/atareg.h>
                     58: #include <dev/ata/atavar.h>
                     59: #include <dev/ic/wdcreg.h>
                     60: #include <dev/ic/wdcvar.h>
                     61:
1.40      bouyer     62: #include <dev/scsipi/scsi_all.h> /* for SCSI status */
                     63:
1.2       bouyer     64: #define DEBUG_INTR   0x01
                     65: #define DEBUG_XFERS  0x02
                     66: #define DEBUG_STATUS 0x04
                     67: #define DEBUG_FUNCS  0x08
                     68: #define DEBUG_PROBE  0x10
1.86      thorpej    69: #ifdef ATADEBUG
1.130     mlelstv    70: #ifndef ATADEBUG_ATAPI_MASK
                     71: #define ATADEBUG_ATAPI_MASK 0x0
                     72: #endif
                     73: int wdcdebug_atapi_mask = ATADEBUG_ATAPI_MASK;
1.86      thorpej    74: #define ATADEBUG_PRINT(args, level) \
1.2       bouyer     75:        if (wdcdebug_atapi_mask & (level)) \
                     76:                printf args
                     77: #else
1.86      thorpej    78: #define ATADEBUG_PRINT(args, level)
1.2       bouyer     79: #endif
                     80:
                     81: #define ATAPI_DELAY 10 /* 10 ms, this is used only before sending a cmd */
1.59      bouyer     82: #define ATAPI_MODE_DELAY 1000  /* 1s, timeout for SET_FEATYRE cmds */
1.65      thorpej    83:
                     84: static int     wdc_atapi_get_params(struct scsipi_channel *, int,
                     85:                                     struct ataparams *);
                     86: static void    wdc_atapi_probe_device(struct atapibus_softc *, int);
                     87: static void    wdc_atapi_minphys (struct buf *bp);
1.124     jdolecek   88: static int     wdc_atapi_start(struct ata_channel *,struct ata_xfer *);
1.87      thorpej    89: static int     wdc_atapi_intr(struct ata_channel *, struct ata_xfer *, int);
                     90: static void    wdc_atapi_kill_xfer(struct ata_channel *,
1.71      bouyer     91:                                    struct ata_xfer *, int);
1.133     jdolecek   92: static void    wdc_atapi_phase_complete(struct ata_xfer *, int);
1.124     jdolecek   93: static void    wdc_atapi_poll(struct ata_channel *, struct ata_xfer *);
1.87      thorpej    94: static void    wdc_atapi_done(struct ata_channel *, struct ata_xfer *);
                     95: static void    wdc_atapi_reset(struct ata_channel *, struct ata_xfer *);
1.65      thorpej    96: static void    wdc_atapi_scsipi_request(struct scsipi_channel *,
                     97:                                         scsipi_adapter_req_t, void *);
                     98: static void    wdc_atapi_kill_pending(struct scsipi_periph *);
                     99: static void    wdc_atapi_polldsc(void *arg);
1.2       bouyer    100:
                    101: #define MAX_SIZE MAXPHYS
                    102:
1.65      thorpej   103: static const struct scsipi_bustype wdc_atapi_bustype = {
1.136     riastrad  104:        .bustype_type = SCSIPI_BUSTYPE_ATAPI,
                    105:        .bustype_cmd = atapi_scsipi_cmd,
                    106:        .bustype_interpret_sense = atapi_interpret_sense,
                    107:        .bustype_printaddr = atapi_print_addr,
                    108:        .bustype_kill_pending = wdc_atapi_kill_pending,
                    109:        .bustype_async_event_xfer_mode = NULL,
1.40      bouyer    110: };
                    111:
1.2       bouyer    112: void
1.65      thorpej   113: wdc_atapibus_attach(struct atabus_softc *ata_sc)
1.2       bouyer    114: {
1.87      thorpej   115:        struct ata_channel *chp = ata_sc->sc_chan;
1.88      thorpej   116:        struct atac_softc *atac = chp->ch_atac;
                    117:        struct scsipi_adapter *adapt = &atac->atac_atapi_adapter._generic;
1.40      bouyer    118:        struct scsipi_channel *chan = &chp->ch_atapi_channel;
1.2       bouyer    119:
1.9       thorpej   120:        /*
1.40      bouyer    121:         * Fill in the scsipi_adapter.
1.9       thorpej   122:         */
1.106     cube      123:        adapt->adapt_dev = atac->atac_dev;
1.88      thorpej   124:        adapt->adapt_nchannels = atac->atac_nchannels;
1.40      bouyer    125:        adapt->adapt_request = wdc_atapi_scsipi_request;
                    126:        adapt->adapt_minphys = wdc_atapi_minphys;
1.88      thorpej   127:        if (atac->atac_cap & ATAC_CAP_NOIRQ)
1.42      bjh21     128:                adapt->adapt_flags |= SCSIPI_ADAPT_POLL_ONLY;
1.88      thorpej   129:        atac->atac_atapi_adapter.atapi_probe_device = wdc_atapi_probe_device;
1.40      bouyer    130:
                    131:        /*
                    132:         * Fill in the scsipi_channel.
                    133:         */
                    134:        memset(chan, 0, sizeof(*chan));
                    135:        chan->chan_adapter = adapt;
                    136:        chan->chan_bustype = &wdc_atapi_bustype;
1.67      thorpej   137:        chan->chan_channel = chp->ch_channel;
1.40      bouyer    138:        chan->chan_flags = SCSIPI_CHAN_OPENINGS;
                    139:        chan->chan_openings = 1;
                    140:        chan->chan_max_periph = 1;
1.135     chs       141:        chan->chan_ntargets = chp->ch_ndrives;
1.40      bouyer    142:        chan->chan_nluns = 1;
                    143:
1.138.4.1! thorpej   144:        chp->atapibus = config_found(ata_sc->sc_dev, chan, atapiprint,
        !           145:            CFARG_IATTR, "atapi",
        !           146:            CFARG_EOL);
1.2       bouyer    147: }
                    148:
1.65      thorpej   149: static void
                    150: wdc_atapi_minphys(struct buf *bp)
1.2       bouyer    151: {
1.40      bouyer    152:
                    153:        if (bp->b_bcount > MAX_SIZE)
1.2       bouyer    154:                bp->b_bcount = MAX_SIZE;
                    155:        minphys(bp);
                    156: }
                    157:
1.28      enami     158: /*
1.40      bouyer    159:  * Kill off all pending xfers for a periph.
1.28      enami     160:  *
1.123     mlelstv   161:  * Must be called with adapter lock held
1.28      enami     162:  */
1.65      thorpej   163: static void
                    164: wdc_atapi_kill_pending(struct scsipi_periph *periph)
1.28      enami     165: {
1.88      thorpej   166:        struct atac_softc *atac =
1.106     cube      167:            device_private(periph->periph_channel->chan_adapter->adapt_dev);
1.87      thorpej   168:        struct ata_channel *chp =
1.88      thorpej   169:            atac->atac_channels[periph->periph_channel->chan_channel];
1.28      enami     170:
1.82      thorpej   171:        ata_kill_pending(&chp->ch_drive[periph->periph_target]);
1.28      enami     172: }
                    173:
1.65      thorpej   174: static void
1.87      thorpej   175: wdc_atapi_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer, int reason)
1.28      enami     176: {
1.124     jdolecek  177:        struct scsipi_xfer *sc_xfer = xfer->c_scsipi;
                    178:        bool deactivate = true;
1.28      enami     179:
                    180:        /* remove this command from xfer queue */
1.71      bouyer    181:        switch (reason) {
1.124     jdolecek  182:        case KILL_GONE_INACTIVE:
                    183:                deactivate = false;
                    184:                /* FALLTHROUGH */
1.71      bouyer    185:        case KILL_GONE:
                    186:                sc_xfer->error = XS_DRIVER_STUFFUP;
                    187:                break;
                    188:        case KILL_RESET:
                    189:                sc_xfer->error = XS_RESET;
                    190:                break;
                    191:        default:
                    192:                printf("wdc_ata_bio_kill_xfer: unknown reason %d\n",
                    193:                    reason);
                    194:                panic("wdc_ata_bio_kill_xfer");
                    195:        }
1.124     jdolecek  196:
                    197:        if (deactivate)
                    198:                ata_deactivate_xfer(chp, xfer);
                    199:
1.81      thorpej   200:        ata_free_xfer(chp, xfer);
1.73      bouyer    201:        scsipi_done(sc_xfer);
1.28      enami     202: }
                    203:
1.65      thorpej   204: static int
                    205: wdc_atapi_get_params(struct scsipi_channel *chan, int drive,
                    206:     struct ataparams *id)
1.2       bouyer    207: {
1.106     cube      208:        struct wdc_softc *wdc = device_private(chan->chan_adapter->adapt_dev);
1.88      thorpej   209:        struct atac_softc *atac = &wdc->sc_atac;
1.87      thorpej   210:        struct wdc_regs *wdr = &wdc->regs[chan->chan_channel];
1.88      thorpej   211:        struct ata_channel *chp = atac->atac_channels[chan->chan_channel];
1.124     jdolecek  212:        struct ata_xfer *xfer;
                    213:        int rv;
                    214:
1.131     jdolecek  215:        xfer = ata_get_xfer(chp, false);
1.124     jdolecek  216:        if (xfer == NULL) {
                    217:                printf("wdc_atapi_get_params: no xfer\n");
                    218:                return EBUSY;
                    219:        }
1.2       bouyer    220:
1.124     jdolecek  221:        xfer->c_ata_c.r_command = ATAPI_SOFT_RESET;
                    222:        xfer->c_ata_c.r_st_bmask = 0;
                    223:        xfer->c_ata_c.r_st_pmask = 0;
                    224:        xfer->c_ata_c.flags = AT_WAIT | AT_POLL;
                    225:        xfer->c_ata_c.timeout = WDC_RESET_WAIT;
1.138     jdolecek  226:
                    227:        wdc_exec_command(&chp->ch_drive[drive], xfer);
                    228:        ata_wait_cmd(chp, xfer);
                    229:
1.124     jdolecek  230:        if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
1.86      thorpej   231:                ATADEBUG_PRINT(("wdc_atapi_get_params: ATAPI_SOFT_RESET "
1.59      bouyer    232:                    "failed for drive %s:%d:%d: error 0x%x\n",
1.106     cube      233:                    device_xname(atac->atac_dev), chp->ch_channel, drive,
1.124     jdolecek  234:                    xfer->c_ata_c.r_error), DEBUG_PROBE);
                    235:                rv = -1;
                    236:                goto out_xfer;
1.2       bouyer    237:        }
1.59      bouyer    238:        chp->ch_drive[drive].state = 0;
1.2       bouyer    239:
1.124     jdolecek  240:        ata_free_xfer(chp, xfer);
                    241:
1.99      christos  242:        (void)bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_status], 0);
1.92      perry     243:
1.2       bouyer    244:        /* Some ATAPI devices need a bit more time after software reset. */
                    245:        delay(5000);
1.57      mycroft   246:        if (ata_get_params(&chp->ch_drive[drive], AT_WAIT, id) != 0) {
1.86      thorpej   247:                ATADEBUG_PRINT(("wdc_atapi_get_params: ATAPI_IDENTIFY_DEVICE "
1.124     jdolecek  248:                    "failed for drive %s:%d:%d\n",
                    249:                    device_xname(atac->atac_dev), chp->ch_channel, drive),
                    250:                    DEBUG_PROBE);
                    251:                rv = -1;
                    252:                goto out;
                    253:        }
                    254:        rv = 0;
                    255: out:
                    256:        return rv;
                    257:
                    258: out_xfer:
                    259:        ata_free_xfer(chp, xfer);
                    260:        return rv;
1.2       bouyer    261: }
                    262:
1.65      thorpej   263: static void
                    264: wdc_atapi_probe_device(struct atapibus_softc *sc, int target)
1.33      bouyer    265: {
1.40      bouyer    266:        struct scsipi_channel *chan = sc->sc_channel;
                    267:        struct scsipi_periph *periph;
1.33      bouyer    268:        struct ataparams ids;
                    269:        struct ataparams *id = &ids;
1.106     cube      270:        struct wdc_softc *wdc = device_private(chan->chan_adapter->adapt_dev);
1.88      thorpej   271:        struct atac_softc *atac = &wdc->sc_atac;
                    272:        struct ata_channel *chp = atac->atac_channels[chan->chan_channel];
1.46      bouyer    273:        struct ata_drive_datas *drvp = &chp->ch_drive[target];
1.40      bouyer    274:        struct scsipibus_attach_args sa;
1.33      bouyer    275:        char serial_number[21], model[41], firmware_revision[9];
1.89      thorpej   276:        int s;
1.33      bouyer    277:
1.40      bouyer    278:        /* skip if already attached */
                    279:        if (scsipi_lookup_periph(chan, target, 0) != NULL)
1.33      bouyer    280:                return;
1.40      bouyer    281:
1.119     bouyer    282:        /* if no ATAPI device detected at wdc attach time, skip */
                    283:        if (drvp->drive_type != ATA_DRIVET_ATAPI) {
                    284:                ATADEBUG_PRINT(("wdc_atapi_probe_device: "
                    285:                    "drive %d not present\n", target), DEBUG_PROBE);
                    286:                return;
                    287:        }
                    288:
1.57      mycroft   289:        if (wdc_atapi_get_params(chan, target, id) == 0) {
1.33      bouyer    290: #ifdef ATAPI_DEBUG_PROBE
                    291:                printf("%s drive %d: cmdsz 0x%x drqtype 0x%x\n",
1.107     cube      292:                    device_xname(sc->sc_dev), target,
1.33      bouyer    293:                    id->atap_config & ATAPI_CFG_CMD_MASK,
                    294:                    id->atap_config & ATAPI_CFG_DRQ_MASK);
                    295: #endif
1.134     chs       296:                periph = scsipi_alloc_periph(M_WAITOK);
1.40      bouyer    297:                periph->periph_dev = NULL;
                    298:                periph->periph_channel = chan;
                    299:                periph->periph_switch = &atapi_probe_periphsw;
                    300:                periph->periph_target = target;
                    301:                periph->periph_lun = 0;
1.56      mycroft   302:                periph->periph_quirks = PQUIRK_ONLYBIG;
1.40      bouyer    303:
                    304: #ifdef SCSIPI_DEBUG
                    305:                if (SCSIPI_DEBUG_TYPE == SCSIPI_BUSTYPE_ATAPI &&
                    306:                    SCSIPI_DEBUG_TARGET == target)
                    307:                        periph->periph_dbflags |= SCSIPI_DEBUG_FLAGS;
                    308: #endif
                    309:                periph->periph_type = ATAPI_CFG_TYPE(id->atap_config);
                    310:                if (id->atap_config & ATAPI_CFG_REMOV)
                    311:                        periph->periph_flags |= PERIPH_REMOVABLE;
1.89      thorpej   312:                if (periph->periph_type == T_SEQUENTIAL) {
                    313:                        s = splbio();
1.118     bouyer    314:                        drvp->drive_flags |= ATA_DRIVE_ATAPIDSCW;
1.89      thorpej   315:                        splx(s);
                    316:                }
1.40      bouyer    317:
                    318:                sa.sa_periph = periph;
                    319:                sa.sa_inqbuf.type =  ATAPI_CFG_TYPE(id->atap_config);
                    320:                sa.sa_inqbuf.removable = id->atap_config & ATAPI_CFG_REMOV ?
                    321:                    T_REMOV : T_FIXED;
1.122     christos  322:                strnvisx(model, sizeof(model), id->atap_model,
                    323:                    sizeof(id->atap_model), VIS_TRIM|VIS_SAFE|VIS_OCTAL);
                    324:                strnvisx(serial_number, sizeof(serial_number),
                    325:                    id->atap_serial, sizeof(id->atap_serial),
                    326:                    VIS_TRIM|VIS_SAFE|VIS_OCTAL);
                    327:                strnvisx(firmware_revision, sizeof(firmware_revision),
                    328:                    id->atap_revision, sizeof(id->atap_revision),
                    329:                    VIS_TRIM|VIS_SAFE|VIS_OCTAL);
1.33      bouyer    330:                sa.sa_inqbuf.vendor = model;
                    331:                sa.sa_inqbuf.product = serial_number;
                    332:                sa.sa_inqbuf.revision = firmware_revision;
1.40      bouyer    333:
                    334:                /*
                    335:                 * Determine the operating mode capabilities of the device.
                    336:                 */
                    337:                if ((id->atap_config & ATAPI_CFG_CMD_MASK) == ATAPI_CFG_CMD_16)
                    338:                        periph->periph_cap |= PERIPH_CAP_CMD16;
                    339:                /* XXX This is gross. */
                    340:                periph->periph_cap |= (id->atap_config & ATAPI_CFG_DRQ_MASK);
                    341:
                    342:                drvp->drv_softc = atapi_probe_device(sc, target, periph, &sa);
                    343:
                    344:                if (drvp->drv_softc)
1.80      thorpej   345:                        ata_probe_caps(drvp);
1.89      thorpej   346:                else {
                    347:                        s = splbio();
1.118     bouyer    348:                        drvp->drive_type = ATA_DRIVET_NONE;
1.89      thorpej   349:                        splx(s);
                    350:                }
1.69      bouyer    351:        } else {
1.89      thorpej   352:                s = splbio();
1.118     bouyer    353:                drvp->drive_type = ATA_DRIVET_NONE;
1.89      thorpej   354:                splx(s);
1.33      bouyer    355:        }
                    356: }
                    357:
1.131     jdolecek  358: static const struct ata_xfer_ops wdc_atapi_xfer_ops = {
                    359:        .c_start = wdc_atapi_start,
                    360:        .c_intr = wdc_atapi_intr,
                    361:        .c_poll = wdc_atapi_poll,
                    362:        .c_abort = wdc_atapi_reset,
                    363:        .c_kill_xfer = wdc_atapi_kill_xfer,
                    364: };
                    365:
1.65      thorpej   366: static void
                    367: wdc_atapi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
                    368:     void *arg)
1.40      bouyer    369: {
                    370:        struct scsipi_adapter *adapt = chan->chan_adapter;
                    371:        struct scsipi_periph *periph;
1.2       bouyer    372:        struct scsipi_xfer *sc_xfer;
1.106     cube      373:        struct wdc_softc *wdc = device_private(adapt->adapt_dev);
1.88      thorpej   374:        struct atac_softc *atac = &wdc->sc_atac;
1.63      thorpej   375:        struct ata_xfer *xfer;
1.40      bouyer    376:        int channel = chan->chan_channel;
                    377:        int drive, s;
                    378:
                    379:        switch (req) {
                    380:        case ADAPTER_REQ_RUN_XFER:
                    381:                sc_xfer = arg;
                    382:                periph = sc_xfer->xs_periph;
                    383:                drive = periph->periph_target;
                    384:
1.86      thorpej   385:                ATADEBUG_PRINT(("wdc_atapi_scsipi_request %s:%d:%d\n",
1.106     cube      386:                    device_xname(atac->atac_dev), channel, drive),
                    387:                    DEBUG_XFERS);
                    388:                if (!device_is_active(atac->atac_dev)) {
1.40      bouyer    389:                        sc_xfer->error = XS_DRIVER_STUFFUP;
                    390:                        scsipi_done(sc_xfer);
                    391:                        return;
                    392:                }
                    393:
1.131     jdolecek  394:                xfer = ata_get_xfer(atac->atac_channels[channel], false);
1.40      bouyer    395:                if (xfer == NULL) {
                    396:                        sc_xfer->error = XS_RESOURCE_SHORTAGE;
                    397:                        scsipi_done(sc_xfer);
                    398:                        return;
                    399:                }
                    400:
                    401:                if (sc_xfer->xs_control & XS_CTL_POLL)
                    402:                        xfer->c_flags |= C_POLL;
1.102     itohy     403: #if NATA_DMA
1.88      thorpej   404:                if ((atac->atac_channels[channel]->ch_drive[drive].drive_flags &
1.118     bouyer    405:                    (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) && sc_xfer->datalen > 0)
1.59      bouyer    406:                        xfer->c_flags |= C_DMA;
1.102     itohy     407: #endif
                    408: #if NATA_DMA && NATA_PIOBM
                    409:                else
                    410: #endif
1.101     itohy     411: #if NATA_PIOBM
1.102     itohy     412:                if ((atac->atac_cap & ATAC_CAP_PIOBM) &&
1.101     itohy     413:                    sc_xfer->datalen > 0)
                    414:                        xfer->c_flags |= C_PIOBM;
                    415: #endif
1.63      thorpej   416:                xfer->c_drive = drive;
1.40      bouyer    417:                xfer->c_flags |= C_ATAPI;
1.102     itohy     418: #if NATA_DMA
1.40      bouyer    419:                if (sc_xfer->cmd->opcode == GPCMD_REPORT_KEY ||
                    420:                    sc_xfer->cmd->opcode == GPCMD_SEND_KEY ||
                    421:                    sc_xfer->cmd->opcode == GPCMD_READ_DVD_STRUCTURE) {
                    422:                        /*
                    423:                         * DVD authentication commands must always be done in
                    424:                         * PIO mode.
                    425:                         */
1.59      bouyer    426:                        xfer->c_flags &= ~C_DMA;
1.40      bouyer    427:                }
1.104     reinoud   428:
1.52      bouyer    429:                /*
1.104     reinoud   430:                 * DMA normally can't deal with transfers which are not a
                    431:                 * multiple of its databus width. It's a bug to request odd
                    432:                 * length transfers for ATAPI.
                    433:                 *
                    434:                 * Some devices also can't cope with unaligned DMA xfers
                    435:                 * either. Also some devices seem to not handle DMA xfers of
                    436:                 * less than 4 bytes.
                    437:                 *
                    438:                 * By enforcing at least 4 byte aligned offset and length for
                    439:                 * DMA, we might use PIO where DMA could be allowed but better
                    440:                 * safe than sorry as recent problems proved.
                    441:                 *
                    442:                 * Offending structures that are thus done by PIO instead of
                    443:                 * DMA are normally small structures since all bulkdata is
                    444:                 * aligned. But as the request may come from userland, we have
                    445:                 * to protect against it anyway.
                    446:                 *
                    447:                 * XXX check for the 32 bit wide flag?
1.52      bouyer    448:                 */
1.104     reinoud   449:
                    450:                if (((uintptr_t) sc_xfer->data) & 0x03)
1.103     reinoud   451:                        xfer->c_flags &= ~C_DMA;
1.104     reinoud   452:                if ((sc_xfer->datalen < 4) || (sc_xfer->datalen & 0x03))
1.59      bouyer    453:                        xfer->c_flags &= ~C_DMA;
1.102     itohy     454: #endif /* NATA_DMA */
1.52      bouyer    455:
1.63      thorpej   456:                xfer->c_databuf = sc_xfer->data;
1.40      bouyer    457:                xfer->c_bcount = sc_xfer->datalen;
1.131     jdolecek  458:                xfer->ops = &wdc_atapi_xfer_ops;
                    459:                xfer->c_scsipi = sc_xfer;
                    460:                xfer->c_atapi.c_dscpoll = 0;
1.40      bouyer    461:                s = splbio();
1.88      thorpej   462:                ata_exec_xfer(atac->atac_channels[channel], xfer);
1.2       bouyer    463: #ifdef DIAGNOSTIC
1.40      bouyer    464:                if ((sc_xfer->xs_control & XS_CTL_POLL) != 0 &&
                    465:                    (sc_xfer->xs_status & XS_STS_DONE) == 0)
                    466:                        panic("wdc_atapi_scsipi_request: polled command "
                    467:                            "not done");
1.2       bouyer    468: #endif
1.40      bouyer    469:                splx(s);
                    470:                return;
                    471:
                    472:        default:
                    473:                /* Not supported, nothing to do. */
1.41      lukem     474:                ;
1.40      bouyer    475:        }
1.2       bouyer    476: }
                    477:
1.124     jdolecek  478: static int
1.87      thorpej   479: wdc_atapi_start(struct ata_channel *chp, struct ata_xfer *xfer)
1.2       bouyer    480: {
1.88      thorpej   481:        struct atac_softc *atac = chp->ch_atac;
                    482:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.87      thorpej   483:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.124     jdolecek  484:        struct scsipi_xfer *sc_xfer = xfer->c_scsipi;
1.63      thorpej   485:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
1.59      bouyer    486:        int wait_flags = (sc_xfer->xs_control & XS_CTL_POLL) ? AT_POLL : 0;
1.124     jdolecek  487:        int tfd;
1.93      christos  488:        const char *errstring;
1.2       bouyer    489:
1.86      thorpej   490:        ATADEBUG_PRINT(("wdc_atapi_start %s:%d:%d, scsi flags 0x%x \n",
1.106     cube      491:            device_xname(atac->atac_dev), chp->ch_channel, drvp->drive,
1.27      thorpej   492:            sc_xfer->xs_control), DEBUG_XFERS);
1.124     jdolecek  493:
                    494:        ata_channel_lock_owned(chp);
                    495:
1.102     itohy     496: #if NATA_DMA
1.59      bouyer    497:        if ((xfer->c_flags & C_DMA) && (drvp->n_xfers <= NXFER))
                    498:                drvp->n_xfers++;
1.102     itohy     499: #endif
1.59      bouyer    500:        /* Do control operations specially. */
                    501:        if (__predict_false(drvp->state < READY)) {
1.94      peter     502:                /* If it's not a polled command, we need the kernel thread */
1.137     jdolecek  503:                if ((sc_xfer->xs_control & XS_CTL_POLL) == 0
                    504:                    && !ata_is_thread_run(chp))
1.124     jdolecek  505:                        return ATASTART_TH;
1.59      bouyer    506:                /*
                    507:                 * disable interrupts, all commands here should be quick
1.111     snj       508:                 * enough to be able to poll, and we don't go here that often
1.59      bouyer    509:                 */
1.120     tsutsui   510:                bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
1.59      bouyer    511:                     WDCTL_4BIT | WDCTL_IDS);
1.85      thorpej   512:                if (wdc->select)
1.67      thorpej   513:                        wdc->select(chp, xfer->c_drive);
1.87      thorpej   514:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.63      thorpej   515:                    WDSD_IBM | (xfer->c_drive << 4));
1.59      bouyer    516:                /* Don't try to set mode if controller can't be adjusted */
1.88      thorpej   517:                if (atac->atac_set_modes == NULL)
1.59      bouyer    518:                        goto ready;
                    519:                /* Also don't try if the drive didn't report its mode */
1.118     bouyer    520:                if ((drvp->drive_flags & ATA_DRIVE_MODE) == 0)
1.59      bouyer    521:                        goto ready;
                    522:                errstring = "unbusy";
1.124     jdolecek  523:                if (wdc_wait_for_unbusy(chp, ATAPI_DELAY, wait_flags, &tfd))
1.59      bouyer    524:                        goto timeout;
                    525:                wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
                    526:                    0x08 | drvp->PIO_mode, WDSF_SET_MODE);
                    527:                errstring = "piomode";
1.124     jdolecek  528:                if (wdc_wait_for_unbusy(chp, ATAPI_MODE_DELAY, wait_flags,
                    529:                    &tfd))
1.59      bouyer    530:                        goto timeout;
1.124     jdolecek  531:                if (ATACH_ST(tfd) & WDCS_ERR) {
                    532:                        if (ATACH_ST(tfd) == WDCE_ABRT) {
1.59      bouyer    533:                                /*
1.76      mycroft   534:                                 * Some ATAPI drives reject PIO settings.
                    535:                                 * Fall back to PIO mode 3 since that's the
                    536:                                 * minimum for ATAPI.
1.59      bouyer    537:                                 */
1.76      mycroft   538:                                printf("%s:%d:%d: PIO mode %d rejected, "
                    539:                                    "falling back to PIO mode 3\n",
1.106     cube      540:                                    device_xname(atac->atac_dev),
1.76      mycroft   541:                                    chp->ch_channel, xfer->c_drive,
                    542:                                    drvp->PIO_mode);
                    543:                                if (drvp->PIO_mode > 3)
                    544:                                        drvp->PIO_mode = 3;
                    545:                        } else
                    546:                                goto error;
1.59      bouyer    547:                }
1.102     itohy     548: #if NATA_DMA
                    549: #if NATA_UDMA
1.118     bouyer    550:                if (drvp->drive_flags & ATA_DRIVE_UDMA) {
1.59      bouyer    551:                        wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
                    552:                            0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
1.102     itohy     553:                } else
                    554: #endif
1.118     bouyer    555:                if (drvp->drive_flags & ATA_DRIVE_DMA) {
1.59      bouyer    556:                        wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
                    557:                            0x20 | drvp->DMA_mode, WDSF_SET_MODE);
                    558:                } else {
                    559:                        goto ready;
                    560:                }
                    561:                errstring = "dmamode";
1.124     jdolecek  562:                if (wdc_wait_for_unbusy(chp, ATAPI_MODE_DELAY, wait_flags,
                    563:                    &tfd))
1.59      bouyer    564:                        goto timeout;
1.124     jdolecek  565:                if (ATACH_ST(tfd) & WDCS_ERR) {
                    566:                        if (ATACH_ERR(tfd) == WDCE_ABRT) {
1.102     itohy     567: #if NATA_UDMA
1.118     bouyer    568:                                if (drvp->drive_flags & ATA_DRIVE_UDMA)
1.76      mycroft   569:                                        goto error;
1.102     itohy     570:                                else
                    571: #endif
                    572:                                {
1.76      mycroft   573:                                        /*
                    574:                                         * The drive rejected our DMA setting.
                    575:                                         * Fall back to mode 1.
                    576:                                         */
                    577:                                        printf("%s:%d:%d: DMA mode %d rejected, "
                    578:                                            "falling back to DMA mode 0\n",
1.106     cube      579:                                            device_xname(atac->atac_dev),
1.76      mycroft   580:                                            chp->ch_channel, xfer->c_drive,
                    581:                                            drvp->DMA_mode);
                    582:                                        if (drvp->DMA_mode > 0)
                    583:                                                drvp->DMA_mode = 0;
                    584:                                }
                    585:                        } else
                    586:                                goto error;
                    587:                }
1.102     itohy     588: #endif /* NATA_DMA */
1.59      bouyer    589: ready:
                    590:                drvp->state = READY;
1.87      thorpej   591:                bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
1.59      bouyer    592:                    WDCTL_4BIT);
1.70      bouyer    593:                delay(10); /* some drives need a little delay here */
1.30      bouyer    594:        }
1.24      bouyer    595:        /* start timeout machinery */
1.27      thorpej   596:        if ((sc_xfer->xs_control & XS_CTL_POLL) == 0)
1.131     jdolecek  597:                callout_reset(&chp->c_timo_callout, mstohz(sc_xfer->timeout),
                    598:                    wdctimeout, chp);
1.59      bouyer    599:
1.85      thorpej   600:        if (wdc->select)
1.67      thorpej   601:                wdc->select(chp, xfer->c_drive);
1.87      thorpej   602:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.63      thorpej   603:            WDSD_IBM | (xfer->c_drive << 4));
1.124     jdolecek  604:        switch (wdc_wait_for_unbusy(chp, ATAPI_DELAY, wait_flags, &tfd)) {
1.59      bouyer    605:        case WDCWAIT_OK:
                    606:                break;
                    607:        case WDCWAIT_TOUT:
1.2       bouyer    608:                printf("wdc_atapi_start: not ready, st = %02x\n",
1.124     jdolecek  609:                    ATACH_ST(tfd));
1.3       bouyer    610:                sc_xfer->error = XS_TIMEOUT;
1.124     jdolecek  611:                return ATASTART_ABORT;
1.59      bouyer    612:        case WDCWAIT_THR:
1.124     jdolecek  613:                return ATASTART_TH;
1.2       bouyer    614:        }
                    615:
                    616:        /*
                    617:         * Even with WDCS_ERR, the device should accept a command packet
                    618:         * Limit length to what can be stuffed into the cylinder register
                    619:         * (16 bits).  Some CD-ROMs seem to interpret '0' as 65536,
                    620:         * but not all devices do that and it's not obvious from the
                    621:         * ATAPI spec that that behaviour should be expected.  If more
                    622:         * data is necessary, multiple data transfer phases will be done.
                    623:         */
1.5       bouyer    624:
1.92      perry     625:        wdccommand(chp, xfer->c_drive, ATAPI_PKT_CMD,
1.29      bouyer    626:            xfer->c_bcount <= 0xffff ? xfer->c_bcount : 0xffff,
1.92      perry     627:            0, 0, 0,
1.102     itohy     628: #if NATA_DMA
                    629:            (xfer->c_flags & C_DMA) ? ATAPI_PKT_CMD_FTRE_DMA :
                    630: #endif
                    631:            0
                    632:            );
1.92      perry     633:
1.101     itohy     634: #if NATA_PIOBM
                    635:        if (xfer->c_flags & C_PIOBM) {
                    636:                int error;
                    637:                int dma_flags = (sc_xfer->xs_control & XS_CTL_DATA_IN)
                    638:                    ?  WDC_DMA_READ : 0;
                    639:                if (xfer->c_flags & C_POLL) {
                    640:                        /* XXX not supported yet --- fall back to PIO */
                    641:                        xfer->c_flags &= ~C_PIOBM;
                    642:                } else {
                    643:                        /* Init the DMA channel. */
                    644:                        error = (*wdc->dma_init)(wdc->dma_arg,
                    645:                            chp->ch_channel, xfer->c_drive,
                    646:                            (char *)xfer->c_databuf,
                    647:                            xfer->c_bcount,
                    648:                            dma_flags | WDC_DMA_PIOBM_ATAPI);
                    649:                        if (error) {
                    650:                                if (error == EINVAL) {
                    651:                                        /*
                    652:                                         * We can't do DMA on this transfer
                    653:                                         * for some reason.  Fall back to
                    654:                                         * PIO.
                    655:                                         */
                    656:                                        xfer->c_flags &= ~C_PIOBM;
                    657:                                        error = 0;
                    658:                                } else {
                    659:                                        sc_xfer->error = XS_DRIVER_STUFFUP;
                    660:                                        errstring = "piobm";
                    661:                                        goto error;
                    662:                                }
                    663:                        }
                    664:                }
                    665:        }
                    666: #endif
1.2       bouyer    667:        /*
1.92      perry     668:         * If there is no interrupt for CMD input, busy-wait for it (done in
1.124     jdolecek  669:         * the interrupt routine. Poll routine will exit early in this case.
1.2       bouyer    670:         */
1.40      bouyer    671:        if ((sc_xfer->xs_periph->periph_cap & ATAPI_CFG_DRQ_MASK) !=
1.124     jdolecek  672:            ATAPI_CFG_IRQ_DRQ || (sc_xfer->xs_control & XS_CTL_POLL))
                    673:                return ATASTART_POLL;
1.129     jdolecek  674:        else {
                    675:                chp->ch_flags |= ATACH_IRQ_WAIT;
1.124     jdolecek  676:                return ATASTART_STARTED;
1.129     jdolecek  677:        }
1.124     jdolecek  678:
1.59      bouyer    679: timeout:
                    680:        printf("%s:%d:%d: %s timed out\n",
1.106     cube      681:            device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive,
1.67      thorpej   682:            errstring);
1.59      bouyer    683:        sc_xfer->error = XS_TIMEOUT;
1.87      thorpej   684:        bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
1.70      bouyer    685:        delay(10); /* some drives need a little delay here */
1.124     jdolecek  686:        return ATASTART_ABORT;
                    687:
1.59      bouyer    688: error:
                    689:        printf("%s:%d:%d: %s ",
1.106     cube      690:            device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive,
1.59      bouyer    691:            errstring);
1.124     jdolecek  692:        printf("error (0x%x)\n", ATACH_ERR(tfd));
1.59      bouyer    693:        sc_xfer->error = XS_SHORTSENSE;
1.124     jdolecek  694:        sc_xfer->sense.atapi_sense = ATACH_ERR(tfd);
1.87      thorpej   695:        bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
1.70      bouyer    696:        delay(10); /* some drives need a little delay here */
1.124     jdolecek  697:        return ATASTART_ABORT;
                    698: }
                    699:
                    700: static void
                    701: wdc_atapi_poll(struct ata_channel *chp, struct ata_xfer *xfer)
                    702: {
                    703:        /*
                    704:         * If there is no interrupt for CMD input, busy-wait for it (done in
                    705:         * the interrupt routine. If it is a polled command, call the interrupt
                    706:         * routine until command is done.
                    707:         */
                    708:        const bool poll = ((xfer->c_scsipi->xs_control & XS_CTL_POLL) != 0);
                    709:
                    710:        /* Wait for at last 400ns for status bit to be valid */
                    711:        DELAY(1);
                    712:        wdc_atapi_intr(chp, xfer, 0);
                    713:
                    714:        if (!poll)
                    715:                return;
                    716:
                    717: #if NATA_DMA
                    718:        if (chp->ch_flags & ATACH_DMA_WAIT) {
                    719:                wdc_dmawait(chp, xfer, xfer->c_scsipi->timeout);
                    720:                chp->ch_flags &= ~ATACH_DMA_WAIT;
                    721:        }
                    722: #endif
                    723:        while ((xfer->c_scsipi->xs_status & XS_STS_DONE) == 0) {
                    724:                /* Wait for at last 400ns for status bit to be valid */
                    725:                DELAY(1);
                    726:                wdc_atapi_intr(chp, xfer, 0);
                    727:        }
1.2       bouyer    728: }
                    729:
1.65      thorpej   730: static int
1.128     jdolecek  731: wdc_atapi_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
1.2       bouyer    732: {
1.88      thorpej   733:        struct atac_softc *atac = chp->ch_atac;
                    734:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.87      thorpej   735:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.124     jdolecek  736:        struct scsipi_xfer *sc_xfer = xfer->c_scsipi;
1.63      thorpej   737:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
1.2       bouyer    738:        int len, phase, i, retries=0;
1.124     jdolecek  739:        int ire, tfd;
1.102     itohy     740: #if NATA_DMA
                    741:        int error;
                    742: #endif
                    743: #if NATA_DMA || NATA_PIOBM
1.2       bouyer    744:        int dma_flags = 0;
1.102     itohy     745: #endif
1.8       bouyer    746:        void *cmd;
1.2       bouyer    747:
1.86      thorpej   748:        ATADEBUG_PRINT(("wdc_atapi_intr %s:%d:%d\n",
1.106     cube      749:            device_xname(atac->atac_dev), chp->ch_channel, drvp->drive),
1.67      thorpej   750:            DEBUG_INTR);
1.2       bouyer    751:
1.124     jdolecek  752:        ata_channel_lock(chp);
                    753:
1.2       bouyer    754:        /* Is it not a transfer, but a control operation? */
                    755:        if (drvp->state < READY) {
                    756:                printf("%s:%d:%d: bad state %d in wdc_atapi_intr\n",
1.106     cube      757:                    device_xname(atac->atac_dev), chp->ch_channel,
                    758:                    xfer->c_drive, drvp->state);
1.55      provos    759:                panic("wdc_atapi_intr: bad state");
1.2       bouyer    760:        }
1.24      bouyer    761:        /*
                    762:         * If we missed an interrupt in a PIO transfer, reset and restart.
                    763:         * Don't try to continue transfer, we may have missed cycles.
                    764:         */
                    765:        if ((xfer->c_flags & (C_TIMEOU | C_DMA)) == C_TIMEOU) {
1.124     jdolecek  766:                ata_channel_unlock(chp);
1.24      bouyer    767:                sc_xfer->error = XS_TIMEOUT;
                    768:                wdc_atapi_reset(chp, xfer);
1.25      bouyer    769:                return 1;
1.92      perry     770:        }
1.24      bouyer    771:
1.101     itohy     772: #if NATA_PIOBM
                    773:        /* Transfer-done interrupt for busmastering PIO operation */
                    774:        if ((xfer->c_flags & C_PIOBM) && (chp->ch_flags & ATACH_PIOBM_WAIT)) {
                    775:                chp->ch_flags &= ~ATACH_PIOBM_WAIT;
                    776:
                    777:                /* restore transfer length */
                    778:                len = xfer->c_bcount;
1.131     jdolecek  779:                if (xfer->c_atapi.c_lenoff < 0)
                    780:                        len += xfer->c_atapi.c_lenoff;
1.101     itohy     781:
                    782:                if (sc_xfer->xs_control & XS_CTL_DATA_IN)
                    783:                        goto end_piobm_datain;
                    784:                else
                    785:                        goto end_piobm_dataout;
                    786:        }
                    787: #endif
                    788:
1.64      thorpej   789:        /* Ack interrupt done in wdc_wait_for_unbusy */
1.85      thorpej   790:        if (wdc->select)
1.67      thorpej   791:                wdc->select(chp, xfer->c_drive);
1.87      thorpej   792:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.63      thorpej   793:            WDSD_IBM | (xfer->c_drive << 4));
1.64      thorpej   794:        if (wdc_wait_for_unbusy(chp,
1.128     jdolecek  795:            (irq == 0) ? sc_xfer->timeout : 0, AT_POLL, &tfd) == WDCWAIT_TOUT) {
                    796:                if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
1.124     jdolecek  797:                        ata_channel_unlock(chp);
1.19      bouyer    798:                        return 0; /* IRQ was not for us */
1.124     jdolecek  799:                }
1.16      bouyer    800:                printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n",
1.106     cube      801:                    device_xname(atac->atac_dev), chp->ch_channel,
                    802:                    xfer->c_drive, xfer->c_bcount, xfer->c_skip);
1.102     itohy     803: #if NATA_DMA
1.33      bouyer    804:                if (xfer->c_flags & C_DMA) {
1.59      bouyer    805:                        ata_dmaerr(drvp,
                    806:                            (xfer->c_flags & C_POLL) ? AT_POLL : 0);
1.33      bouyer    807:                }
1.102     itohy     808: #endif
1.3       bouyer    809:                sc_xfer->error = XS_TIMEOUT;
1.132     jdolecek  810:                ata_channel_unlock(chp);
1.2       bouyer    811:                wdc_atapi_reset(chp, xfer);
                    812:                return 1;
                    813:        }
1.85      thorpej   814:        if (wdc->irqack)
1.67      thorpej   815:                wdc->irqack(chp);
1.36      bouyer    816:
1.102     itohy     817: #if NATA_DMA
1.48      bouyer    818:        /*
                    819:         * If we missed an IRQ and were using DMA, flag it as a DMA error
                    820:         * and reset device.
                    821:         */
1.33      bouyer    822:        if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA)) {
1.59      bouyer    823:                ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0);
1.48      bouyer    824:                sc_xfer->error = XS_RESET;
1.132     jdolecek  825:                ata_channel_unlock(chp);
1.48      bouyer    826:                wdc_atapi_reset(chp, xfer);
                    827:                return (1);
1.33      bouyer    828:        }
1.102     itohy     829: #endif
1.92      perry     830:        /*
1.8       bouyer    831:         * if the request sense command was aborted, report the short sense
                    832:         * previously recorded, else continue normal processing
                    833:         */
                    834:
1.102     itohy     835: #if NATA_DMA || NATA_PIOBM
1.101     itohy     836:        if (xfer->c_flags & (C_DMA | C_PIOBM))
1.40      bouyer    837:                dma_flags = (sc_xfer->xs_control & XS_CTL_DATA_IN)
                    838:                    ?  WDC_DMA_READ : 0;
1.102     itohy     839: #endif
1.2       bouyer    840: again:
1.87      thorpej   841:        len = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_lo], 0) +
                    842:            256 * bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_hi], 0);
                    843:        ire = bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_ireason], 0);
1.124     jdolecek  844:        phase = (ire & (WDCI_CMD | WDCI_IN)) | (ATACH_ST(tfd) & WDCS_DRQ);
1.86      thorpej   845:        ATADEBUG_PRINT(("wdc_atapi_intr: c_bcount %d len %d st 0x%x err 0x%x "
1.2       bouyer    846:            "ire 0x%x :", xfer->c_bcount,
1.124     jdolecek  847:            len, ATACH_ST(tfd), ATACH_ERR(tfd), ire), DEBUG_INTR);
1.2       bouyer    848:
                    849:        switch (phase) {
                    850:        case PHASE_CMDOUT:
1.57      mycroft   851:                cmd = sc_xfer->cmd;
1.86      thorpej   852:                ATADEBUG_PRINT(("PHASE_CMDOUT\n"), DEBUG_INTR);
1.102     itohy     853: #if NATA_DMA
1.2       bouyer    854:                /* Init the DMA channel if necessary */
                    855:                if (xfer->c_flags & C_DMA) {
1.95      thorpej   856:                        error = (*wdc->dma_init)(wdc->dma_arg,
1.67      thorpej   857:                            chp->ch_channel, xfer->c_drive,
1.95      thorpej   858:                            xfer->c_databuf, xfer->c_bcount, dma_flags);
                    859:                        if (error) {
                    860:                                if (error == EINVAL) {
                    861:                                        /*
                    862:                                         * We can't do DMA on this transfer
                    863:                                         * for some reason.  Fall back to
                    864:                                         * PIO.
                    865:                                         */
                    866:                                        xfer->c_flags &= ~C_DMA;
                    867:                                        error = 0;
                    868:                                } else {
                    869:                                        sc_xfer->error = XS_DRIVER_STUFFUP;
                    870:                                        break;
                    871:                                }
1.2       bouyer    872:                        }
                    873:                }
1.102     itohy     874: #endif
1.75      mycroft   875:
1.2       bouyer    876:                /* send packet command */
                    877:                /* Commands are 12 or 16 bytes long. It's 32-bit aligned */
1.77      mycroft   878:                wdc->dataout_pio(chp, drvp->drive_flags, cmd, sc_xfer->cmdlen);
1.75      mycroft   879:
1.102     itohy     880: #if NATA_DMA
1.2       bouyer    881:                /* Start the DMA channel if necessary */
                    882:                if (xfer->c_flags & C_DMA) {
1.67      thorpej   883:                        (*wdc->dma_start)(wdc->dma_arg,
                    884:                            chp->ch_channel, xfer->c_drive);
1.87      thorpej   885:                        chp->ch_flags |= ATACH_DMA_WAIT;
1.2       bouyer    886:                }
1.102     itohy     887: #endif
1.129     jdolecek  888:
                    889:                if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) {
                    890:                        chp->ch_flags |= ATACH_IRQ_WAIT;
                    891:                }
                    892:
1.124     jdolecek  893:                ata_channel_unlock(chp);
1.2       bouyer    894:                return 1;
                    895:
                    896:         case PHASE_DATAOUT:
                    897:                /* write data */
1.86      thorpej   898:                ATADEBUG_PRINT(("PHASE_DATAOUT\n"), DEBUG_INTR);
1.102     itohy     899: #if NATA_DMA
1.27      thorpej   900:                if ((sc_xfer->xs_control & XS_CTL_DATA_OUT) == 0 ||
1.2       bouyer    901:                    (xfer->c_flags & C_DMA) != 0) {
1.15      bouyer    902:                        printf("wdc_atapi_intr: bad data phase DATAOUT\n");
1.2       bouyer    903:                        if (xfer->c_flags & C_DMA) {
1.59      bouyer    904:                                ata_dmaerr(drvp,
                    905:                                    (xfer->c_flags & C_POLL) ? AT_POLL : 0);
1.2       bouyer    906:                        }
1.3       bouyer    907:                        sc_xfer->error = XS_TIMEOUT;
1.132     jdolecek  908:                        ata_channel_unlock(chp);
1.2       bouyer    909:                        wdc_atapi_reset(chp, xfer);
                    910:                        return 1;
                    911:                }
1.102     itohy     912: #endif
1.131     jdolecek  913:                xfer->c_atapi.c_lenoff = len - xfer->c_bcount;
1.2       bouyer    914:                if (xfer->c_bcount < len) {
                    915:                        printf("wdc_atapi_intr: warning: write only "
                    916:                            "%d of %d requested bytes\n", xfer->c_bcount, len);
1.101     itohy     917:                        len = xfer->c_bcount;
                    918:                }
                    919:
                    920: #if NATA_PIOBM
                    921:                if (xfer->c_flags & C_PIOBM) {
                    922:                        /* start the busmastering PIO */
                    923:                        (*wdc->piobm_start)(wdc->dma_arg,
                    924:                            chp->ch_channel, xfer->c_drive,
                    925:                            xfer->c_skip, len, WDC_PIOBM_XFER_IRQ);
1.129     jdolecek  926:                        chp->ch_flags |= ATACH_DMA_WAIT | ATACH_IRQ_WAIT |
                    927:                            ATACH_PIOBM_WAIT;
1.124     jdolecek  928:                        ata_channel_unlock(chp);
1.101     itohy     929:                        return 1;
1.2       bouyer    930:                }
1.101     itohy     931: #endif
                    932:                wdc->dataout_pio(chp, drvp->drive_flags,
1.120     tsutsui   933:                    (char *)xfer->c_databuf + xfer->c_skip, len);
1.101     itohy     934:
                    935: #if NATA_PIOBM
                    936:        end_piobm_dataout:
                    937: #endif
1.131     jdolecek  938:                for (i = xfer->c_atapi.c_lenoff; i > 0; i -= 2)
1.101     itohy     939:                        bus_space_write_2(wdr->cmd_iot,
                    940:                            wdr->cmd_iohs[wd_data], 0, 0);
                    941:
                    942:                xfer->c_skip += len;
                    943:                xfer->c_bcount -= len;
1.129     jdolecek  944:                if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) {
                    945:                        chp->ch_flags |= ATACH_IRQ_WAIT;
                    946:                }
1.124     jdolecek  947:                ata_channel_unlock(chp);
1.2       bouyer    948:                return 1;
                    949:
                    950:        case PHASE_DATAIN:
                    951:                /* Read data */
1.86      thorpej   952:                ATADEBUG_PRINT(("PHASE_DATAIN\n"), DEBUG_INTR);
1.102     itohy     953: #if NATA_DMA
1.92      perry     954:                if ((sc_xfer->xs_control & XS_CTL_DATA_IN) == 0 ||
1.2       bouyer    955:                    (xfer->c_flags & C_DMA) != 0) {
1.15      bouyer    956:                        printf("wdc_atapi_intr: bad data phase DATAIN\n");
1.2       bouyer    957:                        if (xfer->c_flags & C_DMA) {
1.59      bouyer    958:                                ata_dmaerr(drvp,
                    959:                                    (xfer->c_flags & C_POLL) ? AT_POLL : 0);
1.2       bouyer    960:                        }
1.3       bouyer    961:                        sc_xfer->error = XS_TIMEOUT;
1.132     jdolecek  962:                        ata_channel_unlock(chp);
1.2       bouyer    963:                        wdc_atapi_reset(chp, xfer);
                    964:                        return 1;
                    965:                }
1.102     itohy     966: #endif
1.131     jdolecek  967:                xfer->c_atapi.c_lenoff = len - xfer->c_bcount;
1.2       bouyer    968:                if (xfer->c_bcount < len) {
                    969:                        printf("wdc_atapi_intr: warning: reading only "
                    970:                            "%d of %d bytes\n", xfer->c_bcount, len);
1.101     itohy     971:                        len = xfer->c_bcount;
                    972:                }
                    973:
                    974: #if NATA_PIOBM
                    975:                if (xfer->c_flags & C_PIOBM) {
                    976:                        /* start the busmastering PIO */
                    977:                        (*wdc->piobm_start)(wdc->dma_arg,
                    978:                            chp->ch_channel, xfer->c_drive,
                    979:                            xfer->c_skip, len, WDC_PIOBM_XFER_IRQ);
1.129     jdolecek  980:                        chp->ch_flags |= ATACH_DMA_WAIT | ATACH_IRQ_WAIT |
                    981:                            ATACH_PIOBM_WAIT;
1.124     jdolecek  982:                        ata_channel_unlock(chp);
1.101     itohy     983:                        return 1;
                    984:                }
                    985: #endif
                    986:                wdc->datain_pio(chp, drvp->drive_flags,
                    987:                    (char *)xfer->c_databuf + xfer->c_skip, len);
                    988:
                    989: #if NATA_PIOBM
                    990:        end_piobm_datain:
                    991: #endif
1.131     jdolecek  992:                if (xfer->c_atapi.c_lenoff > 0)
                    993:                        wdcbit_bucket(chp, xfer->c_atapi.c_lenoff);
1.101     itohy     994:
                    995:                xfer->c_skip += len;
                    996:                xfer->c_bcount -= len;
1.129     jdolecek  997:                if ((sc_xfer->xs_control & XS_CTL_POLL) == 0) {
                    998:                        chp->ch_flags |= ATACH_IRQ_WAIT;
                    999:                }
1.124     jdolecek 1000:                ata_channel_unlock(chp);
1.2       bouyer   1001:                return 1;
                   1002:
                   1003:        case PHASE_ABORTED:
                   1004:        case PHASE_COMPLETED:
1.86      thorpej  1005:                ATADEBUG_PRINT(("PHASE_COMPLETED\n"), DEBUG_INTR);
1.102     itohy    1006: #if NATA_DMA
1.2       bouyer   1007:                if (xfer->c_flags & C_DMA) {
1.40      bouyer   1008:                        xfer->c_bcount -= sc_xfer->datalen;
                   1009:                }
1.102     itohy    1010: #endif
1.40      bouyer   1011:                sc_xfer->resid = xfer->c_bcount;
1.124     jdolecek 1012:                /* this will unlock channel lock too */
1.133     jdolecek 1013:                wdc_atapi_phase_complete(xfer, tfd);
1.45      bouyer   1014:                return(1);
1.2       bouyer   1015:
                   1016:        default:
                   1017:                if (++retries<500) {
                   1018:                        DELAY(100);
1.124     jdolecek 1019:                        tfd = ATACH_ERR_ST(
                   1020:                            bus_space_read_1(wdr->cmd_iot,
                   1021:                                wdr->cmd_iohs[wd_error], 0),
                   1022:                            bus_space_read_1(wdr->cmd_iot,
                   1023:                                wdr->cmd_iohs[wd_status], 0)
                   1024:                        );
1.2       bouyer   1025:                        goto again;
                   1026:                }
                   1027:                printf("wdc_atapi_intr: unknown phase 0x%x\n", phase);
1.124     jdolecek 1028:                if (ATACH_ST(tfd) & WDCS_ERR) {
1.8       bouyer   1029:                        sc_xfer->error = XS_SHORTSENSE;
1.124     jdolecek 1030:                        sc_xfer->sense.atapi_sense = ATACH_ERR(tfd);
1.2       bouyer   1031:                } else {
1.102     itohy    1032: #if NATA_DMA
1.33      bouyer   1033:                        if (xfer->c_flags & C_DMA) {
1.59      bouyer   1034:                                ata_dmaerr(drvp,
                   1035:                                    (xfer->c_flags & C_POLL) ? AT_POLL : 0);
1.33      bouyer   1036:                        }
1.102     itohy    1037: #endif
1.16      bouyer   1038:                        sc_xfer->error = XS_RESET;
1.132     jdolecek 1039:                        ata_channel_unlock(chp);
1.16      bouyer   1040:                        wdc_atapi_reset(chp, xfer);
                   1041:                        return (1);
1.2       bouyer   1042:                }
                   1043:        }
1.86      thorpej  1044:        ATADEBUG_PRINT(("wdc_atapi_intr: wdc_atapi_done() (end), error 0x%x "
1.2       bouyer   1045:            "sense 0x%x\n", sc_xfer->error, sc_xfer->sense.atapi_sense),
                   1046:            DEBUG_INTR);
1.124     jdolecek 1047:        ata_channel_unlock(chp);
1.2       bouyer   1048:        wdc_atapi_done(chp, xfer);
                   1049:        return (1);
                   1050: }
                   1051:
1.65      thorpej  1052: static void
1.133     jdolecek 1053: wdc_atapi_phase_complete(struct ata_xfer *xfer, int tfd)
1.45      bouyer   1054: {
1.87      thorpej  1055:        struct ata_channel *chp = xfer->c_chp;
1.88      thorpej  1056:        struct atac_softc *atac = chp->ch_atac;
1.102     itohy    1057: #if NATA_DMA || NATA_PIOBM
1.88      thorpej  1058:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.102     itohy    1059: #endif
1.124     jdolecek 1060:        struct scsipi_xfer *sc_xfer = xfer->c_scsipi;
1.63      thorpej  1061:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
1.124     jdolecek 1062:
                   1063:        ata_channel_lock_owned(chp);
1.45      bouyer   1064:
                   1065:        /* wait for DSC if needed */
1.118     bouyer   1066:        if (drvp->drive_flags & ATA_DRIVE_ATAPIDSCW) {
1.86      thorpej  1067:                ATADEBUG_PRINT(("wdc_atapi_phase_complete(%s:%d:%d) "
1.106     cube     1068:                    "polldsc %d\n", device_xname(atac->atac_dev),
                   1069:                    chp->ch_channel,
1.131     jdolecek 1070:                    xfer->c_drive, xfer->c_atapi.c_dscpoll), DEBUG_XFERS);
1.57      mycroft  1071: #if 1
                   1072:                if (cold)
                   1073:                        panic("wdc_atapi_phase_complete: cold");
                   1074: #endif
1.59      bouyer   1075:                if (wdcwait(chp, WDCS_DSC, WDCS_DSC, 10,
1.124     jdolecek 1076:                    AT_POLL, &tfd) == WDCWAIT_TOUT) {
1.57      mycroft  1077:                        /* 10ms not enough, try again in 1 tick */
1.131     jdolecek 1078:                        if (xfer->c_atapi.c_dscpoll++ >
1.57      mycroft  1079:                            mstohz(sc_xfer->timeout)) {
1.59      bouyer   1080:                                printf("%s:%d:%d: wait_for_dsc "
                   1081:                                    "failed\n",
1.106     cube     1082:                                    device_xname(atac->atac_dev),
1.67      thorpej  1083:                                    chp->ch_channel, xfer->c_drive);
1.124     jdolecek 1084:                                ata_channel_unlock(chp);
1.45      bouyer   1085:                                sc_xfer->error = XS_TIMEOUT;
                   1086:                                wdc_atapi_reset(chp, xfer);
1.124     jdolecek 1087:                        } else {
1.131     jdolecek 1088:                                callout_reset(&chp->c_timo_callout, 1,
                   1089:                                    wdc_atapi_polldsc, chp);
1.124     jdolecek 1090:                                ata_channel_unlock(chp);
                   1091:                        }
1.57      mycroft  1092:                        return;
1.45      bouyer   1093:                }
1.127     christos 1094:        }
                   1095:
1.45      bouyer   1096:        /*
1.92      perry    1097:         * Some drive occasionally set WDCS_ERR with
1.45      bouyer   1098:         * "ATA illegal length indication" in the error
                   1099:         * register. If we read some data the sense is valid
                   1100:         * anyway, so don't report the error.
                   1101:         */
1.124     jdolecek 1102:        if (ATACH_ST(tfd) & WDCS_ERR &&
1.45      bouyer   1103:            ((sc_xfer->xs_control & XS_CTL_REQSENSE) == 0 ||
                   1104:            sc_xfer->resid == sc_xfer->datalen)) {
                   1105:                /* save the short sense */
                   1106:                sc_xfer->error = XS_SHORTSENSE;
1.124     jdolecek 1107:                sc_xfer->sense.atapi_sense = ATACH_ERR(tfd);
1.45      bouyer   1108:                if ((sc_xfer->xs_periph->periph_quirks &
                   1109:                    PQUIRK_NOSENSE) == 0) {
                   1110:                        /* ask scsipi to send a REQUEST_SENSE */
                   1111:                        sc_xfer->error = XS_BUSY;
                   1112:                        sc_xfer->status = SCSI_CHECK;
1.102     itohy    1113:                }
                   1114: #if NATA_DMA || NATA_PIOBM
                   1115:                else if (wdc->dma_status &
1.45      bouyer   1116:                    (WDC_DMAST_NOIRQ | WDC_DMAST_ERR)) {
1.102     itohy    1117: #if NATA_DMA
1.59      bouyer   1118:                        ata_dmaerr(drvp,
                   1119:                            (xfer->c_flags & C_POLL) ? AT_POLL : 0);
1.102     itohy    1120: #endif
1.45      bouyer   1121:                        sc_xfer->error = XS_RESET;
1.132     jdolecek 1122:                        ata_channel_unlock(chp);
1.45      bouyer   1123:                        wdc_atapi_reset(chp, xfer);
                   1124:                        return;
                   1125:                }
1.102     itohy    1126: #endif
1.45      bouyer   1127:        }
                   1128:        if (xfer->c_bcount != 0) {
1.86      thorpej  1129:                ATADEBUG_PRINT(("wdc_atapi_intr: bcount value is "
1.45      bouyer   1130:                    "%d after io\n", xfer->c_bcount), DEBUG_XFERS);
                   1131:        }
                   1132: #ifdef DIAGNOSTIC
                   1133:        if (xfer->c_bcount < 0) {
                   1134:                printf("wdc_atapi_intr warning: bcount value "
                   1135:                    "is %d after io\n", xfer->c_bcount);
                   1136:        }
                   1137: #endif
1.86      thorpej  1138:        ATADEBUG_PRINT(("wdc_atapi_phase_complete: wdc_atapi_done(), "
1.45      bouyer   1139:            "error 0x%x sense 0x%x\n", sc_xfer->error,
                   1140:            sc_xfer->sense.atapi_sense), DEBUG_INTR);
1.124     jdolecek 1141:        ata_channel_unlock(chp);
1.45      bouyer   1142:        wdc_atapi_done(chp, xfer);
                   1143: }
                   1144:
1.65      thorpej  1145: static void
1.87      thorpej  1146: wdc_atapi_done(struct ata_channel *chp, struct ata_xfer *xfer)
1.2       bouyer   1147: {
1.88      thorpej  1148:        struct atac_softc *atac = chp->ch_atac;
1.124     jdolecek 1149:        struct scsipi_xfer *sc_xfer = xfer->c_scsipi;
1.2       bouyer   1150:
1.86      thorpej  1151:        ATADEBUG_PRINT(("wdc_atapi_done %s:%d:%d: flags 0x%x\n",
1.106     cube     1152:            device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive,
1.91      reinoud  1153:            (u_int)xfer->c_flags), DEBUG_XFERS);
1.124     jdolecek 1154:
                   1155:        if (ata_waitdrain_xfer_check(chp, xfer))
                   1156:                return;
                   1157:
                   1158:        ata_deactivate_xfer(chp, xfer);
1.81      thorpej  1159:        ata_free_xfer(chp, xfer);
1.40      bouyer   1160:
1.86      thorpej  1161:        ATADEBUG_PRINT(("wdc_atapi_done: scsipi_done\n"), DEBUG_XFERS);
1.25      bouyer   1162:        scsipi_done(sc_xfer);
1.86      thorpej  1163:        ATADEBUG_PRINT(("atastart from wdc_atapi_done, flags 0x%x\n",
1.4       bouyer   1164:            chp->ch_flags), DEBUG_XFERS);
1.84      thorpej  1165:        atastart(chp);
1.2       bouyer   1166: }
                   1167:
1.65      thorpej  1168: static void
1.87      thorpej  1169: wdc_atapi_reset(struct ata_channel *chp, struct ata_xfer *xfer)
1.2       bouyer   1170: {
1.88      thorpej  1171:        struct atac_softc *atac = chp->ch_atac;
1.63      thorpej  1172:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
1.124     jdolecek 1173:        struct scsipi_xfer *sc_xfer = xfer->c_scsipi;
                   1174:        int tfd;
1.2       bouyer   1175:
1.124     jdolecek 1176:        ata_channel_lock(chp);
1.63      thorpej  1177:        wdccommandshort(chp, xfer->c_drive, ATAPI_SOFT_RESET);
1.2       bouyer   1178:        drvp->state = 0;
1.124     jdolecek 1179:        if (wdc_wait_for_unbusy(chp, WDC_RESET_WAIT, AT_POLL, &tfd) != 0) {
1.2       bouyer   1180:                printf("%s:%d:%d: reset failed\n",
1.106     cube     1181:                    device_xname(atac->atac_dev), chp->ch_channel,
1.63      thorpej  1182:                    xfer->c_drive);
1.2       bouyer   1183:                sc_xfer->error = XS_SELTIMEOUT;
                   1184:        }
1.124     jdolecek 1185:        ata_channel_unlock(chp);
1.2       bouyer   1186:        wdc_atapi_done(chp, xfer);
                   1187:        return;
1.45      bouyer   1188: }
                   1189:
1.59      bouyer   1190: static void
1.65      thorpej  1191: wdc_atapi_polldsc(void *arg)
1.45      bouyer   1192: {
1.131     jdolecek 1193:        struct ata_channel *chp = arg;
                   1194:        struct ata_xfer *xfer = ata_queue_get_active_xfer(chp);
                   1195:
                   1196:        KASSERT(xfer != NULL);
1.124     jdolecek 1197:
                   1198:        ata_channel_lock(chp);
1.65      thorpej  1199:
1.124     jdolecek 1200:        /* this will unlock channel lock too */
1.133     jdolecek 1201:        wdc_atapi_phase_complete(xfer, 0);
1.2       bouyer   1202: }

CVSweb <webmaster@jp.NetBSD.org>