wdc.c revision 1.190 1 1.190 mycroft /* $NetBSD: wdc.c,v 1.190 2004/08/11 17:49:27 mycroft 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.190 mycroft __KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.190 2004/08/11 17:49:27 mycroft Exp $");
74 1.12 cgd
75 1.59 hubertf #ifndef WDCDEBUG
76 1.31 bouyer #define WDCDEBUG
77 1.59 hubertf #endif /* WDCDEBUG */
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.71 bouyer #include <sys/pool.h>
87 1.2 bouyer #include <sys/syslog.h>
88 1.2 bouyer #include <sys/proc.h>
89 1.2 bouyer
90 1.2 bouyer #include <machine/intr.h>
91 1.2 bouyer #include <machine/bus.h>
92 1.2 bouyer
93 1.17 sakamoto #ifndef __BUS_SPACE_HAS_STREAM_METHODS
94 1.31 bouyer #define bus_space_write_multi_stream_2 bus_space_write_multi_2
95 1.31 bouyer #define bus_space_write_multi_stream_4 bus_space_write_multi_4
96 1.31 bouyer #define bus_space_read_multi_stream_2 bus_space_read_multi_2
97 1.31 bouyer #define bus_space_read_multi_stream_4 bus_space_read_multi_4
98 1.17 sakamoto #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
99 1.16 sakamoto
100 1.103 bouyer #include <dev/ata/atavar.h>
101 1.31 bouyer #include <dev/ata/atareg.h>
102 1.12 cgd #include <dev/ic/wdcreg.h>
103 1.12 cgd #include <dev/ic/wdcvar.h>
104 1.31 bouyer
105 1.137 bouyer #include "locators.h"
106 1.137 bouyer
107 1.122 thorpej #include "ataraid.h"
108 1.2 bouyer #include "atapibus.h"
109 1.106 bouyer #include "wd.h"
110 1.2 bouyer
111 1.122 thorpej #if NATARAID > 0
112 1.122 thorpej #include <dev/ata/ata_raidvar.h>
113 1.122 thorpej #endif
114 1.122 thorpej
115 1.31 bouyer #define WDCDELAY 100 /* 100 microseconds */
116 1.31 bouyer #define WDCNDELAY_RST (WDC_RESET_WAIT * 1000 / WDCDELAY)
117 1.2 bouyer #if 0
118 1.31 bouyer /* If you enable this, it will report any delays more than WDCDELAY * N long. */
119 1.2 bouyer #define WDCNDELAY_DEBUG 50
120 1.2 bouyer #endif
121 1.2 bouyer
122 1.137 bouyer /* When polling wait that much and then tsleep for 1/hz seconds */
123 1.137 bouyer #define WDCDELAY_POLL 1 /* ms */
124 1.137 bouyer
125 1.137 bouyer /* timeout for the control commands */
126 1.137 bouyer #define WDC_CTRL_DELAY 10000 /* 10s, for the recall command */
127 1.137 bouyer
128 1.71 bouyer struct pool wdc_xfer_pool;
129 1.2 bouyer
130 1.106 bouyer #if NWD > 0
131 1.103 bouyer extern const struct ata_bustype wdc_ata_bustype; /* in ata_wdc.c */
132 1.106 bouyer #else
133 1.106 bouyer /* A fake one, the autoconfig will print "wd at foo ... not configured */
134 1.106 bouyer const struct ata_bustype wdc_ata_bustype = {
135 1.106 bouyer SCSIPI_BUSTYPE_ATA,
136 1.106 bouyer NULL,
137 1.106 bouyer NULL,
138 1.106 bouyer NULL,
139 1.106 bouyer NULL,
140 1.106 bouyer NULL,
141 1.106 bouyer NULL,
142 1.106 bouyer NULL
143 1.106 bouyer };
144 1.106 bouyer #endif
145 1.102 bouyer
146 1.168 thorpej static int wdcprobe1(struct wdc_channel*, int);
147 1.168 thorpej static void __wdcerror(struct wdc_channel*, char *);
148 1.168 thorpej static int __wdcwait_reset(struct wdc_channel *, int, int);
149 1.168 thorpej static void __wdccommand_done(struct wdc_channel *, struct ata_xfer *);
150 1.182 bouyer static void __wdccommand_done_end(struct wdc_channel *, struct ata_xfer *);
151 1.182 bouyer static void __wdccommand_kill_xfer(struct wdc_channel *,
152 1.182 bouyer struct ata_xfer *, int);
153 1.168 thorpej static void __wdccommand_start(struct wdc_channel *, struct ata_xfer *);
154 1.182 bouyer static int __wdccommand_intr(struct wdc_channel *, struct ata_xfer *, int);
155 1.168 thorpej static int __wdcwait(struct wdc_channel *, int, int, int);
156 1.31 bouyer
157 1.31 bouyer #define DEBUG_INTR 0x01
158 1.31 bouyer #define DEBUG_XFERS 0x02
159 1.31 bouyer #define DEBUG_STATUS 0x04
160 1.31 bouyer #define DEBUG_FUNCS 0x08
161 1.31 bouyer #define DEBUG_PROBE 0x10
162 1.74 enami #define DEBUG_DETACH 0x20
163 1.87 bouyer #define DEBUG_DELAY 0x40
164 1.31 bouyer #ifdef WDCDEBUG
165 1.32 bouyer int wdcdebug_mask = 0;
166 1.31 bouyer int wdc_nxfer = 0;
167 1.31 bouyer #define WDCDEBUG_PRINT(args, level) if (wdcdebug_mask & (level)) printf args
168 1.2 bouyer #else
169 1.31 bouyer #define WDCDEBUG_PRINT(args, level)
170 1.2 bouyer #endif
171 1.2 bouyer
172 1.162 thorpej /*
173 1.162 thorpej * A queue of atabus instances, used to ensure the same bus probe order
174 1.162 thorpej * for a given hardware configuration at each boot.
175 1.162 thorpej */
176 1.162 thorpej struct atabus_initq_head atabus_initq_head =
177 1.162 thorpej TAILQ_HEAD_INITIALIZER(atabus_initq_head);
178 1.162 thorpej struct simplelock atabus_interlock = SIMPLELOCK_INITIALIZER;
179 1.137 bouyer
180 1.176 thorpej /*
181 1.176 thorpej * Initialize the "shadow register" handles for a standard wdc controller.
182 1.176 thorpej */
183 1.176 thorpej void
184 1.176 thorpej wdc_init_shadow_regs(struct wdc_channel *chp)
185 1.176 thorpej {
186 1.176 thorpej
187 1.176 thorpej chp->cmd_iohs[wd_status] = chp->cmd_iohs[wd_command];
188 1.176 thorpej chp->cmd_iohs[wd_features] = chp->cmd_iohs[wd_error];
189 1.176 thorpej }
190 1.176 thorpej
191 1.162 thorpej /* Test to see controller with at last one attached drive is there.
192 1.162 thorpej * Returns a bit for each possible drive found (0x01 for drive 0,
193 1.162 thorpej * 0x02 for drive 1).
194 1.162 thorpej * Logic:
195 1.162 thorpej * - If a status register is at 0xff, assume there is no drive here
196 1.162 thorpej * (ISA has pull-up resistors). Similarly if the status register has
197 1.162 thorpej * the value we last wrote to the bus (for IDE interfaces without pullups).
198 1.162 thorpej * If no drive at all -> return.
199 1.162 thorpej * - reset the controller, wait for it to complete (may take up to 31s !).
200 1.162 thorpej * If timeout -> return.
201 1.162 thorpej * - test ATA/ATAPI signatures. If at last one drive found -> return.
202 1.162 thorpej * - try an ATA command on the master.
203 1.162 thorpej */
204 1.137 bouyer
205 1.164 thorpej static void
206 1.168 thorpej wdc_drvprobe(struct wdc_channel *chp)
207 1.137 bouyer {
208 1.137 bouyer struct ataparams params;
209 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
210 1.145 christos u_int8_t st0 = 0, st1 = 0;
211 1.164 thorpej int i, error;
212 1.137 bouyer
213 1.164 thorpej if (wdcprobe1(chp, 0) == 0) {
214 1.164 thorpej /* No drives, abort the attach here. */
215 1.164 thorpej return;
216 1.161 thorpej }
217 1.137 bouyer
218 1.137 bouyer /* for ATA/OLD drives, wait for DRDY, 3s timeout */
219 1.137 bouyer for (i = 0; i < mstohz(3000); i++) {
220 1.174 bouyer if (chp->ch_drive[0].drive_flags & (DRIVE_ATA|DRIVE_OLD)) {
221 1.174 bouyer if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
222 1.174 bouyer wdc->select(chp,0);
223 1.174 bouyer bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
224 1.174 bouyer 0, WDSD_IBM);
225 1.174 bouyer delay(10); /* 400ns delay */
226 1.174 bouyer st0 = bus_space_read_1(chp->cmd_iot,
227 1.174 bouyer chp->cmd_iohs[wd_status], 0);
228 1.174 bouyer }
229 1.137 bouyer
230 1.174 bouyer if (chp->ch_drive[1].drive_flags & (DRIVE_ATA|DRIVE_OLD)) {
231 1.174 bouyer if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
232 1.174 bouyer wdc->select(chp,1);
233 1.174 bouyer bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
234 1.174 bouyer 0, WDSD_IBM | 0x10);
235 1.174 bouyer delay(10); /* 400ns delay */
236 1.174 bouyer st1 = bus_space_read_1(chp->cmd_iot,
237 1.174 bouyer chp->cmd_iohs[wd_status], 0);
238 1.174 bouyer }
239 1.137 bouyer
240 1.137 bouyer if (((chp->ch_drive[0].drive_flags & (DRIVE_ATA|DRIVE_OLD))
241 1.137 bouyer == 0 ||
242 1.137 bouyer (st0 & WDCS_DRDY)) &&
243 1.137 bouyer ((chp->ch_drive[1].drive_flags & (DRIVE_ATA|DRIVE_OLD))
244 1.137 bouyer == 0 ||
245 1.137 bouyer (st1 & WDCS_DRDY)))
246 1.137 bouyer break;
247 1.164 thorpej tsleep(¶ms, PRIBIO, "atadrdy", 1);
248 1.137 bouyer }
249 1.137 bouyer if ((st0 & WDCS_DRDY) == 0)
250 1.137 bouyer chp->ch_drive[0].drive_flags &= ~(DRIVE_ATA|DRIVE_OLD);
251 1.137 bouyer if ((st1 & WDCS_DRDY) == 0)
252 1.137 bouyer chp->ch_drive[1].drive_flags &= ~(DRIVE_ATA|DRIVE_OLD);
253 1.137 bouyer
254 1.137 bouyer WDCDEBUG_PRINT(("%s:%d: wait DRDY st0 0x%x st1 0x%x\n",
255 1.169 thorpej wdc->sc_dev.dv_xname,
256 1.169 thorpej chp->ch_channel, st0, st1), DEBUG_PROBE);
257 1.137 bouyer
258 1.137 bouyer /* Wait a bit, some devices are weird just after a reset. */
259 1.137 bouyer delay(5000);
260 1.137 bouyer
261 1.137 bouyer for (i = 0; i < 2; i++) {
262 1.171 thorpej /* XXX This should be done by other code. */
263 1.137 bouyer chp->ch_drive[i].chnl_softc = chp;
264 1.137 bouyer chp->ch_drive[i].drive = i;
265 1.171 thorpej
266 1.137 bouyer /*
267 1.137 bouyer * Init error counter so that an error withing the first xfers
268 1.137 bouyer * will trigger a downgrade
269 1.137 bouyer */
270 1.137 bouyer chp->ch_drive[i].n_dmaerrs = NERRS_MAX-1;
271 1.137 bouyer
272 1.137 bouyer /* If controller can't do 16bit flag the drives as 32bit */
273 1.169 thorpej if ((wdc->cap &
274 1.137 bouyer (WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32)) ==
275 1.137 bouyer WDC_CAPABILITY_DATA32)
276 1.137 bouyer chp->ch_drive[i].drive_flags |= DRIVE_CAP32;
277 1.137 bouyer if ((chp->ch_drive[i].drive_flags & DRIVE) == 0)
278 1.137 bouyer continue;
279 1.137 bouyer
280 1.144 briggs /* Shortcut in case we've been shutdown */
281 1.144 briggs if (chp->ch_flags & WDCF_SHUTDOWN)
282 1.164 thorpej return;
283 1.144 briggs
284 1.137 bouyer /* issue an identify, to try to detect ghosts */
285 1.137 bouyer error = ata_get_params(&chp->ch_drive[i],
286 1.137 bouyer AT_WAIT | AT_POLL, ¶ms);
287 1.137 bouyer if (error != CMD_OK) {
288 1.164 thorpej tsleep(¶ms, PRIBIO, "atacnf", mstohz(1000));
289 1.144 briggs
290 1.144 briggs /* Shortcut in case we've been shutdown */
291 1.144 briggs if (chp->ch_flags & WDCF_SHUTDOWN)
292 1.164 thorpej return;
293 1.144 briggs
294 1.137 bouyer error = ata_get_params(&chp->ch_drive[i],
295 1.137 bouyer AT_WAIT | AT_POLL, ¶ms);
296 1.137 bouyer }
297 1.137 bouyer if (error == CMD_OK) {
298 1.152 wiz /* If IDENTIFY succeeded, this is not an OLD ctrl */
299 1.137 bouyer chp->ch_drive[0].drive_flags &= ~DRIVE_OLD;
300 1.137 bouyer chp->ch_drive[1].drive_flags &= ~DRIVE_OLD;
301 1.137 bouyer } else {
302 1.155 bouyer chp->ch_drive[i].drive_flags &=
303 1.137 bouyer ~(DRIVE_ATA | DRIVE_ATAPI);
304 1.137 bouyer WDCDEBUG_PRINT(("%s:%d:%d: IDENTIFY failed (%d)\n",
305 1.169 thorpej wdc->sc_dev.dv_xname,
306 1.169 thorpej chp->ch_channel, i, error), DEBUG_PROBE);
307 1.137 bouyer if ((chp->ch_drive[i].drive_flags & DRIVE_OLD) == 0)
308 1.137 bouyer continue;
309 1.137 bouyer /*
310 1.137 bouyer * Pre-ATA drive ?
311 1.137 bouyer * Test registers writability (Error register not
312 1.137 bouyer * writable, but cyllo is), then try an ATA command.
313 1.137 bouyer */
314 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_SELECT)
315 1.169 thorpej wdc->select(chp,i);
316 1.157 fvdl bus_space_write_1(chp->cmd_iot,
317 1.157 fvdl chp->cmd_iohs[wd_sdh], 0, WDSD_IBM | (i << 4));
318 1.137 bouyer delay(10); /* 400ns delay */
319 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_error],
320 1.157 fvdl 0, 0x58);
321 1.157 fvdl bus_space_write_1(chp->cmd_iot,
322 1.157 fvdl chp->cmd_iohs[wd_cyl_lo], 0, 0xa5);
323 1.157 fvdl if (bus_space_read_1(chp->cmd_iot,
324 1.157 fvdl chp->cmd_iohs[wd_error], 0) == 0x58 ||
325 1.157 fvdl bus_space_read_1(chp->cmd_iot,
326 1.157 fvdl chp->cmd_iohs[wd_cyl_lo], 0) != 0xa5) {
327 1.137 bouyer WDCDEBUG_PRINT(("%s:%d:%d: register "
328 1.137 bouyer "writability failed\n",
329 1.169 thorpej wdc->sc_dev.dv_xname,
330 1.169 thorpej chp->ch_channel, i), DEBUG_PROBE);
331 1.137 bouyer chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
332 1.155 bouyer continue;
333 1.137 bouyer }
334 1.166 thorpej if (wdc_wait_for_ready(chp, 10000, 0) == WDCWAIT_TOUT) {
335 1.137 bouyer WDCDEBUG_PRINT(("%s:%d:%d: not ready\n",
336 1.169 thorpej wdc->sc_dev.dv_xname,
337 1.169 thorpej chp->ch_channel, i), DEBUG_PROBE);
338 1.137 bouyer chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
339 1.137 bouyer continue;
340 1.137 bouyer }
341 1.157 fvdl bus_space_write_1(chp->cmd_iot,
342 1.157 fvdl chp->cmd_iohs[wd_command], 0, WDCC_RECAL);
343 1.137 bouyer delay(10); /* 400ns delay */
344 1.166 thorpej if (wdc_wait_for_ready(chp, 10000, 0) == WDCWAIT_TOUT) {
345 1.137 bouyer WDCDEBUG_PRINT(("%s:%d:%d: WDCC_RECAL failed\n",
346 1.169 thorpej wdc->sc_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.155 bouyer } else {
350 1.155 bouyer chp->ch_drive[0].drive_flags &=
351 1.155 bouyer ~(DRIVE_ATA | DRIVE_ATAPI);
352 1.155 bouyer chp->ch_drive[1].drive_flags &=
353 1.155 bouyer ~(DRIVE_ATA | DRIVE_ATAPI);
354 1.137 bouyer }
355 1.137 bouyer }
356 1.137 bouyer }
357 1.164 thorpej }
358 1.164 thorpej
359 1.164 thorpej void
360 1.164 thorpej atabusconfig(struct atabus_softc *atabus_sc)
361 1.164 thorpej {
362 1.168 thorpej struct wdc_channel *chp = atabus_sc->sc_chan;
363 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
364 1.189 mycroft int i;
365 1.164 thorpej struct atabus_initq *atabus_initq = NULL;
366 1.164 thorpej
367 1.164 thorpej /* Probe for the drives. */
368 1.169 thorpej (*wdc->drv_probe)(chp);
369 1.137 bouyer
370 1.137 bouyer WDCDEBUG_PRINT(("atabusattach: ch_drive_flags 0x%x 0x%x\n",
371 1.137 bouyer chp->ch_drive[0].drive_flags, chp->ch_drive[1].drive_flags),
372 1.137 bouyer DEBUG_PROBE);
373 1.137 bouyer
374 1.137 bouyer /* If no drives, abort here */
375 1.137 bouyer if ((chp->ch_drive[0].drive_flags & DRIVE) == 0 &&
376 1.137 bouyer (chp->ch_drive[1].drive_flags & DRIVE) == 0)
377 1.137 bouyer goto out;
378 1.137 bouyer
379 1.164 thorpej /* Shortcut in case we've been shutdown */
380 1.164 thorpej if (chp->ch_flags & WDCF_SHUTDOWN)
381 1.164 thorpej goto out;
382 1.164 thorpej
383 1.137 bouyer /* Make sure the devices probe in atabus order to avoid jitter. */
384 1.137 bouyer simple_lock(&atabus_interlock);
385 1.137 bouyer while(1) {
386 1.137 bouyer atabus_initq = TAILQ_FIRST(&atabus_initq_head);
387 1.137 bouyer if (atabus_initq->atabus_sc == atabus_sc)
388 1.137 bouyer break;
389 1.137 bouyer ltsleep(&atabus_initq_head, PRIBIO, "ata_initq", 0,
390 1.137 bouyer &atabus_interlock);
391 1.137 bouyer }
392 1.137 bouyer simple_unlock(&atabus_interlock);
393 1.137 bouyer
394 1.137 bouyer /*
395 1.137 bouyer * Attach an ATAPI bus, if needed.
396 1.137 bouyer */
397 1.137 bouyer if ((chp->ch_drive[0].drive_flags & DRIVE_ATAPI) ||
398 1.137 bouyer (chp->ch_drive[1].drive_flags & DRIVE_ATAPI)) {
399 1.137 bouyer #if NATAPIBUS > 0
400 1.137 bouyer wdc_atapibus_attach(atabus_sc);
401 1.137 bouyer #else
402 1.137 bouyer /*
403 1.137 bouyer * Fake the autoconfig "not configured" message
404 1.137 bouyer */
405 1.137 bouyer aprint_normal("atapibus at %s not configured\n",
406 1.169 thorpej wdc->sc_dev.dv_xname);
407 1.137 bouyer chp->atapibus = NULL;
408 1.141 bouyer chp->ch_drive[0].drive_flags &= ~DRIVE_ATAPI;
409 1.141 bouyer chp->ch_drive[1].drive_flags &= ~DRIVE_ATAPI;
410 1.137 bouyer #endif
411 1.137 bouyer }
412 1.137 bouyer
413 1.137 bouyer for (i = 0; i < 2; i++) {
414 1.137 bouyer struct ata_device adev;
415 1.137 bouyer if ((chp->ch_drive[i].drive_flags &
416 1.137 bouyer (DRIVE_ATA | DRIVE_OLD)) == 0) {
417 1.137 bouyer continue;
418 1.137 bouyer }
419 1.137 bouyer memset(&adev, 0, sizeof(struct ata_device));
420 1.137 bouyer adev.adev_bustype = &wdc_ata_bustype;
421 1.169 thorpej adev.adev_channel = chp->ch_channel;
422 1.137 bouyer adev.adev_openings = 1;
423 1.137 bouyer adev.adev_drv_data = &chp->ch_drive[i];
424 1.137 bouyer chp->ata_drives[i] = config_found(&atabus_sc->sc_dev,
425 1.162 thorpej &adev, ataprint);
426 1.141 bouyer if (chp->ata_drives[i] != NULL)
427 1.137 bouyer wdc_probe_caps(&chp->ch_drive[i]);
428 1.141 bouyer else
429 1.141 bouyer chp->ch_drive[i].drive_flags &=
430 1.141 bouyer ~(DRIVE_ATA | DRIVE_OLD);
431 1.137 bouyer }
432 1.137 bouyer
433 1.137 bouyer /* now that we know the drives, the controller can set its modes */
434 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_MODE) {
435 1.169 thorpej wdc->set_modes(chp);
436 1.137 bouyer wdc_print_modes(chp);
437 1.137 bouyer }
438 1.137 bouyer #if NATARAID > 0
439 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_RAID)
440 1.137 bouyer for (i = 0; i < 2; i++)
441 1.137 bouyer if (chp->ata_drives[i] != NULL)
442 1.137 bouyer ata_raid_check_component(chp->ata_drives[i]);
443 1.137 bouyer #endif /* NATARAID > 0 */
444 1.137 bouyer
445 1.137 bouyer /*
446 1.152 wiz * reset drive_flags for unattached devices, reset state for attached
447 1.137 bouyer * ones
448 1.137 bouyer */
449 1.137 bouyer for (i = 0; i < 2; i++) {
450 1.137 bouyer if (chp->ch_drive[i].drv_softc == NULL)
451 1.137 bouyer chp->ch_drive[i].drive_flags = 0;
452 1.137 bouyer else
453 1.137 bouyer chp->ch_drive[i].state = 0;
454 1.137 bouyer }
455 1.137 bouyer
456 1.163 thorpej out:
457 1.137 bouyer if (atabus_initq == NULL) {
458 1.137 bouyer simple_lock(&atabus_interlock);
459 1.137 bouyer while(1) {
460 1.137 bouyer atabus_initq = TAILQ_FIRST(&atabus_initq_head);
461 1.137 bouyer if (atabus_initq->atabus_sc == atabus_sc)
462 1.137 bouyer break;
463 1.137 bouyer ltsleep(&atabus_initq_head, PRIBIO, "ata_initq", 0,
464 1.137 bouyer &atabus_interlock);
465 1.137 bouyer }
466 1.137 bouyer simple_unlock(&atabus_interlock);
467 1.137 bouyer }
468 1.137 bouyer simple_lock(&atabus_interlock);
469 1.137 bouyer TAILQ_REMOVE(&atabus_initq_head, atabus_initq, atabus_initq);
470 1.137 bouyer simple_unlock(&atabus_interlock);
471 1.137 bouyer
472 1.137 bouyer free(atabus_initq, M_DEVBUF);
473 1.137 bouyer wakeup(&atabus_initq_head);
474 1.137 bouyer
475 1.137 bouyer config_pending_decr();
476 1.189 mycroft
477 1.189 mycroft wdc_delref(chp);
478 1.137 bouyer }
479 1.137 bouyer
480 1.2 bouyer int
481 1.168 thorpej wdcprobe(struct wdc_channel *chp)
482 1.12 cgd {
483 1.163 thorpej
484 1.163 thorpej return (wdcprobe1(chp, 1));
485 1.137 bouyer }
486 1.137 bouyer
487 1.167 thorpej static int
488 1.168 thorpej wdcprobe1(struct wdc_channel *chp, int poll)
489 1.137 bouyer {
490 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
491 1.31 bouyer u_int8_t st0, st1, sc, sn, cl, ch;
492 1.31 bouyer u_int8_t ret_value = 0x03;
493 1.31 bouyer u_int8_t drive;
494 1.156 bouyer int s;
495 1.31 bouyer
496 1.31 bouyer /*
497 1.31 bouyer * Sanity check to see if the wdc channel responds at all.
498 1.31 bouyer */
499 1.31 bouyer
500 1.174 bouyer s = splbio();
501 1.169 thorpej if (wdc == NULL ||
502 1.169 thorpej (wdc->cap & WDC_CAPABILITY_NO_EXTRA_RESETS) == 0) {
503 1.107 dbj
504 1.169 thorpej if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
505 1.169 thorpej wdc->select(chp,0);
506 1.137 bouyer
507 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
508 1.43 kenh WDSD_IBM);
509 1.131 mycroft delay(10); /* 400ns delay */
510 1.157 fvdl st0 = bus_space_read_1(chp->cmd_iot,
511 1.157 fvdl chp->cmd_iohs[wd_status], 0);
512 1.107 dbj
513 1.169 thorpej if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
514 1.169 thorpej wdc->select(chp,1);
515 1.137 bouyer
516 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
517 1.43 kenh WDSD_IBM | 0x10);
518 1.131 mycroft delay(10); /* 400ns delay */
519 1.157 fvdl st1 = bus_space_read_1(chp->cmd_iot,
520 1.157 fvdl chp->cmd_iohs[wd_status], 0);
521 1.43 kenh
522 1.43 kenh WDCDEBUG_PRINT(("%s:%d: before reset, st0=0x%x, st1=0x%x\n",
523 1.169 thorpej wdc != NULL ? wdc->sc_dev.dv_xname : "wdcprobe",
524 1.169 thorpej chp->ch_channel, st0, st1), DEBUG_PROBE);
525 1.43 kenh
526 1.142 bouyer if (st0 == 0xff || st0 == WDSD_IBM)
527 1.43 kenh ret_value &= ~0x01;
528 1.142 bouyer if (st1 == 0xff || st1 == (WDSD_IBM | 0x10))
529 1.43 kenh ret_value &= ~0x02;
530 1.125 mycroft /* Register writability test, drive 0. */
531 1.125 mycroft if (ret_value & 0x01) {
532 1.169 thorpej if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
533 1.169 thorpej wdc->select(chp,0);
534 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
535 1.157 fvdl 0, WDSD_IBM);
536 1.157 fvdl bus_space_write_1(chp->cmd_iot,
537 1.157 fvdl chp->cmd_iohs[wd_cyl_lo], 0, 0x02);
538 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
539 1.174 bouyer chp->cmd_iohs[wd_cyl_lo], 0);
540 1.174 bouyer if (cl != 0x02) {
541 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 0 wd_cyl_lo: "
542 1.174 bouyer "got 0x%x != 0x02\n",
543 1.174 bouyer wdc != NULL ?
544 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
545 1.174 bouyer chp->ch_channel, cl),
546 1.174 bouyer DEBUG_PROBE);
547 1.125 mycroft ret_value &= ~0x01;
548 1.174 bouyer }
549 1.157 fvdl bus_space_write_1(chp->cmd_iot,
550 1.157 fvdl chp->cmd_iohs[wd_cyl_lo], 0, 0x01);
551 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
552 1.174 bouyer chp->cmd_iohs[wd_cyl_lo], 0);
553 1.174 bouyer if (cl != 0x01) {
554 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 0 wd_cyl_lo: "
555 1.174 bouyer "got 0x%x != 0x01\n",
556 1.174 bouyer wdc != NULL ?
557 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
558 1.174 bouyer chp->ch_channel, cl),
559 1.174 bouyer DEBUG_PROBE);
560 1.125 mycroft ret_value &= ~0x01;
561 1.174 bouyer }
562 1.167 thorpej bus_space_write_1(chp->cmd_iot,
563 1.167 thorpej chp->cmd_iohs[wd_sector], 0, 0x01);
564 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
565 1.174 bouyer chp->cmd_iohs[wd_sector], 0);
566 1.174 bouyer if (cl != 0x01) {
567 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 0 wd_sector: "
568 1.174 bouyer "got 0x%x != 0x01\n",
569 1.174 bouyer wdc != NULL ?
570 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
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.157 fvdl bus_space_write_1(chp->cmd_iot,
576 1.157 fvdl chp->cmd_iohs[wd_sector], 0, 0x02);
577 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
578 1.174 bouyer chp->cmd_iohs[wd_sector], 0);
579 1.174 bouyer if (cl != 0x02) {
580 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 0 wd_sector: "
581 1.174 bouyer "got 0x%x != 0x02\n",
582 1.174 bouyer wdc != NULL ?
583 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
584 1.174 bouyer chp->ch_channel, cl),
585 1.174 bouyer DEBUG_PROBE);
586 1.125 mycroft ret_value &= ~0x01;
587 1.174 bouyer }
588 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
589 1.174 bouyer chp->cmd_iohs[wd_cyl_lo], 0);
590 1.174 bouyer if (cl != 0x01) {
591 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 0 wd_cyl_lo(2): "
592 1.174 bouyer "got 0x%x != 0x01\n",
593 1.174 bouyer wdc != NULL ?
594 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
595 1.174 bouyer chp->ch_channel, cl),
596 1.174 bouyer DEBUG_PROBE);
597 1.131 mycroft ret_value &= ~0x01;
598 1.174 bouyer }
599 1.125 mycroft }
600 1.125 mycroft /* Register writability test, drive 1. */
601 1.125 mycroft if (ret_value & 0x02) {
602 1.169 thorpej if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
603 1.169 thorpej wdc->select(chp,1);
604 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
605 1.157 fvdl 0, WDSD_IBM | 0x10);
606 1.167 thorpej bus_space_write_1(chp->cmd_iot,
607 1.167 thorpej chp->cmd_iohs[wd_cyl_lo], 0, 0x02);
608 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
609 1.174 bouyer chp->cmd_iohs[wd_cyl_lo], 0);
610 1.174 bouyer if (cl != 0x02) {
611 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 1 wd_cyl_lo: "
612 1.174 bouyer "got 0x%x != 0x02\n",
613 1.174 bouyer wdc != NULL ?
614 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
615 1.174 bouyer chp->ch_channel, cl),
616 1.174 bouyer DEBUG_PROBE);
617 1.125 mycroft ret_value &= ~0x02;
618 1.174 bouyer }
619 1.157 fvdl bus_space_write_1(chp->cmd_iot,
620 1.157 fvdl chp->cmd_iohs[wd_cyl_lo], 0, 0x01);
621 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
622 1.174 bouyer chp->cmd_iohs[wd_cyl_lo], 0);
623 1.174 bouyer if (cl != 0x01) {
624 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 1 wd_cyl_lo: "
625 1.174 bouyer "got 0x%x != 0x01\n",
626 1.174 bouyer wdc != NULL ?
627 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
628 1.174 bouyer chp->ch_channel, cl),
629 1.174 bouyer DEBUG_PROBE);
630 1.125 mycroft ret_value &= ~0x02;
631 1.174 bouyer }
632 1.157 fvdl bus_space_write_1(chp->cmd_iot,
633 1.157 fvdl chp->cmd_iohs[wd_sector], 0, 0x01);
634 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
635 1.174 bouyer chp->cmd_iohs[wd_sector], 0);
636 1.174 bouyer if (cl != 0x01) {
637 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 1 wd_sector: "
638 1.174 bouyer "got 0x%x != 0x01\n",
639 1.174 bouyer wdc != NULL ?
640 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
641 1.174 bouyer chp->ch_channel, cl),
642 1.174 bouyer DEBUG_PROBE);
643 1.125 mycroft ret_value &= ~0x02;
644 1.174 bouyer }
645 1.167 thorpej bus_space_write_1(chp->cmd_iot,
646 1.167 thorpej chp->cmd_iohs[wd_sector], 0, 0x02);
647 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
648 1.174 bouyer chp->cmd_iohs[wd_sector], 0);
649 1.174 bouyer if (cl != 0x02) {
650 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 1 wd_sector: "
651 1.174 bouyer "got 0x%x != 0x02\n",
652 1.174 bouyer wdc != NULL ?
653 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
654 1.174 bouyer chp->ch_channel, cl),
655 1.174 bouyer DEBUG_PROBE);
656 1.125 mycroft ret_value &= ~0x02;
657 1.174 bouyer }
658 1.174 bouyer cl = bus_space_read_1(chp->cmd_iot,
659 1.174 bouyer chp->cmd_iohs[wd_cyl_lo], 0);
660 1.174 bouyer if (cl != 0x01) {
661 1.174 bouyer WDCDEBUG_PRINT(("%s:%d drive 1 wd_cyl_lo(2): "
662 1.174 bouyer "got 0x%x != 0x01\n",
663 1.174 bouyer wdc != NULL ?
664 1.174 bouyer wdc->sc_dev.dv_xname : "wdcprobe",
665 1.174 bouyer chp->ch_channel, cl),
666 1.174 bouyer DEBUG_PROBE);
667 1.131 mycroft ret_value &= ~0x02;
668 1.174 bouyer }
669 1.125 mycroft }
670 1.137 bouyer
671 1.174 bouyer if (ret_value == 0) {
672 1.174 bouyer splx(s);
673 1.137 bouyer return 0;
674 1.174 bouyer }
675 1.62 bouyer }
676 1.31 bouyer
677 1.174 bouyer
678 1.181 bouyer #if 0 /* XXX this break some ATA or ATAPI devices */
679 1.174 bouyer /*
680 1.174 bouyer * reset bus. Also send an ATAPI_RESET to devices, in case there are
681 1.174 bouyer * ATAPI device out there which don't react to the bus reset
682 1.174 bouyer */
683 1.174 bouyer if (ret_value & 0x01) {
684 1.174 bouyer if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
685 1.174 bouyer wdc->select(chp,0);
686 1.174 bouyer bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
687 1.174 bouyer 0, WDSD_IBM);
688 1.174 bouyer bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_command], 0,
689 1.174 bouyer ATAPI_SOFT_RESET);
690 1.174 bouyer }
691 1.174 bouyer if (ret_value & 0x02) {
692 1.174 bouyer if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
693 1.174 bouyer wdc->select(chp,0);
694 1.174 bouyer bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
695 1.174 bouyer 0, WDSD_IBM | 0x10);
696 1.174 bouyer bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_command], 0,
697 1.174 bouyer ATAPI_SOFT_RESET);
698 1.174 bouyer }
699 1.156 bouyer
700 1.175 bouyer delay(5000);
701 1.181 bouyer #endif
702 1.175 bouyer
703 1.169 thorpej if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
704 1.169 thorpej wdc->select(chp,0);
705 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0, WDSD_IBM);
706 1.137 bouyer delay(10); /* 400ns delay */
707 1.174 bouyer /* assert SRST, wait for reset to complete */
708 1.137 bouyer bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
709 1.137 bouyer WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);
710 1.172 bouyer DELAY(1000);
711 1.172 bouyer bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
712 1.172 bouyer WDCTL_IDS | WDCTL_4BIT);
713 1.137 bouyer DELAY(2000);
714 1.157 fvdl (void) bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_error], 0);
715 1.137 bouyer bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
716 1.137 bouyer delay(10); /* 400ns delay */
717 1.156 bouyer /* ACK interrupt in case there is one pending left (Promise ATA100) */
718 1.169 thorpej if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_IRQACK))
719 1.169 thorpej wdc->irqack(chp);
720 1.156 bouyer splx(s);
721 1.137 bouyer
722 1.137 bouyer ret_value = __wdcwait_reset(chp, ret_value, poll);
723 1.137 bouyer WDCDEBUG_PRINT(("%s:%d: after reset, ret_value=0x%d\n",
724 1.169 thorpej wdc != NULL ? wdc->sc_dev.dv_xname : "wdcprobe", chp->ch_channel,
725 1.137 bouyer ret_value), DEBUG_PROBE);
726 1.12 cgd
727 1.137 bouyer /* if reset failed, there's nothing here */
728 1.137 bouyer if (ret_value == 0)
729 1.137 bouyer return 0;
730 1.67 bouyer
731 1.12 cgd /*
732 1.167 thorpej * Test presence of drives. First test register signatures looking
733 1.167 thorpej * for ATAPI devices. If it's not an ATAPI and reset said there may
734 1.167 thorpej * be something here assume it's ATA or OLD. Ghost will be killed
735 1.167 thorpej * later in attach routine.
736 1.12 cgd */
737 1.137 bouyer for (drive = 0; drive < 2; drive++) {
738 1.137 bouyer if ((ret_value & (0x01 << drive)) == 0)
739 1.137 bouyer continue;
740 1.169 thorpej if (wdc != NULL && wdc->cap & WDC_CAPABILITY_SELECT)
741 1.169 thorpej wdc->select(chp,drive);
742 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
743 1.137 bouyer WDSD_IBM | (drive << 4));
744 1.137 bouyer delay(10); /* 400ns delay */
745 1.137 bouyer /* Save registers contents */
746 1.157 fvdl sc = bus_space_read_1(chp->cmd_iot,
747 1.157 fvdl chp->cmd_iohs[wd_seccnt], 0);
748 1.157 fvdl sn = bus_space_read_1(chp->cmd_iot,
749 1.157 fvdl chp->cmd_iohs[wd_sector], 0);
750 1.157 fvdl cl = bus_space_read_1(chp->cmd_iot,
751 1.157 fvdl chp->cmd_iohs[wd_cyl_lo], 0);
752 1.157 fvdl ch = bus_space_read_1(chp->cmd_iot,
753 1.157 fvdl chp->cmd_iohs[wd_cyl_hi], 0);
754 1.137 bouyer
755 1.137 bouyer WDCDEBUG_PRINT(("%s:%d:%d: after reset, sc=0x%x sn=0x%x "
756 1.137 bouyer "cl=0x%x ch=0x%x\n",
757 1.169 thorpej wdc != NULL ? wdc->sc_dev.dv_xname : "wdcprobe",
758 1.169 thorpej chp->ch_channel, drive, sc, sn, cl, ch), DEBUG_PROBE);
759 1.31 bouyer /*
760 1.137 bouyer * sc & sn are supposted to be 0x1 for ATAPI but in some cases
761 1.137 bouyer * we get wrong values here, so ignore it.
762 1.31 bouyer */
763 1.137 bouyer if (cl == 0x14 && ch == 0xeb) {
764 1.137 bouyer chp->ch_drive[drive].drive_flags |= DRIVE_ATAPI;
765 1.137 bouyer } else {
766 1.137 bouyer chp->ch_drive[drive].drive_flags |= DRIVE_ATA;
767 1.169 thorpej if (wdc == NULL ||
768 1.169 thorpej (wdc->cap & WDC_CAPABILITY_PREATA) != 0)
769 1.137 bouyer chp->ch_drive[drive].drive_flags |= DRIVE_OLD;
770 1.137 bouyer }
771 1.31 bouyer }
772 1.137 bouyer return (ret_value);
773 1.137 bouyer }
774 1.31 bouyer
775 1.137 bouyer void
776 1.168 thorpej wdcattach(struct wdc_channel *chp)
777 1.137 bouyer {
778 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
779 1.137 bouyer static int inited = 0;
780 1.32 bouyer
781 1.137 bouyer if (chp->ch_flags & WDCF_DISABLED)
782 1.137 bouyer return;
783 1.74 enami
784 1.137 bouyer /* initialise global data */
785 1.137 bouyer callout_init(&chp->ch_callout);
786 1.169 thorpej if (wdc->drv_probe == NULL)
787 1.169 thorpej wdc->drv_probe = wdc_drvprobe;
788 1.137 bouyer if (inited == 0) {
789 1.165 thorpej /* Initialize the ata_xfer pool. */
790 1.165 thorpej pool_init(&wdc_xfer_pool, sizeof(struct ata_xfer), 0,
791 1.137 bouyer 0, 0, "wdcspl", NULL);
792 1.137 bouyer inited++;
793 1.133 bouyer }
794 1.165 thorpej TAILQ_INIT(&chp->ch_queue->queue_xfer);
795 1.148 bouyer chp->ch_queue->queue_freeze = 0;
796 1.186 bouyer chp->ch_queue->active_xfer = NULL;
797 1.126 enami
798 1.169 thorpej chp->atabus = config_found(&wdc->sc_dev, chp, atabusprint);
799 1.74 enami }
800 1.74 enami
801 1.163 thorpej int
802 1.163 thorpej wdcactivate(struct device *self, enum devact act)
803 1.137 bouyer {
804 1.137 bouyer struct wdc_softc *wdc = (struct wdc_softc *)self;
805 1.137 bouyer int s, i, error = 0;
806 1.137 bouyer
807 1.137 bouyer s = splbio();
808 1.137 bouyer switch (act) {
809 1.137 bouyer case DVACT_ACTIVATE:
810 1.137 bouyer error = EOPNOTSUPP;
811 1.137 bouyer break;
812 1.137 bouyer
813 1.137 bouyer case DVACT_DEACTIVATE:
814 1.137 bouyer for (i = 0; i < wdc->nchannels; i++) {
815 1.137 bouyer error = config_deactivate(wdc->channels[i]->atabus);
816 1.137 bouyer if (error)
817 1.137 bouyer break;
818 1.137 bouyer }
819 1.137 bouyer break;
820 1.137 bouyer }
821 1.137 bouyer splx(s);
822 1.137 bouyer return (error);
823 1.137 bouyer }
824 1.137 bouyer
825 1.137 bouyer int
826 1.163 thorpej wdcdetach(struct device *self, int flags)
827 1.137 bouyer {
828 1.137 bouyer struct wdc_softc *wdc = (struct wdc_softc *)self;
829 1.168 thorpej struct wdc_channel *chp;
830 1.188 mycroft struct scsipi_adapter *adapt = &wdc->sc_atapi_adapter._generic;
831 1.137 bouyer int i, error = 0;
832 1.137 bouyer
833 1.137 bouyer for (i = 0; i < wdc->nchannels; i++) {
834 1.137 bouyer chp = wdc->channels[i];
835 1.137 bouyer WDCDEBUG_PRINT(("wdcdetach: %s: detaching %s\n",
836 1.137 bouyer wdc->sc_dev.dv_xname, chp->atabus->dv_xname), DEBUG_DETACH);
837 1.137 bouyer error = config_detach(chp->atabus, flags);
838 1.137 bouyer if (error)
839 1.137 bouyer break;
840 1.137 bouyer }
841 1.188 mycroft if (adapt->adapt_refcnt != 0) {
842 1.188 mycroft #ifdef DIAGNOSTIC
843 1.188 mycroft printf("wdcdetach: refcnt should be 0 here??\n");
844 1.188 mycroft #endif
845 1.188 mycroft (void) (*adapt->adapt_enable)(&wdc->sc_dev, 0);
846 1.188 mycroft }
847 1.137 bouyer return (error);
848 1.137 bouyer }
849 1.137 bouyer
850 1.31 bouyer /*
851 1.31 bouyer * Start I/O on a controller, for the given channel.
852 1.31 bouyer * The first xfer may be not for our channel if the channel queues
853 1.31 bouyer * are shared.
854 1.31 bouyer */
855 1.31 bouyer void
856 1.168 thorpej wdcstart(struct wdc_channel *chp)
857 1.31 bouyer {
858 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
859 1.165 thorpej struct ata_xfer *xfer;
860 1.38 bouyer
861 1.38 bouyer #ifdef WDC_DIAGNOSTIC
862 1.38 bouyer int spl1, spl2;
863 1.38 bouyer
864 1.38 bouyer spl1 = splbio();
865 1.38 bouyer spl2 = splbio();
866 1.38 bouyer if (spl2 != spl1) {
867 1.38 bouyer printf("wdcstart: not at splbio()\n");
868 1.38 bouyer panic("wdcstart");
869 1.38 bouyer }
870 1.38 bouyer splx(spl2);
871 1.38 bouyer splx(spl1);
872 1.38 bouyer #endif /* WDC_DIAGNOSTIC */
873 1.12 cgd
874 1.31 bouyer /* is there a xfer ? */
875 1.165 thorpej if ((xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer)) == NULL)
876 1.31 bouyer return;
877 1.47 bouyer
878 1.47 bouyer /* adjust chp, in case we have a shared queue */
879 1.165 thorpej chp = xfer->c_chp;
880 1.47 bouyer
881 1.186 bouyer if (chp->ch_queue->active_xfer != NULL) {
882 1.31 bouyer return; /* channel aleady active */
883 1.31 bouyer }
884 1.148 bouyer if (__predict_false(chp->ch_queue->queue_freeze > 0)) {
885 1.147 bouyer return; /* queue froozen */
886 1.137 bouyer }
887 1.31 bouyer #ifdef DIAGNOSTIC
888 1.31 bouyer if ((chp->ch_flags & WDCF_IRQ_WAIT) != 0)
889 1.118 provos panic("wdcstart: channel waiting for irq");
890 1.31 bouyer #endif
891 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_HWLOCK)
892 1.169 thorpej if (!(*wdc->claim_hw)(chp, 0))
893 1.31 bouyer return;
894 1.12 cgd
895 1.31 bouyer WDCDEBUG_PRINT(("wdcstart: xfer %p channel %d drive %d\n", xfer,
896 1.169 thorpej chp->ch_channel, xfer->c_drive), DEBUG_XFERS);
897 1.165 thorpej if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_RESET) {
898 1.165 thorpej chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_RESET;
899 1.165 thorpej chp->ch_drive[xfer->c_drive].state = 0;
900 1.37 bouyer }
901 1.186 bouyer chp->ch_queue->active_xfer = xfer;
902 1.186 bouyer TAILQ_REMOVE(&chp->ch_queue->queue_xfer, xfer, c_xferchain);
903 1.186 bouyer
904 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_NOIRQ)
905 1.98 bjh21 KASSERT(xfer->c_flags & C_POLL);
906 1.31 bouyer xfer->c_start(chp, xfer);
907 1.31 bouyer }
908 1.2 bouyer
909 1.31 bouyer /* restart an interrupted I/O */
910 1.31 bouyer void
911 1.163 thorpej wdcrestart(void *v)
912 1.31 bouyer {
913 1.168 thorpej struct wdc_channel *chp = v;
914 1.31 bouyer int s;
915 1.2 bouyer
916 1.31 bouyer s = splbio();
917 1.45 drochner wdcstart(chp);
918 1.31 bouyer splx(s);
919 1.2 bouyer }
920 1.31 bouyer
921 1.2 bouyer
922 1.31 bouyer /*
923 1.31 bouyer * Interrupt routine for the controller. Acknowledge the interrupt, check for
924 1.31 bouyer * errors on the current operation, mark it done if necessary, and start the
925 1.31 bouyer * next request. Also check for a partially done transfer, and continue with
926 1.31 bouyer * the next chunk if so.
927 1.31 bouyer */
928 1.12 cgd int
929 1.163 thorpej wdcintr(void *arg)
930 1.12 cgd {
931 1.168 thorpej struct wdc_channel *chp = arg;
932 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
933 1.165 thorpej struct ata_xfer *xfer;
934 1.76 bouyer int ret;
935 1.12 cgd
936 1.169 thorpej if ((wdc->sc_dev.dv_flags & DVF_ACTIVE) == 0) {
937 1.80 enami WDCDEBUG_PRINT(("wdcintr: deactivated controller\n"),
938 1.80 enami DEBUG_INTR);
939 1.80 enami return (0);
940 1.80 enami }
941 1.31 bouyer if ((chp->ch_flags & WDCF_IRQ_WAIT) == 0) {
942 1.31 bouyer WDCDEBUG_PRINT(("wdcintr: inactive controller\n"), DEBUG_INTR);
943 1.113 bouyer /* try to clear the pending interrupt anyway */
944 1.157 fvdl (void)bus_space_read_1(chp->cmd_iot,
945 1.157 fvdl chp->cmd_iohs[wd_status], 0);
946 1.80 enami return (0);
947 1.31 bouyer }
948 1.12 cgd
949 1.31 bouyer WDCDEBUG_PRINT(("wdcintr\n"), DEBUG_INTR);
950 1.186 bouyer xfer = chp->ch_queue->active_xfer;
951 1.186 bouyer #ifdef DIAGNOSTIC
952 1.186 bouyer if (xfer == NULL)
953 1.186 bouyer panic("wdcintr: no xfer");
954 1.186 bouyer #endif
955 1.84 bouyer if (chp->ch_flags & WDCF_DMA_WAIT) {
956 1.169 thorpej wdc->dma_status =
957 1.169 thorpej (*wdc->dma_finish)(wdc->dma_arg, chp->ch_channel,
958 1.185 bouyer xfer->c_drive, WDC_DMAEND_END);
959 1.169 thorpej if (wdc->dma_status & WDC_DMAST_NOIRQ) {
960 1.84 bouyer /* IRQ not for us, not detected by DMA engine */
961 1.84 bouyer return 0;
962 1.84 bouyer }
963 1.84 bouyer chp->ch_flags &= ~WDCF_DMA_WAIT;
964 1.84 bouyer }
965 1.31 bouyer chp->ch_flags &= ~WDCF_IRQ_WAIT;
966 1.76 bouyer ret = xfer->c_intr(chp, xfer, 1);
967 1.76 bouyer if (ret == 0) /* irq was not for us, still waiting for irq */
968 1.76 bouyer chp->ch_flags |= WDCF_IRQ_WAIT;
969 1.76 bouyer return (ret);
970 1.12 cgd }
971 1.12 cgd
972 1.31 bouyer /* Put all disk in RESET state */
973 1.125 mycroft void
974 1.183 bouyer wdc_reset_drive(struct ata_drive_datas *drvp, int flags)
975 1.2 bouyer {
976 1.168 thorpej struct wdc_channel *chp = drvp->chnl_softc;
977 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
978 1.34 bouyer WDCDEBUG_PRINT(("ata_reset_channel %s:%d for drive %d\n",
979 1.169 thorpej wdc->sc_dev.dv_xname, chp->ch_channel, drvp->drive),
980 1.34 bouyer DEBUG_FUNCS);
981 1.182 bouyer
982 1.182 bouyer
983 1.183 bouyer wdc_reset_channel(chp, flags);
984 1.182 bouyer }
985 1.182 bouyer
986 1.183 bouyer void
987 1.183 bouyer wdc_reset_channel(struct wdc_channel *chp, int flags)
988 1.182 bouyer {
989 1.186 bouyer TAILQ_HEAD(, ata_xfer) reset_xfer;
990 1.183 bouyer struct ata_xfer *xfer, *next_xfer;
991 1.182 bouyer int drive;
992 1.182 bouyer
993 1.184 bouyer chp->ch_queue->queue_freeze++;
994 1.186 bouyer TAILQ_INIT(&reset_xfer);
995 1.184 bouyer
996 1.184 bouyer /* if we can poll or wait it's OK, otherwise wake up the kernel
997 1.184 bouyer * thread
998 1.184 bouyer */
999 1.184 bouyer if ((flags & (AT_POLL | AT_WAIT)) == 0) {
1000 1.184 bouyer if (chp->ch_flags & WDCF_TH_RESET) {
1001 1.184 bouyer /* no need to schedule a reset more than one time */
1002 1.184 bouyer return;
1003 1.184 bouyer }
1004 1.184 bouyer chp->ch_flags |= WDCF_TH_RESET;
1005 1.184 bouyer chp->ch_reset_flags = flags & (AT_RST_EMERG | AT_RST_NOCMD);
1006 1.184 bouyer wakeup(&chp->ch_thread);
1007 1.184 bouyer return;
1008 1.184 bouyer }
1009 1.184 bouyer
1010 1.186 bouyer chp->ch_flags &= ~WDCF_IRQ_WAIT;
1011 1.186 bouyer /*
1012 1.186 bouyer * if the current command if on an ATAPI device, issue a
1013 1.186 bouyer * ATAPI_SOFT_RESET
1014 1.186 bouyer */
1015 1.186 bouyer xfer = chp->ch_queue->active_xfer;
1016 1.186 bouyer if (xfer && xfer->c_chp == chp && (xfer->c_flags & C_ATAPI)) {
1017 1.186 bouyer wdccommandshort(chp, xfer->c_drive, ATAPI_SOFT_RESET);
1018 1.186 bouyer if (flags & AT_WAIT)
1019 1.186 bouyer tsleep(&flags, PRIBIO, "atardl", mstohz(1) + 1);
1020 1.186 bouyer else
1021 1.186 bouyer delay(1000);
1022 1.186 bouyer }
1023 1.186 bouyer
1024 1.184 bouyer /* reset the channel */
1025 1.186 bouyer if (flags & AT_WAIT)
1026 1.186 bouyer (void) wdcreset(chp, RESET_SLEEP);
1027 1.186 bouyer else
1028 1.184 bouyer (void) wdcreset(chp, RESET_POLL);
1029 1.184 bouyer
1030 1.184 bouyer /*
1031 1.186 bouyer * wait a bit after reset; in case the DMA engines needs some time
1032 1.184 bouyer * to recover.
1033 1.184 bouyer */
1034 1.184 bouyer if (flags & AT_WAIT)
1035 1.186 bouyer tsleep(&flags, PRIBIO, "atardl", mstohz(1) + 1);
1036 1.184 bouyer else
1037 1.184 bouyer delay(1000);
1038 1.182 bouyer /*
1039 1.182 bouyer * look for pending xfers. If we have a shared queue, we'll also reset
1040 1.182 bouyer * the other channel if the current xfer is running on it.
1041 1.184 bouyer * Then we'll dequeue only the xfers for this channel.
1042 1.182 bouyer */
1043 1.182 bouyer if ((flags & AT_RST_NOCMD) == 0) {
1044 1.186 bouyer /*
1045 1.186 bouyer * move all xfers queued for this channel to the reset queue,
1046 1.186 bouyer * and then process the current xfer and then the reset queue.
1047 1.186 bouyer * We have to use a temporary queue because c_kill_xfer()
1048 1.186 bouyer * may requeue commands.
1049 1.186 bouyer */
1050 1.186 bouyer for (xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer);
1051 1.186 bouyer xfer != NULL; xfer = next_xfer) {
1052 1.186 bouyer next_xfer = TAILQ_NEXT(xfer, c_xferchain);
1053 1.186 bouyer if (xfer->c_chp != chp)
1054 1.186 bouyer continue;
1055 1.186 bouyer TAILQ_REMOVE(&chp->ch_queue->queue_xfer,
1056 1.186 bouyer xfer, c_xferchain);
1057 1.186 bouyer TAILQ_INSERT_TAIL(&reset_xfer, xfer, c_xferchain);
1058 1.186 bouyer }
1059 1.186 bouyer xfer = chp->ch_queue->active_xfer;
1060 1.184 bouyer if (xfer) {
1061 1.184 bouyer if (xfer->c_chp != chp)
1062 1.184 bouyer wdc_reset_channel(xfer->c_chp, flags);
1063 1.184 bouyer else {
1064 1.186 bouyer callout_stop(&chp->ch_callout);
1065 1.184 bouyer /*
1066 1.184 bouyer * If we're waiting for DMA, stop the
1067 1.184 bouyer * DMA engine
1068 1.184 bouyer */
1069 1.184 bouyer if (chp->ch_flags & WDCF_DMA_WAIT) {
1070 1.184 bouyer (*chp->ch_wdc->dma_finish)(
1071 1.184 bouyer chp->ch_wdc->dma_arg,
1072 1.184 bouyer chp->ch_channel,
1073 1.184 bouyer xfer->c_drive,
1074 1.185 bouyer WDC_DMAEND_ABRT_QUIET);
1075 1.186 bouyer chp->ch_flags &= ~WDCF_DMA_WAIT;
1076 1.184 bouyer }
1077 1.186 bouyer chp->ch_queue->active_xfer = NULL;
1078 1.186 bouyer if ((flags & AT_RST_EMERG) == 0)
1079 1.186 bouyer xfer->c_kill_xfer(
1080 1.186 bouyer chp, xfer, KILL_RESET);
1081 1.184 bouyer }
1082 1.184 bouyer }
1083 1.186 bouyer
1084 1.186 bouyer for (xfer = TAILQ_FIRST(&reset_xfer);
1085 1.183 bouyer xfer != NULL; xfer = next_xfer) {
1086 1.183 bouyer next_xfer = TAILQ_NEXT(xfer, c_xferchain);
1087 1.186 bouyer TAILQ_REMOVE(&reset_xfer, xfer, c_xferchain);
1088 1.182 bouyer if ((flags & AT_RST_EMERG) == 0)
1089 1.182 bouyer xfer->c_kill_xfer(chp, xfer, KILL_RESET);
1090 1.182 bouyer }
1091 1.182 bouyer }
1092 1.31 bouyer for (drive = 0; drive < 2; drive++) {
1093 1.31 bouyer chp->ch_drive[drive].state = 0;
1094 1.12 cgd }
1095 1.184 bouyer chp->ch_flags &= ~WDCF_TH_RESET;
1096 1.182 bouyer if ((flags & AT_RST_EMERG) == 0) {
1097 1.182 bouyer chp->ch_queue->queue_freeze--;
1098 1.182 bouyer wdcstart(chp);
1099 1.182 bouyer } else {
1100 1.182 bouyer /* make sure that we can use polled commands */
1101 1.182 bouyer TAILQ_INIT(&chp->ch_queue->queue_xfer);
1102 1.182 bouyer chp->ch_queue->queue_freeze = 0;
1103 1.186 bouyer chp->ch_queue->active_xfer = NULL;
1104 1.182 bouyer }
1105 1.31 bouyer }
1106 1.12 cgd
1107 1.31 bouyer int
1108 1.168 thorpej wdcreset(struct wdc_channel *chp, int poll)
1109 1.31 bouyer {
1110 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1111 1.31 bouyer int drv_mask1, drv_mask2;
1112 1.156 bouyer int s = 0;
1113 1.2 bouyer
1114 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_SELECT)
1115 1.169 thorpej wdc->select(chp,0);
1116 1.156 bouyer if (poll != RESET_SLEEP)
1117 1.156 bouyer s = splbio();
1118 1.157 fvdl /* master */
1119 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0, WDSD_IBM);
1120 1.131 mycroft delay(10); /* 400ns delay */
1121 1.31 bouyer bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
1122 1.131 mycroft WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);
1123 1.131 mycroft delay(2000);
1124 1.157 fvdl (void) bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_error], 0);
1125 1.137 bouyer bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
1126 1.137 bouyer WDCTL_4BIT | WDCTL_IDS);
1127 1.131 mycroft delay(10); /* 400ns delay */
1128 1.156 bouyer if (poll != RESET_SLEEP) {
1129 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_IRQACK)
1130 1.169 thorpej wdc->irqack(chp);
1131 1.156 bouyer splx(s);
1132 1.156 bouyer }
1133 1.2 bouyer
1134 1.31 bouyer drv_mask1 = (chp->ch_drive[0].drive_flags & DRIVE) ? 0x01:0x00;
1135 1.31 bouyer drv_mask1 |= (chp->ch_drive[1].drive_flags & DRIVE) ? 0x02:0x00;
1136 1.137 bouyer drv_mask2 = __wdcwait_reset(chp, drv_mask1,
1137 1.137 bouyer (poll == RESET_SLEEP) ? 0 : 1);
1138 1.137 bouyer if (drv_mask2 != drv_mask1) {
1139 1.31 bouyer printf("%s channel %d: reset failed for",
1140 1.169 thorpej wdc->sc_dev.dv_xname, chp->ch_channel);
1141 1.31 bouyer if ((drv_mask1 & 0x01) != 0 && (drv_mask2 & 0x01) == 0)
1142 1.31 bouyer printf(" drive 0");
1143 1.31 bouyer if ((drv_mask1 & 0x02) != 0 && (drv_mask2 & 0x02) == 0)
1144 1.31 bouyer printf(" drive 1");
1145 1.31 bouyer printf("\n");
1146 1.31 bouyer }
1147 1.137 bouyer bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
1148 1.31 bouyer return (drv_mask1 != drv_mask2) ? 1 : 0;
1149 1.31 bouyer }
1150 1.31 bouyer
1151 1.31 bouyer static int
1152 1.168 thorpej __wdcwait_reset(struct wdc_channel *chp, int drv_mask, int poll)
1153 1.31 bouyer {
1154 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1155 1.137 bouyer int timeout, nloop;
1156 1.149 bouyer u_int8_t st0 = 0, st1 = 0;
1157 1.70 bouyer #ifdef WDCDEBUG
1158 1.146 christos u_int8_t sc0 = 0, sn0 = 0, cl0 = 0, ch0 = 0;
1159 1.146 christos u_int8_t sc1 = 0, sn1 = 0, cl1 = 0, ch1 = 0;
1160 1.70 bouyer #endif
1161 1.137 bouyer
1162 1.137 bouyer if (poll)
1163 1.137 bouyer nloop = WDCNDELAY_RST;
1164 1.137 bouyer else
1165 1.137 bouyer nloop = WDC_RESET_WAIT * hz / 1000;
1166 1.31 bouyer /* wait for BSY to deassert */
1167 1.137 bouyer for (timeout = 0; timeout < nloop; timeout++) {
1168 1.174 bouyer if ((drv_mask & 0x01) != 0) {
1169 1.174 bouyer if (wdc && wdc->cap & WDC_CAPABILITY_SELECT)
1170 1.174 bouyer wdc->select(chp,0);
1171 1.174 bouyer bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
1172 1.174 bouyer 0, WDSD_IBM); /* master */
1173 1.174 bouyer delay(10);
1174 1.174 bouyer st0 = bus_space_read_1(chp->cmd_iot,
1175 1.174 bouyer chp->cmd_iohs[wd_status], 0);
1176 1.70 bouyer #ifdef WDCDEBUG
1177 1.174 bouyer sc0 = bus_space_read_1(chp->cmd_iot,
1178 1.174 bouyer chp->cmd_iohs[wd_seccnt], 0);
1179 1.174 bouyer sn0 = bus_space_read_1(chp->cmd_iot,
1180 1.174 bouyer chp->cmd_iohs[wd_sector], 0);
1181 1.174 bouyer cl0 = bus_space_read_1(chp->cmd_iot,
1182 1.174 bouyer chp->cmd_iohs[wd_cyl_lo], 0);
1183 1.174 bouyer ch0 = bus_space_read_1(chp->cmd_iot,
1184 1.174 bouyer chp->cmd_iohs[wd_cyl_hi], 0);
1185 1.70 bouyer #endif
1186 1.174 bouyer }
1187 1.174 bouyer if ((drv_mask & 0x02) != 0) {
1188 1.174 bouyer if (wdc && wdc->cap & WDC_CAPABILITY_SELECT)
1189 1.174 bouyer wdc->select(chp,1);
1190 1.174 bouyer bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
1191 1.174 bouyer 0, WDSD_IBM | 0x10); /* slave */
1192 1.174 bouyer delay(10);
1193 1.174 bouyer st1 = bus_space_read_1(chp->cmd_iot,
1194 1.174 bouyer chp->cmd_iohs[wd_status], 0);
1195 1.70 bouyer #ifdef WDCDEBUG
1196 1.174 bouyer sc1 = bus_space_read_1(chp->cmd_iot,
1197 1.174 bouyer chp->cmd_iohs[wd_seccnt], 0);
1198 1.174 bouyer sn1 = bus_space_read_1(chp->cmd_iot,
1199 1.174 bouyer chp->cmd_iohs[wd_sector], 0);
1200 1.174 bouyer cl1 = bus_space_read_1(chp->cmd_iot,
1201 1.174 bouyer chp->cmd_iohs[wd_cyl_lo], 0);
1202 1.174 bouyer ch1 = bus_space_read_1(chp->cmd_iot,
1203 1.174 bouyer chp->cmd_iohs[wd_cyl_hi], 0);
1204 1.70 bouyer #endif
1205 1.174 bouyer }
1206 1.31 bouyer
1207 1.31 bouyer if ((drv_mask & 0x01) == 0) {
1208 1.31 bouyer /* no master */
1209 1.31 bouyer if ((drv_mask & 0x02) != 0 && (st1 & WDCS_BSY) == 0) {
1210 1.31 bouyer /* No master, slave is ready, it's done */
1211 1.65 bouyer goto end;
1212 1.31 bouyer }
1213 1.31 bouyer } else if ((drv_mask & 0x02) == 0) {
1214 1.31 bouyer /* no slave */
1215 1.31 bouyer if ((drv_mask & 0x01) != 0 && (st0 & WDCS_BSY) == 0) {
1216 1.31 bouyer /* No slave, master is ready, it's done */
1217 1.65 bouyer goto end;
1218 1.31 bouyer }
1219 1.2 bouyer } else {
1220 1.31 bouyer /* Wait for both master and slave to be ready */
1221 1.31 bouyer if ((st0 & WDCS_BSY) == 0 && (st1 & WDCS_BSY) == 0) {
1222 1.65 bouyer goto end;
1223 1.2 bouyer }
1224 1.2 bouyer }
1225 1.137 bouyer if (poll)
1226 1.137 bouyer delay(WDCDELAY);
1227 1.137 bouyer else
1228 1.137 bouyer tsleep(&nloop, PRIBIO, "atarst", 1);
1229 1.2 bouyer }
1230 1.116 wiz /* Reset timed out. Maybe it's because drv_mask was not right */
1231 1.31 bouyer if (st0 & WDCS_BSY)
1232 1.31 bouyer drv_mask &= ~0x01;
1233 1.31 bouyer if (st1 & WDCS_BSY)
1234 1.31 bouyer drv_mask &= ~0x02;
1235 1.65 bouyer end:
1236 1.70 bouyer WDCDEBUG_PRINT(("%s:%d:0: after reset, sc=0x%x sn=0x%x "
1237 1.70 bouyer "cl=0x%x ch=0x%x\n",
1238 1.169 thorpej wdc != NULL ? wdc->sc_dev.dv_xname : "wdcprobe",
1239 1.169 thorpej chp->ch_channel, sc0, sn0, cl0, ch0), DEBUG_PROBE);
1240 1.70 bouyer WDCDEBUG_PRINT(("%s:%d:1: after reset, sc=0x%x sn=0x%x "
1241 1.70 bouyer "cl=0x%x ch=0x%x\n",
1242 1.169 thorpej wdc != NULL ? wdc->sc_dev.dv_xname : "wdcprobe",
1243 1.169 thorpej chp->ch_channel, sc1, sn1, cl1, ch1), DEBUG_PROBE);
1244 1.70 bouyer
1245 1.149 bouyer WDCDEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%x st1=0x%x\n",
1246 1.169 thorpej wdc != NULL ? wdc->sc_dev.dv_xname : "wdcprobe", chp->ch_channel,
1247 1.149 bouyer st0, st1), DEBUG_PROBE);
1248 1.65 bouyer
1249 1.31 bouyer return drv_mask;
1250 1.2 bouyer }
1251 1.2 bouyer
1252 1.2 bouyer /*
1253 1.31 bouyer * Wait for a drive to be !BSY, and have mask in its status register.
1254 1.31 bouyer * return -1 for a timeout after "timeout" ms.
1255 1.2 bouyer */
1256 1.167 thorpej static int
1257 1.168 thorpej __wdcwait(struct wdc_channel *chp, int mask, int bits, int timeout)
1258 1.2 bouyer {
1259 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1260 1.31 bouyer u_char status;
1261 1.31 bouyer int time = 0;
1262 1.60 abs
1263 1.169 thorpej WDCDEBUG_PRINT(("__wdcwait %s:%d\n", wdc != NULL ?
1264 1.169 thorpej wdc->sc_dev.dv_xname : "none",
1265 1.169 thorpej chp->ch_channel), DEBUG_STATUS);
1266 1.31 bouyer chp->ch_error = 0;
1267 1.31 bouyer
1268 1.31 bouyer timeout = timeout * 1000 / WDCDELAY; /* delay uses microseconds */
1269 1.2 bouyer
1270 1.31 bouyer for (;;) {
1271 1.31 bouyer chp->ch_status = status =
1272 1.157 fvdl bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_status], 0);
1273 1.131 mycroft if ((status & (WDCS_BSY | mask)) == bits)
1274 1.31 bouyer break;
1275 1.31 bouyer if (++time > timeout) {
1276 1.137 bouyer WDCDEBUG_PRINT(("__wdcwait: timeout (time=%d), "
1277 1.87 bouyer "status %x error %x (mask 0x%x bits 0x%x)\n",
1278 1.87 bouyer time, status,
1279 1.157 fvdl bus_space_read_1(chp->cmd_iot,
1280 1.157 fvdl chp->cmd_iohs[wd_error], 0), mask, bits),
1281 1.87 bouyer DEBUG_STATUS | DEBUG_PROBE | DEBUG_DELAY);
1282 1.137 bouyer return(WDCWAIT_TOUT);
1283 1.31 bouyer }
1284 1.31 bouyer delay(WDCDELAY);
1285 1.2 bouyer }
1286 1.87 bouyer #ifdef WDCDEBUG
1287 1.87 bouyer if (time > 0 && (wdcdebug_mask & DEBUG_DELAY))
1288 1.137 bouyer printf("__wdcwait: did busy-wait, time=%d\n", time);
1289 1.87 bouyer #endif
1290 1.31 bouyer if (status & WDCS_ERR)
1291 1.157 fvdl chp->ch_error = bus_space_read_1(chp->cmd_iot,
1292 1.157 fvdl chp->cmd_iohs[wd_error], 0);
1293 1.31 bouyer #ifdef WDCNDELAY_DEBUG
1294 1.31 bouyer /* After autoconfig, there should be no long delays. */
1295 1.31 bouyer if (!cold && time > WDCNDELAY_DEBUG) {
1296 1.186 bouyer struct ata_xfer *xfer = chp->ch_queue->active_xfer;
1297 1.31 bouyer if (xfer == NULL)
1298 1.31 bouyer printf("%s channel %d: warning: busy-wait took %dus\n",
1299 1.169 thorpej wdc->sc_dev.dv_xname, chp->ch_channel,
1300 1.31 bouyer WDCDELAY * time);
1301 1.31 bouyer else
1302 1.31 bouyer printf("%s:%d:%d: warning: busy-wait took %dus\n",
1303 1.169 thorpej wdc->sc_dev.dv_xname, chp->ch_channel,
1304 1.31 bouyer xfer->drive,
1305 1.31 bouyer WDCDELAY * time);
1306 1.2 bouyer }
1307 1.2 bouyer #endif
1308 1.137 bouyer return(WDCWAIT_OK);
1309 1.137 bouyer }
1310 1.137 bouyer
1311 1.137 bouyer /*
1312 1.137 bouyer * Call __wdcwait(), polling using tsleep() or waking up the kernel
1313 1.137 bouyer * thread if possible
1314 1.137 bouyer */
1315 1.137 bouyer int
1316 1.168 thorpej wdcwait(struct wdc_channel *chp, int mask, int bits, int timeout, int flags)
1317 1.137 bouyer {
1318 1.137 bouyer int error, i, timeout_hz = mstohz(timeout);
1319 1.137 bouyer
1320 1.137 bouyer if (timeout_hz == 0 ||
1321 1.137 bouyer (flags & (AT_WAIT | AT_POLL)) == AT_POLL)
1322 1.137 bouyer error = __wdcwait(chp, mask, bits, timeout);
1323 1.137 bouyer else {
1324 1.137 bouyer error = __wdcwait(chp, mask, bits, WDCDELAY_POLL);
1325 1.137 bouyer if (error != 0) {
1326 1.147 bouyer if ((chp->ch_flags & WDCF_TH_RUN) ||
1327 1.147 bouyer (flags & AT_WAIT)) {
1328 1.137 bouyer /*
1329 1.147 bouyer * we're running in the channel thread
1330 1.147 bouyer * or some userland thread context
1331 1.137 bouyer */
1332 1.137 bouyer for (i = 0; i < timeout_hz; i++) {
1333 1.137 bouyer if (__wdcwait(chp, mask, bits,
1334 1.137 bouyer WDCDELAY_POLL) == 0) {
1335 1.137 bouyer error = 0;
1336 1.137 bouyer break;
1337 1.137 bouyer }
1338 1.137 bouyer tsleep(&chp, PRIBIO, "atapoll", 1);
1339 1.137 bouyer }
1340 1.137 bouyer } else {
1341 1.137 bouyer /*
1342 1.137 bouyer * we're probably in interrupt context,
1343 1.137 bouyer * ask the thread to come back here
1344 1.137 bouyer */
1345 1.147 bouyer #ifdef DIAGNOSTIC
1346 1.148 bouyer if (chp->ch_queue->queue_freeze > 0)
1347 1.148 bouyer panic("wdcwait: queue_freeze");
1348 1.147 bouyer #endif
1349 1.148 bouyer chp->ch_queue->queue_freeze++;
1350 1.170 thorpej wakeup(&chp->ch_thread);
1351 1.137 bouyer return(WDCWAIT_THR);
1352 1.137 bouyer }
1353 1.137 bouyer }
1354 1.137 bouyer }
1355 1.163 thorpej return (error);
1356 1.2 bouyer }
1357 1.2 bouyer
1358 1.137 bouyer
1359 1.84 bouyer /*
1360 1.84 bouyer * Busy-wait for DMA to complete
1361 1.84 bouyer */
1362 1.84 bouyer int
1363 1.168 thorpej wdc_dmawait(struct wdc_channel *chp, struct ata_xfer *xfer, int timeout)
1364 1.84 bouyer {
1365 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1366 1.84 bouyer int time;
1367 1.169 thorpej
1368 1.84 bouyer for (time = 0; time < timeout * 1000 / WDCDELAY; time++) {
1369 1.169 thorpej wdc->dma_status =
1370 1.169 thorpej (*wdc->dma_finish)(wdc->dma_arg,
1371 1.185 bouyer chp->ch_channel, xfer->c_drive, WDC_DMAEND_END);
1372 1.169 thorpej if ((wdc->dma_status & WDC_DMAST_NOIRQ) == 0)
1373 1.84 bouyer return 0;
1374 1.84 bouyer delay(WDCDELAY);
1375 1.84 bouyer }
1376 1.84 bouyer /* timeout, force a DMA halt */
1377 1.169 thorpej wdc->dma_status = (*wdc->dma_finish)(wdc->dma_arg,
1378 1.185 bouyer chp->ch_channel, xfer->c_drive, WDC_DMAEND_ABRT);
1379 1.84 bouyer return 1;
1380 1.84 bouyer }
1381 1.84 bouyer
1382 1.31 bouyer void
1383 1.163 thorpej wdctimeout(void *arg)
1384 1.2 bouyer {
1385 1.168 thorpej struct wdc_channel *chp = (struct wdc_channel *)arg;
1386 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1387 1.186 bouyer struct ata_xfer *xfer = chp->ch_queue->active_xfer;
1388 1.31 bouyer int s;
1389 1.2 bouyer
1390 1.31 bouyer WDCDEBUG_PRINT(("wdctimeout\n"), DEBUG_FUNCS);
1391 1.31 bouyer
1392 1.31 bouyer s = splbio();
1393 1.31 bouyer if ((chp->ch_flags & WDCF_IRQ_WAIT) != 0) {
1394 1.31 bouyer __wdcerror(chp, "lost interrupt");
1395 1.88 mrg printf("\ttype: %s tc_bcount: %d tc_skip: %d\n",
1396 1.88 mrg (xfer->c_flags & C_ATAPI) ? "atapi" : "ata",
1397 1.88 mrg xfer->c_bcount,
1398 1.88 mrg xfer->c_skip);
1399 1.84 bouyer if (chp->ch_flags & WDCF_DMA_WAIT) {
1400 1.169 thorpej wdc->dma_status =
1401 1.169 thorpej (*wdc->dma_finish)(wdc->dma_arg,
1402 1.185 bouyer chp->ch_channel, xfer->c_drive,
1403 1.185 bouyer WDC_DMAEND_ABRT);
1404 1.84 bouyer chp->ch_flags &= ~WDCF_DMA_WAIT;
1405 1.84 bouyer }
1406 1.31 bouyer /*
1407 1.119 drochner * Call the interrupt routine. If we just missed an interrupt,
1408 1.31 bouyer * it will do what's needed. Else, it will take the needed
1409 1.31 bouyer * action (reset the device).
1410 1.70 bouyer * Before that we need to reinstall the timeout callback,
1411 1.70 bouyer * in case it will miss another irq while in this transfer
1412 1.70 bouyer * We arbitray chose it to be 1s
1413 1.31 bouyer */
1414 1.81 thorpej callout_reset(&chp->ch_callout, hz, wdctimeout, chp);
1415 1.31 bouyer xfer->c_flags |= C_TIMEOU;
1416 1.31 bouyer chp->ch_flags &= ~WDCF_IRQ_WAIT;
1417 1.66 bouyer xfer->c_intr(chp, xfer, 1);
1418 1.31 bouyer } else
1419 1.31 bouyer __wdcerror(chp, "missing untimeout");
1420 1.31 bouyer splx(s);
1421 1.2 bouyer }
1422 1.2 bouyer
1423 1.31 bouyer /*
1424 1.152 wiz * Probe drive's capabilities, for use by the controller later
1425 1.31 bouyer * Assumes drvp points to an existing drive.
1426 1.31 bouyer * XXX this should be a controller-indep function
1427 1.31 bouyer */
1428 1.2 bouyer void
1429 1.163 thorpej wdc_probe_caps(struct ata_drive_datas *drvp)
1430 1.2 bouyer {
1431 1.31 bouyer struct ataparams params, params2;
1432 1.168 thorpej struct wdc_channel *chp = drvp->chnl_softc;
1433 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1434 1.31 bouyer struct device *drv_dev = drvp->drv_softc;
1435 1.31 bouyer int i, printed;
1436 1.31 bouyer char *sep = "";
1437 1.48 bouyer int cf_flags;
1438 1.31 bouyer
1439 1.125 mycroft if (ata_get_params(drvp, AT_WAIT, ¶ms) != CMD_OK) {
1440 1.31 bouyer /* IDENTIFY failed. Can't tell more about the device */
1441 1.2 bouyer return;
1442 1.2 bouyer }
1443 1.31 bouyer if ((wdc->cap & (WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32)) ==
1444 1.31 bouyer (WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32)) {
1445 1.2 bouyer /*
1446 1.39 bouyer * Controller claims 16 and 32 bit transfers.
1447 1.39 bouyer * Re-do an IDENTIFY with 32-bit transfers,
1448 1.31 bouyer * and compare results.
1449 1.2 bouyer */
1450 1.31 bouyer drvp->drive_flags |= DRIVE_CAP32;
1451 1.125 mycroft ata_get_params(drvp, AT_WAIT, ¶ms2);
1452 1.31 bouyer if (memcmp(¶ms, ¶ms2, sizeof(struct ataparams)) != 0) {
1453 1.31 bouyer /* Not good. fall back to 16bits */
1454 1.31 bouyer drvp->drive_flags &= ~DRIVE_CAP32;
1455 1.31 bouyer } else {
1456 1.125 mycroft aprint_normal("%s: 32-bit data port\n",
1457 1.123 thorpej drv_dev->dv_xname);
1458 1.2 bouyer }
1459 1.2 bouyer }
1460 1.55 bouyer #if 0 /* Some ultra-DMA drives claims to only support ATA-3. sigh */
1461 1.55 bouyer if (params.atap_ata_major > 0x01 &&
1462 1.55 bouyer params.atap_ata_major != 0xffff) {
1463 1.55 bouyer for (i = 14; i > 0; i--) {
1464 1.55 bouyer if (params.atap_ata_major & (1 << i)) {
1465 1.125 mycroft aprint_normal("%s: ATA version %d\n",
1466 1.125 mycroft drv_dev->dv_xname, i);
1467 1.55 bouyer drvp->ata_vers = i;
1468 1.55 bouyer break;
1469 1.55 bouyer }
1470 1.55 bouyer }
1471 1.125 mycroft }
1472 1.55 bouyer #endif
1473 1.2 bouyer
1474 1.31 bouyer /* An ATAPI device is at last PIO mode 3 */
1475 1.31 bouyer if (drvp->drive_flags & DRIVE_ATAPI)
1476 1.31 bouyer drvp->PIO_mode = 3;
1477 1.2 bouyer
1478 1.2 bouyer /*
1479 1.31 bouyer * It's not in the specs, but it seems that some drive
1480 1.31 bouyer * returns 0xffff in atap_extensions when this field is invalid
1481 1.2 bouyer */
1482 1.31 bouyer if (params.atap_extensions != 0xffff &&
1483 1.31 bouyer (params.atap_extensions & WDC_EXT_MODES)) {
1484 1.31 bouyer printed = 0;
1485 1.31 bouyer /*
1486 1.31 bouyer * XXX some drives report something wrong here (they claim to
1487 1.31 bouyer * support PIO mode 8 !). As mode is coded on 3 bits in
1488 1.31 bouyer * SET FEATURE, limit it to 7 (so limit i to 4).
1489 1.116 wiz * If higher mode than 7 is found, abort.
1490 1.31 bouyer */
1491 1.39 bouyer for (i = 7; i >= 0; i--) {
1492 1.31 bouyer if ((params.atap_piomode_supp & (1 << i)) == 0)
1493 1.31 bouyer continue;
1494 1.39 bouyer if (i > 4)
1495 1.39 bouyer return;
1496 1.31 bouyer /*
1497 1.31 bouyer * See if mode is accepted.
1498 1.31 bouyer * If the controller can't set its PIO mode,
1499 1.31 bouyer * assume the defaults are good, so don't try
1500 1.31 bouyer * to set it
1501 1.31 bouyer */
1502 1.31 bouyer if ((wdc->cap & WDC_CAPABILITY_MODE) != 0)
1503 1.137 bouyer /*
1504 1.137 bouyer * It's OK to pool here, it's fast enouth
1505 1.137 bouyer * to not bother waiting for interrupt
1506 1.137 bouyer */
1507 1.31 bouyer if (ata_set_mode(drvp, 0x08 | (i + 3),
1508 1.125 mycroft AT_WAIT) != CMD_OK)
1509 1.2 bouyer continue;
1510 1.31 bouyer if (!printed) {
1511 1.123 thorpej aprint_normal("%s: drive supports PIO mode %d",
1512 1.39 bouyer drv_dev->dv_xname, i + 3);
1513 1.31 bouyer sep = ",";
1514 1.31 bouyer printed = 1;
1515 1.31 bouyer }
1516 1.31 bouyer /*
1517 1.31 bouyer * If controller's driver can't set its PIO mode,
1518 1.31 bouyer * get the highter one for the drive.
1519 1.31 bouyer */
1520 1.31 bouyer if ((wdc->cap & WDC_CAPABILITY_MODE) == 0 ||
1521 1.52 bouyer wdc->PIO_cap >= i + 3) {
1522 1.31 bouyer drvp->PIO_mode = i + 3;
1523 1.48 bouyer drvp->PIO_cap = i + 3;
1524 1.2 bouyer break;
1525 1.2 bouyer }
1526 1.2 bouyer }
1527 1.31 bouyer if (!printed) {
1528 1.31 bouyer /*
1529 1.31 bouyer * We didn't find a valid PIO mode.
1530 1.31 bouyer * Assume the values returned for DMA are buggy too
1531 1.31 bouyer */
1532 1.31 bouyer return;
1533 1.2 bouyer }
1534 1.35 bouyer drvp->drive_flags |= DRIVE_MODE;
1535 1.31 bouyer printed = 0;
1536 1.31 bouyer for (i = 7; i >= 0; i--) {
1537 1.31 bouyer if ((params.atap_dmamode_supp & (1 << i)) == 0)
1538 1.31 bouyer continue;
1539 1.31 bouyer if ((wdc->cap & WDC_CAPABILITY_DMA) &&
1540 1.31 bouyer (wdc->cap & WDC_CAPABILITY_MODE))
1541 1.125 mycroft if (ata_set_mode(drvp, 0x20 | i, AT_WAIT)
1542 1.31 bouyer != CMD_OK)
1543 1.31 bouyer continue;
1544 1.31 bouyer if (!printed) {
1545 1.123 thorpej aprint_normal("%s DMA mode %d", sep, i);
1546 1.31 bouyer sep = ",";
1547 1.31 bouyer printed = 1;
1548 1.31 bouyer }
1549 1.31 bouyer if (wdc->cap & WDC_CAPABILITY_DMA) {
1550 1.31 bouyer if ((wdc->cap & WDC_CAPABILITY_MODE) &&
1551 1.52 bouyer wdc->DMA_cap < i)
1552 1.31 bouyer continue;
1553 1.31 bouyer drvp->DMA_mode = i;
1554 1.48 bouyer drvp->DMA_cap = i;
1555 1.31 bouyer drvp->drive_flags |= DRIVE_DMA;
1556 1.31 bouyer }
1557 1.2 bouyer break;
1558 1.2 bouyer }
1559 1.31 bouyer if (params.atap_extensions & WDC_EXT_UDMA_MODES) {
1560 1.71 bouyer printed = 0;
1561 1.31 bouyer for (i = 7; i >= 0; i--) {
1562 1.31 bouyer if ((params.atap_udmamode_supp & (1 << i))
1563 1.31 bouyer == 0)
1564 1.31 bouyer continue;
1565 1.31 bouyer if ((wdc->cap & WDC_CAPABILITY_MODE) &&
1566 1.31 bouyer (wdc->cap & WDC_CAPABILITY_UDMA))
1567 1.31 bouyer if (ata_set_mode(drvp, 0x40 | i,
1568 1.125 mycroft AT_WAIT) != CMD_OK)
1569 1.31 bouyer continue;
1570 1.71 bouyer if (!printed) {
1571 1.123 thorpej aprint_normal("%s Ultra-DMA mode %d",
1572 1.123 thorpej sep, i);
1573 1.93 wrstuden if (i == 2)
1574 1.123 thorpej aprint_normal(" (Ultra/33)");
1575 1.93 wrstuden else if (i == 4)
1576 1.123 thorpej aprint_normal(" (Ultra/66)");
1577 1.93 wrstuden else if (i == 5)
1578 1.123 thorpej aprint_normal(" (Ultra/100)");
1579 1.117 bouyer else if (i == 6)
1580 1.123 thorpej aprint_normal(" (Ultra/133)");
1581 1.71 bouyer sep = ",";
1582 1.71 bouyer printed = 1;
1583 1.71 bouyer }
1584 1.31 bouyer if (wdc->cap & WDC_CAPABILITY_UDMA) {
1585 1.50 bouyer if ((wdc->cap & WDC_CAPABILITY_MODE) &&
1586 1.52 bouyer wdc->UDMA_cap < i)
1587 1.50 bouyer continue;
1588 1.31 bouyer drvp->UDMA_mode = i;
1589 1.48 bouyer drvp->UDMA_cap = i;
1590 1.31 bouyer drvp->drive_flags |= DRIVE_UDMA;
1591 1.31 bouyer }
1592 1.31 bouyer break;
1593 1.31 bouyer }
1594 1.31 bouyer }
1595 1.123 thorpej aprint_normal("\n");
1596 1.55 bouyer }
1597 1.55 bouyer
1598 1.190 mycroft drvp->drive_flags &= ~DRIVE_NOSTREAM;
1599 1.190 mycroft if (drvp->drive_flags & DRIVE_ATAPI) {
1600 1.190 mycroft if (wdc->cap & WDC_CAPABILITY_ATAPI_NOSTREAM)
1601 1.190 mycroft drvp->drive_flags |= DRIVE_NOSTREAM;
1602 1.190 mycroft } else {
1603 1.190 mycroft if (wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)
1604 1.190 mycroft drvp->drive_flags |= DRIVE_NOSTREAM;
1605 1.190 mycroft }
1606 1.190 mycroft
1607 1.55 bouyer /* Try to guess ATA version here, if it didn't get reported */
1608 1.55 bouyer if (drvp->ata_vers == 0) {
1609 1.55 bouyer if (drvp->drive_flags & DRIVE_UDMA)
1610 1.55 bouyer drvp->ata_vers = 4; /* should be at last ATA-4 */
1611 1.55 bouyer else if (drvp->PIO_cap > 2)
1612 1.55 bouyer drvp->ata_vers = 2; /* should be at last ATA-2 */
1613 1.48 bouyer }
1614 1.48 bouyer cf_flags = drv_dev->dv_cfdata->cf_flags;
1615 1.48 bouyer if (cf_flags & ATA_CONFIG_PIO_SET) {
1616 1.48 bouyer drvp->PIO_mode =
1617 1.48 bouyer (cf_flags & ATA_CONFIG_PIO_MODES) >> ATA_CONFIG_PIO_OFF;
1618 1.48 bouyer drvp->drive_flags |= DRIVE_MODE;
1619 1.48 bouyer }
1620 1.48 bouyer if ((wdc->cap & WDC_CAPABILITY_DMA) == 0) {
1621 1.48 bouyer /* don't care about DMA modes */
1622 1.48 bouyer return;
1623 1.48 bouyer }
1624 1.48 bouyer if (cf_flags & ATA_CONFIG_DMA_SET) {
1625 1.48 bouyer if ((cf_flags & ATA_CONFIG_DMA_MODES) ==
1626 1.48 bouyer ATA_CONFIG_DMA_DISABLE) {
1627 1.48 bouyer drvp->drive_flags &= ~DRIVE_DMA;
1628 1.48 bouyer } else {
1629 1.48 bouyer drvp->DMA_mode = (cf_flags & ATA_CONFIG_DMA_MODES) >>
1630 1.48 bouyer ATA_CONFIG_DMA_OFF;
1631 1.48 bouyer drvp->drive_flags |= DRIVE_DMA | DRIVE_MODE;
1632 1.48 bouyer }
1633 1.101 bouyer }
1634 1.101 bouyer if ((wdc->cap & WDC_CAPABILITY_UDMA) == 0) {
1635 1.101 bouyer /* don't care about UDMA modes */
1636 1.101 bouyer return;
1637 1.48 bouyer }
1638 1.48 bouyer if (cf_flags & ATA_CONFIG_UDMA_SET) {
1639 1.48 bouyer if ((cf_flags & ATA_CONFIG_UDMA_MODES) ==
1640 1.48 bouyer ATA_CONFIG_UDMA_DISABLE) {
1641 1.48 bouyer drvp->drive_flags &= ~DRIVE_UDMA;
1642 1.48 bouyer } else {
1643 1.48 bouyer drvp->UDMA_mode = (cf_flags & ATA_CONFIG_UDMA_MODES) >>
1644 1.48 bouyer ATA_CONFIG_UDMA_OFF;
1645 1.48 bouyer drvp->drive_flags |= DRIVE_UDMA | DRIVE_MODE;
1646 1.48 bouyer }
1647 1.2 bouyer }
1648 1.54 bouyer }
1649 1.54 bouyer
1650 1.54 bouyer /*
1651 1.56 bouyer * downgrade the transfer mode of a drive after an error. return 1 if
1652 1.54 bouyer * downgrade was possible, 0 otherwise.
1653 1.54 bouyer */
1654 1.54 bouyer int
1655 1.163 thorpej wdc_downgrade_mode(struct ata_drive_datas *drvp, int flags)
1656 1.54 bouyer {
1657 1.168 thorpej struct wdc_channel *chp = drvp->chnl_softc;
1658 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1659 1.54 bouyer struct device *drv_dev = drvp->drv_softc;
1660 1.54 bouyer int cf_flags = drv_dev->dv_cfdata->cf_flags;
1661 1.54 bouyer
1662 1.54 bouyer /* if drive or controller don't know its mode, we can't do much */
1663 1.54 bouyer if ((drvp->drive_flags & DRIVE_MODE) == 0 ||
1664 1.54 bouyer (wdc->cap & WDC_CAPABILITY_MODE) == 0)
1665 1.54 bouyer return 0;
1666 1.54 bouyer /* current drive mode was set by a config flag, let it this way */
1667 1.54 bouyer if ((cf_flags & ATA_CONFIG_PIO_SET) ||
1668 1.54 bouyer (cf_flags & ATA_CONFIG_DMA_SET) ||
1669 1.54 bouyer (cf_flags & ATA_CONFIG_UDMA_SET))
1670 1.54 bouyer return 0;
1671 1.54 bouyer
1672 1.61 bouyer /*
1673 1.180 mycroft * If we were using Ultra-DMA mode, downgrade to the next lower mode.
1674 1.73 bouyer */
1675 1.78 bouyer if ((drvp->drive_flags & DRIVE_UDMA) && drvp->UDMA_mode >= 2) {
1676 1.180 mycroft drvp->UDMA_mode--;
1677 1.78 bouyer printf("%s: transfer error, downgrading to Ultra-DMA mode %d\n",
1678 1.73 bouyer drv_dev->dv_xname, drvp->UDMA_mode);
1679 1.73 bouyer }
1680 1.73 bouyer
1681 1.73 bouyer /*
1682 1.180 mycroft * If we were using ultra-DMA, don't downgrade to multiword DMA.
1683 1.61 bouyer */
1684 1.180 mycroft else if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) {
1685 1.61 bouyer drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
1686 1.54 bouyer drvp->PIO_mode = drvp->PIO_cap;
1687 1.56 bouyer printf("%s: transfer error, downgrading to PIO mode %d\n",
1688 1.54 bouyer drv_dev->dv_xname, drvp->PIO_mode);
1689 1.54 bouyer } else /* already using PIO, can't downgrade */
1690 1.54 bouyer return 0;
1691 1.54 bouyer
1692 1.54 bouyer wdc->set_modes(chp);
1693 1.137 bouyer wdc_print_modes(chp);
1694 1.137 bouyer /* reset the channel, which will shedule all drives for setup */
1695 1.183 bouyer wdc_reset_channel(chp, flags | AT_RST_NOCMD);
1696 1.54 bouyer return 1;
1697 1.2 bouyer }
1698 1.2 bouyer
1699 1.2 bouyer int
1700 1.163 thorpej wdc_exec_command(struct ata_drive_datas *drvp, struct wdc_command *wdc_c)
1701 1.31 bouyer {
1702 1.168 thorpej struct wdc_channel *chp = drvp->chnl_softc;
1703 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1704 1.165 thorpej struct ata_xfer *xfer;
1705 1.31 bouyer int s, ret;
1706 1.2 bouyer
1707 1.34 bouyer WDCDEBUG_PRINT(("wdc_exec_command %s:%d:%d\n",
1708 1.169 thorpej wdc->sc_dev.dv_xname, chp->ch_channel, drvp->drive),
1709 1.34 bouyer DEBUG_FUNCS);
1710 1.2 bouyer
1711 1.31 bouyer /* set up an xfer and queue. Wait for completion */
1712 1.31 bouyer xfer = wdc_get_xfer(wdc_c->flags & AT_WAIT ? WDC_CANSLEEP :
1713 1.31 bouyer WDC_NOSLEEP);
1714 1.31 bouyer if (xfer == NULL) {
1715 1.31 bouyer return WDC_TRY_AGAIN;
1716 1.31 bouyer }
1717 1.2 bouyer
1718 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_NOIRQ)
1719 1.98 bjh21 wdc_c->flags |= AT_POLL;
1720 1.31 bouyer if (wdc_c->flags & AT_POLL)
1721 1.31 bouyer xfer->c_flags |= C_POLL;
1722 1.165 thorpej xfer->c_drive = drvp->drive;
1723 1.165 thorpej xfer->c_databuf = wdc_c->data;
1724 1.31 bouyer xfer->c_bcount = wdc_c->bcount;
1725 1.165 thorpej xfer->c_cmd = wdc_c;
1726 1.31 bouyer xfer->c_start = __wdccommand_start;
1727 1.31 bouyer xfer->c_intr = __wdccommand_intr;
1728 1.182 bouyer xfer->c_kill_xfer = __wdccommand_kill_xfer;
1729 1.2 bouyer
1730 1.31 bouyer s = splbio();
1731 1.31 bouyer wdc_exec_xfer(chp, xfer);
1732 1.31 bouyer #ifdef DIAGNOSTIC
1733 1.31 bouyer if ((wdc_c->flags & AT_POLL) != 0 &&
1734 1.31 bouyer (wdc_c->flags & AT_DONE) == 0)
1735 1.118 provos panic("wdc_exec_command: polled command not done");
1736 1.2 bouyer #endif
1737 1.31 bouyer if (wdc_c->flags & AT_DONE) {
1738 1.31 bouyer ret = WDC_COMPLETE;
1739 1.31 bouyer } else {
1740 1.31 bouyer if (wdc_c->flags & AT_WAIT) {
1741 1.69 bouyer while ((wdc_c->flags & AT_DONE) == 0) {
1742 1.69 bouyer tsleep(wdc_c, PRIBIO, "wdccmd", 0);
1743 1.69 bouyer }
1744 1.31 bouyer ret = WDC_COMPLETE;
1745 1.31 bouyer } else {
1746 1.31 bouyer ret = WDC_QUEUED;
1747 1.2 bouyer }
1748 1.2 bouyer }
1749 1.31 bouyer splx(s);
1750 1.31 bouyer return ret;
1751 1.2 bouyer }
1752 1.2 bouyer
1753 1.167 thorpej static void
1754 1.168 thorpej __wdccommand_start(struct wdc_channel *chp, struct ata_xfer *xfer)
1755 1.31 bouyer {
1756 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1757 1.165 thorpej int drive = xfer->c_drive;
1758 1.165 thorpej struct wdc_command *wdc_c = xfer->c_cmd;
1759 1.31 bouyer
1760 1.34 bouyer WDCDEBUG_PRINT(("__wdccommand_start %s:%d:%d\n",
1761 1.169 thorpej wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive),
1762 1.34 bouyer DEBUG_FUNCS);
1763 1.31 bouyer
1764 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_SELECT)
1765 1.169 thorpej wdc->select(chp,drive);
1766 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
1767 1.31 bouyer WDSD_IBM | (drive << 4));
1768 1.137 bouyer switch(wdcwait(chp, wdc_c->r_st_bmask | WDCS_DRQ,
1769 1.137 bouyer wdc_c->r_st_bmask, wdc_c->timeout, wdc_c->flags)) {
1770 1.137 bouyer case WDCWAIT_OK:
1771 1.137 bouyer break;
1772 1.137 bouyer case WDCWAIT_TOUT:
1773 1.31 bouyer wdc_c->flags |= AT_TIMEOU;
1774 1.31 bouyer __wdccommand_done(chp, xfer);
1775 1.53 bouyer return;
1776 1.137 bouyer case WDCWAIT_THR:
1777 1.137 bouyer return;
1778 1.31 bouyer }
1779 1.135 bouyer if (wdc_c->flags & AT_POLL) {
1780 1.135 bouyer /* polled command, disable interrupts */
1781 1.135 bouyer bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
1782 1.135 bouyer WDCTL_4BIT | WDCTL_IDS);
1783 1.135 bouyer }
1784 1.31 bouyer wdccommand(chp, drive, wdc_c->r_command, wdc_c->r_cyl, wdc_c->r_head,
1785 1.178 thorpej wdc_c->r_sector, wdc_c->r_count, wdc_c->r_features);
1786 1.139 bouyer
1787 1.31 bouyer if ((wdc_c->flags & AT_POLL) == 0) {
1788 1.31 bouyer chp->ch_flags |= WDCF_IRQ_WAIT; /* wait for interrupt */
1789 1.81 thorpej callout_reset(&chp->ch_callout, wdc_c->timeout / 1000 * hz,
1790 1.81 thorpej wdctimeout, chp);
1791 1.31 bouyer return;
1792 1.2 bouyer }
1793 1.2 bouyer /*
1794 1.31 bouyer * Polled command. Wait for drive ready or drq. Done in intr().
1795 1.31 bouyer * Wait for at last 400ns for status bit to be valid.
1796 1.2 bouyer */
1797 1.134 mycroft delay(10); /* 400ns delay */
1798 1.66 bouyer __wdccommand_intr(chp, xfer, 0);
1799 1.2 bouyer }
1800 1.2 bouyer
1801 1.167 thorpej static int
1802 1.168 thorpej __wdccommand_intr(struct wdc_channel *chp, struct ata_xfer *xfer, int irq)
1803 1.2 bouyer {
1804 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1805 1.165 thorpej struct wdc_command *wdc_c = xfer->c_cmd;
1806 1.31 bouyer int bcount = wdc_c->bcount;
1807 1.31 bouyer char *data = wdc_c->data;
1808 1.137 bouyer int wflags;
1809 1.137 bouyer
1810 1.137 bouyer if ((wdc_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL)) {
1811 1.137 bouyer /* both wait and poll, we can tsleep here */
1812 1.147 bouyer wflags = AT_WAIT | AT_POLL;
1813 1.137 bouyer } else {
1814 1.137 bouyer wflags = AT_POLL;
1815 1.137 bouyer }
1816 1.31 bouyer
1817 1.163 thorpej again:
1818 1.34 bouyer WDCDEBUG_PRINT(("__wdccommand_intr %s:%d:%d\n",
1819 1.169 thorpej wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive),
1820 1.165 thorpej DEBUG_INTR);
1821 1.137 bouyer /*
1822 1.137 bouyer * after a ATAPI_SOFT_RESET, the device will have released the bus.
1823 1.137 bouyer * Reselect again, it doesn't hurt for others commands, and the time
1824 1.137 bouyer * penalty for the extra regiter write is acceptable,
1825 1.137 bouyer * wdc_exec_command() isn't called often (mosly for autoconfig)
1826 1.137 bouyer */
1827 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
1828 1.165 thorpej WDSD_IBM | (xfer->c_drive << 4));
1829 1.114 bouyer if ((wdc_c->flags & AT_XFDONE) != 0) {
1830 1.114 bouyer /*
1831 1.114 bouyer * We have completed a data xfer. The drive should now be
1832 1.114 bouyer * in its initial state
1833 1.114 bouyer */
1834 1.114 bouyer if (wdcwait(chp, wdc_c->r_st_bmask | WDCS_DRQ,
1835 1.137 bouyer wdc_c->r_st_bmask, (irq == 0) ? wdc_c->timeout : 0,
1836 1.137 bouyer wflags) == WDCWAIT_TOUT) {
1837 1.114 bouyer if (irq && (xfer->c_flags & C_TIMEOU) == 0)
1838 1.114 bouyer return 0; /* IRQ was not for us */
1839 1.114 bouyer wdc_c->flags |= AT_TIMEOU;
1840 1.114 bouyer }
1841 1.131 mycroft goto out;
1842 1.114 bouyer }
1843 1.31 bouyer if (wdcwait(chp, wdc_c->r_st_pmask, wdc_c->r_st_pmask,
1844 1.137 bouyer (irq == 0) ? wdc_c->timeout : 0, wflags) == WDCWAIT_TOUT) {
1845 1.66 bouyer if (irq && (xfer->c_flags & C_TIMEOU) == 0)
1846 1.63 bouyer return 0; /* IRQ was not for us */
1847 1.63 bouyer wdc_c->flags |= AT_TIMEOU;
1848 1.131 mycroft goto out;
1849 1.2 bouyer }
1850 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_IRQACK)
1851 1.169 thorpej wdc->irqack(chp);
1852 1.31 bouyer if (wdc_c->flags & AT_READ) {
1853 1.131 mycroft if ((chp->ch_status & WDCS_DRQ) == 0) {
1854 1.131 mycroft wdc_c->flags |= AT_TIMEOU;
1855 1.131 mycroft goto out;
1856 1.131 mycroft }
1857 1.165 thorpej if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_CAP32) {
1858 1.31 bouyer bus_space_read_multi_4(chp->data32iot, chp->data32ioh,
1859 1.31 bouyer 0, (u_int32_t*)data, bcount >> 2);
1860 1.31 bouyer data += bcount & 0xfffffffc;
1861 1.31 bouyer bcount = bcount & 0x03;
1862 1.31 bouyer }
1863 1.31 bouyer if (bcount > 0)
1864 1.190 mycroft wdc_datain_pio(chp, DRIVE_NOSTREAM, data, bcount);
1865 1.114 bouyer /* at this point the drive should be in its initial state */
1866 1.114 bouyer wdc_c->flags |= AT_XFDONE;
1867 1.137 bouyer /* XXX should read status register here ? */
1868 1.131 mycroft } else if (wdc_c->flags & AT_WRITE) {
1869 1.131 mycroft if ((chp->ch_status & WDCS_DRQ) == 0) {
1870 1.114 bouyer wdc_c->flags |= AT_TIMEOU;
1871 1.131 mycroft goto out;
1872 1.131 mycroft }
1873 1.165 thorpej if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_CAP32) {
1874 1.31 bouyer bus_space_write_multi_4(chp->data32iot, chp->data32ioh,
1875 1.31 bouyer 0, (u_int32_t*)data, bcount >> 2);
1876 1.31 bouyer data += bcount & 0xfffffffc;
1877 1.31 bouyer bcount = bcount & 0x03;
1878 1.31 bouyer }
1879 1.31 bouyer if (bcount > 0)
1880 1.190 mycroft wdc_dataout_pio(chp, DRIVE_NOSTREAM, data, bcount);
1881 1.114 bouyer wdc_c->flags |= AT_XFDONE;
1882 1.114 bouyer if ((wdc_c->flags & AT_POLL) == 0) {
1883 1.114 bouyer chp->ch_flags |= WDCF_IRQ_WAIT; /* wait for interrupt */
1884 1.114 bouyer callout_reset(&chp->ch_callout,
1885 1.114 bouyer wdc_c->timeout / 1000 * hz, wdctimeout, chp);
1886 1.114 bouyer return 1;
1887 1.114 bouyer } else {
1888 1.114 bouyer goto again;
1889 1.114 bouyer }
1890 1.2 bouyer }
1891 1.163 thorpej out:
1892 1.31 bouyer __wdccommand_done(chp, xfer);
1893 1.31 bouyer return 1;
1894 1.2 bouyer }
1895 1.2 bouyer
1896 1.167 thorpej static void
1897 1.168 thorpej __wdccommand_done(struct wdc_channel *chp, struct ata_xfer *xfer)
1898 1.2 bouyer {
1899 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1900 1.165 thorpej struct wdc_command *wdc_c = xfer->c_cmd;
1901 1.2 bouyer
1902 1.34 bouyer WDCDEBUG_PRINT(("__wdccommand_done %s:%d:%d\n",
1903 1.169 thorpej wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive),
1904 1.165 thorpej DEBUG_FUNCS);
1905 1.70 bouyer
1906 1.70 bouyer
1907 1.31 bouyer if (chp->ch_status & WDCS_DWF)
1908 1.31 bouyer wdc_c->flags |= AT_DF;
1909 1.31 bouyer if (chp->ch_status & WDCS_ERR) {
1910 1.31 bouyer wdc_c->flags |= AT_ERROR;
1911 1.31 bouyer wdc_c->r_error = chp->ch_error;
1912 1.31 bouyer }
1913 1.80 enami if ((wdc_c->flags & AT_READREG) != 0 &&
1914 1.169 thorpej (wdc->sc_dev.dv_flags & DVF_ACTIVE) != 0 &&
1915 1.75 enami (wdc_c->flags & (AT_ERROR | AT_DF)) == 0) {
1916 1.157 fvdl wdc_c->r_head = bus_space_read_1(chp->cmd_iot,
1917 1.157 fvdl chp->cmd_iohs[wd_sdh], 0);
1918 1.179 mycroft wdc_c->r_count = bus_space_read_1(chp->cmd_iot,
1919 1.179 mycroft chp->cmd_iohs[wd_seccnt], 0);
1920 1.179 mycroft wdc_c->r_sector = bus_space_read_1(chp->cmd_iot,
1921 1.179 mycroft chp->cmd_iohs[wd_sector], 0);
1922 1.179 mycroft wdc_c->r_cyl |= bus_space_read_1(chp->cmd_iot,
1923 1.179 mycroft chp->cmd_iohs[wd_cyl_lo], 0);
1924 1.157 fvdl wdc_c->r_cyl = bus_space_read_1(chp->cmd_iot,
1925 1.157 fvdl chp->cmd_iohs[wd_cyl_hi], 0) << 8;
1926 1.157 fvdl wdc_c->r_error = bus_space_read_1(chp->cmd_iot,
1927 1.157 fvdl chp->cmd_iohs[wd_error], 0);
1928 1.178 thorpej wdc_c->r_features = bus_space_read_1(chp->cmd_iot,
1929 1.178 thorpej chp->cmd_iohs[wd_features], 0);
1930 1.135 bouyer }
1931 1.186 bouyer callout_stop(&chp->ch_callout);
1932 1.187 bouyer chp->ch_queue->active_xfer = NULL;
1933 1.187 bouyer if (wdc_c->flags & AT_POLL) {
1934 1.187 bouyer /* enable interrupts */
1935 1.187 bouyer bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
1936 1.187 bouyer WDCTL_4BIT);
1937 1.187 bouyer delay(10); /* some drives need a little delay here */
1938 1.187 bouyer }
1939 1.187 bouyer if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_WAITDRAIN) {
1940 1.187 bouyer __wdccommand_kill_xfer(chp, xfer, KILL_GONE);
1941 1.187 bouyer chp->ch_drive[xfer->c_drive].drive_flags &= ~DRIVE_WAITDRAIN;
1942 1.187 bouyer wakeup(&chp->ch_queue->active_xfer);
1943 1.187 bouyer } else
1944 1.187 bouyer __wdccommand_done_end(chp, xfer);
1945 1.182 bouyer }
1946 1.137 bouyer
1947 1.182 bouyer static void
1948 1.182 bouyer __wdccommand_done_end(struct wdc_channel *chp, struct ata_xfer *xfer)
1949 1.182 bouyer {
1950 1.182 bouyer struct wdc_command *wdc_c = xfer->c_cmd;
1951 1.182 bouyer
1952 1.182 bouyer wdc_c->flags |= AT_DONE;
1953 1.31 bouyer wdc_free_xfer(chp, xfer);
1954 1.71 bouyer if (wdc_c->flags & AT_WAIT)
1955 1.71 bouyer wakeup(wdc_c);
1956 1.71 bouyer else if (wdc_c->callback)
1957 1.71 bouyer wdc_c->callback(wdc_c->callback_arg);
1958 1.45 drochner wdcstart(chp);
1959 1.31 bouyer return;
1960 1.2 bouyer }
1961 1.2 bouyer
1962 1.182 bouyer static void
1963 1.182 bouyer __wdccommand_kill_xfer(struct wdc_channel *chp, struct ata_xfer *xfer,
1964 1.182 bouyer int reason)
1965 1.182 bouyer {
1966 1.182 bouyer struct wdc_command *wdc_c = xfer->c_cmd;
1967 1.182 bouyer
1968 1.182 bouyer switch (reason) {
1969 1.182 bouyer case KILL_GONE:
1970 1.182 bouyer wdc_c->flags |= AT_GONE;
1971 1.182 bouyer break;
1972 1.182 bouyer case KILL_RESET:
1973 1.182 bouyer wdc_c->flags |= AT_RESET;
1974 1.182 bouyer break;
1975 1.182 bouyer default:
1976 1.182 bouyer printf("__wdccommand_kill_xfer: unknown reason %d\n",
1977 1.182 bouyer reason);
1978 1.182 bouyer panic("__wdccommand_kill_xfer");
1979 1.182 bouyer }
1980 1.182 bouyer __wdccommand_done_end(chp, xfer);
1981 1.182 bouyer }
1982 1.182 bouyer
1983 1.2 bouyer /*
1984 1.31 bouyer * Send a command. The drive should be ready.
1985 1.2 bouyer * Assumes interrupts are blocked.
1986 1.2 bouyer */
1987 1.31 bouyer void
1988 1.168 thorpej wdccommand(struct wdc_channel *chp, u_int8_t drive, u_int8_t command,
1989 1.163 thorpej u_int16_t cylin, u_int8_t head, u_int8_t sector, u_int8_t count,
1990 1.178 thorpej u_int8_t features)
1991 1.31 bouyer {
1992 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
1993 1.163 thorpej
1994 1.31 bouyer WDCDEBUG_PRINT(("wdccommand %s:%d:%d: command=0x%x cylin=%d head=%d "
1995 1.178 thorpej "sector=%d count=%d features=%d\n", wdc->sc_dev.dv_xname,
1996 1.169 thorpej chp->ch_channel, drive, command, cylin, head, sector, count,
1997 1.178 thorpej features), DEBUG_FUNCS);
1998 1.31 bouyer
1999 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_SELECT)
2000 1.169 thorpej wdc->select(chp,drive);
2001 1.107 dbj
2002 1.31 bouyer /* Select drive, head, and addressing mode. */
2003 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
2004 1.31 bouyer WDSD_IBM | (drive << 4) | head);
2005 1.177 thorpej /* Load parameters into the wd_features register. */
2006 1.177 thorpej bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_features], 0,
2007 1.178 thorpej features);
2008 1.179 mycroft bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_seccnt], 0, count);
2009 1.179 mycroft bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sector], 0, sector);
2010 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_cyl_lo], 0, cylin);
2011 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_cyl_hi],
2012 1.157 fvdl 0, cylin >> 8);
2013 1.108 christos
2014 1.108 christos /* Send command. */
2015 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_command], 0, command);
2016 1.108 christos return;
2017 1.108 christos }
2018 1.108 christos
2019 1.108 christos /*
2020 1.108 christos * Send a 48-bit addressing command. The drive should be ready.
2021 1.108 christos * Assumes interrupts are blocked.
2022 1.108 christos */
2023 1.108 christos void
2024 1.168 thorpej wdccommandext(struct wdc_channel *chp, u_int8_t drive, u_int8_t command,
2025 1.163 thorpej u_int64_t blkno, u_int16_t count)
2026 1.108 christos {
2027 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
2028 1.163 thorpej
2029 1.108 christos WDCDEBUG_PRINT(("wdccommandext %s:%d:%d: command=0x%x blkno=%d "
2030 1.169 thorpej "count=%d\n", wdc->sc_dev.dv_xname,
2031 1.169 thorpej chp->ch_channel, drive, command, (u_int32_t) blkno, count),
2032 1.108 christos DEBUG_FUNCS);
2033 1.108 christos
2034 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_SELECT)
2035 1.169 thorpej wdc->select(chp,drive);
2036 1.108 christos
2037 1.108 christos /* Select drive, head, and addressing mode. */
2038 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
2039 1.108 christos (drive << 4) | WDSD_LBA);
2040 1.108 christos
2041 1.108 christos /* previous */
2042 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_features], 0, 0);
2043 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_seccnt],
2044 1.157 fvdl 0, count >> 8);
2045 1.179 mycroft bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_lba_lo],
2046 1.179 mycroft 0, blkno >> 24);
2047 1.179 mycroft bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_lba_mi],
2048 1.179 mycroft 0, blkno >> 32);
2049 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_lba_hi],
2050 1.157 fvdl 0, blkno >> 40);
2051 1.108 christos
2052 1.108 christos /* current */
2053 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_features], 0, 0);
2054 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_seccnt], 0, count);
2055 1.179 mycroft bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_lba_lo], 0, blkno);
2056 1.179 mycroft bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_lba_mi],
2057 1.179 mycroft 0, blkno >> 8);
2058 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_lba_hi],
2059 1.157 fvdl 0, blkno >> 16);
2060 1.2 bouyer
2061 1.31 bouyer /* Send command. */
2062 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_command], 0, command);
2063 1.31 bouyer return;
2064 1.2 bouyer }
2065 1.2 bouyer
2066 1.2 bouyer /*
2067 1.31 bouyer * Simplified version of wdccommand(). Unbusy/ready/drq must be
2068 1.31 bouyer * tested by the caller.
2069 1.2 bouyer */
2070 1.31 bouyer void
2071 1.168 thorpej wdccommandshort(struct wdc_channel *chp, int drive, int command)
2072 1.2 bouyer {
2073 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
2074 1.2 bouyer
2075 1.31 bouyer WDCDEBUG_PRINT(("wdccommandshort %s:%d:%d command 0x%x\n",
2076 1.169 thorpej wdc->sc_dev.dv_xname, chp->ch_channel, drive, command),
2077 1.31 bouyer DEBUG_FUNCS);
2078 1.107 dbj
2079 1.169 thorpej if (wdc->cap & WDC_CAPABILITY_SELECT)
2080 1.169 thorpej wdc->select(chp,drive);
2081 1.2 bouyer
2082 1.31 bouyer /* Select drive. */
2083 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
2084 1.31 bouyer WDSD_IBM | (drive << 4));
2085 1.2 bouyer
2086 1.157 fvdl bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_command], 0, command);
2087 1.31 bouyer }
2088 1.2 bouyer
2089 1.31 bouyer /* Add a command to the queue and start controller. Must be called at splbio */
2090 1.2 bouyer void
2091 1.168 thorpej wdc_exec_xfer(struct wdc_channel *chp, struct ata_xfer *xfer)
2092 1.2 bouyer {
2093 1.163 thorpej
2094 1.33 bouyer WDCDEBUG_PRINT(("wdc_exec_xfer %p channel %d drive %d\n", xfer,
2095 1.169 thorpej chp->ch_channel, xfer->c_drive), DEBUG_XFERS);
2096 1.2 bouyer
2097 1.31 bouyer /* complete xfer setup */
2098 1.165 thorpej xfer->c_chp = chp;
2099 1.2 bouyer
2100 1.2 bouyer /* insert at the end of command list */
2101 1.165 thorpej TAILQ_INSERT_TAIL(&chp->ch_queue->queue_xfer, xfer, c_xferchain);
2102 1.31 bouyer WDCDEBUG_PRINT(("wdcstart from wdc_exec_xfer, flags 0x%x\n",
2103 1.33 bouyer chp->ch_flags), DEBUG_XFERS);
2104 1.45 drochner wdcstart(chp);
2105 1.31 bouyer }
2106 1.2 bouyer
2107 1.165 thorpej struct ata_xfer *
2108 1.163 thorpej wdc_get_xfer(int flags)
2109 1.2 bouyer {
2110 1.165 thorpej struct ata_xfer *xfer;
2111 1.72 bouyer int s;
2112 1.2 bouyer
2113 1.72 bouyer s = splbio();
2114 1.71 bouyer xfer = pool_get(&wdc_xfer_pool,
2115 1.71 bouyer ((flags & WDC_NOSLEEP) != 0 ? PR_NOWAIT : PR_WAITOK));
2116 1.72 bouyer splx(s);
2117 1.99 chs if (xfer != NULL) {
2118 1.165 thorpej memset(xfer, 0, sizeof(struct ata_xfer));
2119 1.99 chs }
2120 1.2 bouyer return xfer;
2121 1.2 bouyer }
2122 1.2 bouyer
2123 1.2 bouyer void
2124 1.168 thorpej wdc_free_xfer(struct wdc_channel *chp, struct ata_xfer *xfer)
2125 1.2 bouyer {
2126 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
2127 1.2 bouyer int s;
2128 1.2 bouyer
2129 1.31 bouyer if (wdc->cap & WDC_CAPABILITY_HWLOCK)
2130 1.31 bouyer (*wdc->free_hw)(chp);
2131 1.2 bouyer s = splbio();
2132 1.72 bouyer pool_put(&wdc_xfer_pool, xfer);
2133 1.2 bouyer splx(s);
2134 1.75 enami }
2135 1.75 enami
2136 1.75 enami /*
2137 1.168 thorpej * Kill off all pending xfers for a wdc_channel.
2138 1.75 enami *
2139 1.75 enami * Must be called at splbio().
2140 1.75 enami */
2141 1.75 enami void
2142 1.187 bouyer wdc_kill_pending(struct ata_drive_datas *drvp)
2143 1.75 enami {
2144 1.187 bouyer struct wdc_channel *chp = drvp->chnl_softc;
2145 1.186 bouyer struct ata_xfer *xfer, *next_xfer;
2146 1.187 bouyer int s = splbio();
2147 1.75 enami
2148 1.186 bouyer for (xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer);
2149 1.186 bouyer xfer != NULL; xfer = next_xfer) {
2150 1.186 bouyer next_xfer = TAILQ_NEXT(xfer, c_xferchain);
2151 1.187 bouyer if (xfer->c_chp != chp || xfer->c_drive != drvp->drive)
2152 1.186 bouyer continue;
2153 1.186 bouyer TAILQ_REMOVE(&chp->ch_queue->queue_xfer, xfer, c_xferchain);
2154 1.182 bouyer (*xfer->c_kill_xfer)(chp, xfer, KILL_GONE);
2155 1.75 enami }
2156 1.187 bouyer
2157 1.187 bouyer while ((xfer = chp->ch_queue->active_xfer) != NULL) {
2158 1.187 bouyer if (xfer->c_chp == chp && xfer->c_drive == drvp->drive) {
2159 1.187 bouyer drvp->drive_flags |= DRIVE_WAITDRAIN;
2160 1.187 bouyer (void) tsleep(&chp->ch_queue->active_xfer,
2161 1.187 bouyer PRIBIO, "atdrn", 0);
2162 1.187 bouyer } else {
2163 1.187 bouyer /* no more xfer for us */
2164 1.187 bouyer break;
2165 1.187 bouyer }
2166 1.187 bouyer }
2167 1.187 bouyer splx(s);
2168 1.2 bouyer }
2169 1.2 bouyer
2170 1.31 bouyer static void
2171 1.168 thorpej __wdcerror(struct wdc_channel *chp, char *msg)
2172 1.2 bouyer {
2173 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
2174 1.165 thorpej struct ata_xfer *xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer);
2175 1.88 mrg
2176 1.2 bouyer if (xfer == NULL)
2177 1.169 thorpej printf("%s:%d: %s\n", wdc->sc_dev.dv_xname, chp->ch_channel,
2178 1.31 bouyer msg);
2179 1.2 bouyer else
2180 1.169 thorpej printf("%s:%d:%d: %s\n", wdc->sc_dev.dv_xname,
2181 1.169 thorpej chp->ch_channel, xfer->c_drive, msg);
2182 1.2 bouyer }
2183 1.2 bouyer
2184 1.2 bouyer /*
2185 1.2 bouyer * the bit bucket
2186 1.2 bouyer */
2187 1.2 bouyer void
2188 1.168 thorpej wdcbit_bucket(struct wdc_channel *chp, int size)
2189 1.2 bouyer {
2190 1.2 bouyer
2191 1.12 cgd for (; size >= 2; size -= 2)
2192 1.157 fvdl (void)bus_space_read_2(chp->cmd_iot, chp->cmd_iohs[wd_data], 0);
2193 1.12 cgd if (size)
2194 1.157 fvdl (void)bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_data], 0);
2195 1.44 thorpej }
2196 1.44 thorpej
2197 1.44 thorpej int
2198 1.168 thorpej wdc_addref(struct wdc_channel *chp)
2199 1.44 thorpej {
2200 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
2201 1.96 bouyer struct scsipi_adapter *adapt = &wdc->sc_atapi_adapter._generic;
2202 1.44 thorpej int s, error = 0;
2203 1.44 thorpej
2204 1.44 thorpej s = splbio();
2205 1.96 bouyer if (adapt->adapt_refcnt++ == 0 &&
2206 1.96 bouyer adapt->adapt_enable != NULL) {
2207 1.96 bouyer error = (*adapt->adapt_enable)(&wdc->sc_dev, 1);
2208 1.44 thorpej if (error)
2209 1.96 bouyer adapt->adapt_refcnt--;
2210 1.44 thorpej }
2211 1.44 thorpej splx(s);
2212 1.44 thorpej return (error);
2213 1.44 thorpej }
2214 1.44 thorpej
2215 1.44 thorpej void
2216 1.168 thorpej wdc_delref(struct wdc_channel *chp)
2217 1.44 thorpej {
2218 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
2219 1.96 bouyer struct scsipi_adapter *adapt = &wdc->sc_atapi_adapter._generic;
2220 1.44 thorpej int s;
2221 1.44 thorpej
2222 1.44 thorpej s = splbio();
2223 1.96 bouyer if (adapt->adapt_refcnt-- == 1 &&
2224 1.96 bouyer adapt->adapt_enable != NULL)
2225 1.96 bouyer (void) (*adapt->adapt_enable)(&wdc->sc_dev, 0);
2226 1.44 thorpej splx(s);
2227 1.93 wrstuden }
2228 1.93 wrstuden
2229 1.93 wrstuden void
2230 1.168 thorpej wdc_print_modes(struct wdc_channel *chp)
2231 1.93 wrstuden {
2232 1.169 thorpej struct wdc_softc *wdc = chp->ch_wdc;
2233 1.93 wrstuden int drive;
2234 1.93 wrstuden struct ata_drive_datas *drvp;
2235 1.93 wrstuden
2236 1.93 wrstuden for (drive = 0; drive < 2; drive++) {
2237 1.93 wrstuden drvp = &chp->ch_drive[drive];
2238 1.93 wrstuden if ((drvp->drive_flags & DRIVE) == 0)
2239 1.93 wrstuden continue;
2240 1.123 thorpej aprint_normal("%s(%s:%d:%d): using PIO mode %d",
2241 1.93 wrstuden drvp->drv_softc->dv_xname,
2242 1.169 thorpej wdc->sc_dev.dv_xname,
2243 1.169 thorpej chp->ch_channel, drive, drvp->PIO_mode);
2244 1.93 wrstuden if (drvp->drive_flags & DRIVE_DMA)
2245 1.123 thorpej aprint_normal(", DMA mode %d", drvp->DMA_mode);
2246 1.93 wrstuden if (drvp->drive_flags & DRIVE_UDMA) {
2247 1.123 thorpej aprint_normal(", Ultra-DMA mode %d", drvp->UDMA_mode);
2248 1.93 wrstuden if (drvp->UDMA_mode == 2)
2249 1.123 thorpej aprint_normal(" (Ultra/33)");
2250 1.93 wrstuden else if (drvp->UDMA_mode == 4)
2251 1.123 thorpej aprint_normal(" (Ultra/66)");
2252 1.93 wrstuden else if (drvp->UDMA_mode == 5)
2253 1.123 thorpej aprint_normal(" (Ultra/100)");
2254 1.123 thorpej else if (drvp->UDMA_mode == 6)
2255 1.123 thorpej aprint_normal(" (Ultra/133)");
2256 1.93 wrstuden }
2257 1.93 wrstuden if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA))
2258 1.123 thorpej aprint_normal(" (using DMA data transfers)");
2259 1.123 thorpej aprint_normal("\n");
2260 1.93 wrstuden }
2261 1.2 bouyer }
2262 1.190 mycroft
2263 1.190 mycroft void
2264 1.190 mycroft wdc_datain_pio(chp, flags, buf, len)
2265 1.190 mycroft struct wdc_channel *chp;
2266 1.190 mycroft int flags;
2267 1.190 mycroft void *buf;
2268 1.190 mycroft size_t len;
2269 1.190 mycroft {
2270 1.190 mycroft
2271 1.190 mycroft if (flags & DRIVE_NOSTREAM) {
2272 1.190 mycroft if (flags & DRIVE_CAP32) {
2273 1.190 mycroft bus_space_read_multi_4(chp->data32iot,
2274 1.190 mycroft chp->data32ioh, 0, buf, len >> 2);
2275 1.190 mycroft buf = (char *)buf + (len & ~3);
2276 1.190 mycroft len &= 3;
2277 1.190 mycroft }
2278 1.190 mycroft if (len) {
2279 1.190 mycroft bus_space_read_multi_2(chp->cmd_iot,
2280 1.190 mycroft chp->cmd_iohs[wd_data], 0, buf, len >> 1);
2281 1.190 mycroft }
2282 1.190 mycroft } else {
2283 1.190 mycroft if (flags & DRIVE_CAP32) {
2284 1.190 mycroft bus_space_read_multi_stream_4(chp->data32iot,
2285 1.190 mycroft chp->data32ioh, 0, buf, len >> 2);
2286 1.190 mycroft buf = (char *)buf + (len & ~3);
2287 1.190 mycroft len &= 3;
2288 1.190 mycroft }
2289 1.190 mycroft if (len) {
2290 1.190 mycroft bus_space_read_multi_stream_2(chp->cmd_iot,
2291 1.190 mycroft chp->cmd_iohs[wd_data], 0, buf, len >> 1);
2292 1.190 mycroft }
2293 1.190 mycroft }
2294 1.190 mycroft }
2295 1.190 mycroft
2296 1.190 mycroft void
2297 1.190 mycroft wdc_dataout_pio(chp, flags, buf, len)
2298 1.190 mycroft struct wdc_channel *chp;
2299 1.190 mycroft int flags;
2300 1.190 mycroft void *buf;
2301 1.190 mycroft size_t len;
2302 1.190 mycroft {
2303 1.190 mycroft
2304 1.190 mycroft if (flags & DRIVE_NOSTREAM) {
2305 1.190 mycroft if (flags & DRIVE_CAP32) {
2306 1.190 mycroft bus_space_write_multi_4(chp->data32iot,
2307 1.190 mycroft chp->data32ioh, 0, buf, len >> 2);
2308 1.190 mycroft buf = (char *)buf + (len & ~3);
2309 1.190 mycroft len &= 3;
2310 1.190 mycroft }
2311 1.190 mycroft if (len) {
2312 1.190 mycroft bus_space_write_multi_2(chp->cmd_iot,
2313 1.190 mycroft chp->cmd_iohs[wd_data], 0, buf, len >> 1);
2314 1.190 mycroft }
2315 1.190 mycroft } else {
2316 1.190 mycroft if (flags & DRIVE_CAP32) {
2317 1.190 mycroft bus_space_write_multi_stream_4(chp->data32iot,
2318 1.190 mycroft chp->data32ioh, 0, buf, len >> 2);
2319 1.190 mycroft buf = (char *)buf + (len & ~3);
2320 1.190 mycroft len &= 3;
2321 1.190 mycroft }
2322 1.190 mycroft if (len) {
2323 1.190 mycroft bus_space_write_multi_stream_2(chp->cmd_iot,
2324 1.190 mycroft chp->cmd_iohs[wd_data], 0, buf, len >> 1);
2325 1.190 mycroft }
2326 1.190 mycroft }
2327 1.190 mycroft }
2328