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