Annotation of src/sys/dev/ata/ata_wdc.c, Revision 1.6
1.6 ! bouyer 1: /* $NetBSD: ata_wdc.c,v 1.5 1998/10/13 15:02:41 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,
267: xfer->databuf + xfer->c_skip, ata_bio->nbytes,
268: dma_flags) != 0) {
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,
333: xfer->databuf + xfer->c_skip,
334: ata_bio->nbytes >> 2);
335: } else {
336: bus_space_write_multi_2(chp->cmd_iot,
337: chp->cmd_ioh, wd_data,
338: xfer->databuf + xfer->c_skip,
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,
345: xfer->databuf + xfer->c_skip,
346: ata_bio->nbytes >> 2);
347: } else {
348: bus_space_write_multi_stream_2(chp->cmd_iot,
349: chp->cmd_ioh, wd_data,
350: xfer->databuf + xfer->c_skip,
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 */
412: if (xfer->c_flags & C_DMA)
413: (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
414: chp->channel, xfer->drive, dma_flags);
415: ata_bio->error = TIMEOUT;
416: wdc_ata_bio_done(chp, xfer);
417: return 1;
418: }
419:
420: drv_err = wdc_ata_err(chp, ata_bio);
421:
422: /* If we were using DMA, Turn off the DMA channel and check for error */
423: if (xfer->c_flags & C_DMA) {
424: if (ata_bio->flags & ATA_POLL) {
425: /*
426: * IDE drives deassert WDCS_BSY before trasfert is
427: * complete when using DMA. Polling for DRQ to deassert
428: * is not enouth DRQ is not required to be
429: * asserted for DMA transferts, so poll for DRDY.
430: */
431: if (wdcwait(chp, WDCS_DRDY | WDCS_DRQ, WDCS_DRDY,
432: ATA_DELAY) < 0) {
433: printf("%s:%d:%d: polled transfert timed out "
434: "(st=0x%x)\n", chp->wdc->sc_dev.dv_xname,
435: chp->channel, xfer->drive, chp->ch_status);
436: ata_bio->error = TIMEOUT;
437: wdc_ata_bio_done(chp, xfer);
438: return 1;
439: }
440: }
441: if (chp->ch_status & WDCS_DRQ) {
442: if (drv_err != WDC_ATA_ERR) {
443: printf("%s:%d:%d: intr with DRQ (st=0x%x)\n",
444: chp->wdc->sc_dev.dv_xname, chp->channel,
445: xfer->drive, chp->ch_status);
446: ata_bio->error = TIMEOUT;
447: drv_err = WDC_ATA_ERR;
448: }
449: }
450: if ((*chp->wdc->dma_finish)(chp->wdc->dma_arg,
451: chp->channel, xfer->drive, dma_flags) != 0) {
452: if (drv_err != WDC_ATA_ERR) {
453: ata_bio->error = ERR_DMA;
454: drv_err = WDC_ATA_ERR;
455: }
456: }
457: if (drv_err != WDC_ATA_ERR)
458: goto end;
459:
460: }
461:
462: /* if we had an error, end */
463: if (drv_err == WDC_ATA_ERR) {
464: wdc_ata_bio_done(chp, xfer);
465: return 1;
466: }
467:
468: /* If this was a read and not using DMA, fetch the data. */
469: if ((ata_bio->flags & ATA_READ) != 0) {
470: if ((chp->ch_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) !=
471: (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
472: printf("%s:%d:%d: read intr before drq\n",
473: chp->wdc->sc_dev.dv_xname, chp->channel,
474: xfer->drive);
475: ata_bio->error = TIMEOUT;
476: wdc_ata_bio_done(chp, xfer);
477: return 1;
478: }
479: if ((chp->wdc->cap & WDC_CAPABILITY_ATA_NOSTREAM)) {
480: if (drvp->drive_flags & DRIVE_CAP32) {
481: bus_space_read_multi_4(chp->data32iot,
482: chp->data32ioh, 0,
483: xfer->databuf + xfer->c_skip,
484: ata_bio->nbytes >> 2);
485: } else {
486: bus_space_read_multi_2(chp->cmd_iot,
487: chp->cmd_ioh, wd_data,
488: xfer->databuf + xfer->c_skip,
489: ata_bio->nbytes >> 1);
490: }
491: } else {
492: if (drvp->drive_flags & DRIVE_CAP32) {
493: bus_space_read_multi_stream_4(chp->data32iot,
494: chp->data32ioh, 0,
495: xfer->databuf + xfer->c_skip,
496: ata_bio->nbytes >> 2);
497: } else {
498: bus_space_read_multi_stream_2(chp->cmd_iot,
499: chp->cmd_ioh, wd_data,
500: xfer->databuf + xfer->c_skip,
501: ata_bio->nbytes >> 1);
502: }
503: }
504: }
505:
506: end:
507: ata_bio->blkno += ata_bio->nblks;
508: ata_bio->blkdone += ata_bio->nblks;
509: xfer->c_skip += ata_bio->nbytes;
510: xfer->c_bcount -= ata_bio->nbytes;
511: /* See if this transfer is complete. */
512: if (xfer->c_bcount > 0) {
513: if ((ata_bio->flags & ATA_POLL) == 0) {
514: /* Start the next operation */
515: wdc_ata_bio_start(chp, xfer);
516: } else {
517: /* Let wdc_ata_bio_start do the loop */
518: return 1;
519: }
520: } else { /* Done with this transfer */
521: ata_bio->error = NOERROR;
522: wdc_ata_bio_done(chp, xfer);
523: }
524: return 1;
525: }
526:
527: void
528: wdc_ata_bio_done(chp, xfer)
529: struct channel_softc *chp;
530: struct wdc_xfer *xfer;
531: {
532: struct ata_bio *ata_bio = xfer->cmd;
533: int need_done = xfer->c_flags & C_NEEDDONE;
534: int drive = xfer->drive;
535:
1.5 bouyer 536: WDCDEBUG_PRINT(("wdc_ata_bio_done %s:%d:%d: flags 0x%x\n",
537: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
538: (u_int)xfer->c_flags),
1.4 bouyer 539: DEBUG_XFERS);
1.2 bouyer 540:
541: /* feed back residual bcount to our caller */
542: ata_bio->bcount = xfer->c_bcount;
543:
544: /* remove this command from xfer queue */
545: wdc_free_xfer(chp, xfer);
546:
547: ata_bio->flags |= ATA_ITSDONE;
548: if (need_done) {
1.4 bouyer 549: WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);
1.2 bouyer 550: wddone(chp->ch_drive[drive].drv_softc);
551: }
552: WDCDEBUG_PRINT(("wdcstart from wdc_ata_done, flags 0x%x\n",
1.4 bouyer 553: chp->ch_flags), DEBUG_XFERS);
1.2 bouyer 554: wdcstart(chp->wdc, chp->channel);
555: }
556:
557: /*
558: * Implement operations needed before read/write.
559: */
560: int
561: wdc_ata_ctrl_intr(chp, xfer)
562: struct channel_softc *chp;
563: struct wdc_xfer *xfer;
564: {
565: struct ata_bio *ata_bio = xfer->cmd;
566: struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
567: char *errstring = NULL;
568: WDCDEBUG_PRINT(("wdc_ata_ctrl_intr: state %d\n", drvp->state),
569: DEBUG_FUNCS);
570:
571: again:
572: switch (drvp->state) {
573: case RECAL: /* Should not be in this state here */
574: panic("wdc_ata_ctrl_intr: state==RECAL");
575: break;
576:
577: case RECAL_WAIT:
578: errstring = "recal";
579: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
580: goto timeout;
581: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
582: goto error;
583: /* fall through */
584:
585: case PIOMODE:
586: /* Don't try to set modes if controller can't be adjusted */
587: if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)
1.6 ! bouyer 588: goto geometry;
! 589: /* Also don't try if the drive didn't report its mode */
! 590: if ((drvp->drive_flags & DRIVE_MODE) == 0)
1.2 bouyer 591: goto geometry;
592: wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
593: 0x08 | drvp->PIO_mode, WDSF_SET_MODE);
594: drvp->state = PIOMODE_WAIT;
595: break;
596:
597: case PIOMODE_WAIT:
598: errstring = "piomode";
599: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
600: goto timeout;
601: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
602: goto error;
603: /* fall through */
604:
605: case DMAMODE:
606: if (drvp->drive_flags & DRIVE_UDMA) {
607: wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
608: 0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
609: } else if (drvp->drive_flags & DRIVE_DMA) {
610: wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
611: 0x20 | drvp->DMA_mode, WDSF_SET_MODE);
612: } else {
613: goto geometry;
614: }
615: drvp->state = DMAMODE_WAIT;
616: break;
617: case DMAMODE_WAIT:
618: errstring = "dmamode";
619: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
620: goto timeout;
621: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
622: goto error;
623: /* fall through */
624:
625: case GEOMETRY:
626: geometry:
627: if (ata_bio->flags & ATA_LBA)
628: goto multimode;
629: wdccommand(chp, xfer->drive, WDCC_IDP,
630: ata_bio->lp->d_ncylinders,
631: ata_bio->lp->d_ntracks - 1, 0, ata_bio->lp->d_nsectors,
632: (ata_bio->lp->d_type == DTYPE_ST506) ?
633: ata_bio->lp->d_precompcyl / 4 : 0);
634: drvp->state = GEOMETRY_WAIT;
635: break;
636:
637: case GEOMETRY_WAIT:
638: errstring = "geometry";
639: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
640: goto timeout;
641: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
642: goto error;
643: /* fall through */
644:
645: case MULTIMODE:
646: multimode:
647: if (ata_bio->multi == 1)
648: goto ready;
649: wdccommand(chp, xfer->drive, WDCC_SETMULTI, 0, 0, 0,
650: ata_bio->multi, 0);
651: drvp->state = MULTIMODE_WAIT;
652: break;
653:
654: case MULTIMODE_WAIT:
655: errstring = "setmulti";
656: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
657: goto timeout;
658: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
659: goto error;
660: /* fall through */
661:
662: case READY:
663: ready:
664: drvp->state = READY;
665: /*
666: * The drive is usable now
667: */
668: xfer->c_intr = wdc_ata_bio_intr;
669: wdc_ata_bio_start(chp, xfer);
670: return 1;
671: }
672:
673: if ((ata_bio->flags & ATA_POLL) == 0) {
674: chp->ch_flags |= WDCF_IRQ_WAIT;
675: timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
676: } else {
677: goto again;
678: }
679: return 1;
680:
681: timeout:
682: if ((xfer->c_flags & C_TIMEOU) == 0 ) {
683: return 0; /* IRQ was not for us */
684: }
685: printf("%s:%d:%d: %s timed out\n",
686: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, errstring);
687: ata_bio->error = TIMEOUT;
688: drvp->state = 0;
689: wdc_ata_bio_done(chp, xfer);
690: return 0;
691: error:
692: printf("%s:%d:%d: %s ",
693: chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
694: errstring);
695: if (chp->ch_status & WDCS_DWF) {
696: printf("drive fault\n");
697: ata_bio->error = ERR_DF;
698: } else {
699: printf("error (%x)\n", chp->ch_error);
700: ata_bio->r_error = chp->ch_error;
701: ata_bio->error = ERROR;
702: }
703: drvp->state = 0;
704: wdc_ata_bio_done(chp, xfer);
705: return 1;
706: }
707:
708: int
709: wdc_ata_err(chp, ata_bio)
710: struct channel_softc *chp;
711: struct ata_bio *ata_bio;
712: {
713: ata_bio->error = 0;
714: if (chp->ch_status & WDCS_BSY) {
715: ata_bio->error = TIMEOUT;
716: return WDC_ATA_ERR;
717: }
718:
719: if (chp->ch_status & WDCS_DWF) {
720: ata_bio->error = ERR_DF;
721: return WDC_ATA_ERR;
722: }
723:
724: if (chp->ch_status & WDCS_ERR) {
725: ata_bio->error = ERROR;
726: ata_bio->r_error = chp->ch_error;
727: if (ata_bio->r_error & (WDCE_BBK | WDCE_UNC | WDCE_IDNF |
728: WDCE_ABRT | WDCE_TK0NF | WDCE_AMNF))
729: return WDC_ATA_ERR;
730: return WDC_ATA_NOERR;
731: }
732:
733: if (chp->ch_status & WDCS_CORR)
734: ata_bio->flags |= ATA_CORR;
735: return WDC_ATA_NOERR;
736: }
CVSweb <webmaster@jp.NetBSD.org>