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

Annotation of src/sys/dev/ic/wdc.c, Revision 1.15

1.15    ! mycroft     1: /*     $NetBSD: wdc.c,v 1.14 1998/01/15 02:23:43 cgd Exp $ */
1.2       bouyer      2:
                      3: /*
                      4:  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
                      5:  *
                      6:  * DMA and multi-sector PIO handling are derived from code contributed by
                      7:  * Onno van der Linden.
                      8:  *
                      9:  * Atapi support added by Manuel Bouyer.
                     10:  *
1.12      cgd        11:  * Bus_space-ified by Christopher G. Demetriou.
                     12:  *
1.2       bouyer     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. All advertising materials mentioning features or use of this software
                     22:  *    must display the following acknowledgement:
                     23:  *     This product includes software developed by Charles M. Hannum.
                     24:  * 4. The name of the author may not be used to endorse or promote products
                     25:  *    derived from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     28:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     29:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     30:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     31:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     32:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     33:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     34:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     35:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     36:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     37:  */
                     38:
1.12      cgd        39: /*
                     40:  * CODE UNTESTED IN THE CURRENT REVISION:
                     41:  *     * DMA
                     42:  *     * 32-bit data port access.
                     43:  */
                     44:
1.2       bouyer     45: #include <sys/param.h>
                     46: #include <sys/systm.h>
                     47: #include <sys/kernel.h>
                     48: #include <sys/conf.h>
                     49: #include <sys/file.h>
                     50: #include <sys/stat.h>
                     51: #include <sys/ioctl.h>
                     52: #include <sys/buf.h>
                     53: #include <sys/uio.h>
                     54: #include <sys/malloc.h>
                     55: #include <sys/device.h>
                     56: #include <sys/disklabel.h>
                     57: #include <sys/disk.h>
                     58: #include <sys/syslog.h>
                     59: #include <sys/proc.h>
                     60:
                     61: #include <vm/vm.h>
                     62:
                     63: #include <machine/intr.h>
                     64: #include <machine/bus.h>
                     65:
1.12      cgd        66: #include <dev/ic/wdcreg.h>
                     67: #include <dev/ic/wdcvar.h>
                     68: #include <dev/ata/wdlink.h>
1.2       bouyer     69: #include "atapibus.h"
1.12      cgd        70: #include "wdc.h"
1.2       bouyer     71:
                     72: #if NATAPIBUS > 0
                     73: #include <dev/scsipi/scsipi_all.h>
1.12      cgd        74: #include <dev/scsipi/atapi_all.h>
1.2       bouyer     75: #include <dev/scsipi/atapiconf.h>
                     76: #endif
                     77:
                     78: #define        WAITTIME        (10 * hz)       /* time to wait for a completion */
                     79:        /* this is a lot for hard drives, but not for cdroms */
                     80: #define RECOVERYTIME hz/2
                     81: #define WDCDELAY       100
                     82: #define WDCNDELAY      100000  /* delay = 100us; so 10s for a controller state change */
                     83: #if 0
                     84: /* If you enable this, it will report any delays more than 100us * N long. */
                     85: #define WDCNDELAY_DEBUG        50
                     86: #endif
                     87:
                     88: #define        WDIORETRIES     5               /* number of retries before giving up */
                     89:
                     90: #define        WDPART(dev)                     DISKPART(dev)
                     91:
                     92: LIST_HEAD(xfer_free_list, wdc_xfer) xfer_free_list;
                     93:
1.12      cgd        94: int    wdc_init_controller __P((struct wdc_softc *,
                     95:            const struct wdc_attachment_data *));
1.2       bouyer     96: void   wdcstart        __P((struct wdc_softc *));
1.12      cgd        97: int    wdcreset        __P((struct wdc_softc *, int));
1.2       bouyer     98: #define VERBOSE 1
                     99: #define SILENT 0
                    100: void   wdcrestart      __P((void *arg));
                    101: void   wdcunwedge      __P((struct wdc_softc *));
                    102: void   wdctimeout      __P((void *arg));
1.12      cgd       103: int    wdccontrol      __P((struct wdc_softc*, struct wd_link *));
1.2       bouyer    104: void   wdc_free_xfer   __P((struct wdc_xfer *));
                    105: void   wdcerror        __P((struct wdc_softc*, char *));
                    106: void   wdcbit_bucket   __P(( struct wdc_softc *, int));
                    107: #if NWD > 0
1.12      cgd       108: int    wdprint                 __P((void *, const char *));
                    109: int    wdsetctlr               __P((struct wd_link *));
                    110: int    wdc_ata_intr    __P((struct wdc_softc *,struct wdc_xfer *));
1.2       bouyer    111: void   wdc_ata_start   __P((struct wdc_softc *,struct wdc_xfer *));
                    112: void   wdc_ata_done    __P((struct wdc_softc *, struct wdc_xfer *));
                    113: #endif /* NWD > 0 */
                    114: #if NATAPIBUS > 0
                    115: void   wdc_atapi_minphys __P((struct buf *bp));
                    116: void   wdc_atapi_start __P((struct wdc_softc *,struct wdc_xfer *));
1.12      cgd       117: int    wdc_atapi_intr  __P((struct wdc_softc *, struct wdc_xfer *));
1.2       bouyer    118: void   wdc_atapi_done  __P((struct wdc_softc *, struct wdc_xfer *));
1.12      cgd       119: int    wdc_atapi_send_command_packet __P((struct scsipi_xfer *sc_xfer));
1.2       bouyer    120: #define MAX_SIZE MAXPHYS /* XXX */
                    121: #endif
                    122:
1.8       bouyer    123: #ifdef ATAPI_DEBUG2
1.2       bouyer    124: static int wdc_nxfer;
                    125: #endif
                    126:
                    127: #ifdef WDDEBUG
                    128: #define WDDEBUG_PRINT(args)    printf args
                    129: #else
                    130: #define WDDEBUG_PRINT(args)
                    131: #endif
                    132:
                    133: #if NATAPIBUS > 0
                    134: static struct scsipi_adapter wdc_switch  = {
                    135:        wdc_atapi_send_command_packet,
                    136:        wdc_atapi_minphys,
                    137:        0,
                    138:        0
                    139: };
                    140: #endif
                    141:
1.12      cgd       142: /*
                    143:  * wdc_init_controller: Does a quick probe/init of the controller.
                    144:  *
                    145:  * Return values:
                    146:  *     0       No controller present (as far as it can tell).
                    147:  *     >0      Controller present and seemingly functional.
                    148:  *     <0      Controller present, but not working correctly.
                    149:  */
1.2       bouyer    150: int
1.12      cgd       151: wdc_init_controller(wdc, adp)
                    152:        struct wdc_softc *wdc;
                    153:        const struct wdc_attachment_data *adp;
                    154: {
                    155:        bus_space_tag_t iot;
                    156:        bus_space_handle_t ioh;
1.2       bouyer    157:
1.12      cgd       158:        iot = wdc->sc_iot;
                    159:        ioh = wdc->sc_ioh;
1.2       bouyer    160:
1.7       bouyer    161:        if (wdcreset(wdc, SILENT) != 0) {
1.2       bouyer    162:                /*
1.12      cgd       163:                 * If the reset failed, there is no master. test for
                    164:                 * ATAPI signature on the slave device. If no ATAPI
                    165:                 * slave, wait 5s and retry a reset.
1.2       bouyer    166:                 */
1.12      cgd       167:                bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10); /*slave*/
                    168:                if (bus_space_read_1(iot, ioh, wd_cyl_lo) == 0x14 &&
                    169:                    bus_space_read_1(iot, ioh, wd_cyl_hi) == 0xeb) {
1.7       bouyer    170:                        wdc->sc_flags |= WDCF_ONESLAVE;
                    171:                        goto drivefound;
                    172:                } else {
1.2       bouyer    173:                        delay(500000);
                    174:                        if (wdcreset(wdc, SILENT) != 0)
1.12      cgd       175:                                return (0);
1.2       bouyer    176:                }
1.7       bouyer    177:        }
1.9       fvdl      178:        delay(1000);
1.12      cgd       179:
                    180:        /*
                    181:         * Reset succeeded.  Test for ATAPI signature on both master
                    182:         * and slave.
                    183:         */
                    184:        if (bus_space_read_1(iot, ioh, wd_cyl_lo) == 0x14 &&
                    185:                bus_space_read_1(iot, ioh, wd_cyl_hi) == 0xeb)
1.7       bouyer    186:                goto drivefound;
1.12      cgd       187:        bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10);
                    188:        if (bus_space_read_1(iot, ioh, wd_cyl_lo) == 0x14 &&
                    189:                bus_space_read_1(iot, ioh, wd_cyl_hi) == 0xeb) {
1.2       bouyer    190:                wdc->sc_flags |= WDCF_ONESLAVE;
1.7       bouyer    191:                goto drivefound;
1.2       bouyer    192:        }
1.12      cgd       193:
                    194:        /*
                    195:         * Test non-ATAPI registers.  Error register not writable,
                    196:         * but all of cyllo is.
                    197:         */
                    198:        bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM);
                    199:        bus_space_write_1(iot, ioh, wd_error, 0x58);
                    200:        bus_space_write_1(iot, ioh, wd_cyl_lo, 0xa5);
                    201:        if (bus_space_read_1(iot, ioh, wd_error) != 0x58 &&
                    202:            bus_space_read_1(iot, ioh, wd_cyl_lo) == 0xa5)
                    203:                goto drivefound;
                    204:
                    205:        /*
                    206:         * If no drives found, but the resets succeeded, we claim to
                    207:         * have the controller, at least.
                    208:         */
                    209:        return (1);
                    210:
1.7       bouyer    211: drivefound:
1.2       bouyer    212:        /* Select drive 0 or ATAPI slave device */
                    213:        if (wdc->sc_flags & WDCF_ONESLAVE)
1.12      cgd       214:                bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM | 0x10);
1.2       bouyer    215:        else
1.12      cgd       216:                bus_space_write_1(iot, ioh, wd_sdh, WDSD_IBM);
1.2       bouyer    217:
                    218:        /* Wait for controller to become ready. */
                    219:        if (wait_for_unbusy(wdc) < 0)
1.12      cgd       220:                return (-1);
1.2       bouyer    221:
                    222:        /* Start drive diagnostics. */
1.12      cgd       223:        bus_space_write_1(iot, ioh, wd_command, WDCC_DIAGNOSE);
1.2       bouyer    224:
                    225:        /* Wait for command to complete. */
                    226:        if (wait_for_unbusy(wdc) < 0)
1.12      cgd       227:                return (-1);
1.2       bouyer    228:
                    229:        return 1;
                    230: }
                    231:
1.12      cgd       232: int
                    233: wdcprobe(adp)
                    234:        const struct wdc_attachment_data *adp;
                    235: {
                    236:        struct wdc_softc _wdc, *wdc = &_wdc;            /* XXX EWWWWW! */
                    237:        int rv;
                    238:
                    239:        bzero(wdc, sizeof *wdc);
                    240:        strcpy(wdc->sc_dev.dv_xname, "wdcprobe");
                    241:        wdc->sc_adp = adp;
                    242:
                    243:        rv = wdc_init_controller(wdc, adp);
                    244:
                    245:        if (rv < 0)
                    246:                rv = 1;
                    247:        return (rv);
                    248: }
                    249:
1.2       bouyer    250: void
1.12      cgd       251: wdcattach(wdc, adp)
                    252:        struct wdc_softc *wdc;
                    253:        const struct wdc_attachment_data *adp;
1.2       bouyer    254: {
                    255: #if NWD > 0
                    256:        int drive;
                    257: #endif
                    258:
1.12      cgd       259:        wdc->sc_adp = adp;
                    260:        if (wdc_init_controller(wdc, adp) <= 0) {
1.15    ! mycroft   261:                printf("%s: controller wouldn't initialize properly\n",
        !           262:                    wdc->sc_dev.dv_xname);
1.12      cgd       263:                return;
                    264:        }
                    265:
1.2       bouyer    266:        TAILQ_INIT(&wdc->sc_xfer);
                    267:
1.12      cgd       268:        if (wdc->sc_cap & WDC_CAPABILITY_DMA)
                    269:                (*wdc->sc_dma_setup)(wdc->sc_dma_arg);
1.2       bouyer    270:
1.8       bouyer    271: #ifdef ATAPI_DEBUG2
1.2       bouyer    272:        wdc_nxfer = 0;
                    273: #endif
                    274:
                    275: #if NATAPIBUS > 0
                    276:        /*
                    277:         * Attach an ATAPI bus, if configured.
                    278:         */
                    279:        wdc->ab_link = malloc(sizeof(struct scsipi_link), M_DEVBUF, M_NOWAIT);
                    280:        if (wdc->ab_link == NULL) {
1.12      cgd       281:                printf("%s: can't allocate ATAPI link\n",
                    282:                    wdc->sc_dev.dv_xname);
1.2       bouyer    283:                return;
                    284:        }
                    285:        bzero(wdc->ab_link,sizeof(struct scsipi_link));
                    286:        wdc->ab_link->type = BUS_ATAPI;
                    287:        wdc->ab_link->openings = 1;
                    288:        wdc->ab_link->scsipi_atapi.type = ATAPI;
                    289:        wdc->ab_link->scsipi_atapi.channel = 0;
                    290:        wdc->ab_link->adapter_softc = (caddr_t)wdc;
                    291:        wdc->ab_link->adapter = &wdc_switch;
1.12      cgd       292:        (void)config_found(&wdc->sc_dev, (void *)wdc->ab_link, NULL);
1.2       bouyer    293: #endif /* NATAPIBUS > 0 */
                    294: #if NWD > 0
                    295:        /*
                    296:         * Attach standard IDE/ESDI/etc. disks to the controller.
                    297:         */
                    298:        for (drive = 0; drive < 2; drive++) {
1.4       bouyer    299:                /* if a disk is already present, skip */
                    300:                if ((wdc->sc_drives_mask & (1 << drive)) != 0) {
                    301:                        continue;
                    302:                }
1.2       bouyer    303:                /* controller active while autoconf */
                    304:                wdc->sc_flags |= WDCF_ACTIVE;
                    305:
                    306:                if (wdccommandshort(wdc, drive, WDCC_RECAL) != 0 ||
                    307:                    wait_for_ready(wdc) != 0) {
                    308:                        wdc->d_link[drive] = NULL;
                    309:                        wdc->sc_flags &= ~WDCF_ACTIVE;
                    310:                } else {
                    311:                        wdc->sc_flags &= ~WDCF_ACTIVE;
                    312:                        wdc->d_link[drive] = malloc(sizeof(struct wd_link),
                    313:                            M_DEVBUF, M_NOWAIT);
                    314:                        if (wdc->d_link[drive] == NULL) {
                    315:                                printf("%s: can't allocate link for drive %d\n",
1.12      cgd       316:                                    wdc->sc_dev.dv_xname, drive);
1.2       bouyer    317:                                continue;
                    318:                        }
                    319:                        bzero(wdc->d_link[drive],sizeof(struct wd_link));
                    320:                        wdc->d_link[drive]->type = ATA;
                    321:                        wdc->d_link[drive]->wdc_softc =(caddr_t) wdc;
                    322:                        wdc->d_link[drive]->drive = drive;
1.12      cgd       323:                        if (wdc->sc_cap & WDC_CAPABILITY_DMA)
1.2       bouyer    324:                                wdc->d_link[drive]->sc_mode = WDM_DMA;
                    325:                        else
                    326:                                wdc->d_link[drive]->sc_mode = 0;
                    327:
1.4       bouyer    328:                        wdc->sc_drives_mask |= (1 << drive);
1.12      cgd       329:                        (void)config_found(&wdc->sc_dev,
                    330:                            (void *)wdc->d_link[drive], wdprint);
1.2       bouyer    331:                }
                    332:        }
                    333: #endif /* NWD > 0 */
1.10      mikel     334:        /* explicitly select an existing drive, to avoid spurious interrupts */
1.7       bouyer    335:        if (wdc->sc_flags & WDCF_ONESLAVE)
1.12      cgd       336:                bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | 0x10); /* slave */
1.7       bouyer    337:        else
1.12      cgd       338:                bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM); /* master */
1.8       bouyer    339:        /*
                    340:         * Reset controller. The probe, with some combinations of ATA/ATAPI
1.10      mikel     341:         * devices keep it in a mostly working, but strange state (with busy
1.8       bouyer    342:         * led on)
                    343:         */
                    344:        wdcreset(wdc, VERBOSE);
1.2       bouyer    345: }
                    346:
                    347: /*
                    348:  * Start I/O on a controller.  This does the calculation, and starts a read or
                    349:  * write operation.  Called to from wdstart() to start a transfer, from
                    350:  * wdcintr() to continue a multi-sector transfer or start the next transfer, or
                    351:  * wdcrestart() after recovering from an error.
                    352:  */
                    353: void
                    354: wdcstart(wdc)
                    355:        struct wdc_softc *wdc;
                    356: {
                    357:        struct wdc_xfer *xfer;
                    358:
                    359:        if ((wdc->sc_flags & WDCF_ACTIVE) != 0 ) {
                    360:                WDDEBUG_PRINT(("wdcstart: already active\n"));
                    361:                return; /* controller aleady active */
                    362:        }
                    363: #ifdef DIAGNOSTIC
                    364:        if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0)
                    365:                panic("wdcstart: controller waiting for irq\n");
                    366: #endif
                    367:        /* is there a xfer ? */
                    368:        xfer = wdc->sc_xfer.tqh_first;
                    369:        if (xfer == NULL) {
                    370: #ifdef ATAPI_DEBUG2
                    371:                printf("wdcstart: null xfer\n");
                    372: #endif
                    373:                /*
                    374:                 * XXX
                    375:                 * This is a kluge.  See comments in wd_get_parms().
                    376:                 */
                    377:                if ((wdc->sc_flags & WDCF_WANTED) != 0) {
1.8       bouyer    378: #ifdef ATAPI_DEBUG2
1.2       bouyer    379:                        printf("WDCF_WANTED\n");
                    380: #endif
                    381:                        wdc->sc_flags &= ~WDCF_WANTED;
                    382:                        wakeup(wdc);
                    383:                }
                    384:                return;
                    385:        }
                    386:        wdc->sc_flags |= WDCF_ACTIVE;
                    387: #ifdef ATAPI_DEBUG2
                    388:                printf("wdcstart: drive %d\n", (int)xfer->d_link->drive);
                    389: #endif
1.12      cgd       390:     bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | xfer->d_link->drive << 4);
1.2       bouyer    391: #if NATAPIBUS > 0 && NWD > 0
                    392:        if (xfer->c_flags & C_ATAPI) {
                    393: #ifdef ATAPI_DEBUG_WDC
                    394:                printf("wdcstart: atapi\n");
                    395: #endif
                    396:                wdc_atapi_start(wdc,xfer);
                    397:        } else
                    398:                wdc_ata_start(wdc,xfer);
                    399: #else /* NATAPIBUS > 0 && NWD > 0 */
                    400: #if NATAPIBUS > 0
                    401: #ifdef ATAPI_DEBUG_WDC
                    402:        printf("wdcstart: atapi\n");
                    403: #endif
                    404:        wdc_atapi_start(wdc,xfer);
                    405: #endif /* NATAPIBUS > */
                    406: #if NWD > 0
                    407:        wdc_ata_start(wdc,xfer);
                    408: #endif /* NWD > 0 */
                    409: #endif /* NATAPIBUS > 0 && NWD > 0 */
                    410: }
                    411:
                    412: #if NWD > 0
                    413: int
                    414: wdprint(aux, wdc)
                    415:        void *aux;
                    416:        const char *wdc;
                    417: {
                    418:        struct wd_link *d_link = aux;
                    419:
                    420:        if (!wdc)
                    421:                printf(" drive %d", d_link->drive);
                    422:        return QUIET;
                    423: }
                    424:
                    425: void
                    426: wdc_ata_start(wdc, xfer)
                    427:        struct wdc_softc *wdc;
                    428:        struct wdc_xfer *xfer;
                    429: {
                    430:        struct wd_link *d_link;
                    431:        struct buf *bp = xfer->c_bp;
                    432:        int nblks;
                    433:
                    434:        d_link=xfer->d_link;
                    435:
                    436:        if (wdc->sc_errors >= WDIORETRIES) {
                    437:                wderror(d_link, bp, "wdc_ata_start hard error");
                    438:                xfer->c_flags |= C_ERROR;
                    439:                wdc_ata_done(wdc, xfer);
                    440:                return;
                    441:        }
                    442:
                    443:        /* Do control operations specially. */
                    444:        if (d_link->sc_state < READY) {
                    445:                /*
                    446:                 * Actually, we want to be careful not to mess with the control
                    447:                 * state if the device is currently busy, but we can assume
                    448:                 * that we never get to this point if that's the case.
                    449:                 */
                    450:                if (wdccontrol(wdc, d_link) == 0) {
                    451:                        /* The drive is busy.  Wait. */
                    452:                        return;
                    453:                }
                    454:        }
                    455:
                    456:        /*
                    457:         * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
                    458:         * encountered.  If we are in multi-sector mode, then we switch to
                    459:         * single-sector mode and retry the operation from the start.
                    460:         */
                    461:        if (wdc->sc_flags & WDCF_ERROR) {
                    462:                wdc->sc_flags &= ~WDCF_ERROR;
                    463:                if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
                    464:                        wdc->sc_flags |= WDCF_SINGLE;
                    465:                        xfer->c_skip = 0;
                    466:                }
                    467:        }
                    468:
                    469:
                    470:        /* When starting a transfer... */
                    471:        if (xfer->c_skip == 0) {
                    472:                daddr_t blkno;
                    473:
                    474:                WDDEBUG_PRINT(("\n%s: wdc_ata_start %s %d@%d; map ",
                    475:                    wdc->sc_dev.dv_xname,
                    476:                    (xfer->c_flags & B_READ) ? "read" : "write",
                    477:                    xfer->c_bcount, xfer->c_blkno));
                    478:
                    479:                blkno = xfer->c_blkno+xfer->c_p_offset;
                    480:                xfer->c_blkno = blkno / (d_link->sc_lp->d_secsize / DEV_BSIZE);
                    481:        } else {
                    482:                WDDEBUG_PRINT((" %d)%x", xfer->c_skip,
1.12      cgd       483:                    bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_altsts)));
1.2       bouyer    484:        }
                    485:
                    486:        /*
                    487:         * When starting a multi-sector transfer, or doing single-sector
                    488:         * transfers...
                    489:         */
                    490:        if (xfer->c_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
                    491:            d_link->sc_mode == WDM_DMA) {
                    492:                daddr_t blkno = xfer->c_blkno;
                    493:                long cylin, head, sector;
                    494:                int command;
                    495:
                    496:                if ((wdc->sc_flags & WDCF_SINGLE) != 0)
                    497:                        nblks = 1;
                    498:                else if (d_link->sc_mode != WDM_DMA)
                    499:                        nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
                    500:                else
                    501:                        nblks =
                    502:                            min(xfer->c_bcount / d_link->sc_lp->d_secsize, 8);
                    503:
                    504:                /* Check for bad sectors and adjust transfer, if necessary. */
                    505:                if ((d_link->sc_lp->d_flags & D_BADSECT) != 0
                    506: #ifdef B_FORMAT
                    507:                    && (bp->b_flags & B_FORMAT) == 0
                    508: #endif
                    509:                    ) {
                    510:                        long blkdiff;
                    511:                        int i;
                    512:
                    513:                        for (i = 0;
                    514:                            (blkdiff = d_link->sc_badsect[i]) != -1; i++) {
                    515:                                blkdiff -= blkno;
                    516:                                if (blkdiff < 0)
                    517:                                        continue;
                    518:                                if (blkdiff == 0) {
                    519:                                        /* Replace current block of transfer. */
                    520:                                        blkno =
                    521:                                            d_link->sc_lp->d_secperunit -
                    522:                                            d_link->sc_lp->d_nsectors - i - 1;
                    523:                                }
                    524:                                if (blkdiff < nblks) {
                    525:                                        /* Bad block inside transfer. */
                    526:                                        wdc->sc_flags |= WDCF_SINGLE;
                    527:                                        nblks = 1;
                    528:                                }
                    529:                                break;
                    530:                        }
1.10      mikel     531:                        /* Transfer is okay now. */
1.2       bouyer    532:                }
                    533:
                    534:                if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
                    535:                        sector = (blkno >> 0) & 0xff;
                    536:                        cylin = (blkno >> 8) & 0xffff;
                    537:                        head = (blkno >> 24) & 0xf;
                    538:                        head |= WDSD_LBA;
                    539:                } else {
                    540:                        sector = blkno % d_link->sc_lp->d_nsectors;
                    541:                        sector++;       /* Sectors begin with 1, not 0. */
                    542:                        blkno /= d_link->sc_lp->d_nsectors;
                    543:                        head = blkno % d_link->sc_lp->d_ntracks;
                    544:                        blkno /= d_link->sc_lp->d_ntracks;
                    545:                        cylin = blkno;
                    546:                        head |= WDSD_CHS;
                    547:                }
                    548:
                    549:                if (d_link->sc_mode == WDM_PIOSINGLE ||
                    550:                    (wdc->sc_flags & WDCF_SINGLE) != 0)
                    551:                        xfer->c_nblks = 1;
                    552:                else if (d_link->sc_mode == WDM_PIOMULTI)
                    553:                        xfer->c_nblks = min(nblks, d_link->sc_multiple);
                    554:                else
                    555:                        xfer->c_nblks = nblks;
                    556:                xfer->c_nbytes = xfer->c_nblks * d_link->sc_lp->d_secsize;
                    557:
                    558: #ifdef B_FORMAT
                    559:                if (bp->b_flags & B_FORMAT) {
                    560:                        sector = d_link->sc_lp->d_gap3;
                    561:                        nblks = d_link->sc_lp->d_nsectors;
                    562:                        command = WDCC_FORMAT;
                    563:                } else
                    564: #endif
                    565:                switch (d_link->sc_mode) {
                    566:                case WDM_DMA:
                    567:                        command = (xfer->c_flags & B_READ) ?
                    568:                            WDCC_READDMA : WDCC_WRITEDMA;
                    569:                        /* Start the DMA channel. */
1.12      cgd       570:                        (*wdc->sc_dma_start)(wdc->sc_dma_arg,
                    571:                            xfer->databuf + xfer->c_skip, xfer->c_nbytes,
                    572:                            xfer->c_flags & B_READ);
1.2       bouyer    573:                        break;
                    574:
                    575:                case WDM_PIOMULTI:
                    576:                        command = (xfer->c_flags & B_READ) ?
                    577:                            WDCC_READMULTI : WDCC_WRITEMULTI;
                    578:                        break;
                    579:
                    580:                case WDM_PIOSINGLE:
                    581:                        command = (xfer->c_flags & B_READ) ?
                    582:                            WDCC_READ : WDCC_WRITE;
                    583:                        break;
                    584:
                    585:                default:
                    586: #ifdef DIAGNOSTIC
                    587:                        panic("bad wd mode");
                    588: #endif
                    589:                        return;
                    590:                }
                    591:
                    592:                /* Initiate command! */
                    593:                if (wdccommand(wdc, d_link, command, d_link->drive,
                    594:                    cylin, head, sector, nblks) != 0) {
                    595:                        wderror(d_link, NULL,
                    596:                            "wdc_ata_start: timeout waiting for unbusy");
                    597:                        wdcunwedge(wdc);
                    598:                        return;
                    599:                }
                    600:
1.12      cgd       601:                WDDEBUG_PRINT(("sector %lu cylin %lu head %lu addr %p sts %x\n",
1.2       bouyer    602:                    sector, cylin, head, xfer->databuf,
1.12      cgd       603:                    bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_altsts)));
1.2       bouyer    604:
                    605:        } else if (xfer->c_nblks > 1) {
                    606:                /* The number of blocks in the last stretch may be smaller. */
                    607:                nblks = xfer->c_bcount / d_link->sc_lp->d_secsize;
                    608:                if (xfer->c_nblks > nblks) {
                    609:                        xfer->c_nblks = nblks;
                    610:                        xfer->c_nbytes = xfer->c_bcount;
                    611:                }
                    612:        }
                    613:
                    614:        /* If this was a write and not using DMA, push the data. */
                    615:        if (d_link->sc_mode != WDM_DMA &&
                    616:            (xfer->c_flags & (B_READ|B_WRITE)) == B_WRITE) {
                    617:                if (wait_for_drq(wdc) < 0) {
                    618:                        wderror(d_link, NULL,
                    619:                            "wdc_ata_start: timeout waiting for drq");
                    620:                        wdcunwedge(wdc);
                    621:                        return;
                    622:                }
                    623:
1.12      cgd       624:                if ((wdc->sc_cap & WDC_CAPABILITY_DATA32) == 0)
                    625:                        bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh,
                    626:                            wd_data, xfer->databuf + xfer->c_skip,
1.2       bouyer    627:                            xfer->c_nbytes >> 1);
                    628:                else
1.12      cgd       629:                        bus_space_write_multi_4(wdc->sc_iot, wdc->sc_ioh,
                    630:                            wd_data, xfer->databuf + xfer->c_skip,
1.2       bouyer    631:                            xfer->c_nbytes >> 2);
                    632:        }
                    633:
                    634:        wdc->sc_flags |= WDCF_IRQ_WAIT;
                    635:        WDDEBUG_PRINT(("wdc_ata_start: timeout "));
                    636:        timeout(wdctimeout, wdc, WAITTIME);
                    637:        WDDEBUG_PRINT(("done\n"));
                    638: }
                    639:
                    640: int
                    641: wdc_ata_intr(wdc,xfer)
                    642:        struct wdc_softc *wdc;
                    643:        struct wdc_xfer *xfer;
                    644: {
                    645:        struct wd_link *d_link;
                    646:
                    647:        d_link = xfer->d_link;
                    648:
                    649:        if (wait_for_unbusy(wdc) < 0) {
                    650:                wdcerror(wdc, "wdcintr: timeout waiting for unbusy");
1.5       bouyer    651:                return 0;
1.2       bouyer    652:        }
                    653:
1.8       bouyer    654:        wdc->sc_flags &= ~WDCF_IRQ_WAIT;
1.2       bouyer    655:        untimeout(wdctimeout, wdc);
                    656:
                    657:        /* Is it not a transfer, but a control operation? */
                    658:        if (d_link->sc_state < READY) {
                    659:                if (wdccontrol(wdc, d_link) == 0) {
                    660:                        /* The drive is busy.  Wait. */
                    661:                        return 1;
                    662:                }
                    663:                WDDEBUG_PRINT(("wdc_ata_start from wdc_ata_intr(open) flags 0x%x\n",
1.12      cgd       664:                    wdc->sc_flags));
1.2       bouyer    665:                wdc_ata_start(wdc,xfer);
                    666:                return 1;
                    667:        }
                    668:
                    669:        /* Turn off the DMA channel. */
                    670:        if (d_link->sc_mode == WDM_DMA)
1.12      cgd       671:                (*wdc->sc_dma_finish)(wdc->sc_dma_arg);
1.2       bouyer    672:
                    673:        /* Have we an error? */
                    674:        if (wdc->sc_status & WDCS_ERR) {
                    675: #ifdef WDDEBUG
                    676:                wderror(d_link, NULL, "wdc_ata_start");
                    677: #endif
                    678:                if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
                    679:                        wdc->sc_flags |= WDCF_ERROR;
                    680:                        goto restart;
                    681:                }
                    682:
                    683: #ifdef B_FORMAT
                    684:                if (bp->b_flags & B_FORMAT)
                    685:                        goto bad;
                    686: #endif
                    687:
                    688:                if (++wdc->sc_errors < WDIORETRIES) {
                    689:                        if (wdc->sc_errors == (WDIORETRIES + 1) / 2) {
                    690: #if 0
                    691:                                wderror(wd, NULL, "wedgie");
                    692: #endif
                    693:                                wdcunwedge(wdc);
                    694:                                return 1;
                    695:                        }
                    696:                        goto restart;
                    697:                }
                    698:                wderror(d_link, xfer->c_bp, "wdc_ata_intr hard error");
                    699:
                    700: #ifdef B_FORMAT
                    701:        bad:
                    702: #endif
                    703:                xfer->c_flags |= C_ERROR;
                    704:                goto done;
                    705:        }
                    706:
                    707:        /* If this was a read and not using DMA, fetch the data. */
                    708:        if (d_link->sc_mode != WDM_DMA &&
                    709:            (xfer->c_flags & (B_READ|B_WRITE)) == B_READ) {
                    710:                if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
                    711:                    != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
                    712:                        wderror(d_link, NULL, "wdcintr: read intr before drq");
                    713:                        wdcunwedge(wdc);
                    714:                        return 1;
                    715:                }
                    716:
                    717:                /* Pull in data. */
1.12      cgd       718:                if ((wdc->sc_cap & WDC_CAPABILITY_DATA32) == 0)
                    719:                        bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh,
                    720:                            wd_data, xfer->databuf + xfer->c_skip,
                    721:                            xfer->c_nbytes >> 1);
1.2       bouyer    722:                else
1.12      cgd       723:                        bus_space_read_multi_4(wdc->sc_iot, wdc->sc_ioh,
                    724:                            wd_data, xfer->databuf + xfer->c_skip,
                    725:                            xfer->c_nbytes >> 2);
1.2       bouyer    726:        }
                    727:
                    728:        /* If we encountered any abnormalities, flag it as a soft error. */
                    729:        if (wdc->sc_errors > 0 ||
                    730:            (wdc->sc_status & WDCS_CORR) != 0) {
                    731:                wderror(d_link, xfer->c_bp, "soft error (corrected)");
                    732:                wdc->sc_errors = 0;
                    733:        }
                    734:
                    735:        /* Adjust pointers for the next block, if any. */
                    736:        xfer->c_blkno += xfer->c_nblks;
                    737:        xfer->c_skip += xfer->c_nbytes;
                    738:        xfer->c_bcount -= xfer->c_nbytes;
                    739:
                    740:        /* See if this transfer is complete. */
                    741:        if (xfer->c_bcount > 0)
                    742:                goto restart;
                    743:
                    744: done:
                    745:        /* Done with this transfer, with or without error. */
                    746:        wdc_ata_done(wdc, xfer);
1.5       bouyer    747:        return 1;
1.2       bouyer    748:
                    749: restart:
                    750:        /* Start the next operation */
                    751:        WDDEBUG_PRINT(("wdc_ata_start from wdcintr flags 0x%x\n",
                    752:            wdc->sc_flags));
                    753:        wdc_ata_start(wdc, xfer);
                    754:
                    755:        return 1;
                    756: }
                    757:
                    758: void
                    759: wdc_ata_done(wdc, xfer)
                    760:        struct wdc_softc *wdc;
                    761:        struct wdc_xfer *xfer;
                    762: {
                    763:        struct buf *bp = xfer->c_bp;
                    764:        struct wd_link *d_link = xfer->d_link;
                    765:        int s;
                    766:
                    767:        WDDEBUG_PRINT(("wdc_ata_done\n"));
                    768:
                    769:        /* remove this command from xfer queue */
                    770:        s = splbio();
                    771:        TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
                    772:        wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
                    773:        wdc->sc_errors = 0;
                    774:        if (bp) {
                    775:                if (xfer->c_flags & C_ERROR) {
                    776:                        bp->b_flags |= B_ERROR;
                    777:                        bp->b_error = EIO;
                    778:                }
                    779:                bp->b_resid = xfer->c_bcount;
                    780:                wddone(d_link, bp);
                    781:                biodone(bp);
                    782:        } else {
                    783:                wakeup(xfer->databuf);
                    784:        }
                    785:        xfer->c_skip = 0;
                    786:        wdc_free_xfer(xfer);
                    787:        d_link->openings++;
                    788:        wdstart((void*)d_link->wd_softc);
                    789:        WDDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n",
                    790:            wdc->sc_flags));
                    791:        wdcstart(wdc);
                    792:        splx(s);
                    793: }
                    794:
                    795: /*
                    796:  * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
                    797:  */
                    798: int
                    799: wdc_get_parms(wdc, d_link)
                    800:        struct wdc_softc * wdc;
                    801:        struct wd_link *d_link;
                    802: {
                    803:        int i;
                    804:        char tb[DEV_BSIZE];
                    805:        int s, error;
                    806:
                    807:        /*
                    808:         * XXX
                    809:         * The locking done here, and the length of time this may keep the rest
                    810:         * of the system suspended, is a kluge.  This should be rewritten to
                    811:         * set up a transfer and queue it through wdstart(), but it's called
                    812:         * infrequently enough that this isn't a pressing matter.
                    813:         */
                    814:
                    815:        s = splbio();
                    816:
                    817:        while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
                    818:                wdc->sc_flags |= WDCF_WANTED;
                    819:                if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) {
                    820:                        splx(s);
                    821:                        return error;
                    822:                }
                    823:        }
                    824:
                    825:        wdc->sc_flags |= WDCF_ACTIVE;
                    826:
                    827:        if (wdccommandshort(wdc, d_link->drive, WDCC_IDENTIFY) != 0 ||
                    828:            wait_for_drq(wdc) != 0) {
                    829:                /*
                    830:                 * We `know' there's a drive here; just assume it's old.
                    831:                 * This geometry is only used to read the MBR and print a
                    832:                 * (false) attach message.
                    833:                 */
                    834:                strncpy(d_link->sc_lp->d_typename, "ST506",
                    835:                    sizeof d_link->sc_lp->d_typename);
                    836:                d_link->sc_lp->d_type = DTYPE_ST506;
                    837:
                    838:                strncpy(d_link->sc_params.wdp_model, "unknown",
                    839:                    sizeof d_link->sc_params.wdp_model);
                    840:                d_link->sc_params.wdp_config = WD_CFG_FIXED;
                    841:                d_link->sc_params.wdp_cylinders = 1024;
                    842:                d_link->sc_params.wdp_heads = 8;
                    843:                d_link->sc_params.wdp_sectors = 17;
                    844:                d_link->sc_params.wdp_maxmulti = 0;
                    845:                d_link->sc_params.wdp_usedmovsd = 0;
                    846:                d_link->sc_params.wdp_capabilities = 0;
                    847:        } else {
                    848:                strncpy(d_link->sc_lp->d_typename, "ESDI/IDE",
                    849:                    sizeof d_link->sc_lp->d_typename);
                    850:                d_link->sc_lp->d_type = DTYPE_ESDI;
                    851:
                    852:                /* Read in parameter block. */
1.12      cgd       853:                bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
                    854:                    (u_int16_t *)tb, sizeof(tb) >> 1);
1.2       bouyer    855:                bcopy(tb, &d_link->sc_params, sizeof(struct wdparams));
                    856:
                    857:                /* Shuffle string byte order. */
                    858:                for (i = 0; i < sizeof(d_link->sc_params.wdp_model); i += 2) {
                    859:                        u_short *p;
                    860:                        p = (u_short *)(d_link->sc_params.wdp_model + i);
                    861:                        *p = ntohs(*p);
                    862:                }
                    863:        }
                    864:
                    865:        /* Clear any leftover interrupt. */
1.12      cgd       866:        (void) bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
1.2       bouyer    867:
                    868:        /* Restart the queue. */
                    869:        WDDEBUG_PRINT(("wdcstart from wdc_get_parms flags 0x%x\n",
                    870:            wdc->sc_flags));
                    871:        wdc->sc_flags &= ~WDCF_ACTIVE;
                    872:        wdcstart(wdc);
                    873:
                    874:        splx(s);
                    875:        return 0;
                    876: }
                    877:
                    878: /*
                    879:  * Implement operations needed before read/write.
                    880:  * Returns 0 if operation still in progress, 1 if completed.
                    881:  */
                    882: int
                    883: wdccontrol(wdc, d_link)
                    884:        struct wdc_softc *wdc;
                    885:        struct wd_link *d_link;
                    886: {
                    887:        WDDEBUG_PRINT(("wdccontrol\n"));
                    888:
                    889:        switch (d_link->sc_state) {
                    890:        case RECAL:     /* Set SDH, step rate, do recal. */
                    891:                if (wdccommandshort(wdc, d_link->drive, WDCC_RECAL) != 0) {
                    892:                        wderror(d_link, NULL, "wdccontrol: recal failed (1)");
                    893:                        goto bad;
                    894:                }
                    895:                d_link->sc_state = RECAL_WAIT;
                    896:                break;
                    897:
                    898:        case RECAL_WAIT:
                    899:                if (wdc->sc_status & WDCS_ERR) {
                    900:                        wderror(d_link, NULL, "wdccontrol: recal failed (2)");
                    901:                        goto bad;
                    902:                }
                    903:                /* fall through */
                    904:
                    905:        case GEOMETRY:
                    906:                if ((d_link->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
                    907:                        goto multimode;
                    908:                if (wdsetctlr(d_link) != 0) {
                    909:                        /* Already printed a message. */
                    910:                        goto bad;
                    911:                }
                    912:                d_link->sc_state = GEOMETRY_WAIT;
                    913:                break;
                    914:
                    915:        case GEOMETRY_WAIT:
                    916:                if (wdc->sc_status & WDCS_ERR) {
                    917:                        wderror(d_link, NULL, "wdccontrol: geometry failed");
                    918:                        goto bad;
                    919:                }
                    920:                /* fall through */
                    921:
                    922:        case MULTIMODE:
                    923:        multimode:
                    924:                if (d_link->sc_mode != WDM_PIOMULTI)
                    925:                        goto ready;
1.12      cgd       926:                bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt, d_link->sc_multiple);
1.2       bouyer    927:                if (wdccommandshort(wdc, d_link->drive,
                    928:                    WDCC_SETMULTI) != 0) {
                    929:                        wderror(d_link, NULL,
                    930:                            "wdccontrol: setmulti failed (1)");
                    931:                        goto bad;
                    932:                }
                    933:                d_link->sc_state = MULTIMODE_WAIT;
                    934:                break;
                    935:
                    936:        case MULTIMODE_WAIT:
                    937:                if (wdc->sc_status & WDCS_ERR) {
                    938:                        wderror(d_link, NULL,
                    939:                            "wdccontrol: setmulti failed (2)");
                    940:                        goto bad;
                    941:                }
                    942:                /* fall through */
                    943:
                    944:        case READY:
                    945:        ready:
                    946:                wdc->sc_errors = 0;
                    947:                d_link->sc_state = READY;
                    948:                /*
                    949:                 * The rest of the initialization can be done by normal means.
                    950:                 */
                    951:                return 1;
                    952:
                    953:        bad:
                    954:                wdcunwedge(wdc);
                    955:                return 0;
                    956:        }
                    957:
                    958:        wdc->sc_flags |= WDCF_IRQ_WAIT;
                    959:        timeout(wdctimeout, wdc, WAITTIME);
                    960:        return 0;
                    961: }
                    962:
                    963: #endif /* NWD > 0 */
                    964:
                    965:
                    966: /*
                    967:  * Interrupt routine for the controller.  Acknowledge the interrupt, check for
                    968:  * errors on the current operation, mark it done if necessary, and start the
                    969:  * next request.  Also check for a partially done transfer, and continue with
                    970:  * the next chunk if so.
                    971:  */
                    972: int
                    973: wdcintr(arg)
                    974:        void *arg;
                    975: {
                    976:        struct wdc_softc *wdc = arg;
                    977:        struct wdc_xfer *xfer;
                    978:
                    979:        if ((wdc->sc_flags & WDCF_IRQ_WAIT) == 0) {
                    980:                /* Clear the pending interrupt and abort. */
1.12      cgd       981:                u_char s = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
1.2       bouyer    982:
                    983: #ifdef ATAPI_DEBUG_WDC
1.12      cgd       984:                u_char e = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
                    985:                u_char i = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt);
1.2       bouyer    986:                printf("wdcintr: inactive controller, "
                    987:                    "punting st=%02x er=%02x irr=%02x\n", s, e, i);
                    988: #else
1.12      cgd       989:                bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
                    990:                bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt);
1.2       bouyer    991: #endif
                    992:
                    993:                if (s & WDCS_DRQ) {
1.12      cgd       994:                        int len = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_lo) +
                    995:                            256 * bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_hi);
1.2       bouyer    996: #ifdef ATAPI_DEBUG_WDC
                    997:                        printf ("wdcintr: clearing up %d bytes\n", len);
                    998: #endif
                    999:                        wdcbit_bucket (wdc, len);
                   1000:                }
                   1001:                return 0;
                   1002:        }
                   1003:
                   1004:        WDDEBUG_PRINT(("wdcintr\n"));
                   1005:
                   1006:        xfer = wdc->sc_xfer.tqh_first;
                   1007: #if NATAPIBUS > 0 && NWD > 0
                   1008:        if (xfer->c_flags & C_ATAPI) {
1.5       bouyer   1009:                return wdc_atapi_intr(wdc,xfer);
1.2       bouyer   1010:        } else
                   1011:                return wdc_ata_intr(wdc,xfer);
                   1012: #else /* NATAPIBUS > 0  && NWD > 0 */
                   1013: #if NATAPIBUS > 0
1.5       bouyer   1014:        return wdc_atapi_intr(wdc,xfer);
1.2       bouyer   1015: #endif /* NATAPIBUS > 0 */
                   1016: #if NWD > 0
                   1017:        return wdc_ata_intr(wdc,xfer);
                   1018: #endif /* NWD > 0 */
                   1019: #endif /* NATAPIBUS > 0  && NWD > 0 */
                   1020: }
                   1021:
                   1022: int
                   1023: wdcreset(wdc, verb)
                   1024:        struct wdc_softc *wdc;
                   1025:        int verb;
                   1026: {
                   1027:
                   1028:        /* Reset the device. */
1.12      cgd      1029:        bus_space_write_1(wdc->sc_auxiot, wdc->sc_auxioh, wd_aux_ctlr,
                   1030:            WDCTL_RST | WDCTL_IDS);
1.2       bouyer   1031:        delay(1000);
1.12      cgd      1032:        bus_space_write_1(wdc->sc_auxiot, wdc->sc_auxioh, wd_aux_ctlr,
                   1033:            WDCTL_IDS);
1.2       bouyer   1034:        delay(1000);
1.12      cgd      1035:        (void) bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
                   1036:        bus_space_write_1(wdc->sc_auxiot, wdc->sc_auxioh, wd_aux_ctlr,
                   1037:            WDCTL_4BIT);
1.2       bouyer   1038:
                   1039:        if (wait_for_unbusy(wdc) < 0) {
                   1040:                if (verb)
                   1041:                        printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
                   1042:                return 1;
                   1043:        }
                   1044:
                   1045:        return 0;
                   1046: }
                   1047:
                   1048: void
                   1049: wdcrestart(arg)
                   1050:        void *arg;
                   1051: {
                   1052:        struct wdc_softc *wdc = arg;
                   1053:        int s;
                   1054:
                   1055:        s = splbio();
                   1056:        wdcstart(wdc);
                   1057:        splx(s);
                   1058: }
                   1059:
                   1060: /*
                   1061:  * Unwedge the controller after an unexpected error.  We do this by resetting
                   1062:  * it, marking all drives for recalibration, and stalling the queue for a short
                   1063:  * period to give the reset time to finish.
                   1064:  * NOTE: We use a timeout here, so this routine must not be called during
                   1065:  * autoconfig or dump.
                   1066:  */
                   1067: void
                   1068: wdcunwedge(wdc)
                   1069:        struct wdc_softc *wdc;
                   1070: {
                   1071:        int unit;
                   1072:
                   1073: #ifdef ATAPI_DEBUG
                   1074:        printf("wdcunwedge\n");
                   1075: #endif
                   1076:
                   1077:        untimeout(wdctimeout, wdc);
                   1078:        wdc->sc_flags &= ~WDCF_IRQ_WAIT;
                   1079:        (void) wdcreset(wdc, VERBOSE);
                   1080:
                   1081:        /* Schedule recalibrate for all drives on this controller. */
                   1082:        for (unit = 0; unit < 2; unit++) {
1.8       bouyer   1083:                if (!wdc->d_link[unit])
                   1084:                        wdccommandshort(wdc, unit, ATAPI_SOFT_RESET);
                   1085:                else if (wdc->d_link[unit]->sc_state > RECAL)
1.2       bouyer   1086:                        wdc->d_link[unit]->sc_state = RECAL;
                   1087:        }
                   1088:
                   1089:        wdc->sc_flags |= WDCF_ERROR;
                   1090:        ++wdc->sc_errors;
                   1091:
                   1092:        /* Wake up in a little bit and restart the operation. */
                   1093:        WDDEBUG_PRINT(("wdcrestart from wdcunwedge\n"));
                   1094:        wdc->sc_flags &= ~WDCF_ACTIVE;
                   1095:        timeout(wdcrestart, wdc, RECOVERYTIME);
                   1096: }
                   1097:
                   1098: int
                   1099: wdcwait(wdc, mask)
                   1100:        struct wdc_softc *wdc;
                   1101:        int mask;
                   1102: {
                   1103:        int timeout = 0;
                   1104:        u_char status;
                   1105: #ifdef WDCNDELAY_DEBUG
                   1106:        extern int cold;
                   1107: #endif
                   1108:
1.12      cgd      1109:        WDDEBUG_PRINT(("wdcwait\n"));
1.2       bouyer   1110:
                   1111:        for (;;) {
1.12      cgd      1112:                wdc->sc_status = status = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
1.2       bouyer   1113:                /*
                   1114:                 * XXX
                   1115:                 * If a single slave ATAPI device is attached, it may
                   1116:                 * have released the bus. Select it and try again.
                   1117:                 */
                   1118:                if (status == 0xff && wdc->sc_flags & WDCF_ONESLAVE) {
1.12      cgd      1119:                        bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | 0x10);
                   1120:                        wdc->sc_status = status = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
1.2       bouyer   1121:                }
                   1122:                if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
                   1123:                        break;
                   1124:                if (++timeout > WDCNDELAY) {
1.3       bouyer   1125: #ifdef ATAPI_DEBUG
1.12      cgd      1126:                        printf("wdcwait: timeout, status %x error %x\n", status, bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error));
1.2       bouyer   1127: #endif
                   1128:                        return -1;
                   1129:                }
                   1130:                delay(WDCDELAY);
                   1131:        }
                   1132:        if (status & WDCS_ERR) {
1.12      cgd      1133:                wdc->sc_error = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1.2       bouyer   1134:                return WDCS_ERR;
                   1135:        }
                   1136: #ifdef WDCNDELAY_DEBUG
                   1137:        /* After autoconfig, there should be no long delays. */
                   1138:        if (!cold && timeout > WDCNDELAY_DEBUG) {
                   1139:                struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
                   1140:                if (xfer == NULL)
                   1141:                        printf("%s: warning: busy-wait took %dus\n",
                   1142:                        wdc->sc_dev.dv_xname, WDCDELAY * timeout);
                   1143:                else
                   1144:                        printf("%s(%s): warning: busy-wait took %dus\n",
                   1145:                                wdc->sc_dev.dv_xname,
                   1146:                            ((struct device*)xfer->d_link->wd_softc)->dv_xname,
                   1147:                                WDCDELAY * timeout);
                   1148:        }
                   1149: #endif
                   1150:        return 0;
                   1151: }
                   1152:
                   1153: void
                   1154: wdctimeout(arg)
                   1155:        void *arg;
                   1156: {
                   1157:        struct wdc_softc *wdc = (struct wdc_softc *)arg;
1.8       bouyer   1158:        struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
1.2       bouyer   1159:        int s;
                   1160:
                   1161:        WDDEBUG_PRINT(("wdctimeout\n"));
                   1162:
                   1163:        s = splbio();
                   1164:        if ((wdc->sc_flags & WDCF_IRQ_WAIT) != 0) {
1.8       bouyer   1165:                wdcerror(wdc, "lost interrupt");
                   1166:                printf("\ttype: %s\n", (xfer->c_flags & C_ATAPI) ? "atapi":"ata");
                   1167:                printf("\tc_bcount: %d\n", xfer->c_bcount);
                   1168:                printf("\tc_skip: %d\n", xfer->c_skip);
                   1169:                wdcintr(wdc);
1.2       bouyer   1170:                wdc->sc_flags &= ~WDCF_IRQ_WAIT;
                   1171:                wdcunwedge(wdc);
                   1172:        } else
                   1173:                wdcerror(wdc, "missing untimeout");
                   1174:        splx(s);
                   1175: }
                   1176:
                   1177: /*
                   1178:  * Wait for the drive to become ready and send a command.
                   1179:  * Return -1 if busy for too long or 0 otherwise.
                   1180:  * Assumes interrupts are blocked.
                   1181:  */
                   1182: int
                   1183: wdccommand(wdc, d_link, command, drive, cylin, head, sector, count)
                   1184:                struct wdc_softc *wdc;
                   1185:         struct wd_link *d_link;
                   1186:         int command;
                   1187:         int drive, cylin, head, sector, count;
                   1188: {
                   1189:         int stat;
                   1190:
                   1191:        WDDEBUG_PRINT(("wdccommand drive %d\n", drive));
                   1192:
                   1193: #if defined(DIAGNOSTIC) && defined(WDCDEBUG)
                   1194:        if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
                   1195:                printf("wdccommand: controler not active (drive %d)\n", drive);
                   1196: #endif
                   1197:
                   1198:         /* Select drive, head, and addressing mode. */
1.12      cgd      1199:         bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | (drive << 4) | head);
1.2       bouyer   1200:
                   1201:         /* Wait for it to become ready to accept a command. */
                   1202:         if (command == WDCC_IDP || d_link->type == ATAPI)
                   1203:                 stat = wait_for_unbusy(wdc);
                   1204:         else
                   1205:                 stat = wdcwait(wdc, WDCS_DRDY);
                   1206:
                   1207:         if (stat < 0) {
                   1208: #ifdef ATAPI_DEBUG
                   1209:                printf("wdcommand: xfer failed (wait_for_unbusy) status %d\n",
                   1210:                    stat);
                   1211: #endif
                   1212:                 return -1;
                   1213:        }
                   1214:
                   1215:         /* Load parameters. */
                   1216:         if (d_link->type == ATA && d_link->sc_lp->d_type == DTYPE_ST506)
1.12      cgd      1217:                 bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_precomp, d_link->sc_lp->d_precompcyl / 4);
1.2       bouyer   1218:         else
1.12      cgd      1219:                 bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_features, 0);
                   1220:         bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_lo, cylin);
                   1221:         bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_hi, cylin >> 8);
                   1222:         bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sector, sector);
                   1223:         bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_seccnt, count);
1.2       bouyer   1224:
                   1225:         /* Send command. */
1.12      cgd      1226:         bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_command, command);
1.2       bouyer   1227:
                   1228:         return 0;
                   1229: }
                   1230:
                   1231: /*
                   1232:  * Simplified version of wdccommand().
                   1233:  */
                   1234: int
                   1235: wdccommandshort(wdc, drive, command)
                   1236:        struct wdc_softc *wdc;
                   1237:         int drive;
                   1238:         int command;
                   1239: {
                   1240:
                   1241:        WDDEBUG_PRINT(("wdccommandshort\n"));
                   1242:
                   1243: #if defined(DIAGNOSTIC) && defined(WDCDEBUG)
                   1244:        if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
1.10      mikel    1245:                printf("wdccommandshort: controller not active (drive %d)\n",
1.2       bouyer   1246:                    drive);
                   1247: #endif
                   1248:
                   1249:         /* Select drive. */
1.12      cgd      1250:         bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_sdh, WDSD_IBM | (drive << 4));
1.2       bouyer   1251:
                   1252:         if (wdcwait(wdc, WDCS_DRDY) < 0)
                   1253:                 return -1;
                   1254:
1.12      cgd      1255:         bus_space_write_1(wdc->sc_iot, wdc->sc_ioh, wd_command, command);
1.2       bouyer   1256:
                   1257:        return 0;
                   1258: }
                   1259:
                   1260: void
                   1261: wdc_exec_xfer(wdc, d_link, xfer)
                   1262:        struct wdc_softc *wdc;
                   1263:        struct wd_link *d_link;
                   1264:        struct wdc_xfer *xfer;
                   1265: {
                   1266:        int s;
                   1267:
                   1268:        WDDEBUG_PRINT(("wdc_exec_xfer\n"));
                   1269:
                   1270:        s = splbio();
                   1271:
                   1272:        /* insert at the end of command list */
1.12      cgd      1273:        TAILQ_INSERT_TAIL(&wdc->sc_xfer,xfer , c_xferchain);
1.2       bouyer   1274:        WDDEBUG_PRINT(("wdcstart from wdc_exec_xfer, flags 0x%x\n",
                   1275:            wdc->sc_flags));
                   1276:        wdcstart(wdc);
                   1277:        xfer->c_flags |= C_NEEDDONE; /* we can now call upper level done() */
                   1278:        splx(s);
                   1279: }
                   1280:
                   1281: struct wdc_xfer *
                   1282: wdc_get_xfer(flags)
                   1283:        int flags;
                   1284: {
                   1285:        struct wdc_xfer *xfer;
                   1286:        int s;
                   1287:
                   1288:        s = splbio();
                   1289:        if ((xfer = xfer_free_list.lh_first) != NULL) {
                   1290:                LIST_REMOVE(xfer, free_list);
                   1291:                splx(s);
                   1292: #ifdef DIAGNOSTIC
                   1293:                if ((xfer->c_flags & C_INUSE) != 0)
                   1294:                        panic("wdc_get_xfer: xfer already in use\n");
                   1295: #endif
                   1296:        } else {
                   1297:                splx(s);
1.8       bouyer   1298: #ifdef ATAPI_DEBUG2
1.2       bouyer   1299:                printf("wdc:making xfer %d\n",wdc_nxfer);
                   1300: #endif
                   1301:                xfer = malloc(sizeof(*xfer), M_DEVBUF,
                   1302:                    ((flags & IDE_NOSLEEP) != 0 ? M_NOWAIT : M_WAITOK));
                   1303:                if (xfer == NULL)
                   1304:                        return 0;
                   1305:
                   1306: #ifdef DIAGNOSTIC
                   1307:                xfer->c_flags &= ~C_INUSE;
                   1308: #endif
1.8       bouyer   1309: #ifdef ATAPI_DEBUG2
1.2       bouyer   1310:                wdc_nxfer++;
                   1311: #endif
                   1312:        }
                   1313: #ifdef DIAGNOSTIC
                   1314:        if ((xfer->c_flags & C_INUSE) != 0)
                   1315:                panic("wdc_get_xfer: xfer already in use\n");
                   1316: #endif
                   1317:        bzero(xfer,sizeof(struct wdc_xfer));
                   1318:        xfer->c_flags = C_INUSE;
                   1319:        return xfer;
                   1320: }
                   1321:
                   1322: void
                   1323: wdc_free_xfer(xfer)
                   1324:        struct wdc_xfer *xfer;
                   1325: {
                   1326:        int s;
                   1327:
                   1328:        s = splbio();
                   1329:        xfer->c_flags &= ~C_INUSE;
                   1330:        LIST_INSERT_HEAD(&xfer_free_list, xfer, free_list);
                   1331:        splx(s);
                   1332: }
                   1333:
                   1334: void
                   1335: wdcerror(wdc, msg)
                   1336:        struct wdc_softc *wdc;
                   1337:        char *msg;
                   1338: {
                   1339:        struct wdc_xfer *xfer = wdc->sc_xfer.tqh_first;
                   1340:        if (xfer == NULL)
                   1341:                printf("%s: %s\n", wdc->sc_dev.dv_xname, msg);
                   1342:        else
                   1343:                printf("%s(%d): %s\n", wdc->sc_dev.dv_xname,
                   1344:                    xfer->d_link->drive, msg);
                   1345: }
                   1346:
                   1347: /*
                   1348:  * the bit bucket
                   1349:  */
                   1350: void
                   1351: wdcbit_bucket(wdc, size)
                   1352:        struct wdc_softc *wdc;
                   1353:        int size;
                   1354: {
                   1355:
1.12      cgd      1356:        for (; size >= 2; size -= 2)
                   1357:                (void)bus_space_read_2(wdc->sc_iot, wdc->sc_ioh, wd_data);
                   1358:        if (size)
                   1359:                (void)bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_data);
1.2       bouyer   1360: }
                   1361:
                   1362:
                   1363: #if NATAPIBUS > 0
                   1364:
                   1365: void
                   1366: wdc_atapi_minphys (struct buf *bp)
                   1367: {
                   1368:     if(bp->b_bcount > MAX_SIZE)
                   1369:                bp->b_bcount = MAX_SIZE;
                   1370:        minphys(bp);
                   1371: }
                   1372:
                   1373:
                   1374: void
                   1375: wdc_atapi_start(wdc, xfer)
                   1376:        struct wdc_softc *wdc;
                   1377:        struct wdc_xfer *xfer;
                   1378: {
                   1379:        struct scsipi_xfer *sc_xfer = xfer->atapi_cmd;
                   1380:
                   1381: #ifdef ATAPI_DEBUG_WDC
                   1382:        printf("wdc_atapi_start, acp flags %x \n",sc_xfer->flags);
                   1383: #endif
                   1384:        if (wdc->sc_errors >= WDIORETRIES) {
                   1385:                if ((wdc->sc_status & WDCS_ERR) == 0) {
                   1386:                        sc_xfer->error = XS_DRIVER_STUFFUP; /* XXX do we know more ? */
                   1387:                } else {
                   1388:                        sc_xfer->error = XS_SENSE;
1.12      cgd      1389:                        sc_xfer->sense.atapi_sense = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1.2       bouyer   1390:                }
                   1391:                wdc_atapi_done(wdc, xfer);
                   1392:                return;
                   1393:        }
                   1394:        if (wait_for_unbusy(wdc) != 0) {
                   1395:                if ((wdc->sc_status & WDCS_ERR) == 0) {
                   1396:                        printf("wdc_atapi_start: not ready, st = %02x\n",
                   1397:                            wdc->sc_status);
                   1398:                        sc_xfer->error = XS_SELTIMEOUT;
                   1399:                }
                   1400: #if 0 /* don't get the sense yet, as this may be just UNIT ATTENTION */
                   1401:                else {
                   1402: #ifdef ATAPI_DEBUG_WDC
                   1403:                        printf("wdc_atapi_start: sense %02x\n", wdc->sc_error);
                   1404: #endif
                   1405:                        sc_xfer->error = XS_SENSE;
                   1406:                        sc_xfer->sense.atapi_sense = wdc->sc_error;
                   1407:                }
                   1408:                wdc_atapi_done(wdc, xfer);
                   1409:                return;
                   1410: #endif
                   1411:        }
                   1412:
1.12      cgd      1413:        /*
                   1414:         * Limit length to what can be stuffed into the cylinder register
                   1415:         * (16 bits).  Some CD-ROMs seem to interpret '0' as 65536,
                   1416:         * but not all devices do that and it's not obvious from the
                   1417:         * ATAPI spec that that behaviour should be expected.  If more
                   1418:         * data is necessary, multiple data transfer phases will be done.
                   1419:         */
1.2       bouyer   1420:        if (wdccommand(wdc, (struct wd_link*)xfer->d_link, ATAPI_PACKET_COMMAND,
1.12      cgd      1421:            sc_xfer->sc_link->scsipi_atapi.drive,
                   1422:            sc_xfer->datalen <= 0xffff ? sc_xfer->datalen : 0xffff,
1.2       bouyer   1423:                0, 0, 0) != 0) {
1.10      mikel    1424:                printf("wdc_atapi_start: can't send atapi packet command\n");
1.2       bouyer   1425:                sc_xfer->error = XS_DRIVER_STUFFUP;
                   1426:                wdc_atapi_done(wdc, xfer);
                   1427:                return;
                   1428:        }
                   1429:        if ((sc_xfer->sc_link->scsipi_atapi.cap  & 0x0300) != ACAP_DRQ_INTR) {
                   1430:                int i, phase;
                   1431:                for (i=20000; i>0; --i) {
1.12      cgd      1432:                        phase = (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_ireason) &
1.2       bouyer   1433:                            (WDCI_CMD | WDCI_IN)) |
1.12      cgd      1434:                            (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status) & WDCS_DRQ);
1.2       bouyer   1435:                        if (phase == PHASE_CMDOUT)
                   1436:                                break;
                   1437:                        delay(10);
                   1438:                }
                   1439:                if (phase != PHASE_CMDOUT ) {
1.10      mikel    1440:                        printf("wdc_atapi_start: timeout waiting PHASE_CMDOUT");
1.2       bouyer   1441:                        sc_xfer->error = XS_SELTIMEOUT;
                   1442:                        wdc_atapi_done(wdc, xfer);
                   1443:                        return;
                   1444:                }
1.12      cgd      1445:                bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
                   1446:                    (u_int16_t *)sc_xfer->cmd, sc_xfer->cmdlen >> 1);
1.2       bouyer   1447:        }
                   1448:        wdc->sc_flags |= WDCF_IRQ_WAIT;
                   1449:
                   1450: #ifdef ATAPI_DEBUG2
                   1451:        printf("wdc_atapi_start: timeout\n");
                   1452: #endif
                   1453:        timeout(wdctimeout, wdc, WAITTIME);
                   1454:        return;
                   1455: }
                   1456:
                   1457:
                   1458: int
                   1459: wdc_atapi_get_params(ab_link, drive, id)
                   1460:        struct scsipi_link *ab_link;
                   1461:        u_int8_t drive;
                   1462:        struct atapi_identify *id;
                   1463: {
                   1464:        struct wdc_softc *wdc = (void*)ab_link->adapter_softc;
                   1465:        int status, len, excess = 0;
                   1466:        int s, error;
                   1467:
1.4       bouyer   1468:        /* if a disk is already present, skip */
                   1469:        if ((wdc->sc_drives_mask & (1 << drive)) != 0) {
1.2       bouyer   1470: #ifdef ATAPI_DEBUG_PROBE
1.4       bouyer   1471:                printf("wdc_atapi_get_params: drive %d present\n", drive);
1.2       bouyer   1472: #endif
                   1473:                return 0;
                   1474:        }
                   1475:
                   1476:        /*
                   1477:         * If there is only one ATAPI slave on the bus,don't probe
                   1478:         * drive 0 (master)
                   1479:         */
                   1480:
                   1481:        if (wdc->sc_flags & WDCF_ONESLAVE && drive != 1)
                   1482:                return 0;
                   1483:
                   1484: #ifdef ATAPI_DEBUG_PROBE
                   1485:        printf("wdc_atapi_get_params: probing drive %d\n", drive);
                   1486: #endif
                   1487:
                   1488:        /*
                   1489:         * XXX
                   1490:         * The locking done here, and the length of time this may keep the rest
                   1491:         * of the system suspended, is a kluge.  This should be rewritten to
                   1492:         * set up a transfer and queue it through wdstart(), but it's called
                   1493:         * infrequently enough that this isn't a pressing matter.
                   1494:         */
                   1495:
                   1496:        s = splbio();
                   1497:
                   1498:        while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
                   1499:                wdc->sc_flags |= WDCF_WANTED;
                   1500:                if ((error = tsleep(wdc, PRIBIO | PCATCH, "atprm", 0)) != 0) {
                   1501:                        splx(s);
                   1502:                        return error;
                   1503:                }
                   1504:        }
                   1505:
                   1506:        wdc->sc_flags |= WDCF_ACTIVE;
                   1507:        error = 1;
                   1508:        (void)wdcreset(wdc, VERBOSE);
                   1509:        if ((status = wdccommand(wdc, (struct wd_link*)(&(ab_link->scsipi_atapi)),
                   1510:            ATAPI_SOFT_RESET, drive, 0, 0, 0, 0)) != 0) {
                   1511: #ifdef ATAPI_DEBUG
                   1512:                printf("wdc_atapi_get_params: ATAPI_SOFT_RESET"
                   1513:                    "failed for drive %d: status %d error %d\n",
                   1514:                    drive, status, wdc->sc_error);
                   1515: #endif
                   1516:                error = 0;
                   1517:                goto end;
                   1518:        }
                   1519:        if ((status = wait_for_unbusy(wdc)) != 0) {
                   1520: #ifdef ATAPI_DEBUG
                   1521:        printf("wdc_atapi_get_params: wait_for_unbusy failed "
                   1522:            "for drive %d: status %d error %d\n",
                   1523:            drive, status, wdc->sc_error);
                   1524: #endif
                   1525:                error = 0;
                   1526:                goto end;
                   1527:        }
                   1528:
                   1529:        if (wdccommand(wdc, (struct wd_link*)(&(ab_link->scsipi_atapi)),
                   1530:                ATAPI_IDENTIFY_DEVICE, drive, sizeof(struct atapi_identify),
                   1531:                0, 0, 0) != 0 ||
                   1532:            atapi_ready(wdc) != 0) {
                   1533: #ifdef ATAPI_DEBUG_PROBE
                   1534:                printf("ATAPI_IDENTIFY_DEVICE failed for drive %d\n", drive);
                   1535: #endif
                   1536:                error = 0;
                   1537:                goto end;
                   1538:        }
1.12      cgd      1539:        len = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_lo) + 256 *
                   1540:            bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_hi);
1.2       bouyer   1541:        if (len != sizeof(struct atapi_identify)) {
                   1542:                printf("Warning drive %d returned %d/%d of "
                   1543:                    "indentify device data\n", drive, len,
                   1544:                    sizeof(struct atapi_identify));
                   1545:                excess = len - sizeof(struct atapi_identify);
                   1546:                if (excess < 0)
                   1547:                        excess = 0;
                   1548:        }
1.12      cgd      1549:        bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
                   1550:            (u_int16_t *)id, sizeof(struct atapi_identify) >> 1);
1.2       bouyer   1551:        wdcbit_bucket(wdc, excess);
1.4       bouyer   1552:        wdc->sc_drives_mask |= (1 << drive);
1.2       bouyer   1553:
                   1554:  end:  /* Restart the queue. */
                   1555:        WDDEBUG_PRINT(("wdcstart from wdc_atapi_get_parms flags 0x%x\n",
                   1556:            wdc->sc_flags));
                   1557:        wdc->sc_flags &= ~WDCF_ACTIVE;
                   1558:        wdcstart(wdc);
                   1559:        splx(s);
                   1560:        return error;
                   1561: }
                   1562:
                   1563: int
                   1564: wdc_atapi_send_command_packet(sc_xfer)
                   1565:        struct scsipi_xfer *sc_xfer;
                   1566: {
                   1567:        struct scsipi_link *sc_link = sc_xfer->sc_link;
                   1568:        struct wdc_softc *wdc = (void*)sc_link->adapter_softc;
                   1569:        struct wdc_xfer *xfer;
                   1570:        int flags = sc_xfer->flags;
1.8       bouyer   1571:
1.2       bouyer   1572:        if (flags & SCSI_POLL) {   /* should use the queue and wdc_atapi_start */
                   1573:                struct wdc_xfer xfer_s;
                   1574:                int i, s;
                   1575:
                   1576:                s = splbio();
                   1577: #ifdef ATAPI_DEBUG_WDC
                   1578:                printf("wdc_atapi_send_cmd: "
                   1579:                    "flags 0x%x drive %d cmdlen %d datalen %d",
                   1580:                    sc_xfer->flags, sc_link->scsipi_atapi.drive, sc_xfer->cmdlen,
                   1581:                        sc_xfer->datalen);
                   1582: #endif
                   1583:                xfer = &xfer_s;
                   1584:                bzero(xfer, sizeof(xfer_s));
                   1585:                xfer->c_flags = C_INUSE|C_ATAPI|flags;
                   1586:                xfer->d_link = (struct wd_link *)(&sc_link->scsipi_atapi);
                   1587:                xfer->c_bp = sc_xfer->bp;
                   1588:                xfer->atapi_cmd = sc_xfer;
                   1589:                xfer->c_blkno = 0;
                   1590:                xfer->databuf = sc_xfer->data;
                   1591:                xfer->c_bcount = sc_xfer->datalen;
1.12      cgd      1592:
1.2       bouyer   1593:                if (wait_for_unbusy (wdc) != 0)  {
                   1594:                        if ((wdc->sc_status & WDCS_ERR) == 0) {
                   1595:                                printf("wdc_atapi_send_command: not ready, "
                   1596:                                    "st = %02x\n", wdc->sc_status);
                   1597:                                sc_xfer->error = XS_SELTIMEOUT;
                   1598:                        } else {
                   1599:                                sc_xfer->error = XS_SENSE;
                   1600:                                sc_xfer->sense.atapi_sense = wdc->sc_error;
                   1601:                        }
                   1602:                        splx(s);
                   1603:                        return COMPLETE;
                   1604:                }
                   1605:
1.12      cgd      1606:                /*
                   1607:                 * Limit length to what can be stuffed into the cylinder
                   1608:                 * register (16 bits).  Some CD-ROMs seem to interpret '0'
                   1609:                 * as 65536, but not all devices do that and it's not
                   1610:                 * obvious from the ATAPI spec that that behaviour should
                   1611:                 * be expected.  If more data is necessary, multiple data
                   1612:                 * transfer phases will be done.
                   1613:                 */
1.2       bouyer   1614:                if (wdccommand(wdc, (struct wd_link*)(&sc_link->scsipi_atapi),
1.12      cgd      1615:                    ATAPI_PACKET_COMMAND, sc_link->scsipi_atapi.drive,
                   1616:                    sc_xfer->datalen <= 0xffff ? sc_xfer->datalen : 0xffff,
1.2       bouyer   1617:                    0, 0, 0) != 0) {
1.10      mikel    1618:                        printf("can't send atapi packet command\n");
1.2       bouyer   1619:                        sc_xfer->error = XS_DRIVER_STUFFUP;
                   1620:                        splx(s);
                   1621:                        return COMPLETE;
                   1622:                }
                   1623:
                   1624:                /* Wait for cmd i/o phase. */
                   1625:                for (i = 20000; i > 0; --i) {
                   1626:                        int phase;
1.12      cgd      1627:                        phase = (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_ireason) &
1.2       bouyer   1628:                            (WDCI_CMD | WDCI_IN)) |
1.12      cgd      1629:                            (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status) & WDCS_DRQ);
1.2       bouyer   1630:                        if (phase == PHASE_CMDOUT)
                   1631:                                break;
                   1632:                        delay(10);
                   1633:                }
                   1634: #ifdef ATAPI_DEBUG_WDC
                   1635:                printf("Wait for cmd i/o phase: i = %d\n", i);
                   1636: #endif
                   1637:
1.12      cgd      1638:                bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
                   1639:                    (u_int16_t *)sc_xfer->cmd, sc_xfer->cmdlen >> 1);
1.2       bouyer   1640:
                   1641:                /* Wait for data i/o phase. */
                   1642:                for ( i= 20000; i > 0; --i) {
                   1643:                        int phase;
1.12      cgd      1644:                        phase = (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_ireason) &
1.2       bouyer   1645:                            (WDCI_CMD | WDCI_IN)) |
1.12      cgd      1646:                            (bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status) & WDCS_DRQ);
1.2       bouyer   1647:                        if (phase != PHASE_CMDOUT)
                   1648:                                break;
                   1649:                        delay(10);
                   1650:                }
                   1651:
                   1652: #ifdef ATAPI_DEBUG_WDC
                   1653:                printf("Wait for data i/o phase: i = %d\n", i);
                   1654: #endif
1.8       bouyer   1655:                wdc->sc_flags |= WDCF_IRQ_WAIT;
1.5       bouyer   1656:                while ((sc_xfer->flags & ITSDONE) == 0) {
                   1657:                        wdc_atapi_intr(wdc, xfer);
1.2       bouyer   1658:                        for (i = 2000; i > 0; --i)
1.12      cgd      1659:                                if ((bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status)
1.2       bouyer   1660:                                    & WDCS_DRQ) == 0)
                   1661:                                        break;
                   1662: #ifdef ATAPI_DEBUG_WDC
                   1663:                        printf("wdc_atapi_intr: i = %d\n", i);
                   1664: #endif
                   1665:                }
                   1666:                wdc->sc_flags &= ~(WDCF_IRQ_WAIT | WDCF_SINGLE | WDCF_ERROR);
                   1667:                wdc->sc_errors = 0;
                   1668:                xfer->c_skip = 0;
                   1669:                splx(s);
                   1670:                return COMPLETE;
                   1671:        } else {        /* POLLED */
                   1672:                xfer = wdc_get_xfer(flags & SCSI_NOSLEEP ? IDE_NOSLEEP : 0);
                   1673:                if (xfer == NULL) {
                   1674:                        return TRY_AGAIN_LATER;
                   1675:                }
                   1676:                xfer->c_flags |= C_ATAPI|sc_xfer->flags;
                   1677:                xfer->d_link = (struct wd_link*)(&sc_link->scsipi_atapi);
                   1678:                xfer->c_bp = sc_xfer->bp;
                   1679:                xfer->atapi_cmd = sc_xfer;
                   1680:                xfer->c_blkno = 0;
                   1681:                xfer->databuf = sc_xfer->data;
                   1682:                xfer->c_bcount = sc_xfer->datalen;
                   1683:                wdc_exec_xfer(wdc, xfer->d_link, xfer);
                   1684: #ifdef ATAPI_DEBUG_WDC
                   1685:                printf("wdc_atapi_send_command_packet: wdc_exec_xfer, flags 0x%x\n",
                   1686:                        sc_xfer->flags);
                   1687: #endif
                   1688:                return (sc_xfer->flags & ITSDONE) ? COMPLETE : SUCCESSFULLY_QUEUED;
                   1689:        }
                   1690: }
                   1691:
                   1692: int
                   1693: wdc_atapi_intr(wdc, xfer)
                   1694:        struct wdc_softc *wdc;
                   1695:        struct wdc_xfer *xfer;
                   1696: {
                   1697:        struct scsipi_xfer *sc_xfer = xfer->atapi_cmd;
                   1698:        int len, phase, i, retries=0;
                   1699:        int err, st, ire;
                   1700:
                   1701: #ifdef ATAPI_DEBUG2
                   1702:        printf("wdc_atapi_intr: %s\n", wdc->sc_dev.dv_xname);
                   1703: #endif
                   1704:
                   1705:        if (wait_for_unbusy(wdc) < 0) {
                   1706:                if ((wdc->sc_status & WDCS_ERR) == 0) {
                   1707:                        printf("wdc_atapi_intr: controller busy\n");
1.5       bouyer   1708:                        return 0;
1.2       bouyer   1709:                } else {
                   1710:                        sc_xfer->error = XS_SENSE;
                   1711:                        sc_xfer->sense.atapi_sense = wdc->sc_error;
                   1712:                }
                   1713: #ifdef ATAPI_DEBUG_WDC
                   1714:                printf("wdc_atapi_intr: wdc_atapi_done(), error %d\n",
                   1715:                        sc_xfer->error);
                   1716: #endif
                   1717:                wdc_atapi_done(wdc, xfer);
                   1718:                return 0;
                   1719:        }
                   1720:
                   1721:
                   1722: again:
1.12      cgd      1723:        len = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_lo) +
                   1724:            256 * bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_cyl_hi);
1.2       bouyer   1725:
1.12      cgd      1726:        st = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_status);
                   1727:        err = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
                   1728:        ire = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_ireason);
1.2       bouyer   1729:
                   1730:        phase = (ire & (WDCI_CMD | WDCI_IN)) | (st & WDCS_DRQ);
                   1731: #ifdef ATAPI_DEBUG_WDC
                   1732:        printf("wdc_atapi_intr: len %d st %d err %d ire %d :",
                   1733:            len, st, err, ire);
                   1734: #endif
                   1735:        switch (phase) {
                   1736:        case PHASE_CMDOUT:
                   1737:                /* send packet command */
                   1738: #ifdef ATAPI_DEBUG_WDC
                   1739:                printf("PHASE_CMDOUT\n");
                   1740: #endif
                   1741:
                   1742: #ifdef ATAPI_DEBUG_WDC
                   1743:                {
                   1744:                        int i;
                   1745:                        char *c = (char *)sc_xfer->cmd;
                   1746:                        printf("wdc_atapi_intr: cmd ");
                   1747:                        for (i = 0; i < sc_xfer->cmdlen; i++)
                   1748:                                printf("%x ", c[i]);
                   1749:                        printf("\n");
                   1750:                }
                   1751: #endif
                   1752:
1.12      cgd      1753:                bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
                   1754:                    (u_int16_t *)sc_xfer->cmd, sc_xfer->cmdlen >> 1);
1.2       bouyer   1755:                return 1;
                   1756:
                   1757:        case PHASE_DATAOUT:
                   1758:                /* write data */
                   1759: #ifdef ATAPI_DEBUG_WDC
                   1760:                printf("PHASE_DATAOUT\n");
                   1761: #endif
                   1762:                if ((sc_xfer->flags & SCSI_DATA_OUT) == 0) {
                   1763:                        printf("wdc_atapi_intr: bad data phase\n");
                   1764:                        sc_xfer->error = XS_DRIVER_STUFFUP;
1.5       bouyer   1765:                        return 0;
1.2       bouyer   1766:                }
                   1767:                if (xfer->c_bcount < len) {
                   1768:                        printf("wdc_atapi_intr: warning: write only "
                   1769:                            "%d of %d requested bytes\n", xfer->c_bcount, len);
1.12      cgd      1770:                        bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh,
                   1771:                            wd_data, xfer->databuf + xfer->c_skip,
                   1772:                            xfer->c_bcount >> 1);
                   1773:                        for (i = xfer->c_bcount; i < len; i += 2)
                   1774:                                bus_space_write_2(wdc->sc_iot, wdc->sc_ioh,
                   1775:                                    wd_data, 0);
1.8       bouyer   1776:                        xfer->c_skip += xfer->c_bcount;
1.2       bouyer   1777:                        xfer->c_bcount = 0;
                   1778:                } else {
1.12      cgd      1779:                        bus_space_write_multi_2(wdc->sc_iot, wdc->sc_ioh,
                   1780:                            wd_data, xfer->databuf + xfer->c_skip, len >> 1);
1.2       bouyer   1781:                        xfer->c_skip += len;
                   1782:                        xfer->c_bcount -= len;
                   1783:                }
1.8       bouyer   1784:                return 1;
1.2       bouyer   1785:
                   1786:        case PHASE_DATAIN:
                   1787:                /* Read data */
                   1788: #ifdef ATAPI_DEBUG_WDC
                   1789:                printf("PHASE_DATAIN\n");
                   1790: #endif
                   1791:                if ((sc_xfer->flags & SCSI_DATA_IN) == 0) {
                   1792:                        printf("wdc_atapi_intr: bad data phase\n");
                   1793:                        sc_xfer->error = XS_DRIVER_STUFFUP;
1.5       bouyer   1794:                        return 0;
1.2       bouyer   1795:                }
                   1796:                if (xfer->c_bcount < len) {
                   1797:                        printf("wdc_atapi_intr: warning: reading only "
                   1798:                            "%d of %d bytes\n", xfer->c_bcount, len);
1.12      cgd      1799:                        bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh,
                   1800:                            wd_data, xfer->databuf + xfer->c_skip,
                   1801:                            xfer->c_bcount >> 1);
1.2       bouyer   1802:                        wdcbit_bucket(wdc, len - xfer->c_bcount);
1.8       bouyer   1803:                        xfer->c_skip += xfer->c_bcount;
1.2       bouyer   1804:                        xfer->c_bcount = 0;
                   1805:                } else {
1.12      cgd      1806:                        bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh,
                   1807:                            wd_data, xfer->databuf + xfer->c_skip, len >> 1);
1.2       bouyer   1808:                        xfer->c_skip += len;
                   1809:                        xfer->c_bcount -=len;
                   1810:                }
1.8       bouyer   1811:                return 1;
1.2       bouyer   1812:
                   1813:        case PHASE_ABORTED:
                   1814:        case PHASE_COMPLETED:
                   1815: #ifdef ATAPI_DEBUG_WDC
                   1816:                printf("PHASE_COMPLETED\n");
                   1817: #endif
                   1818:                if (st & WDCS_ERR) {
                   1819:                        sc_xfer->error = XS_SENSE;
1.12      cgd      1820:                        sc_xfer->sense.atapi_sense = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1.2       bouyer   1821:                }
                   1822: #ifdef ATAPI_DEBUG_WDC
                   1823:                if (xfer->c_bcount != 0) {
                   1824:                        printf("wdc_atapi_intr warning: bcount value "
                   1825:                            "is %d after io\n", xfer->c_bcount);
                   1826:                }
                   1827: #endif
                   1828:                break;
                   1829:
                   1830:        default:
                   1831:         if (++retries<500) {
                   1832:             DELAY(100);
                   1833:             goto again;
                   1834:         }
                   1835:                printf("wdc_atapi_intr: unknown phase %d\n", phase);
                   1836:                if (st & WDCS_ERR) {
                   1837:                        sc_xfer->error = XS_SENSE;
1.12      cgd      1838:                        sc_xfer->sense.atapi_sense = bus_space_read_1(wdc->sc_iot, wdc->sc_ioh, wd_error);
1.2       bouyer   1839:                } else {
                   1840:                        sc_xfer->error = XS_DRIVER_STUFFUP;
                   1841:                }
                   1842:        }
                   1843:
                   1844: #ifdef ATAPI_DEBUG_WDC
                   1845:                printf("wdc_atapi_intr: wdc_atapi_done() (end), error %d\n",
                   1846:                        sc_xfer->error);
                   1847: #endif
                   1848:        wdc_atapi_done(wdc, xfer);
1.5       bouyer   1849:        return (1);
1.2       bouyer   1850: }
                   1851:
                   1852:
                   1853: void
                   1854: wdc_atapi_done(wdc, xfer)
                   1855:        struct wdc_softc *wdc;
                   1856:        struct wdc_xfer *xfer;
                   1857: {
                   1858:        struct scsipi_xfer *sc_xfer = xfer->atapi_cmd;
                   1859:        int s;
                   1860:        int need_done =  xfer->c_flags & C_NEEDDONE;
                   1861:
                   1862: #ifdef ATAPI_DEBUG
                   1863:        printf("wdc_atapi_done: flags 0x%x\n", (u_int)xfer->c_flags);
                   1864: #endif
                   1865:        sc_xfer->resid = xfer->c_bcount;
1.8       bouyer   1866:        wdc->sc_flags &= ~WDCF_IRQ_WAIT;
1.2       bouyer   1867:
                   1868:        /* remove this command from xfer queue */
                   1869:        wdc->sc_errors = 0;
                   1870:        xfer->c_skip = 0;
                   1871:        if ((xfer->c_flags & SCSI_POLL) == 0) {
                   1872:                s = splbio();
                   1873:                untimeout(wdctimeout, wdc);
                   1874:                TAILQ_REMOVE(&wdc->sc_xfer, xfer, c_xferchain);
                   1875:                wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
                   1876:                wdc_free_xfer(xfer);
                   1877:                sc_xfer->flags |= ITSDONE;
                   1878:                if (need_done) {
                   1879: #ifdef ATAPI_DEBUG
                   1880:                printf("wdc_atapi_done: scsipi_done\n");
                   1881: #endif
                   1882:                        scsipi_done(sc_xfer);
                   1883:                }
                   1884: #ifdef WDDEBUG
                   1885:                printf("wdcstart from wdc_atapi_intr, flags 0x%x\n",
                   1886:                    wdc->sc_flags);
                   1887: #endif
                   1888:                wdcstart(wdc);
                   1889:            splx(s);
1.8       bouyer   1890:        } else {
1.2       bouyer   1891:                wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR | WDCF_ACTIVE);
1.8       bouyer   1892:                sc_xfer->flags |= ITSDONE;
                   1893:        }
1.2       bouyer   1894: }
                   1895:
                   1896: #endif /* NATAPIBUS > 0 */

CVSweb <webmaster@jp.NetBSD.org>