Line data Source code
1 : /* $OpenBSD: ata_wdc.c,v 1.51 2017/12/30 20:46:59 guenther Exp $ */
2 : /* $NetBSD: ata_wdc.c,v 1.21 1999/08/09 09:43:11 bouyer Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1998, 2001 Manuel Bouyer.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : *
27 : */
28 :
29 : /*-
30 : * Copyright (c) 1998 The NetBSD Foundation, Inc.
31 : * All rights reserved.
32 : *
33 : * This code is derived from software contributed to The NetBSD Foundation
34 : * by Charles M. Hannum, by Onno van der Linden and by Manuel Bouyer.
35 : *
36 : * Redistribution and use in source and binary forms, with or without
37 : * modification, are permitted provided that the following conditions
38 : * are met:
39 : * 1. Redistributions of source code must retain the above copyright
40 : * notice, this list of conditions and the following disclaimer.
41 : * 2. Redistributions in binary form must reproduce the above copyright
42 : * notice, this list of conditions and the following disclaimer in the
43 : * documentation and/or other materials provided with the distribution.
44 : *
45 : * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
46 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
47 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
49 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55 : * POSSIBILITY OF SUCH DAMAGE.
56 : */
57 :
58 : #include <sys/param.h>
59 : #include <sys/systm.h>
60 : #include <sys/kernel.h>
61 : #include <sys/stat.h>
62 : #include <sys/buf.h>
63 : #include <sys/malloc.h>
64 : #include <sys/device.h>
65 : #include <sys/disklabel.h>
66 : #include <sys/disk.h>
67 : #include <sys/syslog.h>
68 :
69 : #include <machine/intr.h>
70 : #include <machine/bus.h>
71 :
72 : #include <dev/ata/atavar.h>
73 : #include <dev/ic/wdcreg.h>
74 : #include <dev/ic/wdcvar.h>
75 : #include <dev/ata/wdvar.h>
76 :
77 : #ifdef HIBERNATE
78 : #include <sys/hibernate.h>
79 : #endif
80 :
81 : #define DEBUG_INTR 0x01
82 : #define DEBUG_XFERS 0x02
83 : #define DEBUG_STATUS 0x04
84 : #define DEBUG_FUNCS 0x08
85 : #define DEBUG_PROBE 0x10
86 :
87 : #ifdef WDCDEBUG
88 : #ifndef WDCDEBUG_WD_MASK
89 : #define WDCDEBUG_WD_MASK 0x00
90 : #endif
91 : int wdcdebug_wd_mask = WDCDEBUG_WD_MASK;
92 : #define WDCDEBUG_PRINT(args, level) do { \
93 : if ((wdcdebug_wd_mask & (level)) != 0) \
94 : printf args; \
95 : } while (0)
96 : #else
97 : #define WDCDEBUG_PRINT(args, level)
98 : #endif
99 :
100 : #define ATA_DELAY 45000 /* 45s for a drive I/O */
101 :
102 : void wdc_ata_bio_start(struct channel_softc *, struct wdc_xfer *);
103 : void _wdc_ata_bio_start(struct channel_softc *, struct wdc_xfer *);
104 : int wdc_ata_bio_intr(struct channel_softc *, struct wdc_xfer *, int);
105 : void wdc_ata_bio_kill_xfer(struct channel_softc *, struct wdc_xfer *);
106 : void wdc_ata_bio_done(struct channel_softc *, struct wdc_xfer *);
107 : int wdc_ata_ctrl_intr(struct channel_softc *, struct wdc_xfer *, int);
108 : int wdc_ata_err(struct ata_drive_datas *, struct ata_bio *);
109 : #define WDC_ATA_NOERR 0x00 /* Drive doesn't report an error */
110 : #define WDC_ATA_RECOV 0x01 /* There was a recovered error */
111 : #define WDC_ATA_ERR 0x02 /* Drive reports an error */
112 :
113 : #ifdef HIBERNATE
114 : int
115 0 : wd_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, size_t size, int op, void *page)
116 : {
117 : struct {
118 : struct wd_softc wd;
119 : struct wdc_xfer xfer;
120 : struct channel_softc chp;
121 : daddr_t poffset;
122 : size_t psize;
123 0 : } *my = page;
124 0 : struct wd_softc *real_wd, *wd = &my->wd;
125 0 : struct wdc_xfer *xfer = &my->xfer;
126 0 : struct channel_softc *chp = &my->chp;
127 : struct ata_bio *ata_bio;
128 : extern struct cfdriver wd_cd;
129 :
130 : /* early call for initialization */
131 0 : if (op == HIB_INIT) {
132 0 : my->poffset = blkno;
133 0 : my->psize = size;
134 0 : return(0);
135 : }
136 :
137 0 : real_wd = (struct wd_softc *)disk_lookup(&wd_cd, DISKUNIT(dev));
138 0 : if (real_wd == NULL)
139 0 : return (ENODEV);
140 :
141 0 : if (op == HIB_DONE) {
142 0 : struct wdc_softc *wdc = chp->wdc;
143 0 : config_suspend(&wdc->sc_dev, DVACT_RESUME);
144 : return (0);
145 : }
146 :
147 0 : if (blkno > my->psize)
148 0 : return (E2BIG);
149 0 : blkno += my->poffset;
150 :
151 : /*
152 : * Craft a fake set of softc and related structures
153 : * which we think the driver modifies. Some of these will
154 : * have pointers which reach to unsafe places, but..
155 : */
156 0 : bcopy(real_wd->drvp->chnl_softc, &my->chp, sizeof my->chp);
157 0 : chp->ch_drive[0].chnl_softc = chp;
158 0 : chp->ch_drive[1].chnl_softc = chp;
159 :
160 0 : bcopy(real_wd, &my->wd, sizeof my->wd);
161 0 : ata_bio = &wd->sc_wdc_bio;
162 0 : ata_bio->wd = wd; /* fixup ata_bio->wd */
163 0 : wd->drvp = &chp->ch_drive[real_wd->drvp->drive];
164 :
165 : /* Fill the request and submit it */
166 0 : wd->sc_wdc_bio.blkno = blkno;
167 0 : wd->sc_wdc_bio.flags = ATA_POLL | ATA_LBA48;
168 0 : if (op == HIB_R)
169 0 : wd->sc_wdc_bio.flags |= ATA_READ;
170 0 : wd->sc_wdc_bio.bcount = size;
171 0 : wd->sc_wdc_bio.databuf = (caddr_t)addr;
172 0 : wd->sc_wdc_bio.wd = wd;
173 :
174 0 : bzero(&my->xfer, sizeof my->xfer);
175 0 : xfer->c_flags |= C_PRIVATEXFER; /* Our xfer is totally private */
176 0 : xfer->c_flags |= C_POLL;
177 0 : xfer->drive = wd->drvp->drive;
178 0 : xfer->cmd = ata_bio;
179 0 : xfer->databuf = ata_bio->databuf;
180 0 : xfer->c_bcount = ata_bio->bcount;
181 0 : xfer->c_start = wdc_ata_bio_start;
182 0 : xfer->c_intr = wdc_ata_bio_intr;
183 0 : xfer->c_kill_xfer = wdc_ata_bio_kill_xfer;
184 0 : wdc_exec_xfer(chp, xfer);
185 0 : return (ata_bio->flags & ATA_ITSDONE) ? 0 : EIO;
186 0 : }
187 : #endif /* HIBERNATE */
188 :
189 : /*
190 : * Handle block I/O operation. Return WDC_COMPLETE, WDC_QUEUED, or
191 : * WDC_TRY_AGAIN. Must be called at splbio().
192 : */
193 : int
194 0 : wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
195 : {
196 : struct wdc_xfer *xfer;
197 0 : struct channel_softc *chp = drvp->chnl_softc;
198 :
199 0 : xfer = wdc_get_xfer(WDC_NOSLEEP);
200 0 : if (xfer == NULL)
201 0 : return WDC_TRY_AGAIN;
202 0 : if (ata_bio->flags & ATA_POLL)
203 0 : xfer->c_flags |= C_POLL;
204 0 : if (!(ata_bio->flags & ATA_POLL) &&
205 0 : (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
206 0 : (ata_bio->flags & ATA_SINGLE) == 0 &&
207 0 : (ata_bio->bcount > 512 ||
208 0 : (chp->wdc->quirks & WDC_QUIRK_NOSHORTDMA) == 0))
209 0 : xfer->c_flags |= C_DMA;
210 0 : xfer->drive = drvp->drive;
211 0 : xfer->cmd = ata_bio;
212 0 : xfer->databuf = ata_bio->databuf;
213 0 : xfer->c_bcount = ata_bio->bcount;
214 0 : xfer->c_start = wdc_ata_bio_start;
215 0 : xfer->c_intr = wdc_ata_bio_intr;
216 0 : xfer->c_kill_xfer = wdc_ata_bio_kill_xfer;
217 0 : wdc_exec_xfer(chp, xfer);
218 0 : return (ata_bio->flags & ATA_ITSDONE) ? WDC_COMPLETE : WDC_QUEUED;
219 0 : }
220 :
221 : void
222 0 : wdc_ata_bio_start(struct channel_softc *chp, struct wdc_xfer *xfer)
223 : {
224 0 : struct ata_bio *ata_bio = xfer->cmd;
225 : WDCDEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
226 : chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
227 : DEBUG_XFERS);
228 :
229 : /* start timeout machinery */
230 0 : if ((ata_bio->flags & ATA_POLL) == 0)
231 0 : timeout_add_msec(&chp->ch_timo, ATA_DELAY);
232 0 : _wdc_ata_bio_start(chp, xfer);
233 0 : }
234 :
235 : void
236 0 : _wdc_ata_bio_start(struct channel_softc *chp, struct wdc_xfer *xfer)
237 : {
238 0 : struct ata_bio *ata_bio = xfer->cmd;
239 0 : struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
240 : u_int16_t cyl;
241 : u_int8_t head, sect, cmd = 0;
242 : int nblks;
243 : int ata_delay;
244 : int error, dma_flags = 0;
245 :
246 : WDCDEBUG_PRINT(("_wdc_ata_bio_start %s:%d:%d\n",
247 : chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
248 : DEBUG_INTR | DEBUG_XFERS);
249 : /* Do control operations specially. */
250 0 : if (drvp->state < READY) {
251 : /*
252 : * Actually, we want to be careful not to mess with the control
253 : * state if the device is currently busy, but we can assume
254 : * that we never get to this point if that's the case.
255 : */
256 : /* at this point, we should only be in RECAL state */
257 0 : if (drvp->state != RECAL) {
258 0 : printf("%s:%d:%d: bad state %d in _wdc_ata_bio_start\n",
259 0 : chp->wdc->sc_dev.dv_xname, chp->channel,
260 0 : xfer->drive, drvp->state);
261 0 : panic("_wdc_ata_bio_start: bad state");
262 : }
263 0 : xfer->c_intr = wdc_ata_ctrl_intr;
264 0 : wdc_set_drive(chp, xfer->drive);
265 0 : if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY) != 0)
266 : goto timeout;
267 0 : wdccommandshort(chp, xfer->drive, WDCC_RECAL);
268 0 : drvp->state = RECAL_WAIT;
269 0 : if ((ata_bio->flags & ATA_POLL) == 0) {
270 0 : chp->ch_flags |= WDCF_IRQ_WAIT;
271 0 : } else {
272 : /* Wait for at last 400ns for status bit to be valid */
273 0 : DELAY(1);
274 0 : wdc_ata_ctrl_intr(chp, xfer, 0);
275 : }
276 0 : return;
277 : }
278 :
279 0 : if (xfer->c_flags & C_DMA) {
280 0 : if (drvp->n_xfers <= NXFER)
281 0 : drvp->n_xfers++;
282 0 : dma_flags = (ata_bio->flags & ATA_READ) ? WDC_DMA_READ : 0;
283 0 : if (ata_bio->flags & ATA_LBA48)
284 0 : dma_flags |= WDC_DMA_LBA48;
285 : }
286 0 : if (ata_bio->flags & ATA_SINGLE)
287 : ata_delay = ATA_DELAY;
288 : else
289 : ata_delay = ATA_DELAY;
290 : again:
291 : /*
292 : *
293 : * When starting a multi-sector transfer, or doing single-sector
294 : * transfers...
295 : */
296 0 : if (xfer->c_skip == 0 || (ata_bio->flags & ATA_SINGLE) != 0) {
297 0 : if (ata_bio->flags & ATA_SINGLE)
298 0 : nblks = 1;
299 : else
300 0 : nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
301 0 : if (ata_bio->flags & ATA_LBA) {
302 0 : sect = (ata_bio->blkno >> 0) & 0xff;
303 0 : cyl = (ata_bio->blkno >> 8) & 0xffff;
304 0 : head = (ata_bio->blkno >> 24) & 0x0f;
305 0 : head |= WDSD_LBA;
306 0 : } else {
307 0 : int blkno = ata_bio->blkno;
308 0 : sect = blkno % ata_bio->lp->d_nsectors;
309 0 : sect++; /* Sectors begin with 1, not 0. */
310 0 : blkno /= ata_bio->lp->d_nsectors;
311 0 : head = blkno % ata_bio->lp->d_ntracks;
312 0 : blkno /= ata_bio->lp->d_ntracks;
313 0 : cyl = blkno;
314 0 : head |= WDSD_CHS;
315 : }
316 0 : if (xfer->c_flags & C_DMA) {
317 0 : ata_bio->nblks = nblks;
318 0 : ata_bio->nbytes = xfer->c_bcount;
319 0 : if (ata_bio->flags & ATA_LBA48)
320 0 : cmd = (ata_bio->flags & ATA_READ) ?
321 : WDCC_READDMA_EXT : WDCC_WRITEDMA_EXT;
322 : else
323 0 : cmd = (ata_bio->flags & ATA_READ) ?
324 : WDCC_READDMA : WDCC_WRITEDMA;
325 : /* Init the DMA channel. */
326 0 : error = (*chp->wdc->dma_init)(chp->wdc->dma_arg,
327 0 : chp->channel, xfer->drive,
328 0 : (char *)xfer->databuf + xfer->c_skip,
329 0 : ata_bio->nbytes, dma_flags);
330 0 : if (error) {
331 0 : if (error == EINVAL) {
332 : /*
333 : * We can't do DMA on this transfer
334 : * for some reason. Fall back to
335 : * PIO.
336 : */
337 0 : xfer->c_flags &= ~C_DMA;
338 : error = 0;
339 0 : goto do_pio;
340 : }
341 0 : ata_bio->error = ERR_DMA;
342 0 : ata_bio->r_error = 0;
343 0 : wdc_ata_bio_done(chp, xfer);
344 0 : return;
345 : }
346 : /* Initiate command */
347 0 : wdc_set_drive(chp, xfer->drive);
348 0 : if (wait_for_ready(chp, ata_delay) < 0)
349 : goto timeout;
350 :
351 : /* start the DMA channel (before) */
352 0 : if (chp->ch_flags & WDCF_DMA_BEFORE_CMD)
353 0 : (*chp->wdc->dma_start)(chp->wdc->dma_arg,
354 0 : chp->channel, xfer->drive);
355 :
356 0 : if (ata_bio->flags & ATA_LBA48) {
357 0 : wdccommandext(chp, xfer->drive, cmd,
358 0 : (u_int64_t)ata_bio->blkno, nblks);
359 0 : } else {
360 0 : wdccommand(chp, xfer->drive, cmd, cyl,
361 0 : head, sect, nblks, 0);
362 : }
363 :
364 : /* start the DMA channel (after) */
365 0 : if ((chp->ch_flags & WDCF_DMA_BEFORE_CMD) == 0)
366 0 : (*chp->wdc->dma_start)(chp->wdc->dma_arg,
367 0 : chp->channel, xfer->drive);
368 :
369 0 : chp->ch_flags |= WDCF_DMA_WAIT;
370 : /* wait for irq */
371 0 : goto intr;
372 : } /* else not DMA */
373 : do_pio:
374 0 : ata_bio->nblks = min(nblks, ata_bio->multi);
375 0 : ata_bio->nbytes = ata_bio->nblks * ata_bio->lp->d_secsize;
376 0 : KASSERT(nblks == 1 || (ata_bio->flags & ATA_SINGLE) == 0);
377 0 : if (ata_bio->nblks > 1) {
378 0 : if (ata_bio->flags & ATA_LBA48)
379 0 : cmd = (ata_bio->flags & ATA_READ) ?
380 : WDCC_READMULTI_EXT : WDCC_WRITEMULTI_EXT;
381 : else
382 0 : cmd = (ata_bio->flags & ATA_READ) ?
383 : WDCC_READMULTI : WDCC_WRITEMULTI;
384 : } else {
385 0 : if (ata_bio->flags & ATA_LBA48)
386 0 : cmd = (ata_bio->flags & ATA_READ) ?
387 : WDCC_READ_EXT : WDCC_WRITE_EXT;
388 : else
389 0 : cmd = (ata_bio->flags & ATA_READ) ?
390 : WDCC_READ : WDCC_WRITE;
391 : }
392 : /* Initiate command! */
393 0 : wdc_set_drive(chp, xfer->drive);
394 0 : if (wait_for_ready(chp, ata_delay) < 0)
395 : goto timeout;
396 0 : if (ata_bio->flags & ATA_LBA48) {
397 0 : wdccommandext(chp, xfer->drive, cmd,
398 0 : (u_int64_t)ata_bio->blkno, nblks);
399 0 : } else {
400 0 : wdccommand(chp, xfer->drive, cmd, cyl,
401 0 : head, sect, nblks, 0);
402 : }
403 0 : } else if (ata_bio->nblks > 1) {
404 : /* The number of blocks in the last stretch may be smaller. */
405 0 : nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
406 0 : if (ata_bio->nblks > nblks) {
407 0 : ata_bio->nblks = nblks;
408 0 : ata_bio->nbytes = xfer->c_bcount;
409 0 : }
410 : }
411 : /* If this was a write and not using DMA, push the data. */
412 0 : if ((ata_bio->flags & ATA_READ) == 0) {
413 0 : if (wait_for_drq(chp, ata_delay) != 0) {
414 0 : printf("%s:%d:%d: timeout waiting for DRQ, "
415 : "st=0x%b, err=0x%02x\n",
416 0 : chp->wdc->sc_dev.dv_xname, chp->channel,
417 0 : xfer->drive, chp->ch_status, WDCS_BITS,
418 0 : chp->ch_error);
419 0 : if (wdc_ata_err(drvp, ata_bio) != WDC_ATA_ERR)
420 0 : ata_bio->error = TIMEOUT;
421 0 : wdc_ata_bio_done(chp, xfer);
422 0 : return;
423 : }
424 0 : if (wdc_ata_err(drvp, ata_bio) == WDC_ATA_ERR) {
425 0 : wdc_ata_bio_done(chp, xfer);
426 0 : return;
427 : }
428 0 : wdc_output_bytes(drvp, (char *)xfer->databuf + xfer->c_skip,
429 0 : ata_bio->nbytes);
430 0 : }
431 :
432 : intr: /* Wait for IRQ (either real or polled) */
433 0 : if ((ata_bio->flags & ATA_POLL) == 0) {
434 0 : chp->ch_flags |= WDCF_IRQ_WAIT;
435 0 : } else {
436 : /* Wait for at last 400ns for status bit to be valid */
437 0 : delay(1);
438 0 : if (chp->ch_flags & WDCF_DMA_WAIT) {
439 0 : wdc_dmawait(chp, xfer, ATA_DELAY);
440 0 : chp->ch_flags &= ~WDCF_DMA_WAIT;
441 0 : }
442 0 : wdc_ata_bio_intr(chp, xfer, 0);
443 0 : if ((ata_bio->flags & ATA_ITSDONE) == 0)
444 0 : goto again;
445 : }
446 0 : return;
447 : timeout:
448 0 : if (chp->ch_status == 0xff)
449 0 : return;
450 0 : printf("%s:%d:%d: not ready, st=0x%b, err=0x%02x\n",
451 0 : chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
452 0 : chp->ch_status, WDCS_BITS, chp->ch_error);
453 0 : if (wdc_ata_err(drvp, ata_bio) != WDC_ATA_ERR)
454 0 : ata_bio->error = TIMEOUT;
455 0 : wdc_ata_bio_done(chp, xfer);
456 0 : return;
457 0 : }
458 :
459 : int
460 0 : wdc_ata_bio_intr(struct channel_softc *chp, struct wdc_xfer *xfer, int irq)
461 : {
462 0 : struct ata_bio *ata_bio = xfer->cmd;
463 0 : struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
464 : int drv_err;
465 :
466 : WDCDEBUG_PRINT(("wdc_ata_bio_intr %s:%d:%d\n",
467 : chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
468 : DEBUG_INTR | DEBUG_XFERS);
469 :
470 :
471 : /* Is it not a transfer, but a control operation? */
472 0 : if (drvp->state < READY) {
473 0 : printf("%s:%d:%d: bad state %d in wdc_ata_bio_intr\n",
474 0 : chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
475 : drvp->state);
476 0 : panic("wdc_ata_bio_intr: bad state");
477 : }
478 :
479 : /*
480 : * reset on timeout. This will cause extra resets in the case
481 : * of occasional lost interrupts
482 : */
483 0 : if (xfer->c_flags & C_TIMEOU)
484 : goto timeout;
485 :
486 : /* Ack interrupt done by wait_for_unbusy */
487 0 : if (wait_for_unbusy(chp,
488 0 : (irq == 0) ? ATA_DELAY : 0) < 0) {
489 0 : if (irq)
490 0 : return 0; /* IRQ was not for us */
491 0 : printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
492 0 : chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
493 0 : xfer->c_bcount, xfer->c_skip);
494 :
495 0 : goto timeout;
496 : }
497 0 : if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
498 0 : chp->wdc->irqack(chp);
499 :
500 0 : drv_err = wdc_ata_err(drvp, ata_bio);
501 :
502 0 : if (xfer->c_flags & C_DMA) {
503 0 : if (chp->wdc->dma_status != 0) {
504 0 : if (drv_err != WDC_ATA_ERR) {
505 0 : ata_bio->error = ERR_DMA;
506 : drv_err = WDC_ATA_ERR;
507 0 : }
508 : }
509 0 : if (chp->ch_status & WDCS_DRQ) {
510 0 : if (drv_err != WDC_ATA_ERR) {
511 0 : printf("%s:%d:%d: intr with DRQ (st=0x%b)\n",
512 0 : chp->wdc->sc_dev.dv_xname, chp->channel,
513 0 : xfer->drive, chp->ch_status, WDCS_BITS);
514 0 : ata_bio->error = TIMEOUT;
515 : drv_err = WDC_ATA_ERR;
516 0 : }
517 : }
518 0 : if (drv_err != WDC_ATA_ERR)
519 : goto end;
520 0 : ata_dmaerr(drvp);
521 0 : }
522 :
523 : /* if we had an error, end */
524 0 : if (drv_err == WDC_ATA_ERR) {
525 0 : wdc_ata_bio_done(chp, xfer);
526 0 : return 1;
527 : }
528 :
529 : /* If this was a read and not using DMA, fetch the data. */
530 0 : if ((ata_bio->flags & ATA_READ) != 0) {
531 0 : if ((chp->ch_status & WDCS_DRQ) != WDCS_DRQ) {
532 0 : printf("%s:%d:%d: read intr before drq\n",
533 0 : chp->wdc->sc_dev.dv_xname, chp->channel,
534 0 : xfer->drive);
535 0 : ata_bio->error = TIMEOUT;
536 0 : wdc_ata_bio_done(chp, xfer);
537 0 : return 1;
538 : }
539 0 : wdc_input_bytes(drvp, (char *)xfer->databuf + xfer->c_skip,
540 0 : ata_bio->nbytes);
541 0 : }
542 : end:
543 0 : ata_bio->blkno += ata_bio->nblks;
544 0 : ata_bio->blkdone += ata_bio->nblks;
545 0 : xfer->c_skip += ata_bio->nbytes;
546 0 : xfer->c_bcount -= ata_bio->nbytes;
547 : /* See if this transfer is complete. */
548 0 : if (xfer->c_bcount > 0) {
549 0 : if ((ata_bio->flags & ATA_POLL) == 0) {
550 : /* Start the next operation */
551 0 : _wdc_ata_bio_start(chp, xfer);
552 : } else {
553 : /* Let _wdc_ata_bio_start do the loop */
554 0 : return 1;
555 : }
556 0 : } else { /* Done with this transfer */
557 0 : ata_bio->error = NOERROR;
558 0 : wdc_ata_bio_done(chp, xfer);
559 : }
560 0 : return 1;
561 :
562 : timeout:
563 0 : if (xfer->c_flags & C_DMA)
564 0 : ata_dmaerr(drvp);
565 :
566 0 : ata_bio->error = TIMEOUT;
567 0 : wdc_ata_bio_done(chp, xfer);
568 0 : return 1;
569 0 : }
570 :
571 : void
572 0 : wdc_ata_bio_kill_xfer(struct channel_softc *chp, struct wdc_xfer *xfer)
573 : {
574 0 : struct ata_bio *ata_bio = xfer->cmd;
575 :
576 0 : timeout_del(&chp->ch_timo);
577 : /* remove this command from xfer queue */
578 0 : wdc_free_xfer(chp, xfer);
579 :
580 0 : ata_bio->flags |= ATA_ITSDONE;
581 0 : ata_bio->error = ERR_NODEV;
582 0 : ata_bio->r_error = WDCE_ABRT;
583 0 : if ((ata_bio->flags & ATA_POLL) == 0) {
584 : WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);
585 0 : wddone(ata_bio->wd);
586 0 : }
587 0 : }
588 :
589 : void
590 0 : wdc_ata_bio_done(struct channel_softc *chp, struct wdc_xfer *xfer)
591 : {
592 0 : struct ata_bio *ata_bio = xfer->cmd;
593 :
594 : WDCDEBUG_PRINT(("wdc_ata_bio_done %s:%d:%d: flags 0x%x\n",
595 : chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
596 : (u_int)xfer->c_flags),
597 : DEBUG_XFERS);
598 :
599 0 : if ((xfer->c_flags & C_PRIVATEXFER) == 0)
600 0 : timeout_del(&chp->ch_timo);
601 :
602 : /* feed back residual bcount to our caller */
603 0 : ata_bio->bcount = xfer->c_bcount;
604 :
605 : /* remove this command from xfer queue */
606 0 : wdc_free_xfer(chp, xfer);
607 :
608 0 : ata_bio->flags |= ATA_ITSDONE;
609 0 : if ((ata_bio->flags & ATA_POLL) == 0) {
610 : WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);
611 0 : wddone(ata_bio->wd);
612 0 : }
613 : WDCDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n",
614 : chp->ch_flags), DEBUG_XFERS);
615 0 : wdcstart(chp);
616 0 : }
617 :
618 : /*
619 : * Implement operations needed before read/write.
620 : */
621 : int
622 0 : wdc_ata_ctrl_intr(struct channel_softc *chp, struct wdc_xfer *xfer, int irq)
623 : {
624 0 : struct ata_bio *ata_bio = xfer->cmd;
625 0 : struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
626 : char *errstring = NULL;
627 0 : int delay = (irq == 0) ? ATA_DELAY : 0;
628 :
629 : WDCDEBUG_PRINT(("wdc_ata_ctrl_intr: state %d\n", drvp->state),
630 : DEBUG_FUNCS);
631 :
632 : again:
633 0 : switch (drvp->state) {
634 : case RECAL: /* Should not be in this state here */
635 0 : panic("wdc_ata_ctrl_intr: state==RECAL");
636 : break;
637 :
638 : case RECAL_WAIT:
639 : errstring = "recal";
640 0 : if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
641 : goto timeout;
642 0 : if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
643 0 : chp->wdc->irqack(chp);
644 0 : if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
645 : goto error;
646 : /* FALLTHROUGH */
647 :
648 : case PIOMODE:
649 : /* Don't try to set modes if controller can't be adjusted */
650 0 : if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)
651 : goto geometry;
652 : /* Also don't try if the drive didn't report its mode */
653 0 : if ((drvp->drive_flags & DRIVE_MODE) == 0)
654 : goto geometry;
655 : /* SET FEATURES 0x08 is only for PIO mode > 2 */
656 0 : if (drvp->PIO_mode <= 2)
657 : goto geometry;
658 0 : wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
659 0 : 0x08 | drvp->PIO_mode, WDSF_SET_MODE);
660 0 : drvp->state = PIOMODE_WAIT;
661 0 : break;
662 :
663 : case PIOMODE_WAIT:
664 : errstring = "piomode";
665 0 : if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
666 : goto timeout;
667 0 : if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
668 0 : chp->wdc->irqack(chp);
669 0 : if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
670 : goto error;
671 : /* FALLTHROUGH */
672 :
673 : case DMAMODE:
674 0 : if (drvp->drive_flags & DRIVE_UDMA) {
675 0 : wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
676 0 : 0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
677 0 : } else if (drvp->drive_flags & DRIVE_DMA) {
678 0 : wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
679 0 : 0x20 | drvp->DMA_mode, WDSF_SET_MODE);
680 : } else {
681 : goto geometry;
682 : }
683 0 : drvp->state = DMAMODE_WAIT;
684 0 : break;
685 : case DMAMODE_WAIT:
686 : errstring = "dmamode";
687 0 : if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
688 : goto timeout;
689 0 : if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
690 0 : chp->wdc->irqack(chp);
691 0 : if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
692 : goto error;
693 : /* FALLTHROUGH */
694 :
695 : case GEOMETRY:
696 : geometry:
697 0 : if (ata_bio->flags & ATA_LBA)
698 : goto multimode;
699 0 : wdccommand(chp, xfer->drive, WDCC_IDP,
700 0 : ata_bio->lp->d_ncylinders,
701 0 : ata_bio->lp->d_ntracks - 1, 0, ata_bio->lp->d_nsectors, 0);
702 0 : drvp->state = GEOMETRY_WAIT;
703 0 : break;
704 :
705 : case GEOMETRY_WAIT:
706 : errstring = "geometry";
707 0 : if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
708 : goto timeout;
709 0 : if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
710 0 : chp->wdc->irqack(chp);
711 0 : if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
712 : goto error;
713 : /* FALLTHROUGH */
714 :
715 : case MULTIMODE:
716 : multimode:
717 0 : if (ata_bio->multi == 1)
718 : goto ready;
719 0 : wdccommand(chp, xfer->drive, WDCC_SETMULTI, 0, 0, 0,
720 0 : ata_bio->multi, 0);
721 0 : drvp->state = MULTIMODE_WAIT;
722 0 : break;
723 :
724 : case MULTIMODE_WAIT:
725 : errstring = "setmulti";
726 0 : if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
727 : goto timeout;
728 0 : if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
729 0 : chp->wdc->irqack(chp);
730 0 : if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
731 : goto error;
732 : /* FALLTHROUGH */
733 :
734 : case READY:
735 : ready:
736 0 : drvp->state = READY;
737 : /*
738 : * The drive is usable now
739 : */
740 0 : xfer->c_intr = wdc_ata_bio_intr;
741 0 : _wdc_ata_bio_start(chp, xfer);
742 0 : return 1;
743 : }
744 :
745 0 : if ((ata_bio->flags & ATA_POLL) == 0) {
746 0 : chp->ch_flags |= WDCF_IRQ_WAIT;
747 : } else {
748 0 : goto again;
749 : }
750 0 : return 1;
751 :
752 : timeout:
753 0 : if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
754 0 : return 0; /* IRQ was not for us */
755 : }
756 0 : printf("%s:%d:%d: %s timed out\n",
757 0 : chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, errstring);
758 0 : ata_bio->error = TIMEOUT;
759 0 : drvp->state = 0;
760 0 : wdc_ata_bio_done(chp, xfer);
761 0 : return 0;
762 : error:
763 0 : printf("%s:%d:%d: %s ",
764 0 : chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
765 : errstring);
766 0 : if (chp->ch_status & WDCS_DWF) {
767 0 : printf("drive fault\n");
768 0 : ata_bio->error = ERR_DF;
769 0 : } else {
770 0 : printf("error (%x)\n", chp->ch_error);
771 0 : ata_bio->r_error = chp->ch_error;
772 0 : ata_bio->error = ERROR;
773 : }
774 0 : drvp->state = 0;
775 0 : wdc_ata_bio_done(chp, xfer);
776 0 : return 1;
777 0 : }
778 :
779 : int
780 0 : wdc_ata_err(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
781 : {
782 0 : struct channel_softc *chp = drvp->chnl_softc;
783 0 : ata_bio->error = 0;
784 :
785 0 : if (chp->ch_status == 0xff) {
786 0 : ata_bio->error = ERR_NODEV;
787 0 : return WDC_ATA_ERR;
788 : }
789 0 : if (chp->ch_status & WDCS_BSY) {
790 0 : ata_bio->error = TIMEOUT;
791 0 : return WDC_ATA_ERR;
792 : }
793 :
794 0 : if (chp->ch_status & WDCS_DWF) {
795 0 : ata_bio->error = ERR_DF;
796 0 : return WDC_ATA_ERR;
797 : }
798 :
799 0 : if (chp->ch_status & WDCS_ERR) {
800 0 : ata_bio->error = ERROR;
801 0 : ata_bio->r_error = chp->ch_error;
802 0 : if (drvp->drive_flags & DRIVE_UDMA &&
803 0 : (ata_bio->r_error & WDCE_CRC)) {
804 : /*
805 : * Record the CRC error, to avoid downgrading to
806 : * multiword DMA
807 : */
808 0 : drvp->drive_flags |= DRIVE_DMAERR;
809 0 : }
810 0 : if (ata_bio->r_error & (WDCE_BBK | WDCE_UNC | WDCE_IDNF |
811 : WDCE_ABRT | WDCE_TK0NF | WDCE_AMNF))
812 0 : return WDC_ATA_ERR;
813 0 : return WDC_ATA_NOERR;
814 : }
815 :
816 0 : if (chp->ch_status & WDCS_CORR)
817 0 : ata_bio->flags |= ATA_CORR;
818 0 : return WDC_ATA_NOERR;
819 0 : }
820 :
821 : #if 0
822 : int
823 : wdc_ata_addref(drvp)
824 : struct ata_drive_datas *drvp;
825 : {
826 : struct channel_softc *chp = drvp->chnl_softc;
827 :
828 : return (wdc_addref(chp));
829 : }
830 :
831 : void
832 : wdc_ata_delref(drvp)
833 : struct ata_drive_datas *drvp;
834 : {
835 : struct channel_softc *chp = drvp->chnl_softc;
836 :
837 : wdc_delref(chp);
838 : }
839 : #endif
|