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