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

Annotation of sys/dev/atapiscsi/atapiscsi.c, Revision 1.1

1.1     ! nbrk        1: /*      $OpenBSD: atapiscsi.c,v 1.78 2007/08/06 08:28:09 tom Exp $     */
        !             2:
        !             3: /*
        !             4:  * This code is derived from code with the copyright below.
        !             5:  */
        !             6:
        !             7: /*
        !             8:  * Copyright (c) 1996, 1998 Manuel Bouyer.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by Manuel Bouyer.
        !            21:  * 4. Neither the name of the University nor the names of its contributors
        !            22:  *    may be used to endorse or promote products derived from this software
        !            23:  *    without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            35:  * SUCH DAMAGE.
        !            36:  *
        !            37:  */
        !            38:
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/kernel.h>
        !            43: #include <sys/device.h>
        !            44: #include <sys/buf.h>
        !            45: #include <sys/dkstat.h>
        !            46: #include <sys/disklabel.h>
        !            47: #include <sys/dkstat.h>
        !            48: #include <sys/malloc.h>
        !            49: #include <sys/proc.h>
        !            50: #include <sys/reboot.h>
        !            51: #include <sys/file.h>
        !            52: #include <sys/ioctl.h>
        !            53: #include <sys/timeout.h>
        !            54: #include <scsi/scsi_all.h>
        !            55: #include <scsi/scsi_disk.h>
        !            56: #include <scsi/scsi_tape.h>
        !            57: #include <scsi/scsiconf.h>
        !            58:
        !            59: #include <machine/bus.h>
        !            60: #include <machine/cpu.h>
        !            61: #include <machine/intr.h>
        !            62:
        !            63: #include <dev/ata/atareg.h>
        !            64: #include <dev/ata/atavar.h>
        !            65: #include <dev/ic/wdcreg.h>
        !            66: #include <dev/ic/wdcvar.h>
        !            67: #include <dev/ic/wdcevent.h>
        !            68:
        !            69: /* drive states stored in ata_drive_datas */
        !            70: enum atapi_drive_states {
        !            71:        ATAPI_RESET_BASE_STATE = 0,
        !            72:        ATAPI_DEVICE_RESET_WAIT_STATE = 1,
        !            73:        ATAPI_IDENTIFY_STATE = 2,
        !            74:        ATAPI_IDENTIFY_WAIT_STATE = 3,
        !            75:        ATAPI_PIOMODE_STATE = 4,
        !            76:        ATAPI_PIOMODE_WAIT_STATE = 5,
        !            77:        ATAPI_DMAMODE_STATE = 6,
        !            78:        ATAPI_DMAMODE_WAIT_STATE = 7,
        !            79:        ATAPI_READY_STATE = 8
        !            80: };
        !            81:
        !            82: #define DEBUG_INTR   0x01
        !            83: #define DEBUG_XFERS  0x02
        !            84: #define DEBUG_STATUS 0x04
        !            85: #define DEBUG_FUNCS  0x08
        !            86: #define DEBUG_PROBE  0x10
        !            87: #define DEBUG_DSC    0x20
        !            88: #define DEBUG_POLL   0x40
        !            89: #define DEBUG_ERRORS 0x80   /* Debug error handling code */
        !            90:
        !            91: #if defined(WDCDEBUG)
        !            92: #ifndef WDCDEBUG_ATAPI_MASK
        !            93: #define WDCDEBUG_ATAPI_MASK 0x00
        !            94: #endif
        !            95: int wdcdebug_atapi_mask = WDCDEBUG_ATAPI_MASK;
        !            96: #define WDCDEBUG_PRINT(args, level) do {               \
        !            97:        if ((wdcdebug_atapi_mask & (level)) != 0)       \
        !            98:                printf args;                            \
        !            99: } while (0)
        !           100: #else
        !           101: #define WDCDEBUG_PRINT(args, level)
        !           102: #endif
        !           103:
        !           104: /* 10 ms, this is used only before sending a cmd.  */
        !           105: #define ATAPI_DELAY 10
        !           106: #define ATAPI_RESET_DELAY 1000
        !           107: #define ATAPI_RESET_WAIT 2000
        !           108: #define ATAPI_CTRL_WAIT 4000
        !           109:
        !           110: /* When polling, let the exponential backoff max out at 1 second's interval. */
        !           111: #define ATAPI_POLL_MAXTIC (hz)
        !           112:
        !           113: void  wdc_atapi_start(struct channel_softc *,struct wdc_xfer *);
        !           114:
        !           115: void  wdc_atapi_timer_handler(void *);
        !           116:
        !           117: void  wdc_atapi_real_start(struct channel_softc *, struct wdc_xfer *,
        !           118:     int, struct atapi_return_args *);
        !           119: void  wdc_atapi_real_start_2(struct channel_softc *, struct wdc_xfer *,
        !           120:     int, struct atapi_return_args *);
        !           121: void  wdc_atapi_intr_command(struct channel_softc *, struct wdc_xfer *,
        !           122:     int, struct atapi_return_args *);
        !           123: void  wdc_atapi_intr_data(struct channel_softc *, struct wdc_xfer *,
        !           124:     int, struct atapi_return_args *);
        !           125: void  wdc_atapi_intr_complete(struct channel_softc *, struct wdc_xfer *,
        !           126:     int, struct atapi_return_args *);
        !           127: void  wdc_atapi_pio_intr(struct channel_softc *, struct wdc_xfer *,
        !           128:     int, struct atapi_return_args *);
        !           129: void  wdc_atapi_send_packet(struct channel_softc *, struct wdc_xfer *,
        !           130:     int, struct atapi_return_args *);
        !           131: void  wdc_atapi_ctrl(struct channel_softc *, struct wdc_xfer *,
        !           132:     int, struct atapi_return_args *);
        !           133:
        !           134: char  *wdc_atapi_in_data_phase(struct wdc_xfer *, int, int);
        !           135:
        !           136: int   wdc_atapi_intr(struct channel_softc *, struct wdc_xfer *, int);
        !           137: void  wdc_atapi_done(struct channel_softc *, struct wdc_xfer *,
        !           138:        int, struct atapi_return_args *);
        !           139: void  wdc_atapi_reset(struct channel_softc *, struct wdc_xfer *,
        !           140:        int, struct atapi_return_args *);
        !           141: void  wdc_atapi_reset_2(struct channel_softc *, struct wdc_xfer *,
        !           142:        int, struct atapi_return_args *);
        !           143:
        !           144: void  wdc_atapi_tape_done(struct channel_softc *, struct wdc_xfer *,
        !           145:        int, struct atapi_return_args *);
        !           146: #define MAX_SIZE MAXPHYS
        !           147:
        !           148: struct atapiscsi_softc;
        !           149: struct atapiscsi_xfer;
        !           150:
        !           151: int    atapiscsi_match(struct device *, void *, void *);
        !           152: void   atapiscsi_attach(struct device *, struct device *, void *);
        !           153: int    atapiscsi_detach(struct device *, int);
        !           154: int     atapi_to_scsi_sense(struct scsi_xfer *, u_int8_t);
        !           155:
        !           156: enum atapi_state { as_none, as_data, as_completed };
        !           157:
        !           158: struct atapiscsi_softc {
        !           159:        struct device  sc_dev;
        !           160:        struct  scsi_link  sc_adapterlink;
        !           161:        struct channel_softc *chp;
        !           162:        enum atapi_state protocol_phase;
        !           163:
        !           164:        int drive;
        !           165: };
        !           166:
        !           167: void  wdc_atapi_minphys(struct buf *bp);
        !           168: int   wdc_atapi_ioctl(struct scsi_link *,
        !           169:        u_long, caddr_t, int, struct proc *);
        !           170: int   wdc_atapi_send_cmd(struct scsi_xfer *sc_xfer);
        !           171:
        !           172: static struct scsi_adapter atapiscsi_switch =
        !           173: {
        !           174:        wdc_atapi_send_cmd,
        !           175:        wdc_atapi_minphys,
        !           176:        NULL,
        !           177:        NULL,
        !           178:        wdc_atapi_ioctl
        !           179: };
        !           180:
        !           181: static struct scsi_device atapiscsi_dev =
        !           182: {
        !           183:        NULL,
        !           184:        NULL,
        !           185:        NULL,
        !           186:        NULL,
        !           187: };
        !           188:
        !           189: /* Inital version shares bus_link structure so it can easily
        !           190:    be "attached to current" wdc driver */
        !           191:
        !           192: struct cfattach atapiscsi_ca = {
        !           193:        sizeof(struct atapiscsi_softc), atapiscsi_match, atapiscsi_attach,
        !           194:            atapiscsi_detach
        !           195: };
        !           196:
        !           197: struct cfdriver atapiscsi_cd = {
        !           198:        NULL, "atapiscsi", DV_DULL
        !           199: };
        !           200:
        !           201:
        !           202: int
        !           203: atapiscsi_match(parent, match, aux)
        !           204:        struct device *parent;
        !           205:        void *match, *aux;
        !           206:
        !           207: {
        !           208:        struct ata_atapi_attach *aa_link = aux;
        !           209:        struct cfdata *cf = match;
        !           210:
        !           211:        if (aa_link == NULL)
        !           212:                return (0);
        !           213:
        !           214:        if (aa_link->aa_type != T_ATAPI)
        !           215:                return (0);
        !           216:
        !           217:        if (cf->cf_loc[0] != aa_link->aa_channel &&
        !           218:            cf->cf_loc[0] != -1)
        !           219:                return (0);
        !           220:
        !           221:        return (1);
        !           222: }
        !           223:
        !           224: void
        !           225: atapiscsi_attach(parent, self, aux)
        !           226:        struct device *parent, *self;
        !           227:        void *aux;
        !           228: {
        !           229:        struct atapiscsi_softc *as = (struct atapiscsi_softc *)self;
        !           230:        struct ata_atapi_attach *aa_link = aux;
        !           231:        struct scsibus_attach_args saa;
        !           232:        struct ata_drive_datas *drvp = aa_link->aa_drv_data;
        !           233:        struct channel_softc *chp = drvp->chnl_softc;
        !           234:        struct ataparams *id = &drvp->id;
        !           235:        struct device *child;
        !           236:
        !           237:        printf("\n");
        !           238:
        !           239:        /* Initialize shared data. */
        !           240:        scsi_init();
        !           241:
        !           242: #ifdef WDCDEBUG
        !           243:        if (chp->wdc->sc_dev.dv_cfdata->cf_flags & WDC_OPTION_PROBE_VERBOSE)
        !           244:                wdcdebug_atapi_mask |= DEBUG_PROBE;
        !           245: #endif
        !           246:
        !           247:        as->chp = chp;
        !           248:        as->drive = drvp->drive;
        !           249:        as->sc_adapterlink.adapter_softc = as;
        !           250:        as->sc_adapterlink.adapter_target = 7;
        !           251:        as->sc_adapterlink.adapter_buswidth = 2;
        !           252:        as->sc_adapterlink.adapter = &atapiscsi_switch;
        !           253:        as->sc_adapterlink.device = &atapiscsi_dev;
        !           254:        as->sc_adapterlink.luns = 1;
        !           255:        as->sc_adapterlink.openings = 1;
        !           256:        as->sc_adapterlink.flags = SDEV_ATAPI;
        !           257:
        !           258:        strlcpy(drvp->drive_name, as->sc_dev.dv_xname,
        !           259:            sizeof(drvp->drive_name));
        !           260:        drvp->cf_flags = as->sc_dev.dv_cfdata->cf_flags;
        !           261:
        !           262:        wdc_probe_caps(drvp, id);
        !           263:
        !           264:        WDCDEBUG_PRINT(
        !           265:                ("general config %04x capabilities %04x ",
        !           266:                    id->atap_config, id->atap_capabilities1),
        !           267:                    DEBUG_PROBE);
        !           268:
        !           269:        if ((NERRS_MAX - 2) > 0)
        !           270:                drvp->n_dmaerrs = NERRS_MAX - 2;
        !           271:        else
        !           272:                drvp->n_dmaerrs = 0;
        !           273:        drvp->drive_flags |= DRIVE_DEVICE_RESET;
        !           274:
        !           275:        /* Tape drives do funny DSC stuff */
        !           276:        if (ATAPI_CFG_TYPE(id->atap_config) ==
        !           277:            ATAPI_CFG_TYPE_SEQUENTIAL)
        !           278:                drvp->atapi_cap |= ACAP_DSC;
        !           279:
        !           280:        if ((id->atap_config & ATAPI_CFG_CMD_MASK) ==
        !           281:            ATAPI_CFG_CMD_16)
        !           282:                drvp->atapi_cap |= ACAP_LEN;
        !           283:
        !           284:        drvp->atapi_cap |=
        !           285:            (id->atap_config & ATAPI_CFG_DRQ_MASK);
        !           286:
        !           287:        WDCDEBUG_PRINT(("driver caps %04x\n", drvp->atapi_cap),
        !           288:            DEBUG_PROBE);
        !           289:
        !           290:        bzero(&saa, sizeof(saa));
        !           291:        saa.saa_sc_link = &as->sc_adapterlink;
        !           292:
        !           293:        child = config_found((struct device *)as, &saa, scsiprint);
        !           294:
        !           295:        if (child != NULL) {
        !           296:                struct scsibus_softc *scsi = (struct scsibus_softc *)child;
        !           297:                struct scsi_link *link = scsi->sc_link[0][0];
        !           298:
        !           299:                if (link) {
        !           300:                        strlcpy(drvp->drive_name,
        !           301:                            ((struct device *)(link->device_softc))->dv_xname,
        !           302:                            sizeof(drvp->drive_name));
        !           303:
        !           304:                        wdc_print_caps(drvp);
        !           305:                }
        !           306:        }
        !           307:
        !           308: #ifdef WDCDEBUG
        !           309:        if (chp->wdc->sc_dev.dv_cfdata->cf_flags & WDC_OPTION_PROBE_VERBOSE)
        !           310:                wdcdebug_atapi_mask &= ~DEBUG_PROBE;
        !           311: #endif
        !           312: }
        !           313:
        !           314: int
        !           315: atapiscsi_detach(dev, flags)
        !           316:        struct device *dev;
        !           317:        int flags;
        !           318: {
        !           319:        return (config_detach_children(dev, flags));
        !           320: }
        !           321:
        !           322: int
        !           323: wdc_atapi_send_cmd(sc_xfer)
        !           324:        struct scsi_xfer *sc_xfer;
        !           325: {
        !           326:        struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc;
        !           327:        struct channel_softc *chp = as->chp;
        !           328:        struct ata_drive_datas *drvp = &chp->ch_drive[as->drive];
        !           329:        struct wdc_xfer *xfer;
        !           330:        int s, ret;
        !           331:        int idx;
        !           332:
        !           333:        WDCDEBUG_PRINT(("wdc_atapi_send_cmd %s:%d:%d start\n",
        !           334:            chp->wdc->sc_dev.dv_xname, chp->channel, as->drive), DEBUG_XFERS);
        !           335:
        !           336:        if (sc_xfer->sc_link->target != 0) {
        !           337:                sc_xfer->error = XS_DRIVER_STUFFUP;
        !           338:                return (COMPLETE);
        !           339:        }
        !           340:
        !           341:        xfer = wdc_get_xfer(sc_xfer->flags & SCSI_NOSLEEP
        !           342:            ? WDC_NOSLEEP : WDC_CANSLEEP);
        !           343:        if (xfer == NULL) {
        !           344:                return (TRY_AGAIN_LATER);
        !           345:        }
        !           346:        if (sc_xfer->flags & SCSI_POLL)
        !           347:                xfer->c_flags |= C_POLL;
        !           348:        xfer->drive = as->drive;
        !           349:        xfer->c_flags |= C_ATAPI;
        !           350:        xfer->cmd = sc_xfer;
        !           351:        xfer->databuf = sc_xfer->data;
        !           352:        xfer->c_bcount = sc_xfer->datalen;
        !           353:        xfer->c_start = wdc_atapi_start;
        !           354:        xfer->c_intr = wdc_atapi_intr;
        !           355:
        !           356:        timeout_set(&xfer->atapi_poll_to, wdc_atapi_timer_handler, chp);
        !           357:
        !           358:        WDCDEBUG_PRINT(("wdc_atapi_send_cmd %s:%d:%d ",
        !           359:            chp->wdc->sc_dev.dv_xname, chp->channel, as->drive),
        !           360:            DEBUG_XFERS | DEBUG_ERRORS);
        !           361:
        !           362:        for (idx = 0; idx < sc_xfer->cmdlen; idx++) {
        !           363:                WDCDEBUG_PRINT((" %02x",
        !           364:                                   ((unsigned char *)sc_xfer->cmd)[idx]),
        !           365:                    DEBUG_XFERS | DEBUG_ERRORS);
        !           366:        }
        !           367:        WDCDEBUG_PRINT(("\n"), DEBUG_XFERS | DEBUG_ERRORS);
        !           368:
        !           369:        s = splbio();
        !           370:
        !           371:        if (drvp->atapi_cap & ACAP_DSC) {
        !           372:                WDCDEBUG_PRINT(("about to send cmd 0x%x ",
        !           373:                    sc_xfer->cmd->opcode), DEBUG_DSC);
        !           374:                switch (sc_xfer->cmd->opcode) {
        !           375:                case READ:
        !           376:                case WRITE:
        !           377:                        xfer->c_flags |= C_MEDIA_ACCESS;
        !           378:
        !           379:                        /* If we are not in buffer availability mode,
        !           380:                           we limit the first request to 0 bytes, which
        !           381:                           gets us into buffer availability mode without
        !           382:                           holding the bus.  */
        !           383:                        if (!(drvp->drive_flags & DRIVE_DSCBA)) {
        !           384:                                xfer->c_bcount = 0;
        !           385:                                xfer->transfer_len =
        !           386:                                  _3btol(((struct scsi_rw_tape *)
        !           387:                                          sc_xfer->cmd)->len);
        !           388:                                _lto3b(0,
        !           389:                                    ((struct scsi_rw_tape *)
        !           390:                                    sc_xfer->cmd)->len);
        !           391:                                xfer->c_done = wdc_atapi_tape_done;
        !           392:                                WDCDEBUG_PRINT(
        !           393:                                    ("R/W in completion mode, do 0 blocks\n"),
        !           394:                                    DEBUG_DSC);
        !           395:                        } else
        !           396:                                WDCDEBUG_PRINT(("R/W %d blocks %d bytes\n",
        !           397:                                    _3btol(((struct scsi_rw_tape *)
        !           398:                                        sc_xfer->cmd)->len),
        !           399:                                    sc_xfer->datalen),
        !           400:                                    DEBUG_DSC);
        !           401:
        !           402:                        /* DSC will change to buffer availability mode.
        !           403:                           We reflect this in wdc_atapi_intr.  */
        !           404:                        break;
        !           405:
        !           406:                case ERASE:             /* Media access commands */
        !           407:                case LOAD:
        !           408:                case REWIND:
        !           409:                case SPACE:
        !           410:                case WRITE_FILEMARKS:
        !           411: #if 0
        !           412:                case LOCATE:
        !           413:                case READ_POSITION:
        !           414: #endif
        !           415:
        !           416:                        xfer->c_flags |= C_MEDIA_ACCESS;
        !           417:                        break;
        !           418:
        !           419:                default:
        !           420:                        WDCDEBUG_PRINT(("no media access\n"), DEBUG_DSC);
        !           421:                }
        !           422:        }
        !           423:
        !           424:        wdc_exec_xfer(chp, xfer);
        !           425: #ifdef DIAGNOSTIC
        !           426:        if ((xfer->c_flags & C_POLL) != 0 &&
        !           427:            (sc_xfer->flags & ITSDONE) == 0)
        !           428:                panic("wdc_atapi_send_cmd: polled command not done");
        !           429: #endif
        !           430:        ret = (sc_xfer->flags & ITSDONE) ? COMPLETE : SUCCESSFULLY_QUEUED;
        !           431:        splx(s);
        !           432:        return (ret);
        !           433: }
        !           434:
        !           435: void
        !           436: wdc_atapi_minphys (struct buf *bp)
        !           437: {
        !           438:        if(bp->b_bcount > MAX_SIZE)
        !           439:                bp->b_bcount = MAX_SIZE;
        !           440:        minphys(bp);
        !           441: }
        !           442:
        !           443: int
        !           444: wdc_atapi_ioctl (sc_link, cmd, addr, flag, p)
        !           445:        struct   scsi_link *sc_link;
        !           446:        u_long   cmd;
        !           447:        caddr_t  addr;
        !           448:        int      flag;
        !           449:        struct proc *p;
        !           450: {
        !           451:        struct atapiscsi_softc *as = sc_link->adapter_softc;
        !           452:        struct channel_softc *chp = as->chp;
        !           453:        struct ata_drive_datas *drvp = &chp->ch_drive[as->drive];
        !           454:
        !           455:        if (sc_link->target != 0)
        !           456:                return ENOTTY;
        !           457:
        !           458:        return (wdc_ioctl(drvp, cmd, addr, flag, p));
        !           459: }
        !           460:
        !           461:
        !           462: /*
        !           463:  * Returns 1 if we experienced an ATA-level abort command
        !           464:  *           (ABRT bit set but no additional sense)
        !           465:  *         0 if normal command processing
        !           466:  */
        !           467: int
        !           468: atapi_to_scsi_sense(xfer, flags)
        !           469:        struct scsi_xfer *xfer;
        !           470:        u_int8_t flags;
        !           471: {
        !           472:        struct scsi_sense_data *sense = &xfer->sense;
        !           473:        int ret = 0;
        !           474:
        !           475:        xfer->error = XS_SHORTSENSE;
        !           476:
        !           477:        sense->error_code = SSD_ERRCODE_VALID | 0x70;
        !           478:        sense->flags = (flags >> 4);
        !           479:
        !           480:        WDCDEBUG_PRINT(("Atapi error: %d ", (flags >> 4)), DEBUG_ERRORS);
        !           481:
        !           482:        if ((flags & 4) && (sense->flags == 0)) {
        !           483:                sense->flags = SKEY_ABORTED_COMMAND;
        !           484:                WDCDEBUG_PRINT(("ABRT "), DEBUG_ERRORS);
        !           485:                ret = 1;
        !           486:        }
        !           487:
        !           488:        if (flags & 0x1) {
        !           489:                sense->flags |= SSD_ILI;
        !           490:                WDCDEBUG_PRINT(("ILI "), DEBUG_ERRORS);
        !           491:        }
        !           492:
        !           493:        if (flags & 0x2) {
        !           494:                sense->flags |= SSD_EOM;
        !           495:                WDCDEBUG_PRINT(("EOM "), DEBUG_ERRORS);
        !           496:        }
        !           497:
        !           498:        /* Media change requested */
        !           499:        /* Let's ignore these in version 1 */
        !           500:        if (flags & 0x8) {
        !           501:                WDCDEBUG_PRINT(("MCR "), DEBUG_ERRORS);
        !           502:                if (sense->flags == 0)
        !           503:                        xfer->error = XS_NOERROR;
        !           504:        }
        !           505:
        !           506:        WDCDEBUG_PRINT(("\n"), DEBUG_ERRORS);
        !           507:        return (ret);
        !           508: }
        !           509:
        !           510: int wdc_atapi_drive_selected(struct channel_softc *, int);
        !           511:
        !           512: int
        !           513: wdc_atapi_drive_selected(chp, drive)
        !           514:        struct channel_softc *chp;
        !           515:        int drive;
        !           516: {
        !           517:        u_int8_t reg = CHP_READ_REG(chp, wdr_sdh);
        !           518:
        !           519:        WDC_LOG_REG(chp, wdr_sdh, reg);
        !           520:
        !           521:        return ((reg & 0x10) == (drive << 4));
        !           522: }
        !           523:
        !           524: enum atapi_context {
        !           525:        ctxt_process = 0,
        !           526:        ctxt_timer = 1,
        !           527:        ctxt_interrupt = 2
        !           528: };
        !           529:
        !           530: void wdc_atapi_the_machine(struct channel_softc *, struct wdc_xfer *,
        !           531:     enum atapi_context);
        !           532:
        !           533: void wdc_atapi_the_poll_machine(struct channel_softc *, struct wdc_xfer *);
        !           534:
        !           535: void
        !           536: wdc_atapi_start(chp, xfer)
        !           537:        struct channel_softc *chp;
        !           538:        struct wdc_xfer *xfer;
        !           539: {
        !           540:        xfer->next = wdc_atapi_real_start;
        !           541:
        !           542:        wdc_atapi_the_machine(chp, xfer, ctxt_process);
        !           543: }
        !           544:
        !           545:
        !           546: void
        !           547: wdc_atapi_timer_handler(arg)
        !           548:        void *arg;
        !           549: {
        !           550:        struct channel_softc *chp = arg;
        !           551:        struct wdc_xfer *xfer;
        !           552:        int s;
        !           553:
        !           554:        s = splbio();
        !           555:        xfer = TAILQ_FIRST(&chp->ch_queue->sc_xfer);
        !           556:        if (xfer == NULL ||
        !           557:            !timeout_triggered(&xfer->atapi_poll_to)) {
        !           558:                splx(s);
        !           559:                return;
        !           560:        }
        !           561:        xfer->c_flags &= ~C_POLL_MACHINE;
        !           562:        timeout_del(&xfer->atapi_poll_to);
        !           563:        chp->ch_flags &= ~WDCF_IRQ_WAIT;
        !           564:        wdc_atapi_the_machine(chp, xfer, ctxt_timer);
        !           565:        splx(s);
        !           566: }
        !           567:
        !           568:
        !           569: int
        !           570: wdc_atapi_intr(chp, xfer, irq)
        !           571:        struct channel_softc *chp;
        !           572:        struct wdc_xfer *xfer;
        !           573:        int irq;
        !           574: {
        !           575:        timeout_del(&chp->ch_timo);
        !           576:
        !           577:        /* XXX we should consider an alternate signaling regime here */
        !           578:        if (xfer->c_flags & C_TIMEOU) {
        !           579:                xfer->c_flags &= ~C_TIMEOU;
        !           580:                wdc_atapi_the_machine(chp, xfer, ctxt_timer);
        !           581:                return (0);
        !           582:        }
        !           583:
        !           584:        wdc_atapi_the_machine(chp, xfer, ctxt_interrupt);
        !           585:
        !           586:        return (-1);
        !           587: }
        !           588:
        !           589: struct atapi_return_args {
        !           590:        int timeout;
        !           591:        int delay;
        !           592:        int expect_irq;
        !           593: };
        !           594:
        !           595: #define ARGS_INIT {-1, 0, 0}
        !           596:
        !           597: void
        !           598: wdc_atapi_the_poll_machine(chp, xfer)
        !           599:        struct channel_softc *chp;
        !           600:        struct wdc_xfer *xfer;
        !           601: {
        !           602:        int  idx = 0;
        !           603:        int  current_timeout = 10;
        !           604:
        !           605:
        !           606:        while (1) {
        !           607:                struct atapi_return_args retargs = ARGS_INIT;
        !           608:                idx++;
        !           609:
        !           610:                (xfer->next)(chp, xfer, (current_timeout * 1000 <= idx),
        !           611:                    &retargs);
        !           612:
        !           613:                if (xfer->next == NULL) {
        !           614:                        wdc_free_xfer(chp, xfer);
        !           615:                        wdcstart(chp);
        !           616:                        return;
        !           617:                }
        !           618:
        !           619:                if (retargs.timeout != -1) {
        !           620:                        current_timeout = retargs.timeout;
        !           621:                        idx = 0;
        !           622:                }
        !           623:
        !           624:                if (retargs.delay != 0) {
        !           625:                        delay (1000 * retargs.delay);
        !           626:                        idx += 1000 * retargs.delay;
        !           627:                }
        !           628:
        !           629:                DELAY(1);
        !           630:        }
        !           631: }
        !           632:
        !           633:
        !           634: void
        !           635: wdc_atapi_the_machine(chp, xfer, ctxt)
        !           636:        struct channel_softc *chp;
        !           637:        struct wdc_xfer *xfer;
        !           638:        enum atapi_context ctxt;
        !           639: {
        !           640:        int idx = 0;
        !           641:        extern int ticks;
        !           642:        int timeout_delay = hz / 10;
        !           643:
        !           644:        if (xfer->c_flags & C_POLL) {
        !           645:                wdc_disable_intr(chp);
        !           646:
        !           647:                if (ctxt != ctxt_process) {
        !           648:                        if (ctxt == ctxt_interrupt)
        !           649:                                xfer->endticks = 1;
        !           650:
        !           651:                        return;
        !           652:                }
        !           653:
        !           654:                wdc_atapi_the_poll_machine(chp, xfer);
        !           655:                return;
        !           656:        }
        !           657:
        !           658:        /* Don't go through more than 50 state machine steps
        !           659:           before yielding. This tries to limit the amount of time
        !           660:           spent at high SPL */
        !           661:        for (idx = 0; idx < 50; idx++) {
        !           662:                struct atapi_return_args retargs = ARGS_INIT;
        !           663:
        !           664:                (xfer->next)(chp, xfer,
        !           665:                    xfer->endticks && (ticks - xfer->endticks >= 0),
        !           666:                    &retargs);
        !           667:
        !           668:                if (retargs.timeout != -1)
        !           669:                        /*
        !           670:                         * Add 1 tick to compensate for the fact that we
        !           671:                         * can be just microseconds before the tick changes.
        !           672:                         */
        !           673:                        xfer->endticks =
        !           674:                            max((retargs.timeout * hz) / 1000, 1) + 1 + ticks;
        !           675:
        !           676:                if (xfer->next == NULL) {
        !           677:                        if (xfer->c_flags & C_POLL_MACHINE)
        !           678:                                timeout_del(&xfer->atapi_poll_to);
        !           679:
        !           680:                        wdc_free_xfer(chp, xfer);
        !           681:                        wdcstart(chp);
        !           682:
        !           683:                        return;
        !           684:                }
        !           685:
        !           686:                if (retargs.expect_irq) {
        !           687:                        chp->ch_flags |= WDCF_IRQ_WAIT;
        !           688:                        timeout_add(&chp->ch_timo, xfer->endticks - ticks);
        !           689:                        return;
        !           690:                }
        !           691:
        !           692:                if (retargs.delay != 0) {
        !           693:                        timeout_delay = max(retargs.delay * hz / 1000, 1);
        !           694:                        break;
        !           695:                }
        !           696:
        !           697:                DELAY(1);
        !           698:        }
        !           699:
        !           700:        timeout_add(&xfer->atapi_poll_to, timeout_delay);
        !           701:        xfer->c_flags |= C_POLL_MACHINE;
        !           702:
        !           703:        return;
        !           704: }
        !           705:
        !           706:
        !           707: void wdc_atapi_update_status(struct channel_softc *);
        !           708:
        !           709: void
        !           710: wdc_atapi_update_status(chp)
        !           711:        struct channel_softc *chp;
        !           712: {
        !           713:        chp->ch_status = CHP_READ_REG(chp, wdr_status);
        !           714:
        !           715:        WDC_LOG_STATUS(chp, chp->ch_status);
        !           716:
        !           717:        if (chp->ch_status == 0xff && (chp->ch_flags & WDCF_ONESLAVE)) {
        !           718:                wdc_set_drive(chp, 1);
        !           719:
        !           720:                chp->ch_status = CHP_READ_REG(chp, wdr_status);
        !           721:                WDC_LOG_STATUS(chp, chp->ch_status);
        !           722:        }
        !           723:
        !           724:        if ((chp->ch_status & (WDCS_BSY | WDCS_ERR)) == WDCS_ERR) {
        !           725:                chp->ch_error = CHP_READ_REG(chp, wdr_error);
        !           726:                WDC_LOG_ERROR(chp, chp->ch_error);
        !           727:        }
        !           728: }
        !           729:
        !           730: void
        !           731: wdc_atapi_real_start(chp, xfer, timeout, ret)
        !           732:        struct channel_softc *chp;
        !           733:        struct wdc_xfer *xfer;
        !           734:        int timeout;
        !           735:        struct atapi_return_args *ret;
        !           736: {
        !           737: #ifdef WDCDEBUG
        !           738:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !           739: #endif
        !           740:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
        !           741:
        !           742:        /*
        !           743:         * Only set the DMA flag if the transfer is reasonably large.
        !           744:         * At least one older drive failed to complete a 4 byte DMA transfer.
        !           745:         */
        !           746:
        !           747:        /* Turn off DMA flag on REQUEST SENSE */
        !           748:
        !           749:        if (!(xfer->c_flags & (C_POLL | C_SENSE | C_MEDIA_ACCESS)) &&
        !           750:            (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
        !           751:            (xfer->c_bcount > 100))
        !           752:                xfer->c_flags |= C_DMA;
        !           753:        else
        !           754:                xfer->c_flags &= ~C_DMA;
        !           755:
        !           756:
        !           757:        wdc_set_drive(chp, xfer->drive);
        !           758:
        !           759:        DELAY(1);
        !           760:
        !           761:        xfer->next = wdc_atapi_real_start_2;
        !           762:        ret->timeout = ATAPI_DELAY;
        !           763:
        !           764:        WDCDEBUG_PRINT(("wdc_atapi_start %s:%d:%d, scsi flags 0x%x, "
        !           765:            "ATA flags 0x%x\n",
        !           766:            chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive,
        !           767:            sc_xfer->flags, xfer->c_flags), DEBUG_XFERS);
        !           768:
        !           769:
        !           770:        return;
        !           771: }
        !           772:
        !           773:
        !           774: void
        !           775: wdc_atapi_real_start_2(chp, xfer, timeout, ret)
        !           776:        struct channel_softc *chp;
        !           777:        struct wdc_xfer *xfer;
        !           778:        int timeout;
        !           779:        struct atapi_return_args *ret;
        !           780: {
        !           781:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !           782:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
        !           783:
        !           784:        if (timeout) {
        !           785:                printf("wdc_atapi_start: not ready, st = %02x\n",
        !           786:                    chp->ch_status);
        !           787:
        !           788:                sc_xfer->error = XS_TIMEOUT;
        !           789:                xfer->next = wdc_atapi_reset;
        !           790:                return;
        !           791:        } else {
        !           792:                wdc_atapi_update_status(chp);
        !           793:
        !           794:                if (chp->ch_status & (WDCS_BSY | WDCS_DRQ))
        !           795:                        return;
        !           796:        }
        !           797:
        !           798:        /* Do control operations specially. */
        !           799:        if (drvp->state < ATAPI_READY_STATE) {
        !           800:                xfer->next = wdc_atapi_ctrl;
        !           801:                return;
        !           802:        }
        !           803:
        !           804:        xfer->next = wdc_atapi_send_packet;
        !           805:        return;
        !           806: }
        !           807:
        !           808:
        !           809: void
        !           810: wdc_atapi_send_packet(chp, xfer, timeout, ret)
        !           811:        struct channel_softc *chp;
        !           812:        struct wdc_xfer *xfer;
        !           813:        int timeout;
        !           814:        struct atapi_return_args *ret;
        !           815: {
        !           816:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !           817:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
        !           818:
        !           819:        /*
        !           820:         * Even with WDCS_ERR, the device should accept a command packet
        !           821:         * Limit length to what can be stuffed into the cylinder register
        !           822:         * (16 bits).  Some CD-ROMs seem to interpret '0' as 65536,
        !           823:         * but not all devices do that and it's not obvious from the
        !           824:         * ATAPI spec that this behaviour should be expected.  If more
        !           825:         * data is necessary, multiple data transfer phases will be done.
        !           826:         */
        !           827:
        !           828:        wdccommand(chp, xfer->drive, ATAPI_PKT_CMD,
        !           829:            xfer->c_bcount <= 0xfffe ? xfer->c_bcount : 0xfffe,
        !           830:            0, 0, 0,
        !           831:            (xfer->c_flags & C_DMA) ? ATAPI_PKT_CMD_FTRE_DMA : 0);
        !           832:
        !           833:        if (xfer->c_flags & C_DMA)
        !           834:                drvp->n_xfers++;
        !           835:
        !           836:        DELAY(1);
        !           837:
        !           838:        xfer->next = wdc_atapi_intr_command;
        !           839:        ret->timeout = sc_xfer->timeout;
        !           840:
        !           841:        if ((drvp->atapi_cap & ATAPI_CFG_DRQ_MASK) == ATAPI_CFG_IRQ_DRQ) {
        !           842:                /* We expect an IRQ to tell us of the next state */
        !           843:                ret->expect_irq = 1;
        !           844:        }
        !           845:
        !           846:        WDCDEBUG_PRINT(("wdc_atapi_send_packet %s:%d:%d command sent\n",
        !           847:            chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive
        !           848:            ), DEBUG_XFERS);
        !           849:        return;
        !           850: }
        !           851:
        !           852: void
        !           853: wdc_atapi_intr_command(chp, xfer, timeout, ret)
        !           854:        struct channel_softc *chp;
        !           855:        struct wdc_xfer *xfer;
        !           856:        int timeout;
        !           857:        struct atapi_return_args *ret;
        !           858: {
        !           859:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !           860:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
        !           861:        struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc;
        !           862:        int i;
        !           863:        u_int8_t cmd[16];
        !           864:        struct scsi_sense *cmd_reqsense;
        !           865:        int cmdlen = (drvp->atapi_cap & ACAP_LEN) ? 16 : 12;
        !           866:        int dma_flags = ((sc_xfer->flags & SCSI_DATA_IN) ||
        !           867:            (xfer->c_flags & C_SENSE)) ?  WDC_DMA_READ : 0;
        !           868:
        !           869:        wdc_atapi_update_status(chp);
        !           870:
        !           871:        if ((chp->ch_status & WDCS_BSY) || !(chp->ch_status & WDCS_DRQ)) {
        !           872:                if (timeout)
        !           873:                        goto timeout;
        !           874:
        !           875:                return;
        !           876:        }
        !           877:
        !           878:        if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
        !           879:                chp->wdc->irqack(chp);
        !           880:
        !           881:        bzero(cmd, sizeof(cmd));
        !           882:
        !           883:        if (xfer->c_flags & C_SENSE) {
        !           884:                cmd_reqsense = (struct scsi_sense *)&cmd[0];
        !           885:                cmd_reqsense->opcode = REQUEST_SENSE;
        !           886:                cmd_reqsense->length = xfer->c_bcount;
        !           887:        } else
        !           888:                bcopy(sc_xfer->cmd, cmd, sc_xfer->cmdlen);
        !           889:
        !           890:        WDC_LOG_ATAPI_CMD(chp, xfer->drive, xfer->c_flags,
        !           891:            cmdlen, cmd);
        !           892:
        !           893:        for (i = 0; i < 12; i++)
        !           894:                WDCDEBUG_PRINT(("%02x ", cmd[i]), DEBUG_INTR);
        !           895:        WDCDEBUG_PRINT((": PHASE_CMDOUT\n"), DEBUG_INTR);
        !           896:
        !           897:        /* Init the DMA channel if necessary */
        !           898:        if (xfer->c_flags & C_DMA) {
        !           899:                if ((*chp->wdc->dma_init)(chp->wdc->dma_arg,
        !           900:                    chp->channel, xfer->drive, xfer->databuf,
        !           901:                    xfer->c_bcount, dma_flags) != 0) {
        !           902:                        sc_xfer->error = XS_DRIVER_STUFFUP;
        !           903:
        !           904:                        xfer->next = wdc_atapi_reset;
        !           905:                        return;
        !           906:                }
        !           907:        }
        !           908:
        !           909:        wdc_output_bytes(drvp, cmd, cmdlen);
        !           910:
        !           911:        /* Start the DMA channel if necessary */
        !           912:        if (xfer->c_flags & C_DMA) {
        !           913:                (*chp->wdc->dma_start)(chp->wdc->dma_arg,
        !           914:                    chp->channel, xfer->drive);
        !           915:                xfer->next = wdc_atapi_intr_complete;
        !           916:        } else {
        !           917:                if (xfer->c_bcount == 0)
        !           918:                        as->protocol_phase = as_completed;
        !           919:                else
        !           920:                        as->protocol_phase = as_data;
        !           921:
        !           922:                xfer->next = wdc_atapi_pio_intr;
        !           923:        }
        !           924:
        !           925:        ret->expect_irq = 1;
        !           926:
        !           927:        /* If we read/write to a tape we will get into buffer
        !           928:           availability mode.  */
        !           929:        if (drvp->atapi_cap & ACAP_DSC) {
        !           930:                if ((sc_xfer->cmd->opcode == READ ||
        !           931:                       sc_xfer->cmd->opcode == WRITE)) {
        !           932:                        drvp->drive_flags |= DRIVE_DSCBA;
        !           933:                        WDCDEBUG_PRINT(("set DSCBA\n"), DEBUG_DSC);
        !           934:                } else if ((xfer->c_flags & C_MEDIA_ACCESS) &&
        !           935:                    (drvp->drive_flags & DRIVE_DSCBA)) {
        !           936:                        /* Clause 3.2.4 of QIC-157 D.
        !           937:
        !           938:                           Any media access command other than read or
        !           939:                           write will switch DSC back to completion
        !           940:                           mode */
        !           941:                        drvp->drive_flags &= ~DRIVE_DSCBA;
        !           942:                        WDCDEBUG_PRINT(("clear DCSBA\n"), DEBUG_DSC);
        !           943:                }
        !           944:        }
        !           945:
        !           946:        return;
        !           947:
        !           948:  timeout:
        !           949:        printf ("%s:%d:%d: device timeout waiting to send SCSI packet\n",
        !           950:            chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive);
        !           951:
        !           952:        sc_xfer->error = XS_TIMEOUT;
        !           953:        xfer->next = wdc_atapi_reset;
        !           954:        return;
        !           955: }
        !           956:
        !           957:
        !           958: char *
        !           959: wdc_atapi_in_data_phase(xfer, len, ire)
        !           960:        struct wdc_xfer *xfer;
        !           961:        int len, ire;
        !           962: {
        !           963:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !           964:        struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc;
        !           965:        char *message;
        !           966:
        !           967:        if (as->protocol_phase != as_data) {
        !           968:                message = "unexpected data phase";
        !           969:                goto unexpected_state;
        !           970:        }
        !           971:
        !           972:        if (ire & WDCI_CMD) {
        !           973:                message = "unexpectedly in command phase";
        !           974:                goto unexpected_state;
        !           975:        }
        !           976:
        !           977:        if (!(xfer->c_flags & C_SENSE)) {
        !           978:                if (!(sc_xfer->flags & (SCSI_DATA_IN | SCSI_DATA_OUT))) {
        !           979:                        message = "data phase where none expected";
        !           980:                        goto unexpected_state;
        !           981:                }
        !           982:
        !           983:                /* Make sure polarities match */
        !           984:                if (((ire & WDCI_IN) == WDCI_IN) ==
        !           985:                    ((sc_xfer->flags & SCSI_DATA_OUT) == SCSI_DATA_OUT)) {
        !           986:                        message = "data transfer direction disagreement";
        !           987:                        goto unexpected_state;
        !           988:                }
        !           989:        } else {
        !           990:                if (!(ire & WDCI_IN)) {
        !           991:                        message = "data transfer direction disagreement during sense";
        !           992:                        goto unexpected_state;
        !           993:                }
        !           994:        }
        !           995:
        !           996:        if (len == 0) {
        !           997:                message = "zero length transfer requested in data phase";
        !           998:                goto unexpected_state;
        !           999:        }
        !          1000:
        !          1001:
        !          1002:        return (0);
        !          1003:
        !          1004:  unexpected_state:
        !          1005:
        !          1006:        return (message);
        !          1007: }
        !          1008:
        !          1009: void
        !          1010: wdc_atapi_intr_data(chp, xfer, timeout, ret)
        !          1011:        struct channel_softc *chp;
        !          1012:        struct wdc_xfer *xfer;
        !          1013:        int timeout;
        !          1014:        struct atapi_return_args *ret;
        !          1015: {
        !          1016:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !          1017:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
        !          1018:        int len, ire;
        !          1019:        char *message;
        !          1020:        int tohost;
        !          1021:
        !          1022:        len = (CHP_READ_REG(chp, wdr_cyl_hi) << 8) |
        !          1023:            CHP_READ_REG(chp, wdr_cyl_lo);
        !          1024:        WDC_LOG_REG(chp, wdr_cyl_lo, len);
        !          1025:
        !          1026:        ire = CHP_READ_REG(chp, wdr_ireason);
        !          1027:        WDC_LOG_REG(chp, wdr_ireason, ire);
        !          1028:
        !          1029:        if ((message = wdc_atapi_in_data_phase(xfer, len, ire))) {
        !          1030:                /* The drive has dropped BSY before setting up the
        !          1031:                   registers correctly for DATA phase. This drive is
        !          1032:                   not compliant with ATA/ATAPI-4.
        !          1033:
        !          1034:                   Give the drive 100ms to get its house in order
        !          1035:                   before we try again.  */
        !          1036:                WDCDEBUG_PRINT(("wdc_atapi_intr: %s\n", message),
        !          1037:                    DEBUG_ERRORS);
        !          1038:
        !          1039:                if (!timeout) {
        !          1040:                        ret->delay = 100;
        !          1041:                        return;
        !          1042:                }
        !          1043:        }
        !          1044:
        !          1045:        tohost = ((sc_xfer->flags & SCSI_DATA_IN) != 0 ||
        !          1046:            (xfer->c_flags & C_SENSE) != 0);
        !          1047:
        !          1048:        if (xfer->c_bcount >= len) {
        !          1049:                WDCDEBUG_PRINT(("wdc_atapi_intr: c_bcount %d len %d "
        !          1050:                    "st 0x%b err 0x%x "
        !          1051:                    "ire 0x%x\n", xfer->c_bcount,
        !          1052:                    len, chp->ch_status, WDCS_BITS, chp->ch_error, ire),
        !          1053:                    DEBUG_INTR);
        !          1054:
        !          1055:                /* Common case */
        !          1056:                if (!tohost)
        !          1057:                        wdc_output_bytes(drvp, (u_int8_t *)xfer->databuf +
        !          1058:                            xfer->c_skip, len);
        !          1059:                else
        !          1060:                        wdc_input_bytes(drvp, (u_int8_t *)xfer->databuf +
        !          1061:                            xfer->c_skip, len);
        !          1062:
        !          1063:                xfer->c_skip += len;
        !          1064:                xfer->c_bcount -= len;
        !          1065:        } else {
        !          1066:                /* Exceptional case - drive want to transfer more
        !          1067:                   data than we have buffer for */
        !          1068:                if (!tohost) {
        !          1069:                        /* Wouldn't it be better to just abort here rather
        !          1070:                           than to write random stuff to drive? */
        !          1071:                        printf("wdc_atapi_intr: warning: device requesting "
        !          1072:                            "%d bytes, only %d left in buffer\n", len, xfer->c_bcount);
        !          1073:
        !          1074:                        wdc_output_bytes(drvp, (u_int8_t *)xfer->databuf +
        !          1075:                            xfer->c_skip, xfer->c_bcount);
        !          1076:
        !          1077:                        CHP_WRITE_RAW_MULTI_2(chp, NULL,
        !          1078:                            len - xfer->c_bcount);
        !          1079:                } else {
        !          1080:                        printf("wdc_atapi_intr: warning: reading only "
        !          1081:                            "%d of %d bytes\n", xfer->c_bcount, len);
        !          1082:
        !          1083:                        wdc_input_bytes(drvp,
        !          1084:                            (char *)xfer->databuf + xfer->c_skip,
        !          1085:                            xfer->c_bcount);
        !          1086:                        wdcbit_bucket(chp, len - xfer->c_bcount);
        !          1087:                }
        !          1088:
        !          1089:                xfer->c_skip += xfer->c_bcount;
        !          1090:                xfer->c_bcount = 0;
        !          1091:        }
        !          1092:
        !          1093:        ret->expect_irq = 1;
        !          1094:        xfer->next = wdc_atapi_pio_intr;
        !          1095:
        !          1096:        return;
        !          1097: }
        !          1098:
        !          1099: void
        !          1100: wdc_atapi_intr_complete(chp, xfer, timeout, ret)
        !          1101:        struct channel_softc *chp;
        !          1102:        struct wdc_xfer *xfer;
        !          1103:        int timeout;
        !          1104:        struct atapi_return_args *ret;
        !          1105: {
        !          1106:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !          1107:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
        !          1108:        struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc;
        !          1109:
        !          1110:        WDCDEBUG_PRINT(("PHASE_COMPLETED\n"), DEBUG_INTR);
        !          1111:
        !          1112:        if (xfer->c_flags & C_DMA) {
        !          1113:                int retry;
        !          1114:
        !          1115:                if (timeout) {
        !          1116:                        sc_xfer->error = XS_TIMEOUT;
        !          1117:                        ata_dmaerr(drvp);
        !          1118:
        !          1119:                        xfer->next = wdc_atapi_reset;
        !          1120:                        return;
        !          1121:                }
        !          1122:
        !          1123:                for (retry = 5; retry > 0; retry--) {
        !          1124:                        wdc_atapi_update_status(chp);
        !          1125:                        if ((chp->ch_status & (WDCS_BSY | WDCS_DRQ)) == 0)
        !          1126:                                break;
        !          1127:                        DELAY(5);
        !          1128:                }
        !          1129:                if (retry == 0) {
        !          1130:                        ret->expect_irq = 1;
        !          1131:                        return;
        !          1132:                }
        !          1133:
        !          1134:                chp->wdc->dma_status =
        !          1135:                    (*chp->wdc->dma_finish)
        !          1136:                    (chp->wdc->dma_arg, chp->channel,
        !          1137:                        xfer->drive, 1);
        !          1138:
        !          1139:                if (chp->wdc->dma_status & WDC_DMAST_UNDER)
        !          1140:                        xfer->c_bcount = 1;
        !          1141:                else
        !          1142:                        xfer->c_bcount = 0;
        !          1143:        }
        !          1144:
        !          1145:        as->protocol_phase = as_none;
        !          1146:
        !          1147:        if (xfer->c_flags & C_SENSE) {
        !          1148:                if (chp->ch_status & WDCS_ERR) {
        !          1149:                        if (chp->ch_error & WDCE_ABRT) {
        !          1150:                                WDCDEBUG_PRINT(("wdc_atapi_intr: request_sense aborted, "
        !          1151:                                                "calling wdc_atapi_done()"
        !          1152:                                        ), DEBUG_INTR);
        !          1153:                                xfer->next = wdc_atapi_done;
        !          1154:                                return;
        !          1155:                        }
        !          1156:
        !          1157:                        /*
        !          1158:                         * request sense failed ! it's not supposed
        !          1159:                         * to be possible
        !          1160:                         */
        !          1161:                        sc_xfer->error = XS_SHORTSENSE;
        !          1162:                } else if (xfer->c_bcount < sizeof(sc_xfer->sense)) {
        !          1163:                        /* use the sense we just read */
        !          1164:                        sc_xfer->error = XS_SENSE;
        !          1165:                } else {
        !          1166:                        /*
        !          1167:                         * command completed, but no data was read.
        !          1168:                         * use the short sense we saved previously.
        !          1169:                         */
        !          1170:                        sc_xfer->error = XS_SHORTSENSE;
        !          1171:                }
        !          1172:        } else {
        !          1173:                sc_xfer->resid = xfer->c_bcount;
        !          1174:                if (chp->ch_status & WDCS_ERR) {
        !          1175:                        if (!atapi_to_scsi_sense(sc_xfer, chp->ch_error) &&
        !          1176:                            (sc_xfer->sc_link->quirks &
        !          1177:                             ADEV_NOSENSE) == 0) {
        !          1178:                                /*
        !          1179:                                 * let the driver issue a
        !          1180:                                 * 'request sense'
        !          1181:                                 */
        !          1182:                                xfer->databuf = &sc_xfer->sense;
        !          1183:                                xfer->c_bcount = sizeof(sc_xfer->sense);
        !          1184:                                xfer->c_skip = 0;
        !          1185:                                xfer->c_done = NULL;
        !          1186:                                xfer->c_flags |= C_SENSE;
        !          1187:                                xfer->next = wdc_atapi_real_start;
        !          1188:                                return;
        !          1189:                        }
        !          1190:                }
        !          1191:        }
        !          1192:
        !          1193:         if ((xfer->c_flags & C_DMA) &&
        !          1194:            (chp->wdc->dma_status & ~WDC_DMAST_UNDER)) {
        !          1195:                ata_dmaerr(drvp);
        !          1196:                sc_xfer->error = XS_RESET;
        !          1197:
        !          1198:                xfer->next = wdc_atapi_reset;
        !          1199:                return;
        !          1200:        }
        !          1201:
        !          1202:
        !          1203:        if (xfer->c_bcount != 0) {
        !          1204:                WDCDEBUG_PRINT(("wdc_atapi_intr: bcount value is "
        !          1205:                                "%d after io\n", xfer->c_bcount), DEBUG_XFERS);
        !          1206:        }
        !          1207: #ifdef DIAGNOSTIC
        !          1208:        if (xfer->c_bcount < 0) {
        !          1209:                printf("wdc_atapi_intr warning: bcount value "
        !          1210:                       "is %d after io\n", xfer->c_bcount);
        !          1211:        }
        !          1212: #endif
        !          1213:
        !          1214:        WDCDEBUG_PRINT(("wdc_atapi_intr: wdc_atapi_done() (end), error 0x%x "
        !          1215:                        "\n", sc_xfer->error),
        !          1216:                       DEBUG_INTR);
        !          1217:
        !          1218:
        !          1219:        if (xfer->c_done)
        !          1220:                xfer->next = xfer->c_done;
        !          1221:        else
        !          1222:                xfer->next = wdc_atapi_done;
        !          1223:
        !          1224:        return;
        !          1225: }
        !          1226:
        !          1227: void
        !          1228: wdc_atapi_pio_intr(chp, xfer, timeout, ret)
        !          1229:        struct channel_softc *chp;
        !          1230:        struct wdc_xfer *xfer;
        !          1231:        int timeout;
        !          1232:        struct atapi_return_args *ret;
        !          1233: {
        !          1234:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !          1235:        struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc;
        !          1236:        u_int8_t ireason;
        !          1237:
        !          1238:        wdc_atapi_update_status(chp);
        !          1239:
        !          1240:        if (chp->ch_status & WDCS_BSY) {
        !          1241:                if (timeout)
        !          1242:                        goto timeout;
        !          1243:
        !          1244:                return;
        !          1245:        }
        !          1246:
        !          1247:        if (!wdc_atapi_drive_selected(chp, xfer->drive)) {
        !          1248:                WDCDEBUG_PRINT(("wdc_atapi_intr_for_us: wrong drive selected\n"), DEBUG_INTR);
        !          1249:                wdc_set_drive(chp, xfer->drive);
        !          1250:                delay (1);
        !          1251:
        !          1252:                if (!timeout)
        !          1253:                        return;
        !          1254:        }
        !          1255:
        !          1256:        if ((xfer->c_flags & C_MEDIA_ACCESS) &&
        !          1257:            !(chp->ch_status & (WDCS_DSC | WDCS_DRQ))) {
        !          1258:                if (timeout)
        !          1259:                        goto timeout;
        !          1260:
        !          1261:                ret->delay = 100;
        !          1262:                return;
        !          1263:        }
        !          1264:
        !          1265:        if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
        !          1266:                chp->wdc->irqack(chp);
        !          1267:
        !          1268:        ireason = CHP_READ_REG(chp, wdr_ireason);
        !          1269:        WDC_LOG_REG(chp, wdr_ireason, ireason);
        !          1270:
        !          1271:        WDCDEBUG_PRINT(("Phase %d, (0x%b, 0x%x) ", as->protocol_phase,
        !          1272:            chp->ch_status, WDCS_BITS, ireason), DEBUG_INTR );
        !          1273:
        !          1274:        switch (as->protocol_phase) {
        !          1275:        case as_data:
        !          1276:                if ((chp->ch_status & WDCS_DRQ) ||
        !          1277:                    (ireason & 3) != 3) {
        !          1278:                        if (timeout)
        !          1279:                                goto timeout;
        !          1280:
        !          1281:                        wdc_atapi_intr_data(chp, xfer, timeout, ret);
        !          1282:                        return;
        !          1283:                }
        !          1284:
        !          1285:        case as_completed:
        !          1286:                if ((chp->ch_status & WDCS_DRQ) ||
        !          1287:                    (ireason & 3) != 3) {
        !          1288:                        if (timeout)
        !          1289:                                goto timeout;
        !          1290:
        !          1291:                        ret->delay = 100;
        !          1292:                        return;
        !          1293:                }
        !          1294:
        !          1295:                wdc_atapi_intr_complete(chp, xfer, timeout, ret);
        !          1296:                return;
        !          1297:
        !          1298:        default:
        !          1299:                printf ("atapiscsi: Shouldn't get here\n");
        !          1300:                sc_xfer->error = XS_DRIVER_STUFFUP;
        !          1301:                xfer->next = wdc_atapi_reset;
        !          1302:                return;
        !          1303:        }
        !          1304:
        !          1305:        return;
        !          1306: timeout:
        !          1307:        ireason = CHP_READ_REG(chp, wdr_ireason);
        !          1308:        WDC_LOG_REG(chp, wdr_ireason, ireason);
        !          1309:
        !          1310:        printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d, "
        !          1311:            "status=0x%b, ireason=0x%x\n",
        !          1312:            chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
        !          1313:            xfer->c_bcount, xfer->c_skip, chp->ch_status, WDCS_BITS, ireason);
        !          1314:
        !          1315:        sc_xfer->error = XS_TIMEOUT;
        !          1316:        xfer->next = wdc_atapi_reset;
        !          1317:        return;
        !          1318: }
        !          1319:
        !          1320:
        !          1321:
        !          1322: void
        !          1323: wdc_atapi_ctrl(chp, xfer, timeout, ret)
        !          1324:        struct channel_softc *chp;
        !          1325:        struct wdc_xfer *xfer;
        !          1326:        int timeout;
        !          1327:        struct atapi_return_args *ret;
        !          1328: {
        !          1329:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !          1330:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
        !          1331:        char *errstring = NULL;
        !          1332:
        !          1333:        wdc_atapi_update_status(chp);
        !          1334:
        !          1335:        if (!timeout) {
        !          1336:                switch (drvp->state) {
        !          1337:                case ATAPI_IDENTIFY_WAIT_STATE:
        !          1338:                        if (chp->ch_status & WDCS_BSY)
        !          1339:                                return;
        !          1340:                        break;
        !          1341:                default:
        !          1342:                        if (chp->ch_status & (WDCS_BSY | WDCS_DRQ))
        !          1343:                                return;
        !          1344:                        break;
        !          1345:                }
        !          1346:        }
        !          1347:
        !          1348:        if (!wdc_atapi_drive_selected(chp, xfer->drive))
        !          1349:        {
        !          1350:                wdc_set_drive(chp, xfer->drive);
        !          1351:                delay (1);
        !          1352:        }
        !          1353:
        !          1354:        if (timeout) {
        !          1355:                int trigger_timeout = 1;
        !          1356:
        !          1357:                switch (drvp->state) {
        !          1358:                case ATAPI_DEVICE_RESET_WAIT_STATE:
        !          1359:                        errstring = "Device Reset Wait";
        !          1360:                        drvp->drive_flags &= ~DRIVE_DEVICE_RESET;
        !          1361:                        break;
        !          1362:
        !          1363:                case ATAPI_IDENTIFY_WAIT_STATE:
        !          1364:                        errstring = "Identify";
        !          1365:                        if (!(chp->ch_status & WDCS_BSY) &&
        !          1366:                            (chp->ch_status & (WDCS_DRQ | WDCS_ERR)))
        !          1367:                                trigger_timeout = 0;
        !          1368:
        !          1369:                        break;
        !          1370:
        !          1371:                case ATAPI_PIOMODE_STATE:
        !          1372:                        errstring = "Post-Identify";
        !          1373:                        if (!(chp->ch_status & (WDCS_BSY | WDCS_DRQ)))
        !          1374:                                trigger_timeout = 0;
        !          1375:                        break;
        !          1376:
        !          1377:                case ATAPI_PIOMODE_WAIT_STATE:
        !          1378:                        errstring = "PIOMODE";
        !          1379:                        if (chp->ch_status & (WDCS_BSY | WDCS_DRQ))
        !          1380:                                drvp->drive_flags &= ~DRIVE_MODE;
        !          1381:                        else
        !          1382:                                trigger_timeout = 0;
        !          1383:                        break;
        !          1384:                case ATAPI_DMAMODE_WAIT_STATE:
        !          1385:                        errstring = "dmamode";
        !          1386:                        if (chp->ch_status & (WDCS_BSY | WDCS_DRQ))
        !          1387:                                drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
        !          1388:                        else
        !          1389:                                trigger_timeout = 0;
        !          1390:                        break;
        !          1391:
        !          1392:                default:
        !          1393:                        errstring = "unknown state";
        !          1394:                        break;
        !          1395:                }
        !          1396:
        !          1397:                if (trigger_timeout)
        !          1398:                        goto timeout;
        !          1399:        }
        !          1400:
        !          1401:        WDCDEBUG_PRINT(("wdc_atapi_ctrl %s:%d:%d state %d\n",
        !          1402:            chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive, drvp->state),
        !          1403:            DEBUG_INTR | DEBUG_FUNCS);
        !          1404:
        !          1405:        switch (drvp->state) {
        !          1406:                /* My ATAPI slave device likes to assert DASP-/PDIAG- until
        !          1407:                   it is DEVICE RESET. This causes the LED to stay on.
        !          1408:
        !          1409:                   There is a trade-off here. This drive will cause any
        !          1410:                   play-back or seeks happening to be interrupted.
        !          1411:
        !          1412:                   Note that the bus reset that triggered this state
        !          1413:                   (which may have been caused by the other drive on
        !          1414:                   the chain) need not interrupt this playback. It happens
        !          1415:                   to on my Smart & Friendly CD burner.
        !          1416:
        !          1417:                   - csapuntz@
        !          1418:                */
        !          1419:        case ATAPI_RESET_BASE_STATE:
        !          1420:                if ((drvp->drive_flags & DRIVE_DEVICE_RESET) == 0) {
        !          1421:                        drvp->state = ATAPI_IDENTIFY_STATE;
        !          1422:                        break;
        !          1423:                }
        !          1424:
        !          1425:                wdccommandshort(chp, drvp->drive, ATAPI_DEVICE_RESET);
        !          1426:                drvp->state = ATAPI_DEVICE_RESET_WAIT_STATE;
        !          1427:                ret->delay = ATAPI_RESET_DELAY;
        !          1428:                ret->timeout = ATAPI_RESET_WAIT;
        !          1429:                break;
        !          1430:
        !          1431:        case ATAPI_DEVICE_RESET_WAIT_STATE:
        !          1432:                /* FALLTHROUGH */
        !          1433:
        !          1434:        case ATAPI_IDENTIFY_STATE:
        !          1435:                wdccommandshort(chp, drvp->drive, ATAPI_IDENTIFY_DEVICE);
        !          1436:                drvp->state = ATAPI_IDENTIFY_WAIT_STATE;
        !          1437:                ret->delay = 10;
        !          1438:                ret->timeout = ATAPI_RESET_WAIT;
        !          1439:                break;
        !          1440:
        !          1441:        case ATAPI_IDENTIFY_WAIT_STATE: {
        !          1442:                int idx = 0;
        !          1443:
        !          1444:                while ((chp->ch_status & WDCS_DRQ) &&
        !          1445:                    idx++ < 20) {
        !          1446:                        wdcbit_bucket(chp, 512);
        !          1447:
        !          1448:                        DELAY(1);
        !          1449:                        wdc_atapi_update_status(chp);
        !          1450:                }
        !          1451:
        !          1452:                drvp->state = ATAPI_PIOMODE_STATE;
        !          1453:                /*
        !          1454:                 * Note, we can't go directly to set PIO mode
        !          1455:                 * because the drive is free to assert BSY
        !          1456:                 * after the transfer
        !          1457:                 */
        !          1458:                break;
        !          1459:        }
        !          1460:
        !          1461:        case ATAPI_PIOMODE_STATE:
        !          1462:                /* Don't try to set mode if controller can't be adjusted */
        !          1463:                if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)
        !          1464:                        goto ready;
        !          1465:                /* Also don't try if the drive didn't report its mode */
        !          1466:                if ((drvp->drive_flags & DRIVE_MODE) == 0)
        !          1467:                        goto ready;
        !          1468:                /* SET FEATURES 0x08 is only for PIO mode > 2 */
        !          1469:                if (drvp->PIO_mode <= 2)
        !          1470:                        goto ready;
        !          1471:                wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
        !          1472:                    0x08 | drvp->PIO_mode, WDSF_SET_MODE);
        !          1473:                drvp->state = ATAPI_PIOMODE_WAIT_STATE;
        !          1474:                ret->timeout = ATAPI_CTRL_WAIT;
        !          1475:                ret->expect_irq = 1;
        !          1476:                break;
        !          1477:        case ATAPI_PIOMODE_WAIT_STATE:
        !          1478:                if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
        !          1479:                        chp->wdc->irqack(chp);
        !          1480:                if (chp->ch_status & WDCS_ERR) {
        !          1481:                        /* Downgrade straight to PIO mode 3 */
        !          1482:                        drvp->PIO_mode = 3;
        !          1483:                        chp->wdc->set_modes(chp);
        !          1484:                }
        !          1485:        /* FALLTHROUGH */
        !          1486:
        !          1487:        case ATAPI_DMAMODE_STATE:
        !          1488:                if (drvp->drive_flags & DRIVE_UDMA) {
        !          1489:                        wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
        !          1490:                            0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
        !          1491:                } else if (drvp->drive_flags & DRIVE_DMA) {
        !          1492:                        wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
        !          1493:                            0x20 | drvp->DMA_mode, WDSF_SET_MODE);
        !          1494:                } else {
        !          1495:                        goto ready;
        !          1496:                }
        !          1497:                drvp->state = ATAPI_DMAMODE_WAIT_STATE;
        !          1498:
        !          1499:                ret->timeout = ATAPI_CTRL_WAIT;
        !          1500:                ret->expect_irq = 1;
        !          1501:                break;
        !          1502:
        !          1503:        case ATAPI_DMAMODE_WAIT_STATE:
        !          1504:                if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
        !          1505:                        chp->wdc->irqack(chp);
        !          1506:                if (chp->ch_status & WDCS_ERR)
        !          1507:                        drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
        !          1508:        /* FALLTHROUGH */
        !          1509:
        !          1510:        case ATAPI_READY_STATE:
        !          1511:        ready:
        !          1512:                drvp->state = ATAPI_READY_STATE;
        !          1513:                xfer->next = wdc_atapi_real_start;
        !          1514:                break;
        !          1515:        }
        !          1516:        return;
        !          1517:
        !          1518: timeout:
        !          1519:        printf("%s:%d:%d: %s timed out\n",
        !          1520:            chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, errstring);
        !          1521:        sc_xfer->error = XS_TIMEOUT;
        !          1522:        xfer->next = wdc_atapi_reset;
        !          1523:        return;
        !          1524:
        !          1525: }
        !          1526:
        !          1527: void
        !          1528: wdc_atapi_tape_done(chp, xfer, timeout, ret)
        !          1529:        struct channel_softc *chp;
        !          1530:        struct wdc_xfer *xfer;
        !          1531:        int timeout;
        !          1532:        struct atapi_return_args *ret;
        !          1533: {
        !          1534:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !          1535:
        !          1536:        if (sc_xfer->error != XS_NOERROR) {
        !          1537:                xfer->next = wdc_atapi_done;
        !          1538:                return;
        !          1539:        }
        !          1540:
        !          1541:        _lto3b(xfer->transfer_len,
        !          1542:            ((struct scsi_rw_tape *)
        !          1543:                sc_xfer->cmd)->len);
        !          1544:
        !          1545:        xfer->c_bcount = sc_xfer->datalen;
        !          1546:        xfer->c_done = NULL;
        !          1547:        xfer->c_skip = 0;
        !          1548:
        !          1549:        xfer->next = wdc_atapi_real_start;
        !          1550:        return;
        !          1551: }
        !          1552:
        !          1553:
        !          1554: void
        !          1555: wdc_atapi_done(chp, xfer, timeout, ret)
        !          1556:        struct channel_softc *chp;
        !          1557:        struct wdc_xfer *xfer;
        !          1558:        int timeout;
        !          1559:        struct atapi_return_args *ret;
        !          1560: {
        !          1561:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !          1562:
        !          1563:        WDCDEBUG_PRINT(("wdc_atapi_done %s:%d:%d: flags 0x%x error 0x%x\n",
        !          1564:            chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
        !          1565:            (u_int)xfer->c_flags, sc_xfer->error), DEBUG_XFERS);
        !          1566:        WDC_LOG_ATAPI_DONE(chp, xfer->drive, xfer->c_flags, sc_xfer->error);
        !          1567:
        !          1568:        sc_xfer->flags |= ITSDONE;
        !          1569:
        !          1570:        if (xfer->c_flags & C_POLL) {
        !          1571:                wdc_enable_intr(chp);
        !          1572:        } else {
        !          1573:                WDCDEBUG_PRINT(("wdc_atapi_done: scsi_done\n"), DEBUG_XFERS);
        !          1574:                scsi_done(sc_xfer);
        !          1575:        }
        !          1576:
        !          1577:        xfer->next = NULL;
        !          1578:        return;
        !          1579: }
        !          1580:
        !          1581:
        !          1582: void
        !          1583: wdc_atapi_reset(chp, xfer, timeout, ret)
        !          1584:        struct channel_softc *chp;
        !          1585:        struct wdc_xfer *xfer;
        !          1586:        int timeout;
        !          1587:        struct atapi_return_args *ret;
        !          1588: {
        !          1589:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
        !          1590:
        !          1591:        if (drvp->state == 0) {
        !          1592:                xfer->next = wdc_atapi_done;
        !          1593:                return;
        !          1594:        }
        !          1595:
        !          1596:        WDCDEBUG_PRINT(("wdc_atapi_reset\n"), DEBUG_XFERS);
        !          1597:        wdccommandshort(chp, xfer->drive, ATAPI_SOFT_RESET);
        !          1598:        drvp->state = ATAPI_IDENTIFY_STATE;
        !          1599:
        !          1600:        drvp->n_resets++;
        !          1601:        /* Some ATAPI devices need extra time to find their
        !          1602:           brains after a reset
        !          1603:         */
        !          1604:        xfer->next = wdc_atapi_reset_2;
        !          1605:        ret->delay = ATAPI_RESET_DELAY;
        !          1606:        ret->timeout = ATAPI_RESET_WAIT;
        !          1607:        return;
        !          1608: }
        !          1609:
        !          1610: void
        !          1611: wdc_atapi_reset_2(chp, xfer, timeout, ret)
        !          1612:        struct channel_softc *chp;
        !          1613:        struct wdc_xfer *xfer;
        !          1614:        int timeout;
        !          1615:        struct atapi_return_args *ret;
        !          1616: {
        !          1617:        struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
        !          1618:        struct scsi_xfer *sc_xfer = xfer->cmd;
        !          1619:
        !          1620:        if (timeout) {
        !          1621:                printf("%s:%d:%d: soft reset failed\n",
        !          1622:                    chp->wdc->sc_dev.dv_xname, chp->channel,
        !          1623:                    xfer->drive);
        !          1624:                sc_xfer->error = XS_SELTIMEOUT;
        !          1625:                wdc_reset_channel(drvp);
        !          1626:
        !          1627:                xfer->next = wdc_atapi_done;
        !          1628:                return;
        !          1629:        }
        !          1630:
        !          1631:        wdc_atapi_update_status(chp);
        !          1632:
        !          1633:        if (chp->ch_status & (WDCS_BSY | WDCS_DRQ)) {
        !          1634:                return;
        !          1635:        }
        !          1636:
        !          1637:        xfer->next = wdc_atapi_done;
        !          1638:        return;
        !          1639: }

CVSweb