Annotation of src/sys/dev/ata/ata_wdc.c, Revision 1.85.8.1
1.85.8.1! ad 1: /* $NetBSD: ata_wdc.c,v 1.85 2006/09/30 15:56:18 itohy Exp $ */
1.2 bouyer 2:
3: /*
1.41 bouyer 4: * Copyright (c) 1998, 2001, 2003 Manuel Bouyer.
1.2 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:
1.36 bouyer 16: * This product includes software developed by Manuel Bouyer.
1.40 bouyer 17: * 4. The name of the author may not be used to endorse or promote products
18: * derived from this software without specific prior written permission.
1.2 bouyer 19: *
1.27 bouyer 20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1.79 perry 23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1.27 bouyer 24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.2 bouyer 30: */
31:
32: /*-
1.57 mycroft 33: * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
1.2 bouyer 34: * All rights reserved.
35: *
36: * This code is derived from software contributed to The NetBSD Foundation
37: * by Charles M. Hannum, by Onno van der Linden and by Manuel Bouyer.
38: *
39: * Redistribution and use in source and binary forms, with or without
40: * modification, are permitted provided that the following conditions
41: * are met:
42: * 1. Redistributions of source code must retain the above copyright
43: * notice, this list of conditions and the following disclaimer.
44: * 2. Redistributions in binary form must reproduce the above copyright
45: * notice, this list of conditions and the following disclaimer in the
46: * documentation and/or other materials provided with the distribution.
47: * 3. All advertising materials mentioning features or use of this software
48: * must display the following acknowledgement:
49: * This product includes software developed by the NetBSD
50: * Foundation, Inc. and its contributors.
51: * 4. Neither the name of The NetBSD Foundation nor the names of its
52: * contributors may be used to endorse or promote products derived
53: * from this software without specific prior written permission.
54: *
55: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
56: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
57: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
58: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
59: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
60: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
62: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65: * POSSIBILITY OF SUCH DAMAGE.
66: */
1.31 lukem 67:
68: #include <sys/cdefs.h>
1.85.8.1! ad 69: __KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.85 2006/09/30 15:56:18 itohy Exp $");
1.2 bouyer 70:
1.85.8.1! ad 71: #include "opt_ata.h"
1.2 bouyer 72:
73: #include <sys/param.h>
74: #include <sys/systm.h>
75: #include <sys/kernel.h>
76: #include <sys/file.h>
77: #include <sys/stat.h>
78: #include <sys/buf.h>
1.76 yamt 79: #include <sys/bufq.h>
1.2 bouyer 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:
1.84 itohy 95: #include <dev/ata/ataconf.h>
1.2 bouyer 96: #include <dev/ata/atareg.h>
97: #include <dev/ata/atavar.h>
98: #include <dev/ic/wdcreg.h>
99: #include <dev/ic/wdcvar.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
1.71 thorpej 106: #ifdef ATADEBUG
1.41 bouyer 107: extern int wdcdebug_wd_mask; /* inited in wd.c */
1.71 thorpej 108: #define ATADEBUG_PRINT(args, level) \
1.2 bouyer 109: if (wdcdebug_wd_mask & (level)) \
110: printf args
111: #else
1.71 thorpej 112: #define ATADEBUG_PRINT(args, level)
1.2 bouyer 113: #endif
114:
1.17 bouyer 115: #define ATA_DELAY 10000 /* 10s for a drive I/O */
1.2 bouyer 116:
1.45 thorpej 117: static int wdc_ata_bio(struct ata_drive_datas*, struct ata_bio*);
1.72 thorpej 118: static void wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *);
119: static void _wdc_ata_bio_start(struct ata_channel *,struct ata_xfer *);
120: static int wdc_ata_bio_intr(struct ata_channel *, struct ata_xfer *,
1.45 thorpej 121: int);
1.72 thorpej 122: static void wdc_ata_bio_kill_xfer(struct ata_channel *,
1.58 bouyer 123: struct ata_xfer *, int);
1.79 perry 124: static void wdc_ata_bio_done(struct ata_channel *, struct ata_xfer *);
1.45 thorpej 125: static int wdc_ata_err(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 */
1.45 thorpej 129: static int wdc_ata_addref(struct ata_drive_datas *);
130: static void wdc_ata_delref(struct ata_drive_datas *);
1.32 bouyer 131:
132: const struct ata_bustype wdc_ata_bustype = {
133: SCSIPI_BUSTYPE_ATA,
134: wdc_ata_bio,
1.59 bouyer 135: wdc_reset_drive,
1.74 thorpej 136: wdc_reset_channel,
1.32 bouyer 137: wdc_exec_command,
138: ata_get_params,
139: wdc_ata_addref,
140: wdc_ata_delref,
1.66 thorpej 141: ata_kill_pending,
1.32 bouyer 142: };
143:
1.2 bouyer 144: /*
1.64 thorpej 145: * Handle block I/O operation. Return ATACMD_COMPLETE, ATACMD_QUEUED, or
146: * ATACMD_TRY_AGAIN. Must be called at splbio().
1.2 bouyer 147: */
1.45 thorpej 148: static int
1.44 thorpej 149: wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
1.2 bouyer 150: {
1.48 thorpej 151: struct ata_xfer *xfer;
1.72 thorpej 152: struct ata_channel *chp = drvp->chnl_softc;
1.73 thorpej 153: struct atac_softc *atac = chp->ch_atac;
1.2 bouyer 154:
1.65 thorpej 155: xfer = ata_get_xfer(ATAXF_NOSLEEP);
1.2 bouyer 156: if (xfer == NULL)
1.64 thorpej 157: return ATACMD_TRY_AGAIN;
1.73 thorpej 158: if (atac->atac_cap & ATAC_CAP_NOIRQ)
1.30 bjh21 159: ata_bio->flags |= ATA_POLL;
1.2 bouyer 160: if (ata_bio->flags & ATA_POLL)
161: xfer->c_flags |= C_POLL;
1.85 itohy 162: #if NATA_DMA
1.2 bouyer 163: if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
164: (ata_bio->flags & ATA_SINGLE) == 0)
165: xfer->c_flags |= C_DMA;
1.85 itohy 166: #endif
167: #if NATA_DMA && NATA_PIOBM
168: else
169: #endif
1.84 itohy 170: #if NATA_PIOBM
1.85 itohy 171: if (atac->atac_cap & ATAC_CAP_PIOBM)
1.84 itohy 172: xfer->c_flags |= C_PIOBM;
173: #endif
1.48 thorpej 174: xfer->c_drive = drvp->drive;
175: xfer->c_cmd = ata_bio;
176: xfer->c_databuf = ata_bio->databuf;
1.2 bouyer 177: xfer->c_bcount = ata_bio->bcount;
178: xfer->c_start = wdc_ata_bio_start;
179: xfer->c_intr = wdc_ata_bio_intr;
1.22 enami 180: xfer->c_kill_xfer = wdc_ata_bio_kill_xfer;
1.68 thorpej 181: ata_exec_xfer(chp, xfer);
1.64 thorpej 182: return (ata_bio->flags & ATA_ITSDONE) ? ATACMD_COMPLETE : ATACMD_QUEUED;
1.2 bouyer 183: }
184:
1.45 thorpej 185: static void
1.72 thorpej 186: wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
1.2 bouyer 187: {
1.73 thorpej 188: struct atac_softc *atac = chp->ch_atac;
189: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.72 thorpej 190: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.48 thorpej 191: struct ata_bio *ata_bio = xfer->c_cmd;
192: struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
1.41 bouyer 193: int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
1.80 christos 194: const char *errstring;
1.41 bouyer 195:
1.71 thorpej 196: ATADEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
1.73 thorpej 197: atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive),
1.20 bouyer 198: DEBUG_XFERS);
199:
1.41 bouyer 200: /* Do control operations specially. */
201: if (__predict_false(drvp->state < READY)) {
202: /*
203: * Actually, we want to be careful not to mess with the control
204: * state if the device is currently busy, but we can assume
205: * that we never get to this point if that's the case.
206: */
1.81 peter 207: /* If it's not a polled command, we need the kernel thread */
1.41 bouyer 208: if ((xfer->c_flags & C_POLL) == 0 &&
1.72 thorpej 209: (chp->ch_flags & ATACH_TH_RUN) == 0) {
1.42 bouyer 210: chp->ch_queue->queue_freeze++;
1.52 thorpej 211: wakeup(&chp->ch_thread);
1.41 bouyer 212: return;
213: }
214: /*
215: * disable interrupts, all commands here should be quick
216: * enouth to be able to poll, and we don't go here that often
217: */
1.72 thorpej 218: bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
1.41 bouyer 219: WDCTL_4BIT | WDCTL_IDS);
1.70 thorpej 220: if (wdc->select)
1.51 thorpej 221: wdc->select(chp, xfer->c_drive);
1.72 thorpej 222: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.48 thorpej 223: WDSD_IBM | (xfer->c_drive << 4));
1.53 fvdl 224: DELAY(10);
1.41 bouyer 225: errstring = "wait";
226: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
227: goto ctrltimeout;
1.48 thorpej 228: wdccommandshort(chp, xfer->c_drive, WDCC_RECAL);
1.41 bouyer 229: /* Wait for at last 400ns for status bit to be valid */
230: DELAY(1);
231: errstring = "recal";
232: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
233: goto ctrltimeout;
234: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
235: goto ctrlerror;
236: /* Don't try to set modes if controller can't be adjusted */
1.73 thorpej 237: if (atac->atac_set_modes == NULL)
1.41 bouyer 238: goto geometry;
239: /* Also don't try if the drive didn't report its mode */
240: if ((drvp->drive_flags & DRIVE_MODE) == 0)
241: goto geometry;
242: wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
243: 0x08 | drvp->PIO_mode, WDSF_SET_MODE);
244: errstring = "piomode";
245: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
246: goto ctrltimeout;
247: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
248: goto ctrlerror;
1.85 itohy 249: #if NATA_DMA
250: #if NATA_UDMA
1.41 bouyer 251: if (drvp->drive_flags & DRIVE_UDMA) {
252: wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
253: 0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
1.85 itohy 254: } else
255: #endif
256: if (drvp->drive_flags & DRIVE_DMA) {
1.41 bouyer 257: wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
258: 0x20 | drvp->DMA_mode, WDSF_SET_MODE);
259: } else {
260: goto geometry;
1.79 perry 261: }
1.41 bouyer 262: errstring = "dmamode";
263: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
264: goto ctrltimeout;
265: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
266: goto ctrlerror;
1.85 itohy 267: #endif /* NATA_DMA */
1.41 bouyer 268: geometry:
269: if (ata_bio->flags & ATA_LBA)
270: goto multimode;
1.48 thorpej 271: wdccommand(chp, xfer->c_drive, WDCC_IDP,
1.41 bouyer 272: ata_bio->lp->d_ncylinders,
273: ata_bio->lp->d_ntracks - 1, 0, ata_bio->lp->d_nsectors,
274: (ata_bio->lp->d_type == DTYPE_ST506) ?
275: ata_bio->lp->d_precompcyl / 4 : 0);
276: errstring = "geometry";
277: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
278: goto ctrltimeout;
279: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
280: goto ctrlerror;
281: multimode:
282: if (ata_bio->multi == 1)
283: goto ready;
1.48 thorpej 284: wdccommand(chp, xfer->c_drive, WDCC_SETMULTI, 0, 0, 0,
1.41 bouyer 285: ata_bio->multi, 0);
286: errstring = "setmulti";
287: if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
288: goto ctrltimeout;
289: if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
290: goto ctrlerror;
291: ready:
292: drvp->state = READY;
293: /*
294: * The drive is usable now
295: */
1.72 thorpej 296: bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr,
1.41 bouyer 297: WDCTL_4BIT);
1.54 bouyer 298: delay(10); /* some drives need a little delay here */
1.41 bouyer 299: }
300:
1.20 bouyer 301: _wdc_ata_bio_start(chp, xfer);
1.41 bouyer 302: return;
303: ctrltimeout:
304: printf("%s:%d:%d: %s timed out\n",
1.73 thorpej 305: atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive,
1.51 thorpej 306: errstring);
1.41 bouyer 307: ata_bio->error = TIMEOUT;
308: goto ctrldone;
309: ctrlerror:
310: printf("%s:%d:%d: %s ",
1.73 thorpej 311: atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive,
1.41 bouyer 312: errstring);
313: if (chp->ch_status & WDCS_DWF) {
314: printf("drive fault\n");
315: ata_bio->error = ERR_DF;
316: } else {
317: printf("error (%x)\n", chp->ch_error);
318: ata_bio->r_error = chp->ch_error;
319: ata_bio->error = ERROR;
320: }
321: ctrldone:
322: drvp->state = 0;
323: wdc_ata_bio_done(chp, xfer);
1.72 thorpej 324: bus_space_write_1(wdr->ctl_iot, wdr->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
1.41 bouyer 325: return;
1.20 bouyer 326: }
327:
1.45 thorpej 328: static void
1.72 thorpej 329: _wdc_ata_bio_start(struct ata_channel *chp, struct ata_xfer *xfer)
1.20 bouyer 330: {
1.73 thorpej 331: struct atac_softc *atac = chp->ch_atac;
332: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.72 thorpej 333: struct wdc_regs *wdr = &wdc->regs[chp->ch_channel];
1.48 thorpej 334: struct ata_bio *ata_bio = xfer->c_cmd;
335: struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
1.51 thorpej 336: int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
1.2 bouyer 337: u_int16_t cyl;
338: u_int8_t head, sect, cmd = 0;
1.85 itohy 339: int nblks;
340: #if NATA_DMA || NATA_PIOBM
341: int error, dma_flags = 0;
342: #endif
1.2 bouyer 343:
1.71 thorpej 344: ATADEBUG_PRINT(("_wdc_ata_bio_start %s:%d:%d\n",
1.73 thorpej 345: atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive),
1.20 bouyer 346: DEBUG_INTR | DEBUG_XFERS);
1.2 bouyer 347:
1.85 itohy 348: #if NATA_DMA || NATA_PIOBM
1.84 itohy 349: if (xfer->c_flags & (C_DMA | C_PIOBM)) {
1.85 itohy 350: #if NATA_DMA
1.23 bouyer 351: if (drvp->n_xfers <= NXFER)
352: drvp->n_xfers++;
1.85 itohy 353: #endif
1.2 bouyer 354: dma_flags = (ata_bio->flags & ATA_READ) ? WDC_DMA_READ : 0;
1.39 nakayama 355: if (ata_bio->flags & ATA_LBA48)
356: dma_flags |= WDC_DMA_LBA48;
1.2 bouyer 357: }
1.85 itohy 358: #endif
1.2 bouyer 359: again:
360: /*
361: *
362: * When starting a multi-sector transfer, or doing single-sector
363: * transfers...
364: */
365: if (xfer->c_skip == 0 || (ata_bio->flags & ATA_SINGLE) != 0) {
366: if (ata_bio->flags & ATA_SINGLE)
367: nblks = 1;
1.79 perry 368: else
1.2 bouyer 369: nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
370: /* Check for bad sectors and adjust transfer, if necessary. */
371: if ((ata_bio->lp->d_flags & D_BADSECT) != 0) {
372: long blkdiff;
373: int i;
374: for (i = 0; (blkdiff = ata_bio->badsect[i]) != -1;
375: i++) {
376: blkdiff -= ata_bio->blkno;
377: if (blkdiff < 0)
378: continue;
379: if (blkdiff == 0) {
380: /* Replace current block of transfer. */
381: ata_bio->blkno =
382: ata_bio->lp->d_secperunit -
383: ata_bio->lp->d_nsectors - i - 1;
384: }
385: if (blkdiff < nblks) {
386: /* Bad block inside transfer. */
387: ata_bio->flags |= ATA_SINGLE;
388: nblks = 1;
389: }
390: break;
391: }
392: /* Transfer is okay now. */
393: }
1.34 christos 394: if (ata_bio->flags & ATA_LBA48) {
395: sect = 0;
396: cyl = 0;
397: head = 0;
398: } else if (ata_bio->flags & ATA_LBA) {
1.2 bouyer 399: sect = (ata_bio->blkno >> 0) & 0xff;
400: cyl = (ata_bio->blkno >> 8) & 0xffff;
401: head = (ata_bio->blkno >> 24) & 0x0f;
402: head |= WDSD_LBA;
403: } else {
404: int blkno = ata_bio->blkno;
405: sect = blkno % ata_bio->lp->d_nsectors;
406: sect++; /* Sectors begin with 1, not 0. */
407: blkno /= ata_bio->lp->d_nsectors;
408: head = blkno % ata_bio->lp->d_ntracks;
409: blkno /= ata_bio->lp->d_ntracks;
410: cyl = blkno;
411: head |= WDSD_CHS;
412: }
1.85 itohy 413: #if NATA_DMA
1.2 bouyer 414: if (xfer->c_flags & C_DMA) {
415: ata_bio->nblks = nblks;
416: ata_bio->nbytes = xfer->c_bcount;
417: cmd = (ata_bio->flags & ATA_READ) ?
418: WDCC_READDMA : WDCC_WRITEDMA;
419: /* Init the DMA channel. */
1.82 thorpej 420: error = (*wdc->dma_init)(wdc->dma_arg,
1.51 thorpej 421: chp->ch_channel, xfer->c_drive,
1.79 perry 422: (char *)xfer->c_databuf + xfer->c_skip,
1.82 thorpej 423: ata_bio->nbytes, dma_flags);
424: if (error) {
425: if (error == EINVAL) {
426: /*
427: * We can't do DMA on this transfer
428: * for some reason. Fall back to
429: * PIO.
430: */
431: xfer->c_flags &= ~C_DMA;
432: error = 0;
433: goto do_pio;
434: }
1.2 bouyer 435: ata_bio->error = ERR_DMA;
436: ata_bio->r_error = 0;
437: wdc_ata_bio_done(chp, xfer);
438: return;
439: }
440: /* Initiate command */
1.70 thorpej 441: if (wdc->select)
1.51 thorpej 442: wdc->select(chp, xfer->c_drive);
1.72 thorpej 443: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh],
1.48 thorpej 444: 0, WDSD_IBM | (xfer->c_drive << 4));
1.49 thorpej 445: switch(wdc_wait_for_ready(chp, ATA_DELAY, wait_flags)) {
1.41 bouyer 446: case WDCWAIT_OK:
1.79 perry 447: break;
1.41 bouyer 448: case WDCWAIT_TOUT:
1.2 bouyer 449: goto timeout;
1.41 bouyer 450: case WDCWAIT_THR:
451: return;
452: }
1.34 christos 453: if (ata_bio->flags & ATA_LBA48) {
1.75 thorpej 454: wdccommandext(chp, xfer->c_drive, atacmd_to48(cmd),
1.34 christos 455: (u_int64_t)ata_bio->blkno, nblks);
456: } else {
1.48 thorpej 457: wdccommand(chp, xfer->c_drive, cmd, cyl,
1.34 christos 458: head, sect, nblks, 0);
459: }
1.2 bouyer 460: /* start the DMA channel */
1.51 thorpej 461: (*wdc->dma_start)(wdc->dma_arg,
462: chp->ch_channel, xfer->c_drive);
1.72 thorpej 463: chp->ch_flags |= ATACH_DMA_WAIT;
1.41 bouyer 464: /* start timeout machinery */
465: if ((xfer->c_flags & C_POLL) == 0)
466: callout_reset(&chp->ch_callout,
467: ATA_DELAY / 1000 * hz, wdctimeout, chp);
1.2 bouyer 468: /* wait for irq */
469: goto intr;
470: } /* else not DMA */
1.82 thorpej 471: do_pio:
1.85 itohy 472: #endif /* NATA_DMA */
1.84 itohy 473: #if NATA_PIOBM
474: if ((xfer->c_flags & C_PIOBM) && xfer->c_skip == 0) {
475: if (ata_bio->flags & ATA_POLL) {
476: /* XXX not supported yet --- fall back to PIO */
477: xfer->c_flags &= ~C_PIOBM;
478: } else {
479: /* Init the DMA channel. */
480: error = (*wdc->dma_init)(wdc->dma_arg,
481: chp->ch_channel, xfer->c_drive,
482: (char *)xfer->c_databuf + xfer->c_skip,
483: xfer->c_bcount,
484: dma_flags | WDC_DMA_PIOBM_ATA);
485: if (error) {
486: if (error == EINVAL) {
487: /*
488: * We can't do DMA on this
489: * transfer for some reason.
490: * Fall back to PIO.
491: */
492: xfer->c_flags &= ~C_PIOBM;
493: error = 0;
494: } else {
495: ata_bio->error = ERR_DMA;
496: ata_bio->r_error = 0;
497: wdc_ata_bio_done(chp, xfer);
498: return;
499: }
500: }
501: }
502: }
503: #endif
1.2 bouyer 504: ata_bio->nblks = min(nblks, ata_bio->multi);
505: ata_bio->nbytes = ata_bio->nblks * ata_bio->lp->d_secsize;
1.56 mycroft 506: KASSERT(nblks == 1 || (ata_bio->flags & ATA_SINGLE) == 0);
507: if (ata_bio->nblks > 1) {
1.2 bouyer 508: cmd = (ata_bio->flags & ATA_READ) ?
509: WDCC_READMULTI : WDCC_WRITEMULTI;
510: } else {
511: cmd = (ata_bio->flags & ATA_READ) ?
512: WDCC_READ : WDCC_WRITE;
513: }
514: /* Initiate command! */
1.70 thorpej 515: if (wdc->select)
1.51 thorpej 516: wdc->select(chp, xfer->c_drive);
1.72 thorpej 517: bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
1.48 thorpej 518: WDSD_IBM | (xfer->c_drive << 4));
1.49 thorpej 519: switch(wdc_wait_for_ready(chp, ATA_DELAY, wait_flags)) {
1.41 bouyer 520: case WDCWAIT_OK:
521: break;
522: case WDCWAIT_TOUT:
1.2 bouyer 523: goto timeout;
1.41 bouyer 524: case WDCWAIT_THR:
525: return;
526: }
1.34 christos 527: if (ata_bio->flags & ATA_LBA48) {
1.75 thorpej 528: wdccommandext(chp, xfer->c_drive, atacmd_to48(cmd),
1.34 christos 529: (u_int64_t) ata_bio->blkno, nblks);
530: } else {
1.48 thorpej 531: wdccommand(chp, xfer->c_drive, cmd, cyl,
1.34 christos 532: head, sect, nblks,
533: (ata_bio->lp->d_type == DTYPE_ST506) ?
534: ata_bio->lp->d_precompcyl / 4 : 0);
535: }
1.41 bouyer 536: /* start timeout machinery */
537: if ((xfer->c_flags & C_POLL) == 0)
538: callout_reset(&chp->ch_callout,
539: ATA_DELAY / 1000 * hz, wdctimeout, chp);
1.2 bouyer 540: } else if (ata_bio->nblks > 1) {
541: /* The number of blocks in the last stretch may be smaller. */
542: nblks = xfer->c_bcount / ata_bio->lp->d_secsize;
543: if (ata_bio->nblks > nblks) {
544: ata_bio->nblks = nblks;
545: ata_bio->nbytes = xfer->c_bcount;
546: }
547: }
548: /* If this was a write and not using DMA, push the data. */
549: if ((ata_bio->flags & ATA_READ) == 0) {
1.41 bouyer 550: /*
551: * we have to busy-wait here, we can't rely on running in
552: * thread context.
553: */
1.49 thorpej 554: if (wdc_wait_for_drq(chp, ATA_DELAY, AT_POLL) != 0) {
1.2 bouyer 555: printf("%s:%d:%d: timeout waiting for DRQ, "
556: "st=0x%02x, err=0x%02x\n",
1.73 thorpej 557: atac->atac_dev.dv_xname, chp->ch_channel,
1.48 thorpej 558: xfer->c_drive, chp->ch_status, chp->ch_error);
1.16 bouyer 559: if (wdc_ata_err(drvp, ata_bio) != WDC_ATA_ERR)
1.2 bouyer 560: ata_bio->error = TIMEOUT;
561: wdc_ata_bio_done(chp, xfer);
562: return;
563: }
1.16 bouyer 564: if (wdc_ata_err(drvp, ata_bio) == WDC_ATA_ERR) {
1.2 bouyer 565: wdc_ata_bio_done(chp, xfer);
566: return;
567: }
1.84 itohy 568: #if NATA_PIOBM
569: if (xfer->c_flags & C_PIOBM) {
570: /* start the busmastering PIO */
571: (*wdc->piobm_start)(wdc->dma_arg,
572: chp->ch_channel, xfer->c_drive,
573: xfer->c_skip, ata_bio->nbytes, 0);
574: chp->ch_flags |= ATACH_DMA_WAIT;
575: } else
576: #endif
577:
1.63 mycroft 578: wdc->dataout_pio(chp, drvp->drive_flags,
1.62 mycroft 579: (char *)xfer->c_databuf + xfer->c_skip, ata_bio->nbytes);
1.2 bouyer 580: }
581:
1.85 itohy 582: #if NATA_DMA
583: intr:
584: #endif
585: /* Wait for IRQ (either real or polled) */
1.2 bouyer 586: if ((ata_bio->flags & ATA_POLL) == 0) {
1.72 thorpej 587: chp->ch_flags |= ATACH_IRQ_WAIT;
1.2 bouyer 588: } else {
589: /* Wait for at last 400ns for status bit to be valid */
590: delay(1);
1.85 itohy 591: #if NATA_DMA
1.72 thorpej 592: if (chp->ch_flags & ATACH_DMA_WAIT) {
1.26 bouyer 593: wdc_dmawait(chp, xfer, ATA_DELAY);
1.72 thorpej 594: chp->ch_flags &= ~ATACH_DMA_WAIT;
1.26 bouyer 595: }
1.85 itohy 596: #endif
1.19 bouyer 597: wdc_ata_bio_intr(chp, xfer, 0);
1.2 bouyer 598: if ((ata_bio->flags & ATA_ITSDONE) == 0)
599: goto again;
600: }
601: return;
602: timeout:
603: printf("%s:%d:%d: not ready, st=0x%02x, err=0x%02x\n",
1.73 thorpej 604: atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive,
1.2 bouyer 605: chp->ch_status, chp->ch_error);
1.16 bouyer 606: if (wdc_ata_err(drvp, ata_bio) != WDC_ATA_ERR)
1.2 bouyer 607: ata_bio->error = TIMEOUT;
608: wdc_ata_bio_done(chp, xfer);
609: return;
610: }
611:
1.45 thorpej 612: static int
1.72 thorpej 613: wdc_ata_bio_intr(struct ata_channel *chp, struct ata_xfer *xfer, int irq)
1.2 bouyer 614: {
1.73 thorpej 615: struct atac_softc *atac = chp->ch_atac;
616: struct wdc_softc *wdc = CHAN_TO_WDC(chp);
1.48 thorpej 617: struct ata_bio *ata_bio = xfer->c_cmd;
618: struct ata_drive_datas *drvp = &chp->ch_drive[xfer->c_drive];
1.2 bouyer 619: int drv_err;
620:
1.71 thorpej 621: ATADEBUG_PRINT(("wdc_ata_bio_intr %s:%d:%d\n",
1.73 thorpej 622: atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive),
1.2 bouyer 623: DEBUG_INTR | DEBUG_XFERS);
624:
625:
626: /* Is it not a transfer, but a control operation? */
627: if (drvp->state < READY) {
628: printf("%s:%d:%d: bad state %d in wdc_ata_bio_intr\n",
1.73 thorpej 629: atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive,
1.2 bouyer 630: drvp->state);
1.38 provos 631: panic("wdc_ata_bio_intr: bad state");
1.2 bouyer 632: }
633:
1.20 bouyer 634: /*
635: * if we missed an interrupt in a PIO transfer, reset and restart.
636: * Don't try to continue transfer, we may have missed cycles.
637: */
638: if ((xfer->c_flags & (C_TIMEOU | C_DMA)) == C_TIMEOU) {
639: ata_bio->error = TIMEOUT;
640: wdc_ata_bio_done(chp, xfer);
641: return 1;
642: }
643:
1.84 itohy 644: #if NATA_PIOBM
645: /* Transfer-done interrupt for busmastering PIO read */
646: if ((xfer->c_flags & C_PIOBM) && (chp->ch_flags & ATACH_PIOBM_WAIT)) {
647: chp->ch_flags &= ~ATACH_PIOBM_WAIT;
648: goto end;
649: }
650: #endif
651:
1.49 thorpej 652: /* Ack interrupt done by wdc_wait_for_unbusy */
653: if (wdc_wait_for_unbusy(chp, (irq == 0) ? ATA_DELAY : 0, AT_POLL) < 0) {
1.19 bouyer 654: if (irq && (xfer->c_flags & C_TIMEOU) == 0)
1.18 bouyer 655: return 0; /* IRQ was not for us */
1.2 bouyer 656: printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
1.73 thorpej 657: atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive,
1.2 bouyer 658: xfer->c_bcount, xfer->c_skip);
659: ata_bio->error = TIMEOUT;
660: wdc_ata_bio_done(chp, xfer);
661: return 1;
662: }
1.70 thorpej 663: if (wdc->irqack)
1.51 thorpej 664: wdc->irqack(chp);
1.79 perry 665:
1.16 bouyer 666: drv_err = wdc_ata_err(drvp, ata_bio);
1.2 bouyer 667:
1.85 itohy 668: #if NATA_DMA
1.2 bouyer 669: /* If we were using DMA, Turn off the DMA channel and check for error */
670: if (xfer->c_flags & C_DMA) {
671: if (ata_bio->flags & ATA_POLL) {
672: /*
1.13 bouyer 673: * IDE drives deassert WDCS_BSY before transfer is
1.2 bouyer 674: * complete when using DMA. Polling for DRQ to deassert
1.37 wiz 675: * is not enough DRQ is not required to be
1.7 bouyer 676: * asserted for DMA transfers, so poll for DRDY.
1.2 bouyer 677: */
678: if (wdcwait(chp, WDCS_DRDY | WDCS_DRQ, WDCS_DRDY,
1.41 bouyer 679: ATA_DELAY, ATA_POLL) == WDCWAIT_TOUT) {
1.7 bouyer 680: printf("%s:%d:%d: polled transfer timed out "
1.73 thorpej 681: "(st=0x%x)\n", atac->atac_dev.dv_xname,
1.51 thorpej 682: chp->ch_channel, xfer->c_drive,
1.48 thorpej 683: chp->ch_status);
1.2 bouyer 684: ata_bio->error = TIMEOUT;
1.10 bouyer 685: drv_err = WDC_ATA_ERR;
686: }
687: }
1.51 thorpej 688: if (wdc->dma_status != 0) {
1.10 bouyer 689: if (drv_err != WDC_ATA_ERR) {
690: ata_bio->error = ERR_DMA;
691: drv_err = WDC_ATA_ERR;
1.2 bouyer 692: }
693: }
694: if (chp->ch_status & WDCS_DRQ) {
695: if (drv_err != WDC_ATA_ERR) {
696: printf("%s:%d:%d: intr with DRQ (st=0x%x)\n",
1.73 thorpej 697: atac->atac_dev.dv_xname, chp->ch_channel,
1.48 thorpej 698: xfer->c_drive, chp->ch_status);
1.2 bouyer 699: ata_bio->error = TIMEOUT;
700: drv_err = WDC_ATA_ERR;
701: }
702: }
1.77 bouyer 703: if (drv_err != WDC_ATA_ERR)
704: goto end;
1.78 bouyer 705: if (ata_bio->r_error & WDCE_CRC || ata_bio->error == ERR_DMA)
1.55 mycroft 706: ata_dmaerr(drvp, (xfer->c_flags & C_POLL) ? AT_POLL : 0);
1.2 bouyer 707: }
1.85 itohy 708: #endif /* NATA_DMA */
1.2 bouyer 709:
710: /* if we had an error, end */
711: if (drv_err == WDC_ATA_ERR) {
712: wdc_ata_bio_done(chp, xfer);
713: return 1;
714: }
715:
716: /* If this was a read and not using DMA, fetch the data. */
717: if ((ata_bio->flags & ATA_READ) != 0) {
1.14 bouyer 718: if ((chp->ch_status & WDCS_DRQ) != WDCS_DRQ) {
1.2 bouyer 719: printf("%s:%d:%d: read intr before drq\n",
1.73 thorpej 720: atac->atac_dev.dv_xname, chp->ch_channel,
1.48 thorpej 721: xfer->c_drive);
1.2 bouyer 722: ata_bio->error = TIMEOUT;
723: wdc_ata_bio_done(chp, xfer);
724: return 1;
725: }
1.84 itohy 726: #if NATA_PIOBM
727: if (xfer->c_flags & C_PIOBM) {
728: /* start the busmastering PIO */
729: (*wdc->piobm_start)(wdc->dma_arg,
730: chp->ch_channel, xfer->c_drive,
731: xfer->c_skip, ata_bio->nbytes,
732: WDC_PIOBM_XFER_IRQ);
733: chp->ch_flags |= ATACH_DMA_WAIT | ATACH_PIOBM_WAIT | ATACH_IRQ_WAIT;
734: return 1;
735: } else
736: #endif
1.63 mycroft 737: wdc->datain_pio(chp, drvp->drive_flags,
1.62 mycroft 738: (char *)xfer->c_databuf + xfer->c_skip, ata_bio->nbytes);
1.2 bouyer 739: }
740:
1.85 itohy 741: #if NATA_DMA || NATA_PIOBM
1.2 bouyer 742: end:
1.85 itohy 743: #endif
1.2 bouyer 744: ata_bio->blkno += ata_bio->nblks;
745: ata_bio->blkdone += ata_bio->nblks;
746: xfer->c_skip += ata_bio->nbytes;
747: xfer->c_bcount -= ata_bio->nbytes;
748: /* See if this transfer is complete. */
749: if (xfer->c_bcount > 0) {
750: if ((ata_bio->flags & ATA_POLL) == 0) {
751: /* Start the next operation */
1.20 bouyer 752: _wdc_ata_bio_start(chp, xfer);
1.2 bouyer 753: } else {
1.20 bouyer 754: /* Let _wdc_ata_bio_start do the loop */
1.2 bouyer 755: return 1;
756: }
757: } else { /* Done with this transfer */
758: ata_bio->error = NOERROR;
759: wdc_ata_bio_done(chp, xfer);
760: }
761: return 1;
1.22 enami 762: }
763:
1.45 thorpej 764: static void
1.72 thorpej 765: wdc_ata_bio_kill_xfer(struct ata_channel *chp, struct ata_xfer *xfer,
1.58 bouyer 766: int reason)
1.22 enami 767: {
1.48 thorpej 768: struct ata_bio *ata_bio = xfer->c_cmd;
769: int drive = xfer->c_drive;
1.22 enami 770:
1.65 thorpej 771: ata_free_xfer(chp, xfer);
1.22 enami 772:
773: ata_bio->flags |= ATA_ITSDONE;
1.58 bouyer 774: switch (reason) {
775: case KILL_GONE:
776: ata_bio->error = ERR_NODEV;
777: break;
778: case KILL_RESET:
779: ata_bio->error = ERR_RESET;
780: break;
781: default:
782: printf("wdc_ata_bio_kill_xfer: unknown reason %d\n",
783: reason);
784: panic("wdc_ata_bio_kill_xfer");
785: }
1.22 enami 786: ata_bio->r_error = WDCE_ABRT;
1.71 thorpej 787: ATADEBUG_PRINT(("wdc_ata_done: drv_done\n"), DEBUG_XFERS);
1.46 thorpej 788: (*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc);
1.2 bouyer 789: }
790:
1.45 thorpej 791: static void
1.72 thorpej 792: wdc_ata_bio_done(struct ata_channel *chp, struct ata_xfer *xfer)
1.2 bouyer 793: {
1.48 thorpej 794: struct ata_bio *ata_bio = xfer->c_cmd;
795: int drive = xfer->c_drive;
1.2 bouyer 796:
1.71 thorpej 797: ATADEBUG_PRINT(("wdc_ata_bio_done %s:%d:%d: flags 0x%x\n",
1.85.8.1! ad 798: chp->ch_atac->atac_dev.dv_xname, chp->ch_channel, xfer->c_drive,
1.5 bouyer 799: (u_int)xfer->c_flags),
1.4 bouyer 800: DEBUG_XFERS);
1.10 bouyer 801:
1.24 thorpej 802: callout_stop(&chp->ch_callout);
1.2 bouyer 803:
804: /* feed back residual bcount to our caller */
805: ata_bio->bcount = xfer->c_bcount;
806:
1.60 bouyer 807: /* mark controller inactive and free xfer */
808: chp->ch_queue->active_xfer = NULL;
1.65 thorpej 809: ata_free_xfer(chp, xfer);
1.2 bouyer 810:
1.61 bouyer 811: if (chp->ch_drive[drive].drive_flags & DRIVE_WAITDRAIN) {
812: ata_bio->error = ERR_NODEV;
813: chp->ch_drive[drive].drive_flags &= ~DRIVE_WAITDRAIN;
814: wakeup(&chp->ch_queue->active_xfer);
815: }
1.2 bouyer 816: ata_bio->flags |= ATA_ITSDONE;
1.71 thorpej 817: ATADEBUG_PRINT(("wdc_ata_done: drv_done\n"), DEBUG_XFERS);
1.46 thorpej 818: (*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc);
1.71 thorpej 819: ATADEBUG_PRINT(("atastart from wdc_ata_done, flags 0x%x\n",
1.4 bouyer 820: chp->ch_flags), DEBUG_XFERS);
1.69 thorpej 821: atastart(chp);
1.2 bouyer 822: }
823:
1.45 thorpej 824: static int
1.44 thorpej 825: wdc_ata_err(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
1.2 bouyer 826: {
1.72 thorpej 827: struct ata_channel *chp = drvp->chnl_softc;
1.2 bouyer 828: ata_bio->error = 0;
829: if (chp->ch_status & WDCS_BSY) {
830: ata_bio->error = TIMEOUT;
831: return WDC_ATA_ERR;
832: }
833:
834: if (chp->ch_status & WDCS_DWF) {
835: ata_bio->error = ERR_DF;
836: return WDC_ATA_ERR;
837: }
838:
839: if (chp->ch_status & WDCS_ERR) {
840: ata_bio->error = ERROR;
841: ata_bio->r_error = chp->ch_error;
842: if (ata_bio->r_error & (WDCE_BBK | WDCE_UNC | WDCE_IDNF |
843: WDCE_ABRT | WDCE_TK0NF | WDCE_AMNF))
844: return WDC_ATA_ERR;
845: return WDC_ATA_NOERR;
846: }
847:
848: if (chp->ch_status & WDCS_CORR)
849: ata_bio->flags |= ATA_CORR;
850: return WDC_ATA_NOERR;
1.8 thorpej 851: }
852:
1.45 thorpej 853: static int
1.44 thorpej 854: wdc_ata_addref(struct ata_drive_datas *drvp)
1.8 thorpej 855: {
1.72 thorpej 856: struct ata_channel *chp = drvp->chnl_softc;
1.8 thorpej 857:
1.67 thorpej 858: return (ata_addref(chp));
1.8 thorpej 859: }
860:
1.45 thorpej 861: static void
1.44 thorpej 862: wdc_ata_delref(struct ata_drive_datas *drvp)
1.8 thorpej 863: {
1.72 thorpej 864: struct ata_channel *chp = drvp->chnl_softc;
1.8 thorpej 865:
1.67 thorpej 866: ata_delref(chp);
1.2 bouyer 867: }
CVSweb <webmaster@jp.NetBSD.org>