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