[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.292

1.292   ! tsutsui     1: /*     $NetBSD: wdc.c,v 1.291 2018/10/27 05:38:08 maya Exp $ */
1.31      bouyer      2:
                      3: /*
1.137     bouyer      4:  * Copyright (c) 1998, 2001, 2003 Manuel Bouyer.  All rights reserved.
1.31      bouyer      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     17:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     18:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     19:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     20:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     21:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     22:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     23:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     24:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     25:  */
1.2       bouyer     26:
1.27      mycroft    27: /*-
1.220     mycroft    28:  * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
1.27      mycroft    29:  * All rights reserved.
1.2       bouyer     30:  *
1.27      mycroft    31:  * This code is derived from software contributed to The NetBSD Foundation
                     32:  * by Charles M. Hannum, by Onno van der Linden and by Manuel Bouyer.
1.12      cgd        33:  *
1.2       bouyer     34:  * Redistribution and use in source and binary forms, with or without
                     35:  * modification, are permitted provided that the following conditions
                     36:  * are met:
                     37:  * 1. Redistributions of source code must retain the above copyright
                     38:  *    notice, this list of conditions and the following disclaimer.
                     39:  * 2. Redistributions in binary form must reproduce the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer in the
                     41:  *    documentation and/or other materials provided with the distribution.
                     42:  *
1.27      mycroft    43:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     44:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     45:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     46:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     47:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     48:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     49:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     50:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     51:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     52:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     53:  * POSSIBILITY OF SUCH DAMAGE.
1.2       bouyer     54:  */
                     55:
1.12      cgd        56: /*
                     57:  * CODE UNTESTED IN THE CURRENT REVISION:
                     58:  */
1.100     lukem      59:
                     60: #include <sys/cdefs.h>
1.292   ! tsutsui    61: __KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.291 2018/10/27 05:38:08 maya Exp $");
1.12      cgd        62:
1.247     dyoung     63: #include "opt_ata.h"
1.263     bouyer     64: #include "opt_wdc.h"
1.31      bouyer     65:
1.2       bouyer     66: #include <sys/param.h>
                     67: #include <sys/systm.h>
                     68: #include <sys/kernel.h>
                     69: #include <sys/conf.h>
                     70: #include <sys/buf.h>
1.31      bouyer     71: #include <sys/device.h>
1.2       bouyer     72: #include <sys/malloc.h>
                     73: #include <sys/syslog.h>
                     74: #include <sys/proc.h>
                     75:
1.249     ad         76: #include <sys/intr.h>
                     77: #include <sys/bus.h>
1.2       bouyer     78:
1.17      sakamoto   79: #ifndef __BUS_SPACE_HAS_STREAM_METHODS
1.31      bouyer     80: #define bus_space_write_multi_stream_2 bus_space_write_multi_2
                     81: #define bus_space_write_multi_stream_4 bus_space_write_multi_4
                     82: #define bus_space_read_multi_stream_2  bus_space_read_multi_2
                     83: #define bus_space_read_multi_stream_4  bus_space_read_multi_4
1.246     sborrill   84: #define bus_space_read_stream_2        bus_space_read_2
                     85: #define bus_space_read_stream_4        bus_space_read_4
                     86: #define bus_space_write_stream_2       bus_space_write_2
                     87: #define bus_space_write_stream_4       bus_space_write_4
1.17      sakamoto   88: #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
1.16      sakamoto   89:
1.103     bouyer     90: #include <dev/ata/atavar.h>
1.31      bouyer     91: #include <dev/ata/atareg.h>
1.239     bouyer     92: #include <dev/ata/satareg.h>
                     93: #include <dev/ata/satavar.h>
1.12      cgd        94: #include <dev/ic/wdcreg.h>
                     95: #include <dev/ic/wdcvar.h>
1.31      bouyer     96:
1.137     bouyer     97: #include "locators.h"
                     98:
1.2       bouyer     99: #include "atapibus.h"
1.106     bouyer    100: #include "wd.h"
1.240     bouyer    101: #include "sata.h"
1.2       bouyer    102:
1.31      bouyer    103: #define WDCDELAY  100 /* 100 microseconds */
                    104: #define WDCNDELAY_RST (WDC_RESET_WAIT * 1000 / WDCDELAY)
1.2       bouyer    105: #if 0
1.31      bouyer    106: /* If you enable this, it will report any delays more than WDCDELAY * N long. */
1.2       bouyer    107: #define WDCNDELAY_DEBUG        50
                    108: #endif
                    109:
1.284     jdolecek  110: /* When polling wait that much and then kpause for 1/hz seconds */
1.219     perry     111: #define WDCDELAY_POLL 1 /* ms */
1.137     bouyer    112:
                    113: /* timeout for the control commands */
                    114: #define WDC_CTRL_DELAY 10000 /* 10s, for the recall command */
                    115:
1.224     bouyer    116: /*
                    117:  * timeout when waiting for BSY to deassert when probing.
                    118:  * set to 5s. From the standards this could be up to 31, but we can't
1.261     snj       119:  * wait that much at boot time, and 5s seems to be enough.
1.224     bouyer    120:  */
                    121: #define WDC_PROBE_WAIT 5
                    122:
                    123:
1.106     bouyer    124: #if NWD > 0
1.103     bouyer    125: extern const struct ata_bustype wdc_ata_bustype; /* in ata_wdc.c */
1.106     bouyer    126: #else
                    127: /* A fake one, the autoconfig will print "wd at foo ... not configured */
                    128: const struct ata_bustype wdc_ata_bustype = {
1.291     maya      129:        .bustype_type =         SCSIPI_BUSTYPE_ATA,
1.290     maya      130:        .ata_bio =              NULL,
1.291     maya      131:        .ata_reset_drive =      NULL,
1.290     maya      132:        .ata_reset_channel =    wdc_reset_channel,
                    133:        .ata_exec_command =     wdc_exec_command,
                    134:        .ata_get_params =       NULL,
                    135:        .ata_addref =           NULL,
                    136:        .ata_delref =           NULL,
                    137:        .ata_killpending =      NULL,
                    138:        .ata_recovery =         NULL,
1.106     bouyer    139: };
                    140: #endif
1.102     bouyer    141:
1.213     thorpej   142: /* Flags to wdcreset(). */
                    143: #define        RESET_POLL      1
1.284     jdolecek  144: #define        RESET_SLEEP     0       /* wdcreset() will use kpause() */
1.213     thorpej   145:
                    146: static int     wdcprobe1(struct ata_channel *, int);
                    147: static int     wdcreset(struct ata_channel *, int);
1.222     christos  148: static void    __wdcerror(struct ata_channel *, const char *);
1.205     thorpej   149: static int     __wdcwait_reset(struct ata_channel *, int, int);
                    150: static void    __wdccommand_done(struct ata_channel *, struct ata_xfer *);
1.284     jdolecek  151: static void    __wdccommand_poll(struct ata_channel *, struct ata_xfer *);
1.205     thorpej   152: static void    __wdccommand_done_end(struct ata_channel *, struct ata_xfer *);
                    153: static void    __wdccommand_kill_xfer(struct ata_channel *,
1.182     bouyer    154:                                       struct ata_xfer *, int);
1.284     jdolecek  155: static int     __wdccommand_start(struct ata_channel *, struct ata_xfer *);
1.205     thorpej   156: static int     __wdccommand_intr(struct ata_channel *, struct ata_xfer *, int);
1.284     jdolecek  157: static int     __wdcwait(struct ata_channel *, int, int, int, int *);
1.31      bouyer    158:
1.213     thorpej   159: static void    wdc_datain_pio(struct ata_channel *, int, void *, size_t);
                    160: static void    wdc_dataout_pio(struct ata_channel *, int, void *, size_t);
1.31      bouyer    161: #define DEBUG_INTR   0x01
                    162: #define DEBUG_XFERS  0x02
                    163: #define DEBUG_STATUS 0x04
                    164: #define DEBUG_FUNCS  0x08
                    165: #define DEBUG_PROBE  0x10
1.74      enami     166: #define DEBUG_DETACH 0x20
1.87      bouyer    167: #define DEBUG_DELAY  0x40
1.204     thorpej   168: #ifdef ATADEBUG
                    169: extern int atadebug_mask; /* init'ed in ata.c */
1.31      bouyer    170: int wdc_nxfer = 0;
1.204     thorpej   171: #define ATADEBUG_PRINT(args, level)  if (atadebug_mask & (level)) printf args
1.2       bouyer    172: #else
1.204     thorpej   173: #define ATADEBUG_PRINT(args, level)
1.2       bouyer    174: #endif
                    175:
1.162     thorpej   176: /*
1.176     thorpej   177:  * Initialize the "shadow register" handles for a standard wdc controller.
                    178:  */
                    179: void
1.284     jdolecek  180: wdc_init_shadow_regs(struct wdc_regs *wdr)
1.176     thorpej   181: {
1.205     thorpej   182:        wdr->cmd_iohs[wd_status] = wdr->cmd_iohs[wd_command];
                    183:        wdr->cmd_iohs[wd_features] = wdr->cmd_iohs[wd_error];
                    184: }
                    185:
                    186: /*
                    187:  * Allocate a wdc_regs array, based on the number of channels.
                    188:  */
                    189: void
                    190: wdc_allocate_regs(struct wdc_softc *wdc)
                    191: {
                    192:
1.207     thorpej   193:        wdc->regs = malloc(wdc->sc_atac.atac_nchannels *
                    194:                           sizeof(struct wdc_regs), M_DEVBUF, M_WAITOK);
1.176     thorpej   195: }
                    196:
1.240     bouyer    197: #if NSATA > 0
1.239     bouyer    198: /*
                    199:  * probe drives on SATA controllers with standard SATA registers:
                    200:  * bring the PHYs online, read the drive signature and set drive flags
                    201:  * appropriately.
                    202:  */
                    203: void
                    204: wdc_sataprobe(struct ata_channel *chp)
                    205: {
                    206:        struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
1.279     martin    207:        uint8_t st = 0, sc __unused, sn __unused, cl, ch;
1.284     jdolecek  208:        int i;
1.239     bouyer    209:
1.274     bouyer    210:        KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL);
1.239     bouyer    211:
1.284     jdolecek  212:        /* do this before we take lock */
                    213:
                    214:        ata_channel_lock(chp);
                    215:
1.242     bouyer    216:        /* reset the PHY and bring online */
                    217:        switch (sata_reset_interface(chp, wdr->sata_iot, wdr->sata_control,
1.278     bouyer    218:            wdr->sata_status, AT_WAIT)) {
1.239     bouyer    219:        case SStatus_DET_DEV:
1.258     sborrill  220:                /* wait 5s for BSY to clear */
                    221:                for (i = 0; i < WDC_PROBE_WAIT * hz; i++) {
                    222:                        bus_space_write_1(wdr->cmd_iot,
                    223:                            wdr->cmd_iohs[wd_sdh], 0, WDSD_IBM);
                    224:                        delay(10);      /* 400ns delay */
                    225:                        st = bus_space_read_1(wdr->cmd_iot,
                    226:                            wdr->cmd_iohs[wd_status], 0);
                    227:                        if ((st & WDCS_BSY) == 0)
                    228:                                break;
1.284     jdolecek  229:                        ata_delay(chp, 1, "sataprb", AT_WAIT);
1.258     sborrill  230:                }
                    231:                if (i == WDC_PROBE_WAIT * hz)
                    232:                        aprint_error_dev(chp->ch_atac->atac_dev,
                    233:                            "BSY never cleared, status 0x%02x\n", st);
                    234:                sc = bus_space_read_1(wdr->cmd_iot,
1.239     bouyer    235:                    wdr->cmd_iohs[wd_seccnt], 0);
1.258     sborrill  236:                sn = bus_space_read_1(wdr->cmd_iot,
1.239     bouyer    237:                    wdr->cmd_iohs[wd_sector], 0);
1.258     sborrill  238:                cl = bus_space_read_1(wdr->cmd_iot,
1.239     bouyer    239:                    wdr->cmd_iohs[wd_cyl_lo], 0);
1.258     sborrill  240:                ch = bus_space_read_1(wdr->cmd_iot,
1.239     bouyer    241:                    wdr->cmd_iohs[wd_cyl_hi], 0);
1.258     sborrill  242:                ATADEBUG_PRINT(("%s: port %d: sc=0x%x sn=0x%x "
1.239     bouyer    243:                    "cl=0x%x ch=0x%x\n",
1.253     cube      244:                    device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
1.258     sborrill  245:                    sc, sn, cl, ch), DEBUG_PROBE);
1.274     bouyer    246:                if (atabus_alloc_drives(chp, 1) != 0)
                    247:                        return;
1.239     bouyer    248:                /*
1.258     sborrill  249:                 * sc and sn are supposed to be 0x1 for ATAPI, but in some
1.239     bouyer    250:                 * cases we get wrong values here, so ignore it.
                    251:                 */
                    252:                if (cl == 0x14 && ch == 0xeb)
1.274     bouyer    253:                        chp->ch_drive[0].drive_type = ATA_DRIVET_ATAPI;
1.239     bouyer    254:                else
1.274     bouyer    255:                        chp->ch_drive[0].drive_type = ATA_DRIVET_ATA;
1.239     bouyer    256:
1.241     bouyer    257:                /*
                    258:                 * issue a reset in case only the interface part of the drive
                    259:                 * is up
                    260:                 */
                    261:                if (wdcreset(chp, RESET_SLEEP) != 0)
1.274     bouyer    262:                        chp->ch_drive[0].drive_type = ATA_DRIVET_NONE;
1.239     bouyer    263:                break;
                    264:
                    265:        default:
1.242     bouyer    266:                break;
1.239     bouyer    267:        }
1.284     jdolecek  268:
                    269:        ata_channel_unlock(chp);
1.239     bouyer    270: }
1.240     bouyer    271: #endif /* NSATA > 0 */
1.239     bouyer    272:
                    273:
1.162     thorpej   274: /* Test to see controller with at last one attached drive is there.
                    275:  * Returns a bit for each possible drive found (0x01 for drive 0,
                    276:  * 0x02 for drive 1).
                    277:  * Logic:
                    278:  * - If a status register is at 0xff, assume there is no drive here
                    279:  *   (ISA has pull-up resistors).  Similarly if the status register has
                    280:  *   the value we last wrote to the bus (for IDE interfaces without pullups).
                    281:  *   If no drive at all -> return.
                    282:  * - reset the controller, wait for it to complete (may take up to 31s !).
                    283:  *   If timeout -> return.
                    284:  * - test ATA/ATAPI signatures. If at last one drive found -> return.
                    285:  * - try an ATA command on the master.
                    286:  */
1.137     bouyer    287:
1.239     bouyer    288: void
1.205     thorpej   289: wdc_drvprobe(struct ata_channel *chp)
1.137     bouyer    290: {
1.257     pooka     291:        struct ataparams params; /* XXX: large struct */
1.207     thorpej   292:        struct atac_softc *atac = chp->ch_atac;
                    293:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej   294:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.145     christos  295:        u_int8_t st0 = 0, st1 = 0;
1.284     jdolecek  296:        int i, j, error, tfd;
1.137     bouyer    297:
1.274     bouyer    298:        if (atabus_alloc_drives(chp, wdc->wdc_maxdrives) != 0)
                    299:                return;
1.164     thorpej   300:        if (wdcprobe1(chp, 0) == 0) {
                    301:                /* No drives, abort the attach here. */
1.274     bouyer    302:                atabus_free_drives(chp);
1.164     thorpej   303:                return;
1.161     thorpej   304:        }
1.137     bouyer    305:
1.284     jdolecek  306:        ata_channel_lock(chp);
1.137     bouyer    307:        /* for ATA/OLD drives, wait for DRDY, 3s timeout */
                    308:        for (i = 0; i < mstohz(3000); i++) {
1.263     bouyer    309:                /*
                    310:                 * select drive 1 first, so that master is selected on
                    311:                 * exit from the loop
                    312:                 */
1.274     bouyer    313:                if (chp->ch_ndrives > 1 &&
                    314:                    chp->ch_drive[1].drive_type == ATA_DRIVET_ATA) {
1.263     bouyer    315:                        if (wdc->select)
                    316:                                wdc->select(chp,1);
                    317:                        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
                    318:                            0, WDSD_IBM | 0x10);
                    319:                        delay(10);      /* 400ns delay */
                    320:                        st1 = bus_space_read_1(wdr->cmd_iot,
                    321:                            wdr->cmd_iohs[wd_status], 0);
                    322:                }
1.274     bouyer    323:                if (chp->ch_drive[0].drive_type == ATA_DRIVET_ATA) {
1.207     thorpej   324:                        if (wdc->select)
1.174     bouyer    325:                                wdc->select(chp,0);
1.205     thorpej   326:                        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174     bouyer    327:                            0, WDSD_IBM);
                    328:                        delay(10);      /* 400ns delay */
1.205     thorpej   329:                        st0 = bus_space_read_1(wdr->cmd_iot,
                    330:                            wdr->cmd_iohs[wd_status], 0);
1.174     bouyer    331:                }
1.219     perry     332:
                    333:
1.274     bouyer    334:                if ((chp->ch_drive[0].drive_type != ATA_DRIVET_ATA ||
                    335:                     (st0 & WDCS_DRDY)) &&
                    336:                    (chp->ch_ndrives < 2 ||
                    337:                     chp->ch_drive[1].drive_type != ATA_DRIVET_ATA ||
                    338:                     (st1 & WDCS_DRDY)))
1.137     bouyer    339:                        break;
1.263     bouyer    340: #ifdef WDC_NO_IDS
1.284     jdolecek  341:                /* cannot kpause here (can't enable IPL_BIO interrups),
1.263     bouyer    342:                 * delay instead
                    343:                 */
                    344:                delay(1000000 / hz);
                    345: #else
1.284     jdolecek  346:                ata_delay(chp, 1, "atadrdy", AT_WAIT);
1.265     bouyer    347: #endif
1.264     christos  348:        }
1.274     bouyer    349:        if ((st0 & WDCS_DRDY) == 0 &&
                    350:            chp->ch_drive[0].drive_type != ATA_DRIVET_ATAPI)
                    351:                chp->ch_drive[0].drive_type = ATA_DRIVET_NONE;
                    352:        if (chp->ch_ndrives > 1 && (st1 & WDCS_DRDY) == 0 &&
                    353:            chp->ch_drive[1].drive_type != ATA_DRIVET_ATAPI)
                    354:                chp->ch_drive[1].drive_type = ATA_DRIVET_NONE;
1.284     jdolecek  355:        ata_channel_unlock(chp);
1.137     bouyer    356:
1.204     thorpej   357:        ATADEBUG_PRINT(("%s:%d: wait DRDY st0 0x%x st1 0x%x\n",
1.253     cube      358:            device_xname(atac->atac_dev),
1.169     thorpej   359:            chp->ch_channel, st0, st1), DEBUG_PROBE);
1.137     bouyer    360:
                    361:        /* Wait a bit, some devices are weird just after a reset. */
                    362:        delay(5000);
                    363:
1.274     bouyer    364:        for (i = 0; i < chp->ch_ndrives; i++) {
1.238     itohy     365: #if NATA_DMA
1.137     bouyer    366:                /*
1.282     skrll     367:                 * Init error counter so that an error within the first xfers
1.137     bouyer    368:                 * will trigger a downgrade
                    369:                 */
                    370:                chp->ch_drive[i].n_dmaerrs = NERRS_MAX-1;
1.238     itohy     371: #endif
1.137     bouyer    372:
                    373:                /* If controller can't do 16bit flag the drives as 32bit */
1.207     thorpej   374:                if ((atac->atac_cap &
1.212     thorpej   375:                    (ATAC_CAP_DATA16 | ATAC_CAP_DATA32)) == ATAC_CAP_DATA32) {
1.284     jdolecek  376:                        ata_channel_lock(chp);
1.274     bouyer    377:                        chp->ch_drive[i].drive_flags |= ATA_DRIVE_CAP32;
1.284     jdolecek  378:                        ata_channel_unlock(chp);
1.212     thorpej   379:                }
1.274     bouyer    380:                if (chp->ch_drive[i].drive_type == ATA_DRIVET_NONE)
1.137     bouyer    381:                        continue;
                    382:
1.144     briggs    383:                /* Shortcut in case we've been shutdown */
1.205     thorpej   384:                if (chp->ch_flags & ATACH_SHUTDOWN)
1.164     thorpej   385:                        return;
1.144     briggs    386:
1.216     bouyer    387:                /*
                    388:                 * Issue an identify, to try to detect ghosts.
                    389:                 * Note that we can't use interrupts here, because if there
                    390:                 * is no devices, we will get a command aborted without
                    391:                 * interrupts.
                    392:                 */
                    393:                error = ata_get_params(&chp->ch_drive[i],
                    394:                    AT_WAIT | AT_POLL, &params);
1.137     bouyer    395:                if (error != CMD_OK) {
1.284     jdolecek  396:                        ata_channel_lock(chp);
                    397:                        ata_delay(chp, 1000, "atacnf", AT_WAIT);
                    398:                        ata_channel_unlock(chp);
1.144     briggs    399:
                    400:                        /* Shortcut in case we've been shutdown */
1.205     thorpej   401:                        if (chp->ch_flags & ATACH_SHUTDOWN)
1.164     thorpej   402:                                return;
1.144     briggs    403:
1.137     bouyer    404:                        error = ata_get_params(&chp->ch_drive[i],
1.216     bouyer    405:                            AT_WAIT | AT_POLL, &params);
1.137     bouyer    406:                }
1.274     bouyer    407:                if (error != CMD_OK) {
1.204     thorpej   408:                        ATADEBUG_PRINT(("%s:%d:%d: IDENTIFY failed (%d)\n",
1.253     cube      409:                            device_xname(atac->atac_dev),
1.169     thorpej   410:                            chp->ch_channel, i, error), DEBUG_PROBE);
1.284     jdolecek  411:                        ata_channel_lock(chp);
1.274     bouyer    412:                        if (chp->ch_drive[i].drive_type != ATA_DRIVET_ATA ||
                    413:                            (wdc->cap & WDC_CAPABILITY_PREATA) == 0) {
                    414:                                chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
1.284     jdolecek  415:                                ata_channel_unlock(chp);
1.137     bouyer    416:                                continue;
1.274     bouyer    417:                        }
1.137     bouyer    418:                        /*
                    419:                         * Pre-ATA drive ?
                    420:                         * Test registers writability (Error register not
                    421:                         * writable, but cyllo is), then try an ATA command.
                    422:                         */
1.203     thorpej   423:                        if (wdc->select)
1.169     thorpej   424:                                wdc->select(chp,i);
1.205     thorpej   425:                        bus_space_write_1(wdr->cmd_iot,
                    426:                            wdr->cmd_iohs[wd_sdh], 0, WDSD_IBM | (i << 4));
1.137     bouyer    427:                        delay(10);      /* 400ns delay */
1.205     thorpej   428:                        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_error],
1.157     fvdl      429:                            0, 0x58);
1.205     thorpej   430:                        bus_space_write_1(wdr->cmd_iot,
                    431:                            wdr->cmd_iohs[wd_cyl_lo], 0, 0xa5);
                    432:                        if (bus_space_read_1(wdr->cmd_iot,
                    433:                                wdr->cmd_iohs[wd_error], 0) == 0x58 ||
                    434:                            bus_space_read_1(wdr->cmd_iot,
                    435:                                wdr->cmd_iohs[wd_cyl_lo], 0) != 0xa5) {
1.204     thorpej   436:                                ATADEBUG_PRINT(("%s:%d:%d: register "
1.137     bouyer    437:                                    "writability failed\n",
1.253     cube      438:                                    device_xname(atac->atac_dev),
1.169     thorpej   439:                                    chp->ch_channel, i), DEBUG_PROBE);
1.274     bouyer    440:                                    chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
1.284     jdolecek  441:                                    ata_channel_unlock(chp);
1.155     bouyer    442:                                    continue;
1.137     bouyer    443:                        }
1.284     jdolecek  444:                        if (wdc_wait_for_ready(chp, 10000, 0, &tfd) ==
                    445:                            WDCWAIT_TOUT) {
1.204     thorpej   446:                                ATADEBUG_PRINT(("%s:%d:%d: not ready\n",
1.253     cube      447:                                    device_xname(atac->atac_dev),
1.169     thorpej   448:                                    chp->ch_channel, i), DEBUG_PROBE);
1.274     bouyer    449:                                chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
1.284     jdolecek  450:                                ata_channel_unlock(chp);
1.137     bouyer    451:                                continue;
                    452:                        }
1.205     thorpej   453:                        bus_space_write_1(wdr->cmd_iot,
                    454:                            wdr->cmd_iohs[wd_command], 0, WDCC_RECAL);
1.137     bouyer    455:                        delay(10);      /* 400ns delay */
1.284     jdolecek  456:                        if (wdc_wait_for_ready(chp, 10000, 0, &tfd) ==
                    457:                            WDCWAIT_TOUT) {
1.204     thorpej   458:                                ATADEBUG_PRINT(("%s:%d:%d: WDCC_RECAL failed\n",
1.253     cube      459:                                    device_xname(atac->atac_dev),
1.169     thorpej   460:                                    chp->ch_channel, i), DEBUG_PROBE);
1.274     bouyer    461:                                chp->ch_drive[i].drive_type = ATA_DRIVET_NONE;
1.284     jdolecek  462:                                ata_channel_unlock(chp);
1.155     bouyer    463:                        } else {
1.274     bouyer    464:                                for (j = 0; j < chp->ch_ndrives; j++) {
                    465:                                        if (chp->ch_drive[i].drive_type !=
                    466:                                            ATA_DRIVET_NONE) {
                    467:                                                chp->ch_drive[j].drive_type =
                    468:                                                    ATA_DRIVET_OLD;
                    469:                                        }
                    470:                                }
1.284     jdolecek  471:                                ata_channel_unlock(chp);
1.137     bouyer    472:                        }
                    473:                }
                    474:        }
1.164     thorpej   475: }
                    476:
1.2       bouyer    477: int
1.284     jdolecek  478: wdcprobe(struct wdc_regs *wdr)
1.12      cgd       479: {
1.292   ! tsutsui   480:
        !           481:        return wdcprobe_with_reset(wdr, NULL);
        !           482: }
        !           483:
        !           484: int
        !           485: wdcprobe_with_reset(struct wdc_regs *wdr,
        !           486:     void (*do_reset)(struct ata_channel *, int))
        !           487: {
1.284     jdolecek  488:        struct wdc_softc wdc;
                    489:        struct ata_channel ch;
                    490:        int rv;
                    491:
                    492:        memset(&wdc, 0, sizeof(wdc));
                    493:        memset(&ch, 0, sizeof(ch));
                    494:        ata_channel_init(&ch);
                    495:        ch.ch_atac = &wdc.sc_atac;
                    496:        wdc.regs = wdr;
                    497:
1.292   ! tsutsui   498:        /* check the MD reset method */
        !           499:        wdc.reset = (do_reset != NULL) ? do_reset : wdc_do_reset;
1.284     jdolecek  500:
                    501:        rv = wdcprobe1(&ch, 1);
                    502:
                    503:        ata_channel_destroy(&ch);
1.163     thorpej   504:
1.284     jdolecek  505:        return rv;
1.137     bouyer    506: }
                    507:
1.167     thorpej   508: static int
1.205     thorpej   509: wdcprobe1(struct ata_channel *chp, int poll)
1.137     bouyer    510: {
1.207     thorpej   511:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej   512:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.279     martin    513:        u_int8_t st0 = 0, st1 = 0, sc __unused, sn __unused, cl, ch;
1.31      bouyer    514:        u_int8_t ret_value = 0x03;
                    515:        u_int8_t drive;
1.247     dyoung    516:        /* XXX if poll, wdc_probe_count is 0. */
1.224     bouyer    517:        int wdc_probe_count =
1.247     dyoung    518:            poll ? (WDC_PROBE_WAIT / WDCDELAY)
                    519:                 : (WDC_PROBE_WAIT * hz);
1.31      bouyer    520:
                    521:        /*
                    522:         * Sanity check to see if the wdc channel responds at all.
                    523:         */
                    524:
1.284     jdolecek  525:        ata_channel_lock(chp);
1.207     thorpej   526:        if ((wdc->cap & WDC_CAPABILITY_NO_EXTRA_RESETS) == 0) {
1.224     bouyer    527:                while (wdc_probe_count-- > 0) {
                    528:                        if (wdc->select)
                    529:                                wdc->select(chp,0);
1.107     dbj       530:
1.224     bouyer    531:                        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
                    532:                            0, WDSD_IBM);
                    533:                        delay(10);      /* 400ns delay */
                    534:                        st0 = bus_space_read_1(wdr->cmd_iot,
                    535:                            wdr->cmd_iohs[wd_status], 0);
1.137     bouyer    536:
1.224     bouyer    537:                        if (wdc->select)
                    538:                                wdc->select(chp,1);
1.219     perry     539:
1.224     bouyer    540:                        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
                    541:                            0, WDSD_IBM | 0x10);
                    542:                        delay(10);      /* 400ns delay */
                    543:                        st1 = bus_space_read_1(wdr->cmd_iot,
                    544:                            wdr->cmd_iohs[wd_status], 0);
                    545:                        if ((st0 & WDCS_BSY) == 0)
                    546:                                break;
                    547:                }
1.43      kenh      548:
1.204     thorpej   549:                ATADEBUG_PRINT(("%s:%d: before reset, st0=0x%x, st1=0x%x\n",
1.280     msaitoh   550:                        __func__, chp->ch_channel, st0, st1), DEBUG_PROBE);
1.43      kenh      551:
1.142     bouyer    552:                if (st0 == 0xff || st0 == WDSD_IBM)
1.43      kenh      553:                        ret_value &= ~0x01;
1.142     bouyer    554:                if (st1 == 0xff || st1 == (WDSD_IBM | 0x10))
1.43      kenh      555:                        ret_value &= ~0x02;
1.125     mycroft   556:                /* Register writability test, drive 0. */
                    557:                if (ret_value & 0x01) {
1.207     thorpej   558:                        if (wdc->select)
1.169     thorpej   559:                                wdc->select(chp,0);
1.205     thorpej   560:                        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.157     fvdl      561:                            0, WDSD_IBM);
1.205     thorpej   562:                        bus_space_write_1(wdr->cmd_iot,
                    563:                            wdr->cmd_iohs[wd_cyl_lo], 0, 0x02);
                    564:                        cl = bus_space_read_1(wdr->cmd_iot,
                    565:                            wdr->cmd_iohs[wd_cyl_lo], 0);
1.174     bouyer    566:                        if (cl != 0x02) {
1.204     thorpej   567:                                ATADEBUG_PRINT(("%s:%d drive 0 wd_cyl_lo: "
1.174     bouyer    568:                                    "got 0x%x != 0x02\n",
1.280     msaitoh   569:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    570:                                    DEBUG_PROBE);
1.125     mycroft   571:                                ret_value &= ~0x01;
1.174     bouyer    572:                        }
1.205     thorpej   573:                        bus_space_write_1(wdr->cmd_iot,
                    574:                            wdr->cmd_iohs[wd_cyl_lo], 0, 0x01);
                    575:                        cl = bus_space_read_1(wdr->cmd_iot,
                    576:                            wdr->cmd_iohs[wd_cyl_lo], 0);
1.174     bouyer    577:                        if (cl != 0x01) {
1.204     thorpej   578:                                ATADEBUG_PRINT(("%s:%d drive 0 wd_cyl_lo: "
1.174     bouyer    579:                                    "got 0x%x != 0x01\n",
1.280     msaitoh   580:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    581:                                    DEBUG_PROBE);
1.125     mycroft   582:                                ret_value &= ~0x01;
1.174     bouyer    583:                        }
1.205     thorpej   584:                        bus_space_write_1(wdr->cmd_iot,
                    585:                            wdr->cmd_iohs[wd_sector], 0, 0x01);
                    586:                        cl = bus_space_read_1(wdr->cmd_iot,
                    587:                            wdr->cmd_iohs[wd_sector], 0);
1.174     bouyer    588:                        if (cl != 0x01) {
1.204     thorpej   589:                                ATADEBUG_PRINT(("%s:%d drive 0 wd_sector: "
1.174     bouyer    590:                                    "got 0x%x != 0x01\n",
1.280     msaitoh   591:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    592:                                    DEBUG_PROBE);
1.125     mycroft   593:                                ret_value &= ~0x01;
1.174     bouyer    594:                        }
1.205     thorpej   595:                        bus_space_write_1(wdr->cmd_iot,
                    596:                            wdr->cmd_iohs[wd_sector], 0, 0x02);
                    597:                        cl = bus_space_read_1(wdr->cmd_iot,
                    598:                            wdr->cmd_iohs[wd_sector], 0);
1.174     bouyer    599:                        if (cl != 0x02) {
1.204     thorpej   600:                                ATADEBUG_PRINT(("%s:%d drive 0 wd_sector: "
1.174     bouyer    601:                                    "got 0x%x != 0x02\n",
1.280     msaitoh   602:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    603:                                    DEBUG_PROBE);
1.125     mycroft   604:                                ret_value &= ~0x01;
1.174     bouyer    605:                        }
1.205     thorpej   606:                        cl = bus_space_read_1(wdr->cmd_iot,
                    607:                            wdr->cmd_iohs[wd_cyl_lo], 0);
1.174     bouyer    608:                        if (cl != 0x01) {
1.204     thorpej   609:                                ATADEBUG_PRINT(("%s:%d drive 0 wd_cyl_lo(2): "
1.174     bouyer    610:                                    "got 0x%x != 0x01\n",
1.280     msaitoh   611:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    612:                                    DEBUG_PROBE);
1.131     mycroft   613:                                ret_value &= ~0x01;
1.174     bouyer    614:                        }
1.125     mycroft   615:                }
                    616:                /* Register writability test, drive 1. */
                    617:                if (ret_value & 0x02) {
1.207     thorpej   618:                        if (wdc->select)
1.169     thorpej   619:                             wdc->select(chp,1);
1.205     thorpej   620:                        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.157     fvdl      621:                             0, WDSD_IBM | 0x10);
1.205     thorpej   622:                        bus_space_write_1(wdr->cmd_iot,
                    623:                            wdr->cmd_iohs[wd_cyl_lo], 0, 0x02);
                    624:                        cl = bus_space_read_1(wdr->cmd_iot,
                    625:                            wdr->cmd_iohs[wd_cyl_lo], 0);
1.174     bouyer    626:                        if (cl != 0x02) {
1.204     thorpej   627:                                ATADEBUG_PRINT(("%s:%d drive 1 wd_cyl_lo: "
1.174     bouyer    628:                                    "got 0x%x != 0x02\n",
1.280     msaitoh   629:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    630:                                    DEBUG_PROBE);
1.125     mycroft   631:                                ret_value &= ~0x02;
1.174     bouyer    632:                        }
1.205     thorpej   633:                        bus_space_write_1(wdr->cmd_iot,
                    634:                            wdr->cmd_iohs[wd_cyl_lo], 0, 0x01);
                    635:                        cl = bus_space_read_1(wdr->cmd_iot,
                    636:                            wdr->cmd_iohs[wd_cyl_lo], 0);
1.174     bouyer    637:                        if (cl != 0x01) {
1.204     thorpej   638:                                ATADEBUG_PRINT(("%s:%d drive 1 wd_cyl_lo: "
1.174     bouyer    639:                                    "got 0x%x != 0x01\n",
1.280     msaitoh   640:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    641:                                    DEBUG_PROBE);
1.125     mycroft   642:                                ret_value &= ~0x02;
1.174     bouyer    643:                        }
1.205     thorpej   644:                        bus_space_write_1(wdr->cmd_iot,
                    645:                            wdr->cmd_iohs[wd_sector], 0, 0x01);
                    646:                        cl = bus_space_read_1(wdr->cmd_iot,
                    647:                            wdr->cmd_iohs[wd_sector], 0);
1.174     bouyer    648:                        if (cl != 0x01) {
1.204     thorpej   649:                                ATADEBUG_PRINT(("%s:%d drive 1 wd_sector: "
1.174     bouyer    650:                                    "got 0x%x != 0x01\n",
1.280     msaitoh   651:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    652:                                    DEBUG_PROBE);
1.125     mycroft   653:                                ret_value &= ~0x02;
1.174     bouyer    654:                        }
1.205     thorpej   655:                        bus_space_write_1(wdr->cmd_iot,
                    656:                            wdr->cmd_iohs[wd_sector], 0, 0x02);
                    657:                        cl = bus_space_read_1(wdr->cmd_iot,
                    658:                            wdr->cmd_iohs[wd_sector], 0);
1.174     bouyer    659:                        if (cl != 0x02) {
1.204     thorpej   660:                                ATADEBUG_PRINT(("%s:%d drive 1 wd_sector: "
1.174     bouyer    661:                                    "got 0x%x != 0x02\n",
1.280     msaitoh   662:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    663:                                    DEBUG_PROBE);
1.125     mycroft   664:                                ret_value &= ~0x02;
1.174     bouyer    665:                        }
1.205     thorpej   666:                        cl = bus_space_read_1(wdr->cmd_iot,
                    667:                            wdr->cmd_iohs[wd_cyl_lo], 0);
1.174     bouyer    668:                        if (cl != 0x01) {
1.204     thorpej   669:                                ATADEBUG_PRINT(("%s:%d drive 1 wd_cyl_lo(2): "
1.174     bouyer    670:                                    "got 0x%x != 0x01\n",
1.280     msaitoh   671:                                    __func__, chp->ch_channel, cl),
1.174     bouyer    672:                                    DEBUG_PROBE);
1.131     mycroft   673:                                ret_value &= ~0x02;
1.174     bouyer    674:                        }
1.125     mycroft   675:                }
1.137     bouyer    676:
1.174     bouyer    677:                if (ret_value == 0) {
1.284     jdolecek  678:                        ata_channel_unlock(chp);
1.137     bouyer    679:                        return 0;
1.174     bouyer    680:                }
1.62      bouyer    681:        }
1.31      bouyer    682:
1.181     bouyer    683: #if 0 /* XXX this break some ATA or ATAPI devices */
1.174     bouyer    684:        /*
                    685:         * reset bus. Also send an ATAPI_RESET to devices, in case there are
                    686:         * ATAPI device out there which don't react to the bus reset
                    687:         */
                    688:        if (ret_value & 0x01) {
1.207     thorpej   689:                if (wdc->select)
1.174     bouyer    690:                        wdc->select(chp,0);
1.205     thorpej   691:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174     bouyer    692:                     0, WDSD_IBM);
1.205     thorpej   693:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0,
1.174     bouyer    694:                    ATAPI_SOFT_RESET);
                    695:        }
                    696:        if (ret_value & 0x02) {
1.207     thorpej   697:                if (wdc->select)
1.174     bouyer    698:                        wdc->select(chp,0);
1.205     thorpej   699:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174     bouyer    700:                     0, WDSD_IBM | 0x10);
1.205     thorpej   701:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0,
1.174     bouyer    702:                    ATAPI_SOFT_RESET);
                    703:        }
1.156     bouyer    704:
1.175     bouyer    705:        delay(5000);
1.181     bouyer    706: #endif
1.175     bouyer    707:
1.225     bouyer    708:        wdc->reset(chp, RESET_POLL);
1.137     bouyer    709:        DELAY(2000);
1.205     thorpej   710:        (void) bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_error], 0);
1.275     rkujawa   711:
                    712:        if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
                    713:                bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
                    714:                    WDCTL_4BIT);
                    715:
1.263     bouyer    716: #ifdef WDC_NO_IDS
                    717:        ret_value = __wdcwait_reset(chp, ret_value, RESET_POLL);
                    718: #else
1.137     bouyer    719:        ret_value = __wdcwait_reset(chp, ret_value, poll);
1.263     bouyer    720: #endif
1.283     msaitoh   721:        ATADEBUG_PRINT(("%s:%d: after reset, ret_value=%#x\n",
1.280     msaitoh   722:            __func__, chp->ch_channel, ret_value), DEBUG_PROBE);
1.12      cgd       723:
1.137     bouyer    724:        /* if reset failed, there's nothing here */
1.263     bouyer    725:        if (ret_value == 0) {
1.284     jdolecek  726:                ata_channel_unlock(chp);
1.137     bouyer    727:                return 0;
1.263     bouyer    728:        }
1.67      bouyer    729:
1.12      cgd       730:        /*
1.167     thorpej   731:         * Test presence of drives. First test register signatures looking
                    732:         * for ATAPI devices. If it's not an ATAPI and reset said there may
                    733:         * be something here assume it's ATA or OLD.  Ghost will be killed
                    734:         * later in attach routine.
1.12      cgd       735:         */
1.274     bouyer    736:        for (drive = 0; drive < wdc->wdc_maxdrives; drive++) {
1.137     bouyer    737:                if ((ret_value & (0x01 << drive)) == 0)
                    738:                        continue;
1.207     thorpej   739:                if (wdc->select)
1.169     thorpej   740:                        wdc->select(chp,drive);
1.205     thorpej   741:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.137     bouyer    742:                    WDSD_IBM | (drive << 4));
                    743:                delay(10);      /* 400ns delay */
                    744:                /* Save registers contents */
1.205     thorpej   745:                sc = bus_space_read_1(wdr->cmd_iot,
                    746:                    wdr->cmd_iohs[wd_seccnt], 0);
                    747:                sn = bus_space_read_1(wdr->cmd_iot,
                    748:                    wdr->cmd_iohs[wd_sector], 0);
                    749:                cl = bus_space_read_1(wdr->cmd_iot,
                    750:                    wdr->cmd_iohs[wd_cyl_lo], 0);
                    751:                ch = bus_space_read_1(wdr->cmd_iot,
                    752:                     wdr->cmd_iohs[wd_cyl_hi], 0);
1.137     bouyer    753:
1.204     thorpej   754:                ATADEBUG_PRINT(("%s:%d:%d: after reset, sc=0x%x sn=0x%x "
1.280     msaitoh   755:                    "cl=0x%x ch=0x%x\n", __func__, chp->ch_channel, drive, sc,
                    756:                    sn, cl, ch), DEBUG_PROBE);
1.31      bouyer    757:                /*
1.266     jakllsch  758:                 * sc & sn are supposed to be 0x1 for ATAPI but in some cases
1.137     bouyer    759:                 * we get wrong values here, so ignore it.
1.31      bouyer    760:                 */
1.274     bouyer    761:                if (chp->ch_drive != NULL) {
                    762:                        if (cl == 0x14 && ch == 0xeb) {
                    763:                                chp->ch_drive[drive].drive_type = ATA_DRIVET_ATAPI;
                    764:                        } else {
                    765:                                chp->ch_drive[drive].drive_type = ATA_DRIVET_ATA;
                    766:                        }
1.137     bouyer    767:                }
1.31      bouyer    768:        }
1.263     bouyer    769:        /*
                    770:         * Select an existing drive before lowering spl, some WDC_NO_IDS
                    771:         * devices incorrectly assert IRQ on nonexistent slave
                    772:         */
                    773:        if (ret_value & 0x01) {
                    774:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
                    775:                    WDSD_IBM);
                    776:                (void)bus_space_read_1(wdr->cmd_iot,
                    777:                    wdr->cmd_iohs[wd_status], 0);
                    778:        }
1.284     jdolecek  779:        ata_channel_unlock(chp);
1.219     perry     780:        return (ret_value);
1.137     bouyer    781: }
1.31      bouyer    782:
1.137     bouyer    783: void
1.205     thorpej   784: wdcattach(struct ata_channel *chp)
1.137     bouyer    785: {
1.207     thorpej   786:        struct atac_softc *atac = chp->ch_atac;
                    787:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.32      bouyer    788:
1.274     bouyer    789:        KASSERT(wdc->wdc_maxdrives > 0 && wdc->wdc_maxdrives <= WDC_MAXDRIVES);
1.205     thorpej   790:
1.191     mycroft   791:        /* default data transfer methods */
1.210     thorpej   792:        if (wdc->datain_pio == NULL)
1.191     mycroft   793:                wdc->datain_pio = wdc_datain_pio;
1.210     thorpej   794:        if (wdc->dataout_pio == NULL)
1.191     mycroft   795:                wdc->dataout_pio = wdc_dataout_pio;
1.225     bouyer    796:        /* default reset method */
                    797:        if (wdc->reset == NULL)
                    798:                wdc->reset = wdc_do_reset;
1.191     mycroft   799:
1.137     bouyer    800:        /* initialise global data */
1.208     thorpej   801:        if (atac->atac_bustype_ata == NULL)
                    802:                atac->atac_bustype_ata = &wdc_ata_bustype;
1.207     thorpej   803:        if (atac->atac_probe == NULL)
                    804:                atac->atac_probe = wdc_drvprobe;
1.208     thorpej   805: #if NATAPIBUS > 0
                    806:        if (atac->atac_atapibus_attach == NULL)
                    807:                atac->atac_atapibus_attach = wdc_atapibus_attach;
                    808: #endif
1.198     thorpej   809:
1.210     thorpej   810:        ata_channel_attach(chp);
1.74      enami     811: }
                    812:
1.250     dyoung    813: void
                    814: wdc_childdetached(device_t self, device_t child)
                    815: {
                    816:        struct atac_softc *atac = device_private(self);
                    817:        struct ata_channel *chp;
                    818:        int i;
                    819:
                    820:        for (i = 0; i < atac->atac_nchannels; i++) {
                    821:                chp = atac->atac_channels[i];
                    822:                if (child == chp->atabus) {
                    823:                        chp->atabus = NULL;
                    824:                        return;
                    825:                }
                    826:        }
                    827: }
                    828:
1.137     bouyer    829: int
1.250     dyoung    830: wdcdetach(device_t self, int flags)
1.137     bouyer    831: {
1.250     dyoung    832:        struct atac_softc *atac = device_private(self);
1.205     thorpej   833:        struct ata_channel *chp;
1.207     thorpej   834:        struct scsipi_adapter *adapt = &atac->atac_atapi_adapter._generic;
1.137     bouyer    835:        int i, error = 0;
                    836:
1.207     thorpej   837:        for (i = 0; i < atac->atac_nchannels; i++) {
                    838:                chp = atac->atac_channels[i];
1.250     dyoung    839:                if (chp->atabus == NULL)
                    840:                        continue;
1.204     thorpej   841:                ATADEBUG_PRINT(("wdcdetach: %s: detaching %s\n",
1.253     cube      842:                    device_xname(atac->atac_dev), device_xname(chp->atabus)),
1.207     thorpej   843:                    DEBUG_DETACH);
1.251     dyoung    844:                if ((error = config_detach(chp->atabus, flags)) != 0)
                    845:                        return error;
1.284     jdolecek  846:                ata_channel_detach(chp);
1.137     bouyer    847:        }
1.252     dyoung    848:        if (adapt->adapt_refcnt != 0)
                    849:                return EBUSY;
1.251     dyoung    850:        return 0;
1.137     bouyer    851: }
                    852:
1.31      bouyer    853: /* restart an interrupted I/O */
                    854: void
1.163     thorpej   855: wdcrestart(void *v)
1.31      bouyer    856: {
1.205     thorpej   857:        struct ata_channel *chp = v;
1.31      bouyer    858:        int s;
1.2       bouyer    859:
1.31      bouyer    860:        s = splbio();
1.202     thorpej   861:        atastart(chp);
1.31      bouyer    862:        splx(s);
1.2       bouyer    863: }
1.219     perry     864:
1.2       bouyer    865:
1.31      bouyer    866: /*
                    867:  * Interrupt routine for the controller.  Acknowledge the interrupt, check for
                    868:  * errors on the current operation, mark it done if necessary, and start the
                    869:  * next request.  Also check for a partially done transfer, and continue with
                    870:  * the next chunk if so.
                    871:  */
1.12      cgd       872: int
1.163     thorpej   873: wdcintr(void *arg)
1.12      cgd       874: {
1.205     thorpej   875:        struct ata_channel *chp = arg;
1.207     thorpej   876:        struct atac_softc *atac = chp->ch_atac;
                    877:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej   878:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.165     thorpej   879:        struct ata_xfer *xfer;
1.76      bouyer    880:        int ret;
1.12      cgd       881:
1.253     cube      882:        if (!device_is_active(atac->atac_dev)) {
1.204     thorpej   883:                ATADEBUG_PRINT(("wdcintr: deactivated controller\n"),
1.80      enami     884:                    DEBUG_INTR);
                    885:                return (0);
                    886:        }
1.284     jdolecek  887:
1.287     jdolecek  888:        if ((chp->ch_flags & ATACH_IRQ_WAIT) == 0) {
                    889:                ATADEBUG_PRINT(("wdcintr: irq not expected\n"), DEBUG_INTR);
                    890:                goto ignore;
                    891:        }
                    892:
1.284     jdolecek  893:        xfer = ata_queue_get_active_xfer(chp);
                    894:        if (xfer == NULL) {
1.204     thorpej   895:                ATADEBUG_PRINT(("wdcintr: inactive controller\n"), DEBUG_INTR);
1.285     jdolecek  896: ignore:
1.113     bouyer    897:                /* try to clear the pending interrupt anyway */
1.205     thorpej   898:                (void)bus_space_read_1(wdr->cmd_iot,
                    899:                    wdr->cmd_iohs[wd_status], 0);
1.80      enami     900:                return (0);
1.31      bouyer    901:        }
1.12      cgd       902:
1.285     jdolecek  903:        /*
1.286     jdolecek  904:         * On some controllers (e.g. some PCI-IDE) setting the WDCTL_IDS bit
1.285     jdolecek  905:         * actually has no effect, and interrupt is triggered regardless.
                    906:         * Ignore polled commands here, they are processed separately.
                    907:         */
                    908:        if (ISSET(xfer->c_flags, C_POLL)) {
                    909:                ATADEBUG_PRINT(("%s: polled xfer ignored\n", __func__),
                    910:                    DEBUG_INTR);
                    911:                goto ignore;
                    912:        }
                    913:
1.204     thorpej   914:        ATADEBUG_PRINT(("wdcintr\n"), DEBUG_INTR);
1.284     jdolecek  915:        KASSERT(xfer != NULL);
                    916:
1.238     itohy     917: #if NATA_DMA || NATA_PIOBM
1.205     thorpej   918:        if (chp->ch_flags & ATACH_DMA_WAIT) {
1.169     thorpej   919:                wdc->dma_status =
                    920:                    (*wdc->dma_finish)(wdc->dma_arg, chp->ch_channel,
1.185     bouyer    921:                        xfer->c_drive, WDC_DMAEND_END);
1.169     thorpej   922:                if (wdc->dma_status & WDC_DMAST_NOIRQ) {
1.84      bouyer    923:                        /* IRQ not for us, not detected by DMA engine */
                    924:                        return 0;
                    925:                }
1.205     thorpej   926:                chp->ch_flags &= ~ATACH_DMA_WAIT;
1.84      bouyer    927:        }
1.238     itohy     928: #endif
1.287     jdolecek  929:        chp->ch_flags &= ~ATACH_IRQ_WAIT;
1.289     jdolecek  930:        KASSERT(xfer->ops != NULL && xfer->ops->c_intr != NULL);
                    931:        ret = xfer->ops->c_intr(chp, xfer, 1);
1.287     jdolecek  932:        if (ret == 0) /* irq was not for us, still waiting for irq */
                    933:                chp->ch_flags |= ATACH_IRQ_WAIT;
1.76      bouyer    934:        return (ret);
1.12      cgd       935: }
                    936:
1.31      bouyer    937: /* Put all disk in RESET state */
1.125     mycroft   938: void
1.274     bouyer    939: wdc_reset_drive(struct ata_drive_datas *drvp, int flags, uint32_t *sigp)
1.2       bouyer    940: {
1.205     thorpej   941:        struct ata_channel *chp = drvp->chnl_softc;
1.207     thorpej   942:
1.289     jdolecek  943:        ata_channel_lock_owned(chp);
                    944:
1.274     bouyer    945:        KASSERT(sigp == NULL);
                    946:
1.211     thorpej   947:        ATADEBUG_PRINT(("wdc_reset_drive %s:%d for drive %d\n",
1.253     cube      948:            device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
                    949:            drvp->drive), DEBUG_FUNCS);
1.182     bouyer    950:
1.289     jdolecek  951:        ata_thread_run(chp, flags, ATACH_TH_RESET, ATACH_NODRIVE);
1.182     bouyer    952: }
                    953:
1.183     bouyer    954: void
1.205     thorpej   955: wdc_reset_channel(struct ata_channel *chp, int flags)
1.182     bouyer    956: {
1.284     jdolecek  957:        struct ata_xfer *xfer;
1.289     jdolecek  958:
                    959:        ata_channel_lock_owned(chp);
                    960:
1.238     itohy     961: #if NATA_DMA || NATA_PIOBM
1.207     thorpej   962:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.238     itohy     963: #endif
1.184     bouyer    964:
1.287     jdolecek  965:        chp->ch_flags &= ~ATACH_IRQ_WAIT;
                    966:
1.186     bouyer    967:        /*
1.284     jdolecek  968:         * if the current command is on an ATAPI device, issue a
1.186     bouyer    969:         * ATAPI_SOFT_RESET
                    970:         */
1.289     jdolecek  971:        xfer = ata_queue_get_active_xfer_locked(chp);
1.284     jdolecek  972:
1.186     bouyer    973:        if (xfer && xfer->c_chp == chp && (xfer->c_flags & C_ATAPI)) {
                    974:                wdccommandshort(chp, xfer->c_drive, ATAPI_SOFT_RESET);
1.284     jdolecek  975:                ata_delay(chp, 1000, "atardl", flags);
1.186     bouyer    976:        }
                    977:
1.184     bouyer    978:        /* reset the channel */
1.186     bouyer    979:        if (flags & AT_WAIT)
                    980:                (void) wdcreset(chp, RESET_SLEEP);
                    981:        else
1.184     bouyer    982:                (void) wdcreset(chp, RESET_POLL);
                    983:
                    984:        /*
1.186     bouyer    985:         * wait a bit after reset; in case the DMA engines needs some time
1.184     bouyer    986:         * to recover.
                    987:         */
1.284     jdolecek  988:        ata_delay(chp, 1000, "atardl", flags);
                    989:
1.182     bouyer    990:        /*
1.284     jdolecek  991:         * Look for pending xfers. If we have a shared queue, we'll also reset
1.182     bouyer    992:         * the other channel if the current xfer is running on it.
1.284     jdolecek  993:         * Then we'll kill the eventual active transfer explicitely, so that
                    994:         * it is queued for retry immediatelly without waiting for I/O timeout.
1.182     bouyer    995:         */
1.284     jdolecek  996:        if (xfer) {
                    997:                if (xfer->c_chp != chp) {
1.289     jdolecek  998:                        ata_thread_run(xfer->c_chp, flags, ATACH_TH_RESET,
                    999:                            ATACH_NODRIVE);
1.284     jdolecek 1000:                } else {
1.238     itohy    1001: #if NATA_DMA || NATA_PIOBM
1.284     jdolecek 1002:                        /*
                   1003:                         * If we're waiting for DMA, stop the
                   1004:                         * DMA engine
                   1005:                         */
                   1006:                        if (chp->ch_flags & ATACH_DMA_WAIT) {
                   1007:                                (*wdc->dma_finish)(wdc->dma_arg,
                   1008:                                    chp->ch_channel, xfer->c_drive,
                   1009:                                    WDC_DMAEND_ABRT_QUIET);
                   1010:                                chp->ch_flags &= ~ATACH_DMA_WAIT;
                   1011:                        }
1.238     itohy    1012: #endif
1.184     bouyer   1013:                }
1.284     jdolecek 1014:        }
1.186     bouyer   1015:
1.284     jdolecek 1016:        ata_kill_active(chp, KILL_RESET, flags);
1.31      bouyer   1017: }
1.12      cgd      1018:
1.213     thorpej  1019: static int
1.205     thorpej  1020: wdcreset(struct ata_channel *chp, int poll)
1.31      bouyer   1021: {
1.207     thorpej  1022:        struct atac_softc *atac = chp->ch_atac;
                   1023:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej  1024:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.31      bouyer   1025:        int drv_mask1, drv_mask2;
1.225     bouyer   1026:
1.284     jdolecek 1027:        ata_channel_lock_owned(chp);
                   1028:
1.263     bouyer   1029: #ifdef WDC_NO_IDS
                   1030:        poll = RESET_POLL;
                   1031: #endif
1.225     bouyer   1032:        wdc->reset(chp, poll);
                   1033:
1.281     msaitoh  1034:        drv_mask1 = (chp->ch_drive[0].drive_type !=  ATA_DRIVET_NONE)
                   1035:            ? 0x01 : 0x00;
1.274     bouyer   1036:        if (chp->ch_ndrives > 1)
1.281     msaitoh  1037:                drv_mask1 |= (chp->ch_drive[1].drive_type != ATA_DRIVET_NONE)
                   1038:                    ? 0x02 : 0x00;
1.225     bouyer   1039:        drv_mask2 = __wdcwait_reset(chp, drv_mask1,
                   1040:            (poll == RESET_SLEEP) ? 0 : 1);
                   1041:        if (drv_mask2 != drv_mask1) {
1.253     cube     1042:                aprint_error("%s channel %d: reset failed for",
                   1043:                    device_xname(atac->atac_dev), chp->ch_channel);
1.225     bouyer   1044:                if ((drv_mask1 & 0x01) != 0 && (drv_mask2 & 0x01) == 0)
1.253     cube     1045:                        aprint_normal(" drive 0");
1.225     bouyer   1046:                if ((drv_mask1 & 0x02) != 0 && (drv_mask2 & 0x02) == 0)
1.253     cube     1047:                        aprint_normal(" drive 1");
                   1048:                aprint_normal("\n");
1.225     bouyer   1049:        }
1.275     rkujawa  1050:        if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
                   1051:                bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
                   1052:                    WDCTL_4BIT);
                   1053:
1.225     bouyer   1054:        return  (drv_mask1 != drv_mask2) ? 1 : 0;
                   1055: }
                   1056:
                   1057: void
                   1058: wdc_do_reset(struct ata_channel *chp, int poll)
                   1059: {
                   1060:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
                   1061:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.156     bouyer   1062:        int s = 0;
1.2       bouyer   1063:
1.225     bouyer   1064:        if (poll != RESET_SLEEP)
                   1065:                s = splbio();
1.203     thorpej  1066:        if (wdc->select)
1.169     thorpej  1067:                wdc->select(chp,0);
1.157     fvdl     1068:        /* master */
1.205     thorpej  1069:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0, WDSD_IBM);
1.131     mycroft  1070:        delay(10);      /* 400ns delay */
1.225     bouyer   1071:        /* assert SRST, wait for reset to complete */
1.275     rkujawa  1072:        if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL)) {
                   1073:                bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
                   1074:                    WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);
                   1075:                delay(2000);
                   1076:        }
1.205     thorpej  1077:        (void) bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_error], 0);
1.275     rkujawa  1078:        if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
                   1079:                bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
                   1080:                    WDCTL_4BIT | WDCTL_IDS);
1.131     mycroft  1081:        delay(10);      /* 400ns delay */
1.156     bouyer   1082:        if (poll != RESET_SLEEP) {
1.233     bouyer   1083:                /* ACK interrupt in case there is one pending left */
1.203     thorpej  1084:                if (wdc->irqack)
1.169     thorpej  1085:                        wdc->irqack(chp);
1.156     bouyer   1086:                splx(s);
                   1087:        }
1.31      bouyer   1088: }
                   1089:
                   1090: static int
1.205     thorpej  1091: __wdcwait_reset(struct ata_channel *chp, int drv_mask, int poll)
1.31      bouyer   1092: {
1.207     thorpej  1093:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej  1094:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.137     bouyer   1095:        int timeout, nloop;
1.284     jdolecek 1096:        int wflags = poll ? AT_POLL : AT_WAIT;
1.149     bouyer   1097:        u_int8_t st0 = 0, st1 = 0;
1.204     thorpej  1098: #ifdef ATADEBUG
1.146     christos 1099:        u_int8_t sc0 = 0, sn0 = 0, cl0 = 0, ch0 = 0;
                   1100:        u_int8_t sc1 = 0, sn1 = 0, cl1 = 0, ch1 = 0;
1.70      bouyer   1101: #endif
1.137     bouyer   1102:        if (poll)
                   1103:                nloop = WDCNDELAY_RST;
                   1104:        else
                   1105:                nloop = WDC_RESET_WAIT * hz / 1000;
1.31      bouyer   1106:        /* wait for BSY to deassert */
1.137     bouyer   1107:        for (timeout = 0; timeout < nloop; timeout++) {
1.174     bouyer   1108:                if ((drv_mask & 0x01) != 0) {
1.236     bouyer   1109:                        if (wdc->select)
1.174     bouyer   1110:                                wdc->select(chp,0);
1.205     thorpej  1111:                        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174     bouyer   1112:                            0, WDSD_IBM); /* master */
                   1113:                        delay(10);
1.205     thorpej  1114:                        st0 = bus_space_read_1(wdr->cmd_iot,
                   1115:                            wdr->cmd_iohs[wd_status], 0);
1.204     thorpej  1116: #ifdef ATADEBUG
1.205     thorpej  1117:                        sc0 = bus_space_read_1(wdr->cmd_iot,
                   1118:                            wdr->cmd_iohs[wd_seccnt], 0);
                   1119:                        sn0 = bus_space_read_1(wdr->cmd_iot,
                   1120:                            wdr->cmd_iohs[wd_sector], 0);
                   1121:                        cl0 = bus_space_read_1(wdr->cmd_iot,
                   1122:                            wdr->cmd_iohs[wd_cyl_lo], 0);
                   1123:                        ch0 = bus_space_read_1(wdr->cmd_iot,
                   1124:                            wdr->cmd_iohs[wd_cyl_hi], 0);
1.70      bouyer   1125: #endif
1.174     bouyer   1126:                }
                   1127:                if ((drv_mask & 0x02) != 0) {
1.236     bouyer   1128:                        if (wdc->select)
1.174     bouyer   1129:                                wdc->select(chp,1);
1.205     thorpej  1130:                        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.174     bouyer   1131:                            0, WDSD_IBM | 0x10); /* slave */
                   1132:                        delay(10);
1.205     thorpej  1133:                        st1 = bus_space_read_1(wdr->cmd_iot,
                   1134:                            wdr->cmd_iohs[wd_status], 0);
1.204     thorpej  1135: #ifdef ATADEBUG
1.205     thorpej  1136:                        sc1 = bus_space_read_1(wdr->cmd_iot,
                   1137:                            wdr->cmd_iohs[wd_seccnt], 0);
                   1138:                        sn1 = bus_space_read_1(wdr->cmd_iot,
                   1139:                            wdr->cmd_iohs[wd_sector], 0);
                   1140:                        cl1 = bus_space_read_1(wdr->cmd_iot,
                   1141:                            wdr->cmd_iohs[wd_cyl_lo], 0);
                   1142:                        ch1 = bus_space_read_1(wdr->cmd_iot,
                   1143:                            wdr->cmd_iohs[wd_cyl_hi], 0);
1.70      bouyer   1144: #endif
1.174     bouyer   1145:                }
1.31      bouyer   1146:
                   1147:                if ((drv_mask & 0x01) == 0) {
                   1148:                        /* no master */
                   1149:                        if ((drv_mask & 0x02) != 0 && (st1 & WDCS_BSY) == 0) {
                   1150:                                /* No master, slave is ready, it's done */
1.65      bouyer   1151:                                goto end;
1.31      bouyer   1152:                        }
1.231     bouyer   1153:                        if ((drv_mask & 0x02) == 0) {
                   1154:                                /* No master, no slave: it's done */
                   1155:                                goto end;
                   1156:                        }
1.31      bouyer   1157:                } else if ((drv_mask & 0x02) == 0) {
                   1158:                        /* no slave */
                   1159:                        if ((drv_mask & 0x01) != 0 && (st0 & WDCS_BSY) == 0) {
                   1160:                                /* No slave, master is ready, it's done */
1.65      bouyer   1161:                                goto end;
1.31      bouyer   1162:                        }
1.2       bouyer   1163:                } else {
1.31      bouyer   1164:                        /* Wait for both master and slave to be ready */
                   1165:                        if ((st0 & WDCS_BSY) == 0 && (st1 & WDCS_BSY) == 0) {
1.65      bouyer   1166:                                goto end;
1.2       bouyer   1167:                        }
                   1168:                }
1.284     jdolecek 1169:                ata_delay(chp, WDCDELAY, "atarst", wflags);
1.2       bouyer   1170:        }
1.116     wiz      1171:        /* Reset timed out. Maybe it's because drv_mask was not right */
1.31      bouyer   1172:        if (st0 & WDCS_BSY)
                   1173:                drv_mask &= ~0x01;
                   1174:        if (st1 & WDCS_BSY)
                   1175:                drv_mask &= ~0x02;
1.65      bouyer   1176: end:
1.204     thorpej  1177:        ATADEBUG_PRINT(("%s:%d:0: after reset, sc=0x%x sn=0x%x "
1.70      bouyer   1178:            "cl=0x%x ch=0x%x\n",
1.253     cube     1179:             device_xname(chp->ch_atac->atac_dev),
1.169     thorpej  1180:             chp->ch_channel, sc0, sn0, cl0, ch0), DEBUG_PROBE);
1.204     thorpej  1181:        ATADEBUG_PRINT(("%s:%d:1: after reset, sc=0x%x sn=0x%x "
1.70      bouyer   1182:            "cl=0x%x ch=0x%x\n",
1.253     cube     1183:             device_xname(chp->ch_atac->atac_dev),
1.169     thorpej  1184:             chp->ch_channel, sc1, sn1, cl1, ch1), DEBUG_PROBE);
1.70      bouyer   1185:
1.204     thorpej  1186:        ATADEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%x st1=0x%x\n",
1.253     cube     1187:            device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
1.149     bouyer   1188:            st0, st1), DEBUG_PROBE);
1.65      bouyer   1189:
1.31      bouyer   1190:        return drv_mask;
1.2       bouyer   1191: }
                   1192:
                   1193: /*
1.31      bouyer   1194:  * Wait for a drive to be !BSY, and have mask in its status register.
                   1195:  * return -1 for a timeout after "timeout" ms.
1.2       bouyer   1196:  */
1.167     thorpej  1197: static int
1.284     jdolecek 1198: __wdcwait(struct ata_channel *chp, int mask, int bits, int timeout, int *tfd)
1.2       bouyer   1199: {
1.207     thorpej  1200:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej  1201:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.284     jdolecek 1202:        u_char status, error = 0;
1.222     christos 1203:        int xtime = 0;
1.284     jdolecek 1204:        int rv;
1.60      abs      1205:
1.207     thorpej  1206:        ATADEBUG_PRINT(("__wdcwait %s:%d\n",
1.253     cube     1207:                        device_xname(chp->ch_atac->atac_dev),
1.169     thorpej  1208:                        chp->ch_channel), DEBUG_STATUS);
1.284     jdolecek 1209:        *tfd = 0;
1.31      bouyer   1210:
                   1211:        timeout = timeout * 1000 / WDCDELAY; /* delay uses microseconds */
1.2       bouyer   1212:
1.31      bouyer   1213:        for (;;) {
1.284     jdolecek 1214:                status =
1.205     thorpej  1215:                    bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_status], 0);
1.131     mycroft  1216:                if ((status & (WDCS_BSY | mask)) == bits)
1.31      bouyer   1217:                        break;
1.222     christos 1218:                if (++xtime > timeout) {
1.204     thorpej  1219:                        ATADEBUG_PRINT(("__wdcwait: timeout (time=%d), "
1.87      bouyer   1220:                            "status %x error %x (mask 0x%x bits 0x%x)\n",
1.222     christos 1221:                            xtime, status,
1.205     thorpej  1222:                            bus_space_read_1(wdr->cmd_iot,
                   1223:                                wdr->cmd_iohs[wd_error], 0), mask, bits),
1.87      bouyer   1224:                            DEBUG_STATUS | DEBUG_PROBE | DEBUG_DELAY);
1.284     jdolecek 1225:                        rv = WDCWAIT_TOUT;
                   1226:                        goto out;
1.31      bouyer   1227:                }
                   1228:                delay(WDCDELAY);
1.2       bouyer   1229:        }
1.204     thorpej  1230: #ifdef ATADEBUG
1.222     christos 1231:        if (xtime > 0 && (atadebug_mask & DEBUG_DELAY))
                   1232:                printf("__wdcwait: did busy-wait, time=%d\n", xtime);
1.87      bouyer   1233: #endif
1.31      bouyer   1234:        if (status & WDCS_ERR)
1.284     jdolecek 1235:                error = bus_space_read_1(wdr->cmd_iot,
1.205     thorpej  1236:                    wdr->cmd_iohs[wd_error], 0);
1.31      bouyer   1237: #ifdef WDCNDELAY_DEBUG
                   1238:        /* After autoconfig, there should be no long delays. */
1.222     christos 1239:        if (!cold && xtime > WDCNDELAY_DEBUG) {
1.284     jdolecek 1240:                struct ata_xfer *xfer;
                   1241:
                   1242:                xfer = ata_queue_get_active_xfer(chp);
1.31      bouyer   1243:                if (xfer == NULL)
                   1244:                        printf("%s channel %d: warning: busy-wait took %dus\n",
1.253     cube     1245:                            device_xname(chp->ch_atac->atac_dev),
                   1246:                            chp->ch_channel, WDCDELAY * xtime);
1.219     perry    1247:                else
1.31      bouyer   1248:                        printf("%s:%d:%d: warning: busy-wait took %dus\n",
1.253     cube     1249:                            device_xname(chp->ch_atac->atac_dev),
                   1250:                            chp->ch_channel, xfer->c_drive,
1.222     christos 1251:                            WDCDELAY * xtime);
1.2       bouyer   1252:        }
                   1253: #endif
1.284     jdolecek 1254:        rv = WDCWAIT_OK;
                   1255:
                   1256: out:
                   1257:        *tfd = ATACH_ERR_ST(error, status);
                   1258:        return rv;
1.137     bouyer   1259: }
                   1260:
                   1261: /*
1.284     jdolecek 1262:  * Call __wdcwait(), polling using kpause() or waking up the kernel
1.137     bouyer   1263:  * thread if possible
                   1264:  */
                   1265: int
1.284     jdolecek 1266: wdcwait(struct ata_channel *chp, int mask, int bits, int timeout, int flags,
                   1267:     int *tfd)
1.137     bouyer   1268: {
                   1269:        int error, i, timeout_hz = mstohz(timeout);
                   1270:
1.284     jdolecek 1271:        ata_channel_lock_owned(chp);
                   1272:
1.137     bouyer   1273:        if (timeout_hz == 0 ||
                   1274:            (flags & (AT_WAIT | AT_POLL)) == AT_POLL)
1.284     jdolecek 1275:                error = __wdcwait(chp, mask, bits, timeout, tfd);
1.137     bouyer   1276:        else {
1.284     jdolecek 1277:                error = __wdcwait(chp, mask, bits, WDCDELAY_POLL, tfd);
1.137     bouyer   1278:                if (error != 0) {
1.256     bouyer   1279:                        if ((chp->ch_flags & ATACH_TH_RUN) ||
                   1280:                            (flags & AT_WAIT)) {
1.137     bouyer   1281:                                /*
1.147     bouyer   1282:                                 * we're running in the channel thread
                   1283:                                 * or some userland thread context
1.137     bouyer   1284:                                 */
                   1285:                                for (i = 0; i < timeout_hz; i++) {
                   1286:                                        if (__wdcwait(chp, mask, bits,
1.284     jdolecek 1287:                                            WDCDELAY_POLL, tfd) == 0) {
1.137     bouyer   1288:                                                error = 0;
                   1289:                                                break;
                   1290:                                        }
1.284     jdolecek 1291:                                        kpause("atapoll", true, 1,
                   1292:                                            &chp->ch_lock);
1.137     bouyer   1293:                                }
                   1294:                        } else {
                   1295:                                /*
1.256     bouyer   1296:                                 * we're probably in interrupt context,
1.284     jdolecek 1297:                                 * caller must ask the thread to come back here
1.137     bouyer   1298:                                 */
                   1299:                                return(WDCWAIT_THR);
                   1300:                        }
                   1301:                }
                   1302:        }
1.163     thorpej  1303:        return (error);
1.2       bouyer   1304: }
                   1305:
1.137     bouyer   1306:
1.238     itohy    1307: #if NATA_DMA
1.84      bouyer   1308: /*
                   1309:  * Busy-wait for DMA to complete
                   1310:  */
                   1311: int
1.205     thorpej  1312: wdc_dmawait(struct ata_channel *chp, struct ata_xfer *xfer, int timeout)
1.84      bouyer   1313: {
1.207     thorpej  1314:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.222     christos 1315:        int xtime;
1.169     thorpej  1316:
1.222     christos 1317:        for (xtime = 0;  xtime < timeout * 1000 / WDCDELAY; xtime++) {
1.169     thorpej  1318:                wdc->dma_status =
                   1319:                    (*wdc->dma_finish)(wdc->dma_arg,
1.185     bouyer   1320:                        chp->ch_channel, xfer->c_drive, WDC_DMAEND_END);
1.169     thorpej  1321:                if ((wdc->dma_status & WDC_DMAST_NOIRQ) == 0)
1.84      bouyer   1322:                        return 0;
                   1323:                delay(WDCDELAY);
                   1324:        }
                   1325:        /* timeout, force a DMA halt */
1.169     thorpej  1326:        wdc->dma_status = (*wdc->dma_finish)(wdc->dma_arg,
1.185     bouyer   1327:            chp->ch_channel, xfer->c_drive, WDC_DMAEND_ABRT);
1.84      bouyer   1328:        return 1;
                   1329: }
1.238     itohy    1330: #endif
1.84      bouyer   1331:
1.31      bouyer   1332: void
1.163     thorpej  1333: wdctimeout(void *arg)
1.2       bouyer   1334: {
1.289     jdolecek 1335:        struct ata_xfer *xfer;
                   1336:        struct ata_channel *chp = arg;
1.238     itohy    1337: #if NATA_DMA || NATA_PIOBM
1.207     thorpej  1338:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.238     itohy    1339: #endif
1.31      bouyer   1340:        int s;
1.2       bouyer   1341:
1.204     thorpej  1342:        ATADEBUG_PRINT(("wdctimeout\n"), DEBUG_FUNCS);
1.31      bouyer   1343:
                   1344:        s = splbio();
1.289     jdolecek 1345:
                   1346:        callout_ack(&chp->c_timo_callout);
                   1347:
                   1348:        xfer = ata_queue_get_active_xfer(chp);
1.284     jdolecek 1349:        KASSERT(xfer != NULL);
                   1350:
                   1351:        if (ata_timo_xfer_check(xfer)) {
                   1352:                /* Already logged */
                   1353:                goto out;
                   1354:        }
                   1355:
                   1356:        __wdcerror(chp, "lost interrupt");
                   1357:        printf("\ttype: %s tc_bcount: %d tc_skip: %d\n",
                   1358:            (xfer->c_flags & C_ATAPI) ? "atapi" : "ata",
                   1359:            xfer->c_bcount, xfer->c_skip);
1.238     itohy    1360: #if NATA_DMA || NATA_PIOBM
1.284     jdolecek 1361:        if (chp->ch_flags & ATACH_DMA_WAIT) {
                   1362:                wdc->dma_status =
                   1363:                    (*wdc->dma_finish)(wdc->dma_arg, chp->ch_channel,
                   1364:                        xfer->c_drive, WDC_DMAEND_ABRT);
                   1365:                chp->ch_flags &= ~ATACH_DMA_WAIT;
                   1366:        }
1.238     itohy    1367: #endif
1.284     jdolecek 1368:        /*
                   1369:         * Call the interrupt routine. If we just missed an interrupt,
                   1370:         * it will do what's needed. Else, it will take the needed
                   1371:         * action (reset the device).
                   1372:         * Before that we need to reinstall the timeout callback,
                   1373:         * in case it will miss another irq while in this transfer
                   1374:         * We arbitray chose it to be 1s
                   1375:         */
1.289     jdolecek 1376:        callout_reset(&chp->c_timo_callout, hz, wdctimeout, chp);
1.284     jdolecek 1377:        xfer->c_flags |= C_TIMEOU;
1.289     jdolecek 1378:        KASSERT(xfer->ops != NULL && xfer->ops->c_intr != NULL);
                   1379:        xfer->ops->c_intr(chp, xfer, 1);
1.284     jdolecek 1380:
                   1381: out:
1.31      bouyer   1382:        splx(s);
1.2       bouyer   1383: }
                   1384:
1.289     jdolecek 1385: static const struct ata_xfer_ops wdc_cmd_xfer_ops = {
                   1386:        .c_start = __wdccommand_start,
                   1387:        .c_poll = __wdccommand_poll,
                   1388:        .c_abort = __wdccommand_done,
                   1389:        .c_intr = __wdccommand_intr,
                   1390:        .c_kill_xfer = __wdccommand_kill_xfer,
                   1391: };
                   1392:
1.2       bouyer   1393: int
1.284     jdolecek 1394: wdc_exec_command(struct ata_drive_datas *drvp, struct ata_xfer *xfer)
1.31      bouyer   1395: {
1.205     thorpej  1396:        struct ata_channel *chp = drvp->chnl_softc;
1.284     jdolecek 1397:        struct ata_command *ata_c = &xfer->c_ata_c;
1.31      bouyer   1398:        int s, ret;
1.2       bouyer   1399:
1.204     thorpej  1400:        ATADEBUG_PRINT(("wdc_exec_command %s:%d:%d\n",
1.253     cube     1401:            device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
                   1402:            drvp->drive), DEBUG_FUNCS);
1.2       bouyer   1403:
1.31      bouyer   1404:        /* set up an xfer and queue. Wait for completion */
1.247     dyoung   1405:        if (chp->ch_atac->atac_cap & ATAC_CAP_NOIRQ)
1.192     thorpej  1406:                ata_c->flags |= AT_POLL;
                   1407:        if (ata_c->flags & AT_POLL)
1.31      bouyer   1408:                xfer->c_flags |= C_POLL;
1.217     bouyer   1409:        if (ata_c->flags & AT_WAIT)
                   1410:                xfer->c_flags |= C_WAIT;
1.165     thorpej  1411:        xfer->c_drive = drvp->drive;
1.192     thorpej  1412:        xfer->c_databuf = ata_c->data;
                   1413:        xfer->c_bcount = ata_c->bcount;
1.289     jdolecek 1414:        xfer->ops = &wdc_cmd_xfer_ops;
1.2       bouyer   1415:
1.31      bouyer   1416:        s = splbio();
1.201     thorpej  1417:        ata_exec_xfer(chp, xfer);
1.31      bouyer   1418: #ifdef DIAGNOSTIC
1.192     thorpej  1419:        if ((ata_c->flags & AT_POLL) != 0 &&
                   1420:            (ata_c->flags & AT_DONE) == 0)
1.118     provos   1421:                panic("wdc_exec_command: polled command not done");
1.2       bouyer   1422: #endif
1.192     thorpej  1423:        if (ata_c->flags & AT_DONE) {
1.193     thorpej  1424:                ret = ATACMD_COMPLETE;
1.31      bouyer   1425:        } else {
1.192     thorpej  1426:                if (ata_c->flags & AT_WAIT) {
1.289     jdolecek 1427:                        ata_wait_cmd(chp, xfer);
1.193     thorpej  1428:                        ret = ATACMD_COMPLETE;
1.31      bouyer   1429:                } else {
1.193     thorpej  1430:                        ret = ATACMD_QUEUED;
1.2       bouyer   1431:                }
                   1432:        }
1.31      bouyer   1433:        splx(s);
                   1434:        return ret;
1.2       bouyer   1435: }
                   1436:
1.284     jdolecek 1437: static int
1.205     thorpej  1438: __wdccommand_start(struct ata_channel *chp, struct ata_xfer *xfer)
1.219     perry    1439: {
1.207     thorpej  1440:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej  1441:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.165     thorpej  1442:        int drive = xfer->c_drive;
1.230     bouyer   1443:        int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
1.284     jdolecek 1444:        struct ata_command *ata_c = &xfer->c_ata_c;
                   1445:        int tfd;
1.31      bouyer   1446:
1.204     thorpej  1447:        ATADEBUG_PRINT(("__wdccommand_start %s:%d:%d\n",
1.253     cube     1448:            device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
1.281     msaitoh  1449:            xfer->c_drive), DEBUG_FUNCS);
1.31      bouyer   1450:
1.203     thorpej  1451:        if (wdc->select)
1.169     thorpej  1452:                wdc->select(chp,drive);
1.205     thorpej  1453:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.31      bouyer   1454:            WDSD_IBM | (drive << 4));
1.192     thorpej  1455:        switch(wdcwait(chp, ata_c->r_st_bmask | WDCS_DRQ,
1.284     jdolecek 1456:            ata_c->r_st_bmask, ata_c->timeout, wait_flags, &tfd)) {
1.137     bouyer   1457:        case WDCWAIT_OK:
                   1458:                break;
                   1459:        case WDCWAIT_TOUT:
1.192     thorpej  1460:                ata_c->flags |= AT_TIMEOU;
1.284     jdolecek 1461:                return ATASTART_ABORT;
1.137     bouyer   1462:        case WDCWAIT_THR:
1.284     jdolecek 1463:                return ATASTART_TH;
1.31      bouyer   1464:        }
1.192     thorpej  1465:        if (ata_c->flags & AT_POLL) {
1.135     bouyer   1466:                /* polled command, disable interrupts */
1.275     rkujawa  1467:                if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
                   1468:                        bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh,
                   1469:                            wd_aux_ctlr, WDCTL_4BIT | WDCTL_IDS);
1.135     bouyer   1470:        }
1.268     jakllsch 1471:        if ((ata_c->flags & AT_LBA48) != 0) {
                   1472:                wdccommandext(chp, drive, ata_c->r_command,
1.277     jakllsch 1473:                    ata_c->r_lba, ata_c->r_count, ata_c->r_features,
                   1474:                    ata_c->r_device & ~0x10);
1.268     jakllsch 1475:        } else {
                   1476:                wdccommand(chp, drive, ata_c->r_command,
                   1477:                    (ata_c->r_lba >> 8) & 0xffff,
                   1478:                    WDSD_IBM | (drive << 4) |
                   1479:                    (((ata_c->flags & AT_LBA) != 0) ? WDSD_LBA : 0) |
                   1480:                    ((ata_c->r_lba >> 24) & 0x0f),
                   1481:                    ata_c->r_lba & 0xff,
                   1482:                    ata_c->r_count & 0xff,
                   1483:                    ata_c->r_features & 0xff);
                   1484:        }
1.139     bouyer   1485:
1.192     thorpej  1486:        if ((ata_c->flags & AT_POLL) == 0) {
1.287     jdolecek 1487:                chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */
1.289     jdolecek 1488:                callout_reset(&chp->c_timo_callout, ata_c->timeout / 1000 * hz,
                   1489:                    wdctimeout, chp);
1.284     jdolecek 1490:                return ATASTART_STARTED;
1.2       bouyer   1491:        }
1.284     jdolecek 1492:
1.2       bouyer   1493:        /*
1.31      bouyer   1494:         * Polled command. Wait for drive ready or drq. Done in intr().
                   1495:         * Wait for at last 400ns for status bit to be valid.
1.2       bouyer   1496:         */
1.134     mycroft  1497:        delay(10);      /* 400ns delay */
1.284     jdolecek 1498:        return ATASTART_POLL;
                   1499: }
                   1500:
                   1501: static void
                   1502: __wdccommand_poll(struct ata_channel *chp, struct ata_xfer *xfer)
                   1503: {
1.66      bouyer   1504:        __wdccommand_intr(chp, xfer, 0);
1.2       bouyer   1505: }
                   1506:
1.167     thorpej  1507: static int
1.205     thorpej  1508: __wdccommand_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
1.2       bouyer   1509: {
1.207     thorpej  1510:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej  1511:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.284     jdolecek 1512:        struct ata_command *ata_c = &xfer->c_ata_c;
1.192     thorpej  1513:        int bcount = ata_c->bcount;
                   1514:        char *data = ata_c->data;
1.284     jdolecek 1515:        int wflags, tfd;
1.226     bouyer   1516:        int drive_flags;
                   1517:
                   1518:        if (ata_c->r_command == WDCC_IDENTIFY ||
                   1519:            ata_c->r_command == ATAPI_IDENTIFY_DEVICE) {
                   1520:                /*
                   1521:                 * The IDENTIFY data has been designed as an array of
                   1522:                 * u_int16_t, so we can byteswap it on the fly.
                   1523:                 * Historically it's what we have always done so keeping it
                   1524:                 * here ensure binary backward compatibility.
                   1525:                 */
1.274     bouyer   1526:                 drive_flags = ATA_DRIVE_NOSTREAM |
1.229     tacha    1527:                                chp->ch_drive[xfer->c_drive].drive_flags;
1.226     bouyer   1528:        } else {
                   1529:                /*
                   1530:                 * Other data structure are opaque and should be transfered
                   1531:                 * as is.
                   1532:                 */
                   1533:                drive_flags = chp->ch_drive[xfer->c_drive].drive_flags;
                   1534:        }
1.137     bouyer   1535:
1.265     bouyer   1536: #ifdef WDC_NO_IDS
                   1537:        wflags = AT_POLL;
                   1538: #else
1.192     thorpej  1539:        if ((ata_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL)) {
1.284     jdolecek 1540:                /* both wait and poll, we can kpause here */
1.147     bouyer   1541:                wflags = AT_WAIT | AT_POLL;
1.265     bouyer   1542:        } else {
                   1543:                wflags = AT_POLL;
                   1544:        }
1.264     christos 1545: #endif
1.31      bouyer   1546:
1.284     jdolecek 1547:        ata_channel_lock(chp);
                   1548:
                   1549: again:
1.204     thorpej  1550:        ATADEBUG_PRINT(("__wdccommand_intr %s:%d:%d\n",
1.253     cube     1551:            device_xname(chp->ch_atac->atac_dev), chp->ch_channel,
                   1552:            xfer->c_drive), DEBUG_INTR);
1.137     bouyer   1553:        /*
                   1554:         * after a ATAPI_SOFT_RESET, the device will have released the bus.
                   1555:         * Reselect again, it doesn't hurt for others commands, and the time
1.266     jakllsch 1556:         * penalty for the extra register write is acceptable,
                   1557:         * wdc_exec_command() isn't called often (mostly for autoconfig)
1.137     bouyer   1558:         */
1.268     jakllsch 1559:        if ((xfer->c_flags & C_ATAPI) != 0) {
                   1560:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
                   1561:                    WDSD_IBM | (xfer->c_drive << 4));
                   1562:        }
1.192     thorpej  1563:        if ((ata_c->flags & AT_XFDONE) != 0) {
1.114     bouyer   1564:                /*
                   1565:                 * We have completed a data xfer. The drive should now be
                   1566:                 * in its initial state
                   1567:                 */
1.192     thorpej  1568:                if (wdcwait(chp, ata_c->r_st_bmask | WDCS_DRQ,
                   1569:                    ata_c->r_st_bmask, (irq == 0)  ? ata_c->timeout : 0,
1.284     jdolecek 1570:                    wflags, &tfd) ==  WDCWAIT_TOUT) {
                   1571:                        if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
                   1572:                                ata_channel_unlock(chp);
1.114     bouyer   1573:                                return 0; /* IRQ was not for us */
1.284     jdolecek 1574:                        }
1.192     thorpej  1575:                        ata_c->flags |= AT_TIMEOU;
1.114     bouyer   1576:                }
1.131     mycroft  1577:                goto out;
1.114     bouyer   1578:        }
1.192     thorpej  1579:        if (wdcwait(chp, ata_c->r_st_pmask, ata_c->r_st_pmask,
1.284     jdolecek 1580:             (irq == 0)  ? ata_c->timeout : 0, wflags, &tfd) == WDCWAIT_TOUT) {
                   1581:                if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
                   1582:                        ata_channel_unlock(chp);
1.63      bouyer   1583:                        return 0; /* IRQ was not for us */
1.284     jdolecek 1584:                }
1.192     thorpej  1585:                ata_c->flags |= AT_TIMEOU;
1.131     mycroft  1586:                goto out;
1.2       bouyer   1587:        }
1.203     thorpej  1588:        if (wdc->irqack)
1.169     thorpej  1589:                wdc->irqack(chp);
1.192     thorpej  1590:        if (ata_c->flags & AT_READ) {
1.284     jdolecek 1591:                if ((ATACH_ST(tfd) & WDCS_DRQ) == 0) {
1.192     thorpej  1592:                        ata_c->flags |= AT_TIMEOU;
1.131     mycroft  1593:                        goto out;
                   1594:                }
1.226     bouyer   1595:                wdc->datain_pio(chp, drive_flags, data, bcount);
1.114     bouyer   1596:                /* at this point the drive should be in its initial state */
1.192     thorpej  1597:                ata_c->flags |= AT_XFDONE;
1.234     bouyer   1598:                /*
                   1599:                 * XXX checking the status register again here cause some
                   1600:                 * hardware to timeout.
                   1601:                 */
1.192     thorpej  1602:        } else if (ata_c->flags & AT_WRITE) {
1.284     jdolecek 1603:                if ((ATACH_ST(tfd) & WDCS_DRQ) == 0) {
1.192     thorpej  1604:                        ata_c->flags |= AT_TIMEOU;
1.131     mycroft  1605:                        goto out;
                   1606:                }
1.226     bouyer   1607:                wdc->dataout_pio(chp, drive_flags, data, bcount);
1.192     thorpej  1608:                ata_c->flags |= AT_XFDONE;
                   1609:                if ((ata_c->flags & AT_POLL) == 0) {
1.287     jdolecek 1610:                        chp->ch_flags |= ATACH_IRQ_WAIT; /* wait for interrupt */
1.289     jdolecek 1611:                        callout_reset(&chp->c_timo_callout,
                   1612:                            mstohz(ata_c->timeout), wdctimeout, chp);
1.284     jdolecek 1613:                        ata_channel_unlock(chp);
1.114     bouyer   1614:                        return 1;
                   1615:                } else {
                   1616:                        goto again;
                   1617:                }
1.2       bouyer   1618:        }
1.284     jdolecek 1619: out:
                   1620:        if (ATACH_ST(tfd) & WDCS_DWF)
                   1621:                ata_c->flags |= AT_DF;
                   1622:        if (ATACH_ST(tfd) & WDCS_ERR) {
                   1623:                ata_c->flags |= AT_ERROR;
                   1624:                ata_c->r_error = ATACH_ST(tfd);
                   1625:        }
                   1626:
                   1627:        ata_channel_unlock(chp);
                   1628:
1.31      bouyer   1629:        __wdccommand_done(chp, xfer);
                   1630:        return 1;
1.2       bouyer   1631: }
                   1632:
1.167     thorpej  1633: static void
1.205     thorpej  1634: __wdccommand_done(struct ata_channel *chp, struct ata_xfer *xfer)
1.2       bouyer   1635: {
1.207     thorpej  1636:        struct atac_softc *atac = chp->ch_atac;
                   1637:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej  1638:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.284     jdolecek 1639:        struct ata_command *ata_c = &xfer->c_ata_c;
                   1640:        bool start = true;
1.2       bouyer   1641:
1.233     bouyer   1642:        ATADEBUG_PRINT(("__wdccommand_done %s:%d:%d flags 0x%x\n",
1.253     cube     1643:            device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive,
1.233     bouyer   1644:            ata_c->flags), DEBUG_FUNCS);
1.70      bouyer   1645:
1.284     jdolecek 1646:        if (ata_waitdrain_xfer_check(chp, xfer)) {
                   1647:                start = false;
                   1648:                goto out;
                   1649:        }
1.70      bouyer   1650:
1.192     thorpej  1651:        if ((ata_c->flags & AT_READREG) != 0 &&
1.253     cube     1652:            device_is_active(atac->atac_dev) &&
1.192     thorpej  1653:            (ata_c->flags & (AT_ERROR | AT_DF)) == 0) {
1.268     jakllsch 1654:                ata_c->r_status = bus_space_read_1(wdr->cmd_iot,
                   1655:                    wdr->cmd_iohs[wd_status], 0);
                   1656:                ata_c->r_error = bus_space_read_1(wdr->cmd_iot,
                   1657:                    wdr->cmd_iohs[wd_error], 0);
1.205     thorpej  1658:                ata_c->r_count = bus_space_read_1(wdr->cmd_iot,
                   1659:                    wdr->cmd_iohs[wd_seccnt], 0);
1.268     jakllsch 1660:                ata_c->r_lba = (uint64_t)bus_space_read_1(wdr->cmd_iot,
                   1661:                    wdr->cmd_iohs[wd_sector], 0) << 0;
                   1662:                ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
                   1663:                    wdr->cmd_iohs[wd_cyl_lo], 0) << 8;
                   1664:                ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
                   1665:                    wdr->cmd_iohs[wd_cyl_hi], 0) << 16;
                   1666:                ata_c->r_device = bus_space_read_1(wdr->cmd_iot,
                   1667:                    wdr->cmd_iohs[wd_sdh], 0);
                   1668:
                   1669:                if ((ata_c->flags & AT_LBA48) != 0) {
1.275     rkujawa  1670:                        if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL)) {
                   1671:                                if ((ata_c->flags & AT_POLL) != 0)
                   1672:                                        bus_space_write_1(wdr->ctl_iot,
                   1673:                                            wdr->ctl_ioh, wd_aux_ctlr,
                   1674:                                            WDCTL_HOB|WDCTL_4BIT|WDCTL_IDS);
                   1675:                                else
                   1676:                                        bus_space_write_1(wdr->ctl_iot,
                   1677:                                            wdr->ctl_ioh, wd_aux_ctlr,
                   1678:                                            WDCTL_HOB|WDCTL_4BIT);
                   1679:                        }
1.268     jakllsch 1680:                        ata_c->r_count |= bus_space_read_1(wdr->cmd_iot,
                   1681:                            wdr->cmd_iohs[wd_seccnt], 0) << 8;
                   1682:                        ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
                   1683:                            wdr->cmd_iohs[wd_sector], 0) << 24;
                   1684:                        ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
                   1685:                            wdr->cmd_iohs[wd_cyl_lo], 0) << 32;
                   1686:                        ata_c->r_lba |= (uint64_t)bus_space_read_1(wdr->cmd_iot,
                   1687:                            wdr->cmd_iohs[wd_cyl_hi], 0) << 40;
1.275     rkujawa  1688:                        if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL)) {
                   1689:                                if ((ata_c->flags & AT_POLL) != 0)
                   1690:                                        bus_space_write_1(wdr->ctl_iot,
                   1691:                                            wdr->ctl_ioh, wd_aux_ctlr,
                   1692:                                            WDCTL_4BIT|WDCTL_IDS);
                   1693:                                else
                   1694:                                        bus_space_write_1(wdr->ctl_iot,
                   1695:                                            wdr->ctl_ioh, wd_aux_ctlr,
                   1696:                                            WDCTL_4BIT);
                   1697:                        }
1.268     jakllsch 1698:                } else {
                   1699:                        ata_c->r_lba |=
                   1700:                            (uint64_t)(ata_c->r_device & 0x0f) << 24;
                   1701:                }
                   1702:                ata_c->r_device &= 0xf0;
1.135     bouyer   1703:        }
1.284     jdolecek 1704:
1.289     jdolecek 1705:        __wdccommand_done_end(chp, xfer);
                   1706:
1.284     jdolecek 1707:        ata_deactivate_xfer(chp, xfer);
                   1708:
                   1709: out:
1.192     thorpej  1710:        if (ata_c->flags & AT_POLL) {
1.187     bouyer   1711:                /* enable interrupts */
1.275     rkujawa  1712:                if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL))
                   1713:                        bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh,
                   1714:                            wd_aux_ctlr, WDCTL_4BIT);
1.187     bouyer   1715:                delay(10); /* some drives need a little delay here */
                   1716:        }
1.284     jdolecek 1717:
                   1718:        if (start)
                   1719:                atastart(chp);
1.182     bouyer   1720: }
1.219     perry    1721:
1.182     bouyer   1722: static void
1.205     thorpej  1723: __wdccommand_done_end(struct ata_channel *chp, struct ata_xfer *xfer)
1.182     bouyer   1724: {
1.284     jdolecek 1725:        struct ata_command *ata_c = &xfer->c_ata_c;
1.182     bouyer   1726:
1.192     thorpej  1727:        ata_c->flags |= AT_DONE;
1.2       bouyer   1728: }
                   1729:
1.182     bouyer   1730: static void
1.205     thorpej  1731: __wdccommand_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer,
1.182     bouyer   1732:     int reason)
                   1733: {
1.284     jdolecek 1734:        struct ata_command *ata_c = &xfer->c_ata_c;
                   1735:        bool deactivate = true;
1.182     bouyer   1736:
                   1737:        switch (reason) {
1.284     jdolecek 1738:        case KILL_GONE_INACTIVE:
                   1739:                deactivate = false;
                   1740:                /* FALLTHROUGH */
1.182     bouyer   1741:        case KILL_GONE:
1.192     thorpej  1742:                ata_c->flags |= AT_GONE;
1.219     perry    1743:                break;
1.182     bouyer   1744:        case KILL_RESET:
1.192     thorpej  1745:                ata_c->flags |= AT_RESET;
1.182     bouyer   1746:                break;
                   1747:        default:
                   1748:                printf("__wdccommand_kill_xfer: unknown reason %d\n",
                   1749:                    reason);
                   1750:                panic("__wdccommand_kill_xfer");
                   1751:        }
1.284     jdolecek 1752:
1.289     jdolecek 1753:        __wdccommand_done_end(chp, xfer);
                   1754:
1.284     jdolecek 1755:        if (deactivate)
                   1756:                ata_deactivate_xfer(chp, xfer);
1.182     bouyer   1757: }
                   1758:
1.2       bouyer   1759: /*
1.31      bouyer   1760:  * Send a command. The drive should be ready.
1.2       bouyer   1761:  * Assumes interrupts are blocked.
                   1762:  */
1.31      bouyer   1763: void
1.205     thorpej  1764: wdccommand(struct ata_channel *chp, u_int8_t drive, u_int8_t command,
1.163     thorpej  1765:     u_int16_t cylin, u_int8_t head, u_int8_t sector, u_int8_t count,
1.178     thorpej  1766:     u_int8_t features)
1.31      bouyer   1767: {
1.207     thorpej  1768:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej  1769:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.163     thorpej  1770:
1.204     thorpej  1771:        ATADEBUG_PRINT(("wdccommand %s:%d:%d: command=0x%x cylin=%d head=%d "
1.253     cube     1772:            "sector=%d count=%d features=%d\n",
                   1773:            device_xname(chp->ch_atac->atac_dev), chp->ch_channel, drive,
                   1774:            command, cylin, head, sector, count, features), DEBUG_FUNCS);
1.31      bouyer   1775:
1.203     thorpej  1776:        if (wdc->select)
1.169     thorpej  1777:                wdc->select(chp,drive);
1.107     dbj      1778:
1.31      bouyer   1779:        /* Select drive, head, and addressing mode. */
1.205     thorpej  1780:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.31      bouyer   1781:            WDSD_IBM | (drive << 4) | head);
1.177     thorpej  1782:        /* Load parameters into the wd_features register. */
1.205     thorpej  1783:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_features], 0,
1.178     thorpej  1784:            features);
1.205     thorpej  1785:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt], 0, count);
                   1786:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sector], 0, sector);
                   1787:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_lo], 0, cylin);
                   1788:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_cyl_hi],
1.157     fvdl     1789:            0, cylin >> 8);
1.108     christos 1790:
                   1791:        /* Send command. */
1.205     thorpej  1792:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0, command);
1.108     christos 1793:        return;
                   1794: }
                   1795:
                   1796: /*
                   1797:  * Send a 48-bit addressing command. The drive should be ready.
                   1798:  * Assumes interrupts are blocked.
                   1799:  */
                   1800: void
1.205     thorpej  1801: wdccommandext(struct ata_channel *chp, u_int8_t drive, u_int8_t command,
1.277     jakllsch 1802:     u_int64_t blkno, u_int16_t count, u_int16_t features, u_int8_t device)
1.108     christos 1803: {
1.207     thorpej  1804:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej  1805:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.163     thorpej  1806:
1.277     jakllsch 1807:        ATADEBUG_PRINT(("wdccommandext %s:%d:%d: command=0x%02x "
                   1808:            "blkno=0x%012"PRIx64" count=0x%04x features=0x%04x "
                   1809:            "device=0x%02x\n", device_xname(chp->ch_atac->atac_dev),
                   1810:            chp->ch_channel, drive, command, blkno, count, features, device),
1.108     christos 1811:            DEBUG_FUNCS);
                   1812:
1.277     jakllsch 1813:        KASSERT(drive < wdc->wdc_maxdrives);
                   1814:
1.203     thorpej  1815:        if (wdc->select)
1.169     thorpej  1816:                wdc->select(chp,drive);
1.108     christos 1817:
                   1818:        /* Select drive, head, and addressing mode. */
1.205     thorpej  1819:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.277     jakllsch 1820:            (drive << 4) | device);
1.108     christos 1821:
1.218     rearnsha 1822:        if (wdc->cap & WDC_CAPABILITY_WIDEREGS) {
1.267     jakllsch 1823:                bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_features],
                   1824:                    0, features);
1.218     rearnsha 1825:                bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt],
                   1826:                    0, count);
                   1827:                bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_lo],
                   1828:                    0, (((blkno >> 16) & 0xff00) | (blkno & 0x00ff)));
                   1829:                bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_mi],
                   1830:                    0, (((blkno >> 24) & 0xff00) | ((blkno >> 8) & 0x00ff)));
                   1831:                bus_space_write_2(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_hi],
                   1832:                    0, (((blkno >> 32) & 0xff00) | ((blkno >> 16) & 0x00ff)));
                   1833:        } else {
                   1834:                /* previous */
1.267     jakllsch 1835:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_features],
                   1836:                    0, features >> 8);
1.218     rearnsha 1837:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt],
                   1838:                    0, count >> 8);
                   1839:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_lo],
                   1840:                    0, blkno >> 24);
                   1841:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_mi],
                   1842:                    0, blkno >> 32);
                   1843:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_hi],
                   1844:                    0, blkno >> 40);
                   1845:
                   1846:                /* current */
1.267     jakllsch 1847:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_features],
                   1848:                    0, features);
                   1849:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_seccnt],
                   1850:                    0, count);
                   1851:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_lo],
                   1852:                    0, blkno);
1.218     rearnsha 1853:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_mi],
                   1854:                    0, blkno >> 8);
                   1855:                bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_lba_hi],
                   1856:                    0, blkno >> 16);
                   1857:        }
1.2       bouyer   1858:
1.31      bouyer   1859:        /* Send command. */
1.205     thorpej  1860:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0, command);
1.31      bouyer   1861:        return;
1.2       bouyer   1862: }
                   1863:
                   1864: /*
1.31      bouyer   1865:  * Simplified version of wdccommand().  Unbusy/ready/drq must be
                   1866:  * tested by the caller.
1.2       bouyer   1867:  */
1.31      bouyer   1868: void
1.205     thorpej  1869: wdccommandshort(struct ata_channel *chp, int drive, int command)
1.2       bouyer   1870: {
1.207     thorpej  1871:        struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.205     thorpej  1872:        struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.2       bouyer   1873:
1.204     thorpej  1874:        ATADEBUG_PRINT(("wdccommandshort %s:%d:%d command 0x%x\n",
1.253     cube     1875:            device_xname(chp->ch_atac->atac_dev), chp->ch_channel, drive,
                   1876:            command), DEBUG_FUNCS);
1.107     dbj      1877:
1.203     thorpej  1878:        if (wdc->select)
1.169     thorpej  1879:                wdc->select(chp,drive);
1.2       bouyer   1880:
1.31      bouyer   1881:        /* Select drive. */
1.205     thorpej  1882:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.31      bouyer   1883:            WDSD_IBM | (drive << 4));
1.2       bouyer   1884:
1.205     thorpej  1885:        bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_command], 0, command);
1.31      bouyer   1886: }
1.2       bouyer   1887:
1.31      bouyer   1888: static void
1.222     christos 1889: __wdcerror(struct ata_channel *chp, const char *msg)
1.2       bouyer   1890: {
1.207     thorpej  1891:        struct atac_softc *atac = chp->ch_atac;
1.284     jdolecek 1892:        struct ata_xfer *xfer = ata_queue_get_active_xfer(chp);
1.88      mrg      1893:
1.2       bouyer   1894:        if (xfer == NULL)
1.253     cube     1895:                aprint_error("%s:%d: %s\n", device_xname(atac->atac_dev),
                   1896:                    chp->ch_channel, msg);
1.2       bouyer   1897:        else
1.253     cube     1898:                aprint_error("%s:%d:%d: %s\n", device_xname(atac->atac_dev),
1.169     thorpej  1899:                    chp->ch_channel, xfer->c_drive, msg);
1.2       bouyer   1900: }
                   1901:
1.219     perry    1902: /*
1.2       bouyer   1903:  * the bit bucket
                   1904:  */
                   1905: void
1.205     thorpej  1906: wdcbit_bucket(struct ata_channel *chp, int size)
1.2       bouyer   1907: {
1.207     thorpej  1908:        struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
1.2       bouyer   1909:
1.12      cgd      1910:        for (; size >= 2; size -= 2)
1.205     thorpej  1911:                (void)bus_space_read_2(wdr->cmd_iot, wdr->cmd_iohs[wd_data], 0);
1.12      cgd      1912:        if (size)
1.205     thorpej  1913:                (void)bus_space_read_1(wdr->cmd_iot, wdr->cmd_iohs[wd_data], 0);
1.44      thorpej  1914: }
                   1915:
1.213     thorpej  1916: static void
1.222     christos 1917: wdc_datain_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
1.190     mycroft  1918: {
1.207     thorpej  1919:        struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
1.190     mycroft  1920:
1.244     martin   1921: #ifndef __NO_STRICT_ALIGNMENT
                   1922:        if ((uintptr_t)bf & 1)
                   1923:                goto unaligned;
1.274     bouyer   1924:        if ((flags & ATA_DRIVE_CAP32) && ((uintptr_t)bf & 3))
1.244     martin   1925:                goto unaligned;
                   1926: #endif
                   1927:
1.274     bouyer   1928:        if (flags & ATA_DRIVE_NOSTREAM) {
                   1929:                if ((flags & ATA_DRIVE_CAP32) && len > 3) {
1.205     thorpej  1930:                        bus_space_read_multi_4(wdr->data32iot,
1.222     christos 1931:                            wdr->data32ioh, 0, bf, len >> 2);
                   1932:                        bf = (char *)bf + (len & ~3);
1.190     mycroft  1933:                        len &= 3;
                   1934:                }
1.273     christos 1935:                if (len > 1) {
1.205     thorpej  1936:                        bus_space_read_multi_2(wdr->cmd_iot,
1.222     christos 1937:                            wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
1.273     christos 1938:                        bf = (char *)bf + (len & ~1);
                   1939:                        len &= 1;
1.190     mycroft  1940:                }
                   1941:        } else {
1.274     bouyer   1942:                if ((flags & ATA_DRIVE_CAP32) && len > 3) {
1.205     thorpej  1943:                        bus_space_read_multi_stream_4(wdr->data32iot,
1.222     christos 1944:                            wdr->data32ioh, 0, bf, len >> 2);
                   1945:                        bf = (char *)bf + (len & ~3);
1.190     mycroft  1946:                        len &= 3;
                   1947:                }
1.273     christos 1948:                if (len > 1) {
1.205     thorpej  1949:                        bus_space_read_multi_stream_2(wdr->cmd_iot,
1.222     christos 1950:                            wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
1.273     christos 1951:                        bf = (char *)bf + (len & ~1);
                   1952:                        len &= 1;
1.190     mycroft  1953:                }
                   1954:        }
1.273     christos 1955:        if (len)
                   1956:                *((uint8_t *)bf) = bus_space_read_1(wdr->cmd_iot,
                   1957:                            wdr->cmd_iohs[wd_data], 0);
1.244     martin   1958:        return;
                   1959:
                   1960: #ifndef __NO_STRICT_ALIGNMENT
                   1961: unaligned:
1.274     bouyer   1962:        if (flags & ATA_DRIVE_NOSTREAM) {
                   1963:                if (flags & ATA_DRIVE_CAP32) {
1.245     bouyer   1964:                        while (len > 3) {
                   1965:                                uint32_t val;
                   1966:
                   1967:                                val = bus_space_read_4(wdr->data32iot,
                   1968:                                    wdr->data32ioh, 0);
                   1969:                                memcpy(bf, &val, 4);
                   1970:                                bf = (char *)bf + 4;
                   1971:                                len -= 4;
                   1972:                        }
                   1973:                }
                   1974:                while (len > 1) {
                   1975:                        uint16_t val;
                   1976:
                   1977:                        val = bus_space_read_2(wdr->cmd_iot,
                   1978:                            wdr->cmd_iohs[wd_data], 0);
                   1979:                        memcpy(bf, &val, 2);
                   1980:                        bf = (char *)bf + 2;
                   1981:                        len -= 2;
                   1982:                }
                   1983:        } else {
1.274     bouyer   1984:                if (flags & ATA_DRIVE_CAP32) {
1.245     bouyer   1985:                        while (len > 3) {
                   1986:                                uint32_t val;
1.244     martin   1987:
1.245     bouyer   1988:                                val = bus_space_read_stream_4(wdr->data32iot,
                   1989:                                    wdr->data32ioh, 0);
                   1990:                                memcpy(bf, &val, 4);
                   1991:                                bf = (char *)bf + 4;
                   1992:                                len -= 4;
                   1993:                        }
                   1994:                }
                   1995:                while (len > 1) {
                   1996:                        uint16_t val;
                   1997:
                   1998:                        val = bus_space_read_stream_2(wdr->cmd_iot,
1.244     martin   1999:                            wdr->cmd_iohs[wd_data], 0);
1.245     bouyer   2000:                        memcpy(bf, &val, 2);
                   2001:                        bf = (char *)bf + 2;
                   2002:                        len -= 2;
1.244     martin   2003:                }
                   2004:        }
                   2005: #endif
1.190     mycroft  2006: }
                   2007:
1.213     thorpej  2008: static void
1.222     christos 2009: wdc_dataout_pio(struct ata_channel *chp, int flags, void *bf, size_t len)
1.190     mycroft  2010: {
1.207     thorpej  2011:        struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
1.190     mycroft  2012:
1.244     martin   2013: #ifndef __NO_STRICT_ALIGNMENT
                   2014:        if ((uintptr_t)bf & 1)
                   2015:                goto unaligned;
1.274     bouyer   2016:        if ((flags & ATA_DRIVE_CAP32) && ((uintptr_t)bf & 3))
1.244     martin   2017:                goto unaligned;
                   2018: #endif
                   2019:
1.274     bouyer   2020:        if (flags & ATA_DRIVE_NOSTREAM) {
                   2021:                if (flags & ATA_DRIVE_CAP32) {
1.205     thorpej  2022:                        bus_space_write_multi_4(wdr->data32iot,
1.222     christos 2023:                            wdr->data32ioh, 0, bf, len >> 2);
                   2024:                        bf = (char *)bf + (len & ~3);
1.190     mycroft  2025:                        len &= 3;
                   2026:                }
                   2027:                if (len) {
1.205     thorpej  2028:                        bus_space_write_multi_2(wdr->cmd_iot,
1.222     christos 2029:                            wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
1.190     mycroft  2030:                }
                   2031:        } else {
1.274     bouyer   2032:                if (flags & ATA_DRIVE_CAP32) {
1.205     thorpej  2033:                        bus_space_write_multi_stream_4(wdr->data32iot,
1.222     christos 2034:                            wdr->data32ioh, 0, bf, len >> 2);
                   2035:                        bf = (char *)bf + (len & ~3);
1.190     mycroft  2036:                        len &= 3;
                   2037:                }
                   2038:                if (len) {
1.205     thorpej  2039:                        bus_space_write_multi_stream_2(wdr->cmd_iot,
1.222     christos 2040:                            wdr->cmd_iohs[wd_data], 0, bf, len >> 1);
1.190     mycroft  2041:                }
                   2042:        }
1.244     martin   2043:        return;
                   2044:
                   2045: #ifndef __NO_STRICT_ALIGNMENT
                   2046: unaligned:
1.274     bouyer   2047:        if (flags & ATA_DRIVE_NOSTREAM) {
                   2048:                if (flags & ATA_DRIVE_CAP32) {
1.245     bouyer   2049:                        while (len > 3) {
                   2050:                                uint32_t val;
1.244     martin   2051:
1.245     bouyer   2052:                                memcpy(&val, bf, 4);
                   2053:                                bus_space_write_4(wdr->data32iot,
                   2054:                                    wdr->data32ioh, 0, val);
                   2055:                                bf = (char *)bf + 4;
                   2056:                                len -= 4;
                   2057:                        }
                   2058:                }
                   2059:                while (len > 1) {
                   2060:                        uint16_t val;
                   2061:
                   2062:                        memcpy(&val, bf, 2);
                   2063:                        bus_space_write_2(wdr->cmd_iot,
1.244     martin   2064:                            wdr->cmd_iohs[wd_data], 0, val);
1.245     bouyer   2065:                        bf = (char *)bf + 2;
                   2066:                        len -= 2;
1.244     martin   2067:                }
1.245     bouyer   2068:        } else {
1.274     bouyer   2069:                if (flags & ATA_DRIVE_CAP32) {
1.245     bouyer   2070:                        while (len > 3) {
                   2071:                                uint32_t val;
                   2072:
                   2073:                                memcpy(&val, bf, 4);
                   2074:                                bus_space_write_stream_4(wdr->data32iot,
                   2075:                                    wdr->data32ioh, 0, val);
                   2076:                                bf = (char *)bf + 4;
                   2077:                                len -= 4;
                   2078:                        }
                   2079:                }
                   2080:                while (len > 1) {
                   2081:                        uint16_t val;
1.244     martin   2082:
1.245     bouyer   2083:                        memcpy(&val, bf, 2);
                   2084:                        bus_space_write_stream_2(wdr->cmd_iot,
                   2085:                            wdr->cmd_iohs[wd_data], 0, val);
                   2086:                        bf = (char *)bf + 2;
                   2087:                        len -= 2;
                   2088:                }
1.244     martin   2089:        }
                   2090: #endif
1.190     mycroft  2091: }

CVSweb <webmaster@jp.NetBSD.org>