Annotation of src/sys/dev/ata/ata_wdc.c, Revision 1.11
1.11 ! augustss 1: /* $NetBSD: ata_wdc.c,v 1.10 1998/12/16 13:02:03 bouyer 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:
72: #define WDCDEBUG
73:
74: #include <sys/param.h>
75: #include <sys/systm.h>
76: #include <sys/kernel.h>
77: #include <sys/file.h>
78: #include <sys/stat.h>
79: #include <sys/buf.h>
80: #include <sys/malloc.h>
81: #include <sys/device.h>
82: #include <sys/disklabel.h>
83: #include <sys/syslog.h>
84: #include <sys/proc.h>
85:
86: #include <machine/intr.h>
87: #include <machine/bus.h>
88: #ifndef __BUS_SPACE_HAS_STREAM_METHODS
89: #define bus_space_write_multi_stream_2 bus_space_write_multi_2
90: #define bus_space_write_multi_stream_4 bus_space_write_multi_4
91: #define bus_space_read_multi_stream_2 bus_space_read_multi_2
92: #define bus_space_read_multi_stream_4 bus_space_read_multi_4
93: #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
94:
95: #include <dev/ata/atareg.h>
96: #include <dev/ata/atavar.h>
97: #include <dev/ic/wdcreg.h>
98: #include <dev/ic/wdcvar.h>
99: #include <dev/ata/wdvar.h>
100:
101: #define DEBUG_INTR 0x01
102: #define DEBUG_XFERS 0x02
103: #define DEBUG_STATUS 0x04
104: #define DEBUG_FUNCS 0x08
105: #define DEBUG_PROBE 0x10
106: #ifdef WDCDEBUG
1.3 thorpej 107: int wdcdebug_wd_mask = 0;
1.2 bouyer 108: #define WDCDEBUG_PRINT(args, level) \
109: if (wdcdebug_wd_mask & (level)) \
110: printf args
111: #else
112: #define WDCDEBUG_PRINT(args, level)
113: #endif
114:
115: #define ATA_DELAY 10000 /* 10s for a drive I/O */
116:
117: void wdc_ata_bio_start __P((struct channel_softc *,struct wdc_xfer *));
118: int wdc_ata_bio_intr __P((struct channel_softc *, struct wdc_xfer *));
119: void wdc_ata_bio_done __P((struct channel_softc *, struct wdc_xfer *));
120: int wdc_ata_ctrl_intr __P((struct channel_softc *, struct wdc_xfer *));
121: int wdc_ata_err __P((struct channel_softc *, struct ata_bio *));
122: #define WDC_ATA_NOERR 0x00 /* Drive doesn't report an error */
123: #define WDC_ATA_RECOV 0x01 /* There was a recovered error */
124: #define WDC_ATA_ERR 0x02 /* Drive reports an error */
125:
126: /*
127: * Handle block I/O operation. Return WDC_COMPLETE, WDC_QUEUED, or
128: * WDC_TRY_AGAIN. Must be called at splio().
129: */
130: int
131: wdc_ata_bio(drvp, ata_bio)
132: struct ata_drive_datas *drvp;
133: struct ata_bio *ata_bio;
134: {
135: struct wdc_xfer *xfer;
136: struct channel_softc *chp = drvp->chnl_softc;
137:
138: xfer = wdc_get_xfer(WDC_NOSLEEP);
139: if (xfer == NULL)
140: return WDC_TRY_AGAIN;
141: if (ata_bio->flags & ATA_POLL)
142: xfer->c_flags |= C_POLL;
143: if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
144: (ata_bio->flags & ATA_SINGLE) == 0)
145: xfer->c_flags |= C_DMA;
146: xfer->drive = drvp->drive;
147: xfer->cmd = ata_bio;
148: xfer->databuf = ata_bio->databuf;
149: xfer->c_bcount = ata_bio->bcount;
150: xfer->c_start = wdc_ata_bio_start;
151: xfer->c_intr = wdc_ata_bio_intr;
152: wdc_exec_xfer(chp, xfer);
153: return (ata_bio->flags & ATA_ITSDONE) ? WDC_COMPLETE : WDC_QUEUED;
154: }
155:
156: void
157: wdc_ata_bio_start(chp, xfer)
158: struct channel_softc *chp;
159: struct wdc_xfer *xfer;
160: {
161: struct ata_bio *ata_bio = xfer->cmd;
162: struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
163: u_int16_t cyl;
164: u_int8_t head, sect, cmd = 0;
165: int nblks;
166: int dma_flags = 0;
167:
168: WDCDEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
169: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
1.4 bouyer 170: DEBUG_XFERS);
1.2 bouyer 171:
172: /* Do control operations specially. */
173: if (drvp->state < READY) {
174: /*
175: * Actually, we want to be careful not to mess with the control
176: * state if the device is currently busy, but we can assume
177: * that we never get to this point if that's the case.
178: */
179: /* at this point, we should only be in RECAL state */
180: if (drvp->state != RECAL) {
181: printf("%s:%d:%d: bad state %d in wdc_ata_bio_start\n",
182: chp->wdc->sc_dev.dv_xname, chp->channel,
183: xfer->drive, drvp->state);
184: panic("wdc_ata_bio_start: bad state");
185: }
186: xfer->c_intr = wdc_ata_ctrl_intr;
187: bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
188: WDSD_IBM | (xfer->drive << 4));
189: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY) != 0)
190: goto timeout;
191: wdccommandshort(chp, xfer->drive, WDCC_RECAL);
192: drvp->state = RECAL_WAIT;
193: if ((ata_bio->flags & ATA_POLL) == 0) {
194: chp->ch_flags |= WDCF_IRQ_WAIT;
195: timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
196: } else {
197: /* Wait for at last 400ns for status bit to be valid */
198: delay(1);
199: wdc_ata_ctrl_intr(chp, xfer);
200: }
201: return;
202: }
203:
204: if (xfer->c_flags & C_DMA) {
205: dma_flags = (ata_bio->flags & ATA_READ) ? WDC_DMA_READ : 0;
206: dma_flags |= (ata_bio->flags & ATA_POLL) ? WDC_DMA_POLL : 0;
207: }
208: again:
209: /*
210: *
211: * When starting a multi-sector transfer, or doing single-sector
212: * transfers...
213: */
214: if (xfer->c_skip == 0 || (ata_bio->flags & ATA_SINGLE) != 0) {
215: if (ata_bio->flags & ATA_SINGLE)
216: nblks = 1;
217: else
218: nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
219: /* Check for bad sectors and adjust transfer, if necessary. */
220: if ((ata_bio->lp->d_flags & D_BADSECT) != 0) {
221: long blkdiff;
222: int i;
223: for (i = 0; (blkdiff = ata_bio->badsect[i]) != -1;
224: i++) {
225: blkdiff -= ata_bio->blkno;
226: if (blkdiff < 0)
227: continue;
228: if (blkdiff == 0) {
229: /* Replace current block of transfer. */
230: ata_bio->blkno =
231: ata_bio->lp->d_secperunit -
232: ata_bio->lp->d_nsectors - i - 1;
233: }
234: if (blkdiff < nblks) {
235: /* Bad block inside transfer. */
236: ata_bio->flags |= ATA_SINGLE;
237: nblks = 1;
238: }
239: break;
240: }
241: /* Transfer is okay now. */
242: }
243: if (ata_bio->flags & ATA_LBA) {
244: sect = (ata_bio->blkno >> 0) & 0xff;
245: cyl = (ata_bio->blkno >> 8) & 0xffff;
246: head = (ata_bio->blkno >> 24) & 0x0f;
247: head |= WDSD_LBA;
248: } else {
249: int blkno = ata_bio->blkno;
250: sect = blkno % ata_bio->lp->d_nsectors;
251: sect++; /* Sectors begin with 1, not 0. */
252: blkno /= ata_bio->lp->d_nsectors;
253: head = blkno % ata_bio->lp->d_ntracks;
254: blkno /= ata_bio->lp->d_ntracks;
255: cyl = blkno;
256: head |= WDSD_CHS;
257: }
258: if (xfer->c_flags & C_DMA) {
259: ata_bio->nblks = nblks;
260: ata_bio->nbytes = xfer->c_bcount;
261: cmd = (ata_bio->flags & ATA_READ) ?
262: WDCC_READDMA : WDCC_WRITEDMA;
263: nblks = ata_bio->nblks;
264: /* Init the DMA channel. */
265: if ((*chp->wdc->dma_init)(chp->wdc->dma_arg,
266: chp->channel, xfer->drive,
1.11 ! augustss 267: (char *)xfer->databuf + xfer->c_skip,
! 268: ata_bio->nbytes, dma_flags) != 0) {
1.2 bouyer 269: ata_bio->error = ERR_DMA;
270: ata_bio->r_error = 0;
271: wdc_ata_bio_done(chp, xfer);
272: return;
273: }
274: /* Initiate command */
275: bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
276: WDSD_IBM | (xfer->drive << 4));
277: if (wait_for_ready(chp, ATA_DELAY) < 0)
278: goto timeout;
279: wdccommand(chp, xfer->drive, cmd, cyl,
280: head, sect, nblks, 0);
281: /* start the DMA channel */
282: (*chp->wdc->dma_start)(chp->wdc->dma_arg,
283: chp->channel, xfer->drive, dma_flags);
284: /* wait for irq */
285: goto intr;
286: } /* else not DMA */
287: ata_bio->nblks = min(nblks, ata_bio->multi);
288: ata_bio->nbytes = ata_bio->nblks * ata_bio->lp->d_secsize;
289: if (ata_bio->nblks > 1 && (ata_bio->flags & ATA_SINGLE) == 0) {
290: cmd = (ata_bio->flags & ATA_READ) ?
291: WDCC_READMULTI : WDCC_WRITEMULTI;
292: } else {
293: cmd = (ata_bio->flags & ATA_READ) ?
294: WDCC_READ : WDCC_WRITE;
295: }
296: /* Initiate command! */
297: bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
298: WDSD_IBM | (xfer->drive << 4));
299: if (wait_for_ready(chp, ATA_DELAY) < 0)
300: goto timeout;
301: wdccommand(chp, xfer->drive, cmd, cyl,
302: head, sect, nblks,
303: (ata_bio->lp->d_type == DTYPE_ST506) ?
304: ata_bio->lp->d_precompcyl / 4 : 0);
305: } else if (ata_bio->nblks > 1) {
306: /* The number of blocks in the last stretch may be smaller. */
307: nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
308: if (ata_bio->nblks > nblks) {
309: ata_bio->nblks = nblks;
310: ata_bio->nbytes = xfer->c_bcount;
311: }
312: }
313: /* If this was a write and not using DMA, push the data. */
314: if ((ata_bio->flags & ATA_READ) == 0) {
315: if (wait_for_drq(chp, ATA_DELAY) != 0) {
316: printf("%s:%d:%d: timeout waiting for DRQ, "
317: "st=0x%02x, err=0x%02x\n",
318: chp->wdc->sc_dev.dv_xname, chp->channel,
319: xfer->drive, chp->ch_status, chp->ch_error);
320: if (wdc_ata_err(chp, ata_bio) != WDC_ATA_ERR)
321: ata_bio->error = TIMEOUT;
322: wdc_ata_bio_done(chp, xfer);
323: return;
324: }
325: if (wdc_ata_err(chp, ata_bio) == WDC_ATA_ERR) {
326: wdc_ata_bio_done(chp, xfer);
327: return;
328: }
329: if ((chp->wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)) {
330: if (drvp->drive_flags & DRIVE_CAP32) {
331: bus_space_write_multi_4(chp->data32iot,
332: chp->data32ioh, 0,
1.11 ! augustss 333: (char *)xfer->databuf + xfer->c_skip,
1.2 bouyer 334: ata_bio->nbytes >> 2);
335: } else {
336: bus_space_write_multi_2(chp->cmd_iot,
337: chp->cmd_ioh, wd_data,
1.11 ! augustss 338: (char *)xfer->databuf + xfer->c_skip,
1.2 bouyer 339: ata_bio->nbytes >> 1);
340: }
341: } else {
342: if (drvp->drive_flags & DRIVE_CAP32) {
343: bus_space_write_multi_stream_4(chp->data32iot,
344: chp->data32ioh, 0,
1.11 ! augustss 345: (char *)xfer->databuf + xfer->c_skip,
1.2 bouyer 346: ata_bio->nbytes >> 2);
347: } else {
348: bus_space_write_multi_stream_2(chp->cmd_iot,
349: chp->cmd_ioh, wd_data,
1.11 ! augustss 350: (char *)xfer->databuf + xfer->c_skip,
1.2 bouyer 351: ata_bio->nbytes >> 1);
352: }
353: }
354: }
355:
356: intr: /* Wait for IRQ (either real or polled) */
357: if ((ata_bio->flags & ATA_POLL) == 0) {
358: chp->ch_flags |= WDCF_IRQ_WAIT;
359: timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
360: } else {
361: /* Wait for at last 400ns for status bit to be valid */
362: delay(1);
363: wdc_ata_bio_intr(chp, xfer);
364: if ((ata_bio->flags & ATA_ITSDONE) == 0)
365: goto again;
366: }
367: return;
368: timeout:
369: printf("%s:%d:%d: not ready, st=0x%02x, err=0x%02x\n",
370: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
371: chp->ch_status, chp->ch_error);
372: if (wdc_ata_err(chp, ata_bio) != WDC_ATA_ERR)
373: ata_bio->error = TIMEOUT;
374: wdc_ata_bio_done(chp, xfer);
375: return;
376: }
377:
378: int
379: wdc_ata_bio_intr(chp, xfer)
380: struct channel_softc *chp;
381: struct wdc_xfer *xfer;
382: {
383: struct ata_bio *ata_bio = xfer->cmd;
384: struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
385: int drv_err;
386: int dma_flags = 0;
387:
388: WDCDEBUG_PRINT(("wdc_ata_bio_intr %s:%d:%d\n",
389: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
390: DEBUG_INTR | DEBUG_XFERS);
391:
392:
393: /* Is it not a transfer, but a control operation? */
394: if (drvp->state < READY) {
395: printf("%s:%d:%d: bad state %d in wdc_ata_bio_intr\n",
396: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
397: drvp->state);
398: panic("wdc_ata_bio_intr: bad state\n");
399: }
400:
401: if (xfer->c_flags & C_DMA) {
402: dma_flags = (ata_bio->flags & ATA_READ) ? WDC_DMA_READ : 0;
403: dma_flags |= (ata_bio->flags & ATA_POLL) ? WDC_DMA_POLL : 0;
404: }
405:
406: /* Ack interrupt done by wait_for_unbusy */
407: if (wait_for_unbusy(chp, ATA_DELAY) < 0) {
408: printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
409: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
410: xfer->c_bcount, xfer->c_skip);
411: /* if we were using DMA, turn off DMA channel */
1.10 bouyer 412: if (xfer->c_flags & C_DMA) {
1.2 bouyer 413: (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
414: chp->channel, xfer->drive, dma_flags);
1.10 bouyer 415: drvp->n_dmaerrs++;
416: }
1.2 bouyer 417: ata_bio->error = TIMEOUT;
418: wdc_ata_bio_done(chp, xfer);
419: return 1;
420: }
421:
422: drv_err = wdc_ata_err(chp, ata_bio);
423:
424: /* If we were using DMA, Turn off the DMA channel and check for error */
425: if (xfer->c_flags & C_DMA) {
426: if (ata_bio->flags & ATA_POLL) {
427: /*
1.10 bouyer 428: * IDE drives deassert WDCS_BSY before transfert is
1.2 bouyer 429: * complete when using DMA. Polling for DRQ to deassert
430: * is not enouth DRQ is not required to be
1.7 bouyer 431: * asserted for DMA transfers, so poll for DRDY.
1.2 bouyer 432: */
433: if (wdcwait(chp, WDCS_DRDY | WDCS_DRQ, WDCS_DRDY,
434: ATA_DELAY) < 0) {
1.7 bouyer 435: printf("%s:%d:%d: polled transfer timed out "
1.2 bouyer 436: "(st=0x%x)\n", chp->wdc->sc_dev.dv_xname,
437: chp->channel, xfer->drive, chp->ch_status);
438: ata_bio->error = TIMEOUT;
1.10 bouyer 439: drv_err = WDC_ATA_ERR;
440: }
441: }
442: if ((*chp->wdc->dma_finish)(chp->wdc->dma_arg,
443: chp->channel, xfer->drive, dma_flags) != 0) {
444: if (drv_err != WDC_ATA_ERR) {
445: ata_bio->error = ERR_DMA;
446: drv_err = WDC_ATA_ERR;
1.2 bouyer 447: }
448: }
449: if (chp->ch_status & WDCS_DRQ) {
450: if (drv_err != WDC_ATA_ERR) {
451: printf("%s:%d:%d: intr with DRQ (st=0x%x)\n",
452: chp->wdc->sc_dev.dv_xname, chp->channel,
453: xfer->drive, chp->ch_status);
454: ata_bio->error = TIMEOUT;
455: drv_err = WDC_ATA_ERR;
456: }
457: }
458: if (drv_err != WDC_ATA_ERR)
459: goto end;
1.10 bouyer 460: drvp->n_dmaerrs++;
1.2 bouyer 461: }
462:
463: /* if we had an error, end */
464: if (drv_err == WDC_ATA_ERR) {
465: wdc_ata_bio_done(chp, xfer);
466: return 1;
467: }
468:
469: /* If this was a read and not using DMA, fetch the data. */
470: if ((ata_bio->flags & ATA_READ) != 0) {
471: if ((chp->ch_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) !=
472: (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
473: printf("%s:%d:%d: read intr before drq\n",
474: chp->wdc->sc_dev.dv_xname, chp->channel,
475: xfer->drive);
476: ata_bio->error = TIMEOUT;
477: wdc_ata_bio_done(chp, xfer);
478: return 1;
479: }
480: if ((chp->wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)) {
481: if (drvp->drive_flags & DRIVE_CAP32) {
482: bus_space_read_multi_4(chp->data32iot,
483: chp->data32ioh, 0,
1.11 ! augustss 484: (char *)xfer->databuf + xfer->c_skip,
1.2 bouyer 485: ata_bio->nbytes >> 2);
486: } else {
487: bus_space_read_multi_2(chp->cmd_iot,
488: chp->cmd_ioh, wd_data,
1.11 ! augustss 489: (char *)xfer->databuf + xfer->c_skip,
1.2 bouyer 490: ata_bio->nbytes >> 1);
491: }
492: } else {
493: if (drvp->drive_flags & DRIVE_CAP32) {
494: bus_space_read_multi_stream_4(chp->data32iot,
495: chp->data32ioh, 0,
1.11 ! augustss 496: (char *)xfer->databuf + xfer->c_skip,
1.2 bouyer 497: ata_bio->nbytes >> 2);
498: } else {
499: bus_space_read_multi_stream_2(chp->cmd_iot,
500: chp->cmd_ioh, wd_data,
1.11 ! augustss 501: (char *)xfer->databuf + xfer->c_skip,
1.2 bouyer 502: ata_bio->nbytes >> 1);
503: }
504: }
505: }
506:
507: end:
508: ata_bio->blkno += ata_bio->nblks;
509: ata_bio->blkdone += ata_bio->nblks;
510: xfer->c_skip += ata_bio->nbytes;
511: xfer->c_bcount -= ata_bio->nbytes;
512: /* See if this transfer is complete. */
513: if (xfer->c_bcount > 0) {
514: if ((ata_bio->flags & ATA_POLL) == 0) {
515: /* Start the next operation */
516: wdc_ata_bio_start(chp, xfer);
517: } else {
518: /* Let wdc_ata_bio_start do the loop */
519: return 1;
520: }
521: } else { /* Done with this transfer */
522: ata_bio->error = NOERROR;
523: wdc_ata_bio_done(chp, xfer);
524: }
525: return 1;
526: }
527:
528: void
529: wdc_ata_bio_done(chp, xfer)
530: struct channel_softc *chp;
531: struct wdc_xfer *xfer;
532: {
533: struct ata_bio *ata_bio = xfer->cmd;
534: int need_done = xfer->c_flags & C_NEEDDONE;
535: int drive = xfer->drive;
1.10 bouyer 536: struct ata_drive_datas *drvp = &chp->ch_drive[drive];
1.2 bouyer 537:
1.5 bouyer 538: WDCDEBUG_PRINT(("wdc_ata_bio_done %s:%d:%d: flags 0x%x\n",
539: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
540: (u_int)xfer->c_flags),
1.4 bouyer 541: DEBUG_XFERS);
1.10 bouyer 542:
543: if (ata_bio->error == NOERROR)
544: drvp->n_dmaerrs = 0;
545: else if (drvp->n_dmaerrs >= NERRS_MAX) {
546: wdc_downgrade_mode(drvp);
547: }
1.2 bouyer 548:
549: /* feed back residual bcount to our caller */
550: ata_bio->bcount = xfer->c_bcount;
551:
552: /* remove this command from xfer queue */
553: wdc_free_xfer(chp, xfer);
554:
555: ata_bio->flags |= ATA_ITSDONE;
556: if (need_done) {
1.4 bouyer 557: WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);
1.2 bouyer 558: wddone(chp->ch_drive[drive].drv_softc);
559: }
560: WDCDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n",
1.4 bouyer 561: chp->ch_flags), DEBUG_XFERS);
1.9 drochner 562: wdcstart(chp);
1.2 bouyer 563: }
564:
565: /*
566: * Implement operations needed before read/write.
567: */
568: int
569: wdc_ata_ctrl_intr(chp, xfer)
570: struct channel_softc *chp;
571: struct wdc_xfer *xfer;
572: {
573: struct ata_bio *ata_bio = xfer->cmd;
574: struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
575: char *errstring = NULL;
576: WDCDEBUG_PRINT(("wdc_ata_ctrl_intr: state %d\n", drvp->state),
577: DEBUG_FUNCS);
578:
579: again:
580: switch (drvp->state) {
581: case RECAL: /* Should not be in this state here */
582: panic("wdc_ata_ctrl_intr: state==RECAL");
583: break;
584:
585: case RECAL_WAIT:
586: errstring = "recal";
587: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
588: goto timeout;
589: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
590: goto error;
591: /* fall through */
592:
593: case PIOMODE:
594: /* Don't try to set modes if controller can't be adjusted */
595: if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)
1.6 bouyer 596: goto geometry;
597: /* Also don't try if the drive didn't report its mode */
598: if ((drvp->drive_flags & DRIVE_MODE) == 0)
1.2 bouyer 599: goto geometry;
600: wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
601: 0x08 | drvp->PIO_mode, WDSF_SET_MODE);
602: drvp->state = PIOMODE_WAIT;
603: break;
604:
605: case PIOMODE_WAIT:
606: errstring = "piomode";
607: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
608: goto timeout;
609: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
610: goto error;
611: /* fall through */
612:
613: case DMAMODE:
614: if (drvp->drive_flags & DRIVE_UDMA) {
615: wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
616: 0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
617: } else if (drvp->drive_flags & DRIVE_DMA) {
618: wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
619: 0x20 | drvp->DMA_mode, WDSF_SET_MODE);
620: } else {
621: goto geometry;
622: }
623: drvp->state = DMAMODE_WAIT;
624: break;
625: case DMAMODE_WAIT:
626: errstring = "dmamode";
627: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
628: goto timeout;
629: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
630: goto error;
631: /* fall through */
632:
633: case GEOMETRY:
634: geometry:
635: if (ata_bio->flags & ATA_LBA)
636: goto multimode;
637: wdccommand(chp, xfer->drive, WDCC_IDP,
638: ata_bio->lp->d_ncylinders,
639: ata_bio->lp->d_ntracks - 1, 0, ata_bio->lp->d_nsectors,
640: (ata_bio->lp->d_type == DTYPE_ST506) ?
641: ata_bio->lp->d_precompcyl / 4 : 0);
642: drvp->state = GEOMETRY_WAIT;
643: break;
644:
645: case GEOMETRY_WAIT:
646: errstring = "geometry";
647: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
648: goto timeout;
649: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
650: goto error;
651: /* fall through */
652:
653: case MULTIMODE:
654: multimode:
655: if (ata_bio->multi == 1)
656: goto ready;
657: wdccommand(chp, xfer->drive, WDCC_SETMULTI, 0, 0, 0,
658: ata_bio->multi, 0);
659: drvp->state = MULTIMODE_WAIT;
660: break;
661:
662: case MULTIMODE_WAIT:
663: errstring = "setmulti";
664: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
665: goto timeout;
666: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
667: goto error;
668: /* fall through */
669:
670: case READY:
671: ready:
672: drvp->state = READY;
673: /*
674: * The drive is usable now
675: */
676: xfer->c_intr = wdc_ata_bio_intr;
677: wdc_ata_bio_start(chp, xfer);
678: return 1;
679: }
680:
681: if ((ata_bio->flags & ATA_POLL) == 0) {
682: chp->ch_flags |= WDCF_IRQ_WAIT;
683: timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
684: } else {
685: goto again;
686: }
687: return 1;
688:
689: timeout:
690: if ((xfer->c_flags & C_TIMEOU) == 0 ) {
691: return 0; /* IRQ was not for us */
692: }
693: printf("%s:%d:%d: %s timed out\n",
694: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, errstring);
695: ata_bio->error = TIMEOUT;
696: drvp->state = 0;
697: wdc_ata_bio_done(chp, xfer);
698: return 0;
699: error:
700: printf("%s:%d:%d: %s ",
701: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
702: errstring);
703: if (chp->ch_status & WDCS_DWF) {
704: printf("drive fault\n");
705: ata_bio->error = ERR_DF;
706: } else {
707: printf("error (%x)\n", chp->ch_error);
708: ata_bio->r_error = chp->ch_error;
709: ata_bio->error = ERROR;
710: }
711: drvp->state = 0;
712: wdc_ata_bio_done(chp, xfer);
713: return 1;
714: }
715:
716: int
717: wdc_ata_err(chp, ata_bio)
718: struct channel_softc *chp;
719: struct ata_bio *ata_bio;
720: {
721: ata_bio->error = 0;
722: if (chp->ch_status & WDCS_BSY) {
723: ata_bio->error = TIMEOUT;
724: return WDC_ATA_ERR;
725: }
726:
727: if (chp->ch_status & WDCS_DWF) {
728: ata_bio->error = ERR_DF;
729: return WDC_ATA_ERR;
730: }
731:
732: if (chp->ch_status & WDCS_ERR) {
733: ata_bio->error = ERROR;
734: ata_bio->r_error = chp->ch_error;
735: if (ata_bio->r_error & (WDCE_BBK | WDCE_UNC | WDCE_IDNF |
736: WDCE_ABRT | WDCE_TK0NF | WDCE_AMNF))
737: return WDC_ATA_ERR;
738: return WDC_ATA_NOERR;
739: }
740:
741: if (chp->ch_status & WDCS_CORR)
742: ata_bio->flags |= ATA_CORR;
743: return WDC_ATA_NOERR;
1.8 thorpej 744: }
745:
746: int
747: wdc_ata_addref(drvp)
748: struct ata_drive_datas *drvp;
749: {
750: struct channel_softc *chp = drvp->chnl_softc;
751:
752: return (wdc_addref(chp));
753: }
754:
755: void
756: wdc_ata_delref(drvp)
757: struct ata_drive_datas *drvp;
758: {
759: struct channel_softc *chp = drvp->chnl_softc;
760:
761: wdc_delref(chp);
1.2 bouyer 762: }
CVSweb <webmaster@jp.NetBSD.org>