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