File: | dev/ic/wdc.c |
Warning: | line 1360, column 3 Value stored to 'valid_mode_found' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: wdc.c,v 1.136 2019/12/31 10:05:32 mpi Exp $ */ |
2 | /* $NetBSD: wdc.c,v 1.68 1999/06/23 19:00:17 bouyer Exp $ */ |
3 | /* |
4 | * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. |
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 | * |
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 |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
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 |
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 |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ |
26 | |
27 | /*- |
28 | * Copyright (c) 1998 The NetBSD Foundation, Inc. |
29 | * All rights reserved. |
30 | * |
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. |
33 | * |
34 | * Redistribution and use in source and binary forms, with or without |
35 | * modification, are permitted provided that the following conditions |
36 | * are met: |
37 | * 1. Redistributions of source code must retain the above copyright |
38 | * notice, this list of conditions and the following disclaimer. |
39 | * 2. Redistributions in binary form must reproduce the above copyright |
40 | * notice, this list of conditions and the following disclaimer in the |
41 | * documentation and/or other materials provided with the distribution. |
42 | * |
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 |
45 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
46 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
47 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
48 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
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 |
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 |
53 | * POSSIBILITY OF SUCH DAMAGE. |
54 | */ |
55 | |
56 | #include <sys/param.h> |
57 | #include <sys/systm.h> |
58 | #include <sys/kernel.h> |
59 | #include <sys/conf.h> |
60 | #include <sys/buf.h> |
61 | #include <sys/device.h> |
62 | #include <sys/malloc.h> |
63 | #include <sys/syslog.h> |
64 | #include <sys/disk.h> |
65 | #include <sys/pool.h> |
66 | |
67 | #include <machine/intr.h> |
68 | #include <machine/bus.h> |
69 | |
70 | #include <dev/ata/atavar.h> |
71 | #include <dev/ata/atareg.h> |
72 | #include <dev/ic/wdcreg.h> |
73 | #include <dev/ic/wdcvar.h> |
74 | #include <dev/ic/wdcevent.h> |
75 | |
76 | #include <scsi/scsi_all.h> |
77 | #include <scsi/scsiconf.h> |
78 | |
79 | #define WDCDELAY100 100 /* 100 microseconds */ |
80 | #define WDCNDELAY_RST(31000 * 1000 / 100) (WDC_RESET_WAIT31000 * 1000 / WDCDELAY100) |
81 | #if 0 |
82 | /* If you enable this, it will report any delays more than WDCDELAY * N long. */ |
83 | #define WDCNDELAY_DEBUG 50 |
84 | #endif /* 0 */ |
85 | |
86 | struct pool wdc_xfer_pool; |
87 | struct scsi_iopool wdc_xfer_iopool; |
88 | |
89 | void * wdc_xfer_get(void *); |
90 | void wdc_xfer_put(void *, void *); |
91 | |
92 | void __wdcerror(struct channel_softc *, char *); |
93 | int __wdcwait_reset(struct channel_softc *, int); |
94 | void __wdccommand_done(struct channel_softc *, struct wdc_xfer *); |
95 | void __wdccommand_start(struct channel_softc *, struct wdc_xfer *); |
96 | int __wdccommand_intr(struct channel_softc *, struct wdc_xfer *, int); |
97 | int wdprint(void *, const char *); |
98 | void wdc_kill_pending(struct channel_softc *); |
99 | |
100 | #define DEBUG_INTR0x01 0x01 |
101 | #define DEBUG_XFERS0x02 0x02 |
102 | #define DEBUG_STATUS0x04 0x04 |
103 | #define DEBUG_FUNCS0x08 0x08 |
104 | #define DEBUG_PROBE0x10 0x10 |
105 | #define DEBUG_STATUSX0x20 0x20 |
106 | #define DEBUG_SDRIVE0x40 0x40 |
107 | #define DEBUG_DETACH0x80 0x80 |
108 | |
109 | #ifdef WDCDEBUG |
110 | #ifndef WDCDEBUG_MASK |
111 | #define WDCDEBUG_MASK 0x00 |
112 | #endif |
113 | int wdcdebug_mask = WDCDEBUG_MASK; |
114 | int wdc_nxfer = 0; |
115 | #define WDCDEBUG_PRINT(args, level) do { \ |
116 | if ((wdcdebug_mask & (level)) != 0) \ |
117 | printf args; \ |
118 | } while (0) |
119 | #else |
120 | #define WDCDEBUG_PRINT(args, level) |
121 | #endif /* WDCDEBUG */ |
122 | |
123 | int at_poll = AT_POLL0x0010; |
124 | |
125 | int wdc_floating_bus(struct channel_softc *, int); |
126 | int wdc_preata_drive(struct channel_softc *, int); |
127 | int wdc_ata_present(struct channel_softc *, int); |
128 | |
129 | struct cfdriver wdc_cd = { |
130 | NULL((void *)0), "wdc", DV_DULL |
131 | }; |
132 | |
133 | struct channel_softc_vtbl wdc_default_vtbl = { |
134 | wdc_default_read_reg, |
135 | wdc_default_write_reg, |
136 | wdc_default_lba48_write_reg, |
137 | wdc_default_read_raw_multi_2, |
138 | wdc_default_write_raw_multi_2, |
139 | wdc_default_read_raw_multi_4, |
140 | wdc_default_write_raw_multi_4 |
141 | }; |
142 | |
143 | #ifdef WDCDEBUG |
144 | static char *wdc_log_buf = NULL((void *)0); |
145 | static unsigned int wdc_tail = 0; |
146 | static unsigned int wdc_head = 0; |
147 | static unsigned int wdc_log_cap = 16 * 1024; |
148 | static int chp_idx = 1; |
149 | |
150 | void |
151 | wdc_log(struct channel_softc *chp, enum wdcevent_type type, |
152 | unsigned int size, char val[]) |
153 | { |
154 | unsigned int request_size; |
155 | char *ptr; |
156 | int log_size; |
157 | unsigned int head = wdc_head; |
158 | unsigned int tail = wdc_tail; |
159 | |
160 | #ifdef DIAGNOSTIC1 |
161 | if (head > wdc_log_cap || tail > wdc_log_cap) { |
162 | printf ("wdc_log: head %x wdc_tail %x\n", head, |
163 | tail); |
164 | return; |
165 | } |
166 | |
167 | if (size > wdc_log_cap / 2) { |
168 | printf ("wdc_log: type %d size %x\n", type, size); |
169 | return; |
170 | } |
171 | #endif |
172 | |
173 | if (wdc_log_buf == NULL((void *)0)) { |
174 | wdc_log_buf = malloc(wdc_log_cap, M_DEVBUF2, M_NOWAIT0x0002); |
175 | if (wdc_log_buf == NULL((void *)0)) |
176 | return; |
177 | } |
178 | if (chp->ch_log_idx == 0) |
179 | chp->ch_log_idx = chp_idx++; |
180 | |
181 | request_size = size + 2; |
182 | |
183 | /* Check how many bytes are left */ |
184 | log_size = head - tail; |
185 | if (log_size < 0) log_size += wdc_log_cap; |
186 | |
187 | if (log_size + request_size >= wdc_log_cap) { |
188 | int nb = 0; |
189 | int rec_size; |
190 | |
191 | while (nb <= (request_size * 2)) { |
192 | if (wdc_log_buf[tail] == 0) |
193 | rec_size = 1; |
194 | else |
195 | rec_size = (wdc_log_buf[tail + 1] & 0x1f) + 2; |
196 | tail = (tail + rec_size) % wdc_log_cap; |
197 | nb += rec_size; |
198 | } |
199 | } |
200 | |
201 | /* Avoid wrapping in the middle of a request */ |
202 | if (head + request_size >= wdc_log_cap) { |
203 | memset(&wdc_log_buf[head], 0, wdc_log_cap - head)__builtin_memset((&wdc_log_buf[head]), (0), (wdc_log_cap - head)); |
204 | head = 0; |
205 | } |
206 | |
207 | ptr = &wdc_log_buf[head]; |
208 | *ptr++ = type & 0xff; |
209 | *ptr++ = ((chp->ch_log_idx & 0x7) << 5) | (size & 0x1f); |
210 | memcpy(ptr, val, size)__builtin_memcpy((ptr), (val), (size)); |
211 | |
212 | wdc_head = (head + request_size) % wdc_log_cap; |
213 | wdc_tail = tail; |
214 | } |
215 | |
216 | char *wdc_get_log(unsigned int *, unsigned int *); |
217 | |
218 | char * |
219 | wdc_get_log(unsigned int * size, unsigned int *left) |
220 | { |
221 | int log_size; |
222 | char *retbuf = NULL((void *)0); |
223 | int nb, tocopy; |
224 | int s; |
225 | unsigned int head = wdc_head; |
226 | unsigned int tail = wdc_tail; |
227 | |
228 | s = splbio()splraise(0x6); |
229 | |
230 | log_size = (head - tail); |
231 | if (left != NULL((void *)0)) |
232 | *left = 0; |
233 | |
234 | if (log_size < 0) |
235 | log_size += wdc_log_cap; |
236 | |
237 | tocopy = log_size; |
238 | if ((u_int)tocopy > *size) |
239 | tocopy = *size; |
240 | |
241 | if (wdc_log_buf == NULL((void *)0)) { |
242 | *size = 0; |
243 | *left = 0; |
244 | goto out; |
245 | } |
246 | |
247 | #ifdef DIAGNOSTIC1 |
248 | if (head > wdc_log_cap || tail > wdc_log_cap) { |
249 | printf ("wdc_log: head %x tail %x\n", head, |
250 | tail); |
251 | *size = 0; |
252 | *left = 0; |
253 | goto out; |
254 | } |
255 | #endif |
256 | |
257 | retbuf = malloc(tocopy, M_TEMP127, M_NOWAIT0x0002); |
258 | if (retbuf == NULL((void *)0)) { |
259 | *size = 0; |
260 | *left = log_size; |
261 | goto out; |
262 | } |
263 | |
264 | nb = 0; |
265 | for (;;) { |
266 | int rec_size; |
267 | |
268 | if (wdc_log_buf[tail] == 0) |
269 | rec_size = 1; |
270 | else |
271 | rec_size = (wdc_log_buf[tail + 1] & 0x1f) + 2; |
272 | |
273 | if ((nb + rec_size) >= tocopy) |
274 | break; |
275 | |
276 | memcpy(&retbuf[nb], &wdc_log_buf[tail], rec_size)__builtin_memcpy((&retbuf[nb]), (&wdc_log_buf[tail]), (rec_size)); |
277 | tail = (tail + rec_size) % wdc_log_cap; |
278 | nb += rec_size; |
279 | } |
280 | |
281 | wdc_tail = tail; |
282 | *size = nb; |
283 | *left = log_size - nb; |
284 | |
285 | out: |
286 | splx(s)spllower(s); |
287 | return (retbuf); |
288 | } |
289 | #endif /* WDCDEBUG */ |
290 | |
291 | u_int8_t |
292 | wdc_default_read_reg(struct channel_softc *chp, enum wdc_regs reg) |
293 | { |
294 | #ifdef DIAGNOSTIC1 |
295 | if (reg & _WDC_WRONLY32) { |
296 | printf ("wdc_default_read_reg: reading from a write-only register %d\n", reg); |
297 | } |
298 | #endif /* DIAGNOSTIC */ |
299 | |
300 | if (reg & _WDC_AUX8) |
301 | return (bus_space_read_1(chp->ctl_iot, chp->ctl_ioh,((chp->ctl_iot)->read_1((chp->ctl_ioh), (reg & 7 ))) |
302 | reg & _WDC_REGMASK)((chp->ctl_iot)->read_1((chp->ctl_ioh), (reg & 7 )))); |
303 | else |
304 | return (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,((chp->cmd_iot)->read_1((chp->cmd_ioh), (reg & 7 ))) |
305 | reg & _WDC_REGMASK)((chp->cmd_iot)->read_1((chp->cmd_ioh), (reg & 7 )))); |
306 | } |
307 | |
308 | void |
309 | wdc_default_write_reg(struct channel_softc *chp, enum wdc_regs reg, u_int8_t val) |
310 | { |
311 | #ifdef DIAGNOSTIC1 |
312 | if (reg & _WDC_RDONLY16) { |
313 | printf ("wdc_default_write_reg: writing to a read-only register %d\n", reg); |
314 | } |
315 | #endif /* DIAGNOSTIC */ |
316 | |
317 | if (reg & _WDC_AUX8) |
318 | bus_space_write_1(chp->ctl_iot, chp->ctl_ioh,((chp->ctl_iot)->write_1((chp->ctl_ioh), (reg & 7 ), (val))) |
319 | reg & _WDC_REGMASK, val)((chp->ctl_iot)->write_1((chp->ctl_ioh), (reg & 7 ), (val))); |
320 | else |
321 | bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,((chp->cmd_iot)->write_1((chp->cmd_ioh), (reg & 7 ), (val))) |
322 | reg & _WDC_REGMASK, val)((chp->cmd_iot)->write_1((chp->cmd_ioh), (reg & 7 ), (val))); |
323 | } |
324 | |
325 | void |
326 | wdc_default_lba48_write_reg(struct channel_softc *chp, enum wdc_regs reg, |
327 | u_int16_t val) |
328 | { |
329 | /* All registers are two byte deep FIFOs. */ |
330 | CHP_WRITE_REG(chp, reg, val >> 8)((chp)->_vtbl->write_reg)(chp, reg, val >> 8); |
331 | CHP_WRITE_REG(chp, reg, val)((chp)->_vtbl->write_reg)(chp, reg, val); |
332 | } |
333 | |
334 | void |
335 | wdc_default_read_raw_multi_2(struct channel_softc *chp, void *data, |
336 | unsigned int nbytes) |
337 | { |
338 | if (data == NULL((void *)0)) { |
339 | unsigned int i; |
340 | |
341 | for (i = 0; i < nbytes; i += 2) { |
342 | bus_space_read_2(chp->cmd_iot, chp->cmd_ioh, 0)((chp->cmd_iot)->read_2((chp->cmd_ioh), (0))); |
343 | } |
344 | |
345 | return; |
346 | } |
347 | |
348 | bus_space_read_raw_multi_2(chp->cmd_iot, chp->cmd_ioh, 0,((chp->cmd_iot)->read_multi_2((chp->cmd_ioh), (0), ( u_int16_t *)(data), (nbytes) >> 1)) |
349 | data, nbytes)((chp->cmd_iot)->read_multi_2((chp->cmd_ioh), (0), ( u_int16_t *)(data), (nbytes) >> 1)); |
350 | } |
351 | |
352 | |
353 | void |
354 | wdc_default_write_raw_multi_2(struct channel_softc *chp, void *data, |
355 | unsigned int nbytes) |
356 | { |
357 | if (data == NULL((void *)0)) { |
358 | unsigned int i; |
359 | |
360 | for (i = 0; i < nbytes; i += 2) { |
361 | bus_space_write_2(chp->cmd_iot, chp->cmd_ioh, 0, 0)((chp->cmd_iot)->write_2((chp->cmd_ioh), (0), (0))); |
362 | } |
363 | |
364 | return; |
365 | } |
366 | |
367 | bus_space_write_raw_multi_2(chp->cmd_iot, chp->cmd_ioh, 0,((chp->cmd_iot)->write_multi_2((chp->cmd_ioh), (0), ( const u_int16_t *)(data), (nbytes) >> 1)) |
368 | data, nbytes)((chp->cmd_iot)->write_multi_2((chp->cmd_ioh), (0), ( const u_int16_t *)(data), (nbytes) >> 1)); |
369 | } |
370 | |
371 | |
372 | void |
373 | wdc_default_write_raw_multi_4(struct channel_softc *chp, void *data, |
374 | unsigned int nbytes) |
375 | { |
376 | if (data == NULL((void *)0)) { |
377 | unsigned int i; |
378 | |
379 | for (i = 0; i < nbytes; i += 4) { |
380 | bus_space_write_4(chp->cmd_iot, chp->cmd_ioh, 0, 0)((chp->cmd_iot)->write_4((chp->cmd_ioh), (0), (0))); |
381 | } |
382 | |
383 | return; |
384 | } |
385 | |
386 | bus_space_write_raw_multi_4(chp->cmd_iot, chp->cmd_ioh, 0,((chp->cmd_iot)->write_multi_4((chp->cmd_ioh), (0), ( const u_int32_t *)(data), (nbytes) >> 2)) |
387 | data, nbytes)((chp->cmd_iot)->write_multi_4((chp->cmd_ioh), (0), ( const u_int32_t *)(data), (nbytes) >> 2)); |
388 | } |
389 | |
390 | |
391 | void |
392 | wdc_default_read_raw_multi_4(struct channel_softc *chp, void *data, |
393 | unsigned int nbytes) |
394 | { |
395 | if (data == NULL((void *)0)) { |
396 | unsigned int i; |
397 | |
398 | for (i = 0; i < nbytes; i += 4) { |
399 | bus_space_read_4(chp->cmd_iot, chp->cmd_ioh, 0)((chp->cmd_iot)->read_4((chp->cmd_ioh), (0))); |
400 | } |
401 | |
402 | return; |
403 | } |
404 | |
405 | bus_space_read_raw_multi_4(chp->cmd_iot, chp->cmd_ioh, 0,((chp->cmd_iot)->read_multi_4((chp->cmd_ioh), (0), ( u_int32_t *)(data), (nbytes) >> 2)) |
406 | data, nbytes)((chp->cmd_iot)->read_multi_4((chp->cmd_ioh), (0), ( u_int32_t *)(data), (nbytes) >> 2)); |
407 | } |
408 | |
409 | int |
410 | wdprint(void *aux, const char *pnp) |
411 | { |
412 | struct ata_atapi_attach *aa_link = aux; |
413 | if (pnp) |
414 | printf("drive at %s", pnp); |
415 | printf(" channel %d drive %d", aa_link->aa_channel, |
416 | aa_link->aa_drv_data->drive); |
417 | return (UNCONF1); |
418 | } |
419 | |
420 | void |
421 | wdc_disable_intr(struct channel_softc *chp) |
422 | { |
423 | CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_IDS)((chp)->_vtbl->write_reg)(chp, wdr_ctlr, 0x02); |
424 | } |
425 | |
426 | void |
427 | wdc_enable_intr(struct channel_softc *chp) |
428 | { |
429 | CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_4BIT)((chp)->_vtbl->write_reg)(chp, wdr_ctlr, 0x08); |
430 | } |
431 | |
432 | void |
433 | wdc_set_drive(struct channel_softc *chp, int drive) |
434 | { |
435 | CHP_WRITE_REG(chp, wdr_sdh, (drive << 4) | WDSD_IBM)((chp)->_vtbl->write_reg)(chp, wdr_sdh, (drive << 4) | 0xa0); |
436 | WDC_LOG_SET_DRIVE(chp, drive); |
437 | } |
438 | |
439 | int |
440 | wdc_floating_bus(struct channel_softc *chp, int drive) |
441 | { |
442 | u_int8_t cumulative_status, status; |
443 | int iter; |
444 | |
445 | wdc_set_drive(chp, drive); |
446 | delay(10)(*delay_func)(10); |
447 | |
448 | /* Stolen from Phoenix BIOS Drive Autotyping document */ |
449 | cumulative_status = 0; |
450 | for (iter = 0; iter < 100; iter++) { |
451 | CHP_WRITE_REG(chp, wdr_seccnt, 0x7f)((chp)->_vtbl->write_reg)(chp, wdr_seccnt, 0x7f); |
452 | delay (1)(*delay_func)(1); |
453 | |
454 | status = CHP_READ_REG(chp, wdr_status)((chp)->_vtbl->read_reg)(chp, wdr_status); |
455 | |
456 | /* The other bits are meaningless if BSY is set */ |
457 | if (status & WDCS_BSY0x80) |
458 | continue; |
459 | |
460 | cumulative_status |= status; |
461 | |
462 | #define BAD_BIT_COMBO(0x40 | 0x10 | 0x08 | 0x01) (WDCS_DRDY0x40 | WDCS_DSC0x10 | WDCS_DRQ0x08 | WDCS_ERR0x01) |
463 | if ((cumulative_status & BAD_BIT_COMBO(0x40 | 0x10 | 0x08 | 0x01)) == BAD_BIT_COMBO(0x40 | 0x10 | 0x08 | 0x01)) |
464 | return 1; |
465 | } |
466 | |
467 | |
468 | return 0; |
469 | } |
470 | |
471 | int |
472 | wdc_preata_drive(struct channel_softc *chp, int drive) |
473 | { |
474 | if (wdc_floating_bus(chp, drive)) { |
475 | WDCDEBUG_PRINT(("%s:%d:%d: floating bus detected\n", |
476 | chp->wdc->sc_dev.dv_xname, |
477 | chp->channel, drive), DEBUG_PROBE); |
478 | return 0; |
479 | } |
480 | |
481 | wdc_set_drive(chp, drive); |
482 | delay(100)(*delay_func)(100); |
483 | if (wdcwait(chp, WDCS_DRDY | WDCS_DRQ, WDCS_DRDY, 10000)((wdc_wait_for_status((chp), (0x40 | 0x08), (0x40), (10000)) >= 0) ? 0 : -1) != 0) { |
484 | WDCDEBUG_PRINT(("%s:%d:%d: not ready\n", |
485 | chp->wdc->sc_dev.dv_xname, |
486 | chp->channel, drive), DEBUG_PROBE); |
487 | return 0; |
488 | } |
489 | |
490 | CHP_WRITE_REG(chp, wdr_command, WDCC_RECAL)((chp)->_vtbl->write_reg)(chp, wdr_command, 0x10); |
491 | WDC_LOG_ATA_CMDSHORT(chp, WDCC_RECAL); |
492 | if (wdcwait(chp, WDCS_DRDY | WDCS_DRQ, WDCS_DRDY, 10000)((wdc_wait_for_status((chp), (0x40 | 0x08), (0x40), (10000)) >= 0) ? 0 : -1) != 0) { |
493 | WDCDEBUG_PRINT(("%s:%d:%d: WDCC_RECAL failed\n", |
494 | chp->wdc->sc_dev.dv_xname, |
495 | chp->channel, drive), DEBUG_PROBE); |
496 | return 0; |
497 | } |
498 | |
499 | return 1; |
500 | } |
501 | |
502 | int |
503 | wdc_ata_present(struct channel_softc *chp, int drive) |
504 | { |
505 | int time_to_done; |
506 | int retry_cnt = 0; |
507 | |
508 | wdc_set_drive(chp, drive); |
509 | delay(10)(*delay_func)(10); |
510 | |
511 | retry: |
512 | /* |
513 | You're actually supposed to wait up to 10 seconds |
514 | for DRDY. However, as a practical matter, most |
515 | drives assert DRDY very quickly after dropping BSY. |
516 | |
517 | The 10 seconds wait is sub-optimal because, according |
518 | to the ATA standard, the master should reply with 00 |
519 | for any reads to a non-existent slave. |
520 | */ |
521 | time_to_done = wdc_wait_for_status(chp, |
522 | (WDCS_DRDY0x40 | WDCS_DSC0x10 | WDCS_DRQ0x08), |
523 | (WDCS_DRDY0x40 | WDCS_DSC0x10), 1000); |
524 | if (time_to_done == -1) { |
525 | if (retry_cnt == 0 && chp->ch_status == 0x00) { |
526 | /* At least one flash card needs to be kicked */ |
527 | wdccommandshort(chp, drive, WDCC_CHECK_PWR0xe5); |
528 | retry_cnt++; |
529 | goto retry; |
530 | } |
531 | WDCDEBUG_PRINT(("%s:%d:%d: DRDY test timed out with status" |
532 | " %02x\n", |
533 | chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", |
534 | chp->channel, drive, chp->ch_status), |
535 | DEBUG_PROBE); |
536 | return 0; |
537 | } |
538 | |
539 | if ((chp->ch_status & 0xfc) != (WDCS_DRDY0x40 | WDCS_DSC0x10)) { |
540 | WDCDEBUG_PRINT(("%s:%d:%d: status test for 0x50 failed with" |
541 | " %02x\n", |
542 | chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", |
543 | chp->channel, drive, chp->ch_status), |
544 | DEBUG_PROBE); |
545 | |
546 | return 0; |
547 | } |
548 | |
549 | WDCDEBUG_PRINT(("%s:%d:%d: waiting for ready %d msec\n", |
550 | chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", |
551 | chp->channel, drive, time_to_done), DEBUG_PROBE); |
552 | |
553 | /* |
554 | * Test register writability |
555 | */ |
556 | CHP_WRITE_REG(chp, wdr_cyl_lo, 0xaa)((chp)->_vtbl->write_reg)(chp, wdr_cyl_lo, 0xaa); |
557 | CHP_WRITE_REG(chp, wdr_cyl_hi, 0x55)((chp)->_vtbl->write_reg)(chp, wdr_cyl_hi, 0x55); |
558 | CHP_WRITE_REG(chp, wdr_seccnt, 0xff)((chp)->_vtbl->write_reg)(chp, wdr_seccnt, 0xff); |
559 | DELAY(10)(*delay_func)(10); |
560 | |
561 | if (CHP_READ_REG(chp, wdr_cyl_lo)((chp)->_vtbl->read_reg)(chp, wdr_cyl_lo) != 0xaa && |
562 | CHP_READ_REG(chp, wdr_cyl_hi)((chp)->_vtbl->read_reg)(chp, wdr_cyl_hi) != 0x55) { |
563 | WDCDEBUG_PRINT(("%s:%d:%d: register writability failed\n", |
564 | chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", |
565 | chp->channel, drive), DEBUG_PROBE); |
566 | return 0; |
567 | } |
568 | |
569 | return 1; |
570 | } |
571 | |
572 | |
573 | /* |
574 | * Test to see controller with at least one attached drive is there. |
575 | * Returns a bit for each possible drive found (0x01 for drive 0, |
576 | * 0x02 for drive 1). |
577 | * Logic: |
578 | * - If a status register is at 0x7f or 0xff, assume there is no drive here |
579 | * (ISA has pull-up resistors). Similarly if the status register has |
580 | * the value we last wrote to the bus (for IDE interfaces without pullups). |
581 | * If no drive at all -> return. |
582 | * - reset the controller, wait for it to complete (may take up to 31s !). |
583 | * If timeout -> return. |
584 | * - test ATA/ATAPI signatures. If at last one drive found -> return. |
585 | * - try an ATA command on the master. |
586 | */ |
587 | |
588 | int |
589 | wdcprobe(struct channel_softc *chp) |
590 | { |
591 | u_int8_t st0, st1, sc, sn, cl, ch; |
592 | u_int8_t ret_value = 0x03; |
593 | u_int8_t drive; |
594 | #ifdef WDCDEBUG |
595 | int savedmask = wdcdebug_mask; |
596 | #endif |
597 | |
598 | if (chp->_vtbl == 0) { |
599 | int s = splbio()splraise(0x6); |
600 | chp->_vtbl = &wdc_default_vtbl; |
601 | splx(s)spllower(s); |
602 | } |
603 | |
604 | #ifdef WDCDEBUG |
605 | if ((chp->ch_flags & WDCF_VERBOSE_PROBE0x40) || |
606 | (chp->wdc && |
607 | (chp->wdc->sc_dev.dv_cfdata->cf_flags & WDC_OPTION_PROBE_VERBOSE0x10000))) |
608 | wdcdebug_mask |= DEBUG_PROBE0x10; |
609 | #endif /* WDCDEBUG */ |
610 | |
611 | if (chp->wdc == NULL((void *)0) || |
612 | (chp->wdc->cap & WDC_CAPABILITY_NO_EXTRA_RESETS0x0100) == 0) { |
613 | /* Sample the statuses of drive 0 and 1 into st0 and st1 */ |
614 | wdc_set_drive(chp, 0); |
615 | delay(10)(*delay_func)(10); |
616 | st0 = CHP_READ_REG(chp, wdr_status)((chp)->_vtbl->read_reg)(chp, wdr_status); |
617 | WDC_LOG_STATUS(chp, st0); |
618 | wdc_set_drive(chp, 1); |
619 | delay(10)(*delay_func)(10); |
620 | st1 = CHP_READ_REG(chp, wdr_status)((chp)->_vtbl->read_reg)(chp, wdr_status); |
621 | WDC_LOG_STATUS(chp, st1); |
622 | |
623 | WDCDEBUG_PRINT(("%s:%d: before reset, st0=0x%b, st1=0x%b\n", |
624 | chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", |
625 | chp->channel, st0, WDCS_BITS, st1, WDCS_BITS), |
626 | DEBUG_PROBE); |
627 | |
628 | if (st0 == 0xff || st0 == WDSD_IBM0xa0) |
629 | ret_value &= ~0x01; |
630 | if (st1 == 0xff || st1 == (WDSD_IBM0xa0 | 0x10)) |
631 | ret_value &= ~0x02; |
632 | if (ret_value == 0) |
633 | return 0; |
634 | } |
635 | |
636 | /* reset the channel */ |
637 | wdc_do_reset(chp); |
638 | |
639 | ret_value = __wdcwait_reset(chp, ret_value); |
640 | WDCDEBUG_PRINT(("%s:%d: after reset, ret_value=0x%d\n", |
641 | chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", chp->channel, |
642 | ret_value), DEBUG_PROBE); |
643 | |
644 | if (ret_value == 0) |
645 | return 0; |
646 | |
647 | if (chp->wdc && (chp->wdc->quirks & WDC_QUIRK_NOATAPI0x0004)) |
648 | goto noatapi; |
649 | |
650 | /* |
651 | * Use signatures to find potential ATAPI drives |
652 | */ |
653 | for (drive = 0; drive < 2; drive++) { |
654 | if ((ret_value & (0x01 << drive)) == 0) |
655 | continue; |
656 | wdc_set_drive(chp, drive); |
657 | delay(10)(*delay_func)(10); |
658 | /* Save registers contents */ |
659 | st0 = CHP_READ_REG(chp, wdr_status)((chp)->_vtbl->read_reg)(chp, wdr_status); |
660 | sc = CHP_READ_REG(chp, wdr_seccnt)((chp)->_vtbl->read_reg)(chp, wdr_seccnt); |
661 | sn = CHP_READ_REG(chp, wdr_sector)((chp)->_vtbl->read_reg)(chp, wdr_sector); |
662 | cl = CHP_READ_REG(chp, wdr_cyl_lo)((chp)->_vtbl->read_reg)(chp, wdr_cyl_lo); |
663 | ch = CHP_READ_REG(chp, wdr_cyl_hi)((chp)->_vtbl->read_reg)(chp, wdr_cyl_hi); |
664 | WDC_LOG_REG(chp, wdr_cyl_lo, (ch << 8) | cl); |
665 | |
666 | WDCDEBUG_PRINT(("%s:%d:%d: after reset, st=0x%b, sc=0x%x" |
667 | " sn=0x%x cl=0x%x ch=0x%x\n", |
668 | chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", |
669 | chp->channel, drive, st0, WDCS_BITS, sc, sn, cl, ch), |
670 | DEBUG_PROBE); |
671 | /* |
672 | * This is a simplification of the test in the ATAPI |
673 | * spec since not all drives seem to set the other regs |
674 | * correctly. |
675 | */ |
676 | if (cl == 0x14 && ch == 0xeb) |
677 | chp->ch_drive[drive].drive_flags |= DRIVE_ATAPI0x0002; |
678 | } |
679 | |
680 | noatapi: |
681 | if (chp->wdc && (chp->wdc->quirks & WDC_QUIRK_NOATA0x0002)) |
682 | goto noata; |
683 | |
684 | /* |
685 | * Detect ATA drives by poking around the registers |
686 | */ |
687 | for (drive = 0; drive < 2; drive++) { |
688 | if ((ret_value & (0x01 << drive)) == 0) |
689 | continue; |
690 | if (chp->ch_drive[drive].drive_flags & DRIVE_ATAPI0x0002) |
691 | continue; |
692 | |
693 | wdc_disable_intr(chp); |
694 | /* ATA detect */ |
695 | if (wdc_ata_present(chp, drive)) { |
696 | chp->ch_drive[drive].drive_flags |= DRIVE_ATA0x0001; |
697 | if (chp->wdc == NULL((void *)0) || |
698 | (chp->wdc->cap & WDC_CAPABILITY_PREATA0x0200) != 0) |
699 | chp->ch_drive[drive].drive_flags |= DRIVE_OLD0x0004; |
700 | } else { |
701 | ret_value &= ~(1 << drive); |
702 | } |
703 | wdc_enable_intr(chp); |
704 | } |
705 | |
706 | noata: |
707 | |
708 | #ifdef WDCDEBUG |
709 | wdcdebug_mask = savedmask; |
710 | #endif |
711 | return (ret_value); |
712 | } |
713 | |
714 | struct channel_queue * |
715 | wdc_alloc_queue(void) |
716 | { |
717 | static int inited = 0; |
718 | struct channel_queue *queue; |
719 | |
720 | /* Initialize global data. */ |
721 | if (inited == 0) { |
722 | /* Initialize the wdc_xfer pool. */ |
723 | pool_init(&wdc_xfer_pool, sizeof(struct wdc_xfer), 0, IPL_BIO0x6, |
724 | 0, "wdcxfer", NULL((void *)0)); |
725 | scsi_iopool_init(&wdc_xfer_iopool, NULL((void *)0), |
726 | wdc_xfer_get, wdc_xfer_put); |
727 | inited = 1; |
728 | } |
729 | |
730 | queue = malloc(sizeof(*queue), M_DEVBUF2, M_NOWAIT0x0002); |
731 | if (queue != NULL((void *)0)) { |
732 | TAILQ_INIT(&queue->sc_xfer)do { (&queue->sc_xfer)->tqh_first = ((void *)0); (& queue->sc_xfer)->tqh_last = &(&queue->sc_xfer )->tqh_first; } while (0); |
733 | } |
734 | return (queue); |
735 | } |
736 | |
737 | void |
738 | wdc_free_queue(struct channel_queue *queue) |
739 | { |
740 | free(queue, M_DEVBUF2, sizeof(*queue)); |
741 | } |
742 | |
743 | void |
744 | wdcattach(struct channel_softc *chp) |
745 | { |
746 | int i; |
747 | struct ata_atapi_attach aa_link; |
748 | #ifdef WDCDEBUG |
749 | int savedmask = wdcdebug_mask; |
750 | #endif |
751 | |
752 | if (!cold) |
753 | at_poll = AT_WAIT0x0008; |
754 | |
755 | if (chp->wdc->reset == NULL((void *)0)) |
756 | chp->wdc->reset = wdc_do_reset; |
757 | |
758 | timeout_set(&chp->ch_timo, wdctimeout, chp); |
759 | |
760 | if (!chp->_vtbl) |
761 | chp->_vtbl = &wdc_default_vtbl; |
762 | |
763 | for (i = 0; i < 2; i++) { |
764 | chp->ch_drive[i].chnl_softc = chp; |
765 | chp->ch_drive[i].drive = i; |
766 | } |
767 | |
768 | if (chp->wdc->drv_probe != NULL((void *)0)) { |
769 | chp->wdc->drv_probe(chp); |
770 | } else { |
771 | if (wdcprobe(chp) == 0) |
772 | /* If no drives, abort attach here. */ |
773 | return; |
774 | } |
775 | |
776 | /* ATAPI drives need settling time. Give them 250ms */ |
777 | if ((chp->ch_drive[0].drive_flags & DRIVE_ATAPI0x0002) || |
778 | (chp->ch_drive[1].drive_flags & DRIVE_ATAPI0x0002)) { |
779 | delay(250 * 1000)(*delay_func)(250 * 1000); |
780 | } |
781 | |
782 | #ifdef WDCDEBUG |
783 | if (chp->wdc->sc_dev.dv_cfdata->cf_flags & WDC_OPTION_PROBE_VERBOSE0x10000) |
784 | wdcdebug_mask |= DEBUG_PROBE0x10; |
785 | |
786 | if ((chp->ch_drive[0].drive_flags & DRIVE_ATAPI0x0002) || |
787 | (chp->ch_drive[1].drive_flags & DRIVE_ATAPI0x0002)) { |
788 | wdcdebug_mask = DEBUG_PROBE0x10; |
789 | } |
790 | #endif /* WDCDEBUG */ |
791 | |
792 | for (i = 0; i < 2; i++) { |
793 | struct ata_drive_datas *drvp = &chp->ch_drive[i]; |
794 | |
795 | /* If controller can't do 16bit flag the drives as 32bit */ |
796 | if ((chp->wdc->cap & |
797 | (WDC_CAPABILITY_DATA160x0001 | WDC_CAPABILITY_DATA320x0002)) == |
798 | WDC_CAPABILITY_DATA320x0002) |
799 | drvp->drive_flags |= DRIVE_CAP320x0008; |
800 | |
801 | if ((drvp->drive_flags & DRIVE(0x0001|0x0002|0x0004)) == 0) |
802 | continue; |
803 | |
804 | if (i == 1 && ((chp->ch_drive[0].drive_flags & DRIVE(0x0001|0x0002|0x0004)) == 0)) |
805 | chp->ch_flags |= WDCF_ONESLAVE0x02; |
806 | /* |
807 | * Wait a bit, some devices are weird just after a reset. |
808 | * Then issue a IDENTIFY command, to try to detect slave ghost. |
809 | */ |
810 | delay(5000)(*delay_func)(5000); |
811 | if (ata_get_params(&chp->ch_drive[i], at_poll, &drvp->id) == |
812 | CMD_OK0) { |
813 | /* If IDENTIFY succeeded, this is not an OLD ctrl */ |
814 | drvp->drive_flags &= ~DRIVE_OLD0x0004; |
815 | } else { |
816 | bzero(&drvp->id, sizeof(struct ataparams))__builtin_bzero((&drvp->id), (sizeof(struct ataparams) )); |
817 | drvp->drive_flags &= |
818 | ~(DRIVE_ATA0x0001 | DRIVE_ATAPI0x0002); |
819 | WDCDEBUG_PRINT(("%s:%d:%d: IDENTIFY failed\n", |
820 | chp->wdc->sc_dev.dv_xname, |
821 | chp->channel, i), DEBUG_PROBE); |
822 | |
823 | if ((drvp->drive_flags & DRIVE_OLD0x0004) && |
824 | !wdc_preata_drive(chp, i)) |
825 | drvp->drive_flags &= ~DRIVE_OLD0x0004; |
826 | } |
827 | } |
828 | |
829 | WDCDEBUG_PRINT(("wdcattach: ch_drive_flags 0x%x 0x%x\n", |
830 | chp->ch_drive[0].drive_flags, chp->ch_drive[1].drive_flags), |
831 | DEBUG_PROBE); |
832 | |
833 | /* If no drives, abort here */ |
834 | if ((chp->ch_drive[0].drive_flags & DRIVE(0x0001|0x0002|0x0004)) == 0 && |
835 | (chp->ch_drive[1].drive_flags & DRIVE(0x0001|0x0002|0x0004)) == 0) |
836 | goto exit; |
837 | |
838 | for (i = 0; i < 2; i++) { |
839 | if ((chp->ch_drive[i].drive_flags & DRIVE(0x0001|0x0002|0x0004)) == 0) { |
840 | continue; |
841 | } |
842 | bzero(&aa_link, sizeof(struct ata_atapi_attach))__builtin_bzero((&aa_link), (sizeof(struct ata_atapi_attach ))); |
843 | if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI0x0002) |
844 | aa_link.aa_type = T_ATAPI1; |
845 | else |
846 | aa_link.aa_type = T_ATA0; |
847 | aa_link.aa_channel = chp->channel; |
848 | aa_link.aa_openings = 1; |
849 | aa_link.aa_drv_data = &chp->ch_drive[i]; |
850 | config_found(&chp->wdc->sc_dev, (void *)&aa_link, wdprint)config_found_sm((&chp->wdc->sc_dev), ((void *)& aa_link), (wdprint), ((void *)0)); |
851 | } |
852 | |
853 | /* |
854 | * reset drive_flags for unattached devices, reset state for attached |
855 | * ones |
856 | */ |
857 | for (i = 0; i < 2; i++) { |
858 | if (chp->ch_drive[i].drive_name[0] == 0) |
859 | chp->ch_drive[i].drive_flags = 0; |
860 | } |
861 | |
862 | exit: |
863 | #ifdef WDCDEBUG |
864 | wdcdebug_mask = savedmask; |
865 | #endif |
866 | return; /* for the ``exit'' label above */ |
867 | } |
868 | |
869 | /* |
870 | * Start I/O on a controller, for the given channel. |
871 | * The first xfer may be not for our channel if the channel queues |
872 | * are shared. |
873 | */ |
874 | void |
875 | wdcstart(struct channel_softc *chp) |
876 | { |
877 | struct wdc_xfer *xfer; |
878 | |
879 | splassert(IPL_BIO)do { if (splassert_ctl > 0) { splassert_check(0x6, __func__ ); } } while (0); |
880 | |
881 | /* is there a xfer ? */ |
882 | if ((xfer = TAILQ_FIRST(&chp->ch_queue->sc_xfer)((&chp->ch_queue->sc_xfer)->tqh_first)) == NULL((void *)0)) { |
883 | return; |
884 | } |
885 | |
886 | /* adjust chp, in case we have a shared queue */ |
887 | chp = xfer->chp; |
888 | |
889 | if ((chp->ch_flags & WDCF_ACTIVE0x01) != 0 ) { |
890 | return; /* channel already active */ |
891 | } |
892 | #ifdef DIAGNOSTIC1 |
893 | if ((chp->ch_flags & WDCF_IRQ_WAIT0x10) != 0) |
894 | panic("wdcstart: channel waiting for irq"); |
895 | #endif /* DIAGNOSTIC */ |
896 | |
897 | WDCDEBUG_PRINT(("wdcstart: xfer %p channel %d drive %d\n", xfer, |
898 | chp->channel, xfer->drive), DEBUG_XFERS); |
899 | chp->ch_flags |= WDCF_ACTIVE0x01; |
900 | if (chp->ch_drive[xfer->drive].drive_flags & DRIVE_RESET0x0080) { |
901 | chp->ch_drive[xfer->drive].drive_flags &= ~DRIVE_RESET0x0080; |
902 | chp->ch_drive[xfer->drive].state = 0; |
903 | } |
904 | xfer->c_start(chp, xfer); |
905 | } |
906 | |
907 | int |
908 | wdcdetach(struct channel_softc *chp, int flags) |
909 | { |
910 | int s, rv; |
911 | |
912 | s = splbio()splraise(0x6); |
913 | chp->dying = 1; |
914 | |
915 | wdc_kill_pending(chp); |
916 | timeout_del(&chp->ch_timo); |
917 | |
918 | rv = config_detach_children((struct device *)chp->wdc, flags); |
919 | splx(s)spllower(s); |
920 | |
921 | return (rv); |
922 | } |
923 | |
924 | /* |
925 | * Interrupt routine for the controller. Acknowledge the interrupt, check for |
926 | * errors on the current operation, mark it done if necessary, and start the |
927 | * next request. Also check for a partially done transfer, and continue with |
928 | * the next chunk if so. |
929 | */ |
930 | int |
931 | wdcintr(void *arg) |
932 | { |
933 | struct channel_softc *chp = arg; |
934 | struct wdc_xfer *xfer; |
935 | u_int8_t st = 0; |
936 | int ret = 0; |
937 | |
938 | if ((chp->ch_flags & WDCF_IRQ_WAIT0x10) == 0) { |
939 | /* Acknowledge interrupt by reading status */ |
940 | if (chp->_vtbl == 0) |
941 | st = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,((chp->cmd_iot)->read_1((chp->cmd_ioh), (wdr_status & 7))) |
942 | wdr_status & _WDC_REGMASK)((chp->cmd_iot)->read_1((chp->cmd_ioh), (wdr_status & 7))); |
943 | else |
944 | st = CHP_READ_REG(chp, wdr_status)((chp)->_vtbl->read_reg)(chp, wdr_status); |
945 | if (st == 0xff) |
946 | return (-1); |
947 | |
948 | WDCDEBUG_PRINT(("wdcintr: inactive controller\n"), DEBUG_INTR); |
949 | return ret; |
950 | } |
951 | |
952 | WDCDEBUG_PRINT(("wdcintr\n"), DEBUG_INTR); |
953 | xfer = TAILQ_FIRST(&chp->ch_queue->sc_xfer)((&chp->ch_queue->sc_xfer)->tqh_first); |
954 | if (chp->ch_flags & WDCF_DMA_WAIT0x20) { |
955 | chp->wdc->dma_status = |
956 | (*chp->wdc->dma_finish)(chp->wdc->dma_arg, chp->channel, |
957 | xfer->drive, 0); |
958 | if (chp->wdc->dma_status == 0xff) |
959 | return (-1); |
960 | if (chp->wdc->dma_status & WDC_DMAST_NOIRQ0x01) { |
961 | /* IRQ not for us, not detected by DMA engine */ |
962 | return 0; |
963 | } |
964 | chp->ch_flags &= ~WDCF_DMA_WAIT0x20; |
965 | } |
966 | |
967 | chp->ch_flags &= ~WDCF_IRQ_WAIT0x10; |
968 | ret = xfer->c_intr(chp, xfer, 1); |
969 | if (ret == 0) /* irq was not for us, still waiting for irq */ |
970 | chp->ch_flags |= WDCF_IRQ_WAIT0x10; |
971 | return (ret); |
972 | } |
973 | |
974 | /* Put all disk in RESET state */ |
975 | void |
976 | wdc_reset_channel(struct ata_drive_datas *drvp, int nowait) |
977 | { |
978 | struct channel_softc *chp = drvp->chnl_softc; |
979 | int drive; |
980 | |
981 | WDCDEBUG_PRINT(("ata_reset_channel %s:%d for drive %d\n", |
982 | chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive), |
983 | DEBUG_FUNCS); |
984 | (void) wdcreset(chp, nowait ? NOWAIT0x02 : VERBOSE0x01); |
985 | for (drive = 0; drive < 2; drive++) { |
986 | chp->ch_drive[drive].state = 0; |
987 | } |
988 | } |
989 | |
990 | int |
991 | wdcreset(struct channel_softc *chp, int flags) |
992 | { |
993 | int drv_mask1, drv_mask2; |
994 | |
995 | if (!chp->_vtbl) |
996 | chp->_vtbl = &wdc_default_vtbl; |
997 | |
998 | chp->wdc->reset(chp); |
999 | |
1000 | if (flags & NOWAIT0x02) |
1001 | return 0; |
1002 | |
1003 | drv_mask1 = (chp->ch_drive[0].drive_flags & DRIVE(0x0001|0x0002|0x0004)) ? 0x01:0x00; |
1004 | drv_mask1 |= (chp->ch_drive[1].drive_flags & DRIVE(0x0001|0x0002|0x0004)) ? 0x02:0x00; |
1005 | drv_mask2 = __wdcwait_reset(chp, drv_mask1); |
1006 | |
1007 | if ((flags & VERBOSE0x01) && drv_mask2 != drv_mask1) { |
1008 | printf("%s channel %d: reset failed for", |
1009 | chp->wdc->sc_dev.dv_xname, chp->channel); |
1010 | if ((drv_mask1 & 0x01) != 0 && (drv_mask2 & 0x01) == 0) |
1011 | printf(" drive 0"); |
1012 | if ((drv_mask1 & 0x02) != 0 && (drv_mask2 & 0x02) == 0) |
1013 | printf(" drive 1"); |
1014 | printf("\n"); |
1015 | } |
1016 | |
1017 | return (drv_mask1 != drv_mask2) ? 1 : 0; |
1018 | } |
1019 | |
1020 | void |
1021 | wdc_do_reset(struct channel_softc *chp) |
1022 | { |
1023 | wdc_set_drive(chp, 0); |
1024 | DELAY(10)(*delay_func)(10); |
1025 | CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_4BIT | WDCTL_RST)((chp)->_vtbl->write_reg)(chp, wdr_ctlr, 0x08 | 0x04); |
1026 | delay(10000)(*delay_func)(10000); |
1027 | CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_4BIT)((chp)->_vtbl->write_reg)(chp, wdr_ctlr, 0x08); |
1028 | delay(10000)(*delay_func)(10000); |
1029 | } |
1030 | |
1031 | int |
1032 | __wdcwait_reset(struct channel_softc *chp, int drv_mask) |
1033 | { |
1034 | int timeout; |
1035 | u_int8_t st0, er0, st1, er1; |
1036 | |
1037 | /* wait for BSY to deassert */ |
1038 | for (timeout = 0; timeout < WDCNDELAY_RST(31000 * 1000 / 100); timeout++) { |
1039 | wdc_set_drive(chp, 0); |
1040 | delay(10)(*delay_func)(10); |
1041 | st0 = CHP_READ_REG(chp, wdr_status)((chp)->_vtbl->read_reg)(chp, wdr_status); |
1042 | er0 = CHP_READ_REG(chp, wdr_error)((chp)->_vtbl->read_reg)(chp, wdr_error); |
1043 | wdc_set_drive(chp, 1); |
1044 | delay(10)(*delay_func)(10); |
1045 | st1 = CHP_READ_REG(chp, wdr_status)((chp)->_vtbl->read_reg)(chp, wdr_status); |
1046 | er1 = CHP_READ_REG(chp, wdr_error)((chp)->_vtbl->read_reg)(chp, wdr_error); |
1047 | |
1048 | if ((drv_mask & 0x01) == 0) { |
1049 | /* no master */ |
1050 | if ((drv_mask & 0x02) != 0 && (st1 & WDCS_BSY0x80) == 0) { |
1051 | /* No master, slave is ready, it's done */ |
1052 | goto end; |
1053 | } |
1054 | } else if ((drv_mask & 0x02) == 0) { |
1055 | /* no slave */ |
1056 | if ((drv_mask & 0x01) != 0 && (st0 & WDCS_BSY0x80) == 0) { |
1057 | /* No slave, master is ready, it's done */ |
1058 | goto end; |
1059 | } |
1060 | } else { |
1061 | /* Wait for both master and slave to be ready */ |
1062 | if ((st0 & WDCS_BSY0x80) == 0 && (st1 & WDCS_BSY0x80) == 0) { |
1063 | goto end; |
1064 | } |
1065 | } |
1066 | delay(WDCDELAY)(*delay_func)(100); |
1067 | } |
1068 | /* Reset timed out. Maybe it's because drv_mask was not right */ |
1069 | if (st0 & WDCS_BSY0x80) |
1070 | drv_mask &= ~0x01; |
1071 | if (st1 & WDCS_BSY0x80) |
1072 | drv_mask &= ~0x02; |
1073 | end: |
1074 | WDCDEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%b, er0=0x%x, " |
1075 | "st1=0x%b, er1=0x%x, reset time=%d msec\n", |
1076 | chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", chp->channel, |
1077 | st0, WDCS_BITS, er0, st1, WDCS_BITS, er1, |
1078 | timeout * WDCDELAY / 1000), DEBUG_PROBE); |
1079 | |
1080 | return drv_mask; |
1081 | } |
1082 | |
1083 | /* |
1084 | * Wait for a drive to be !BSY, and have mask in its status register. |
1085 | * return -1 for a timeout after "timeout" ms. |
1086 | */ |
1087 | int |
1088 | wdc_wait_for_status(struct channel_softc *chp, int mask, int bits, int timeout) |
1089 | { |
1090 | u_char status; |
1091 | int time = 0; |
1092 | |
1093 | WDCDEBUG_PRINT(("wdcwait %s:%d\n", chp->wdc ?chp->wdc->sc_dev.dv_xname |
1094 | :"none", chp->channel), DEBUG_STATUS); |
1095 | chp->ch_error = 0; |
1096 | |
1097 | timeout = timeout * 1000 / WDCDELAY100; /* delay uses microseconds */ |
1098 | |
1099 | for (;;) { |
1100 | chp->ch_status = status = CHP_READ_REG(chp, wdr_status)((chp)->_vtbl->read_reg)(chp, wdr_status); |
1101 | WDC_LOG_STATUS(chp, chp->ch_status); |
1102 | |
1103 | if (status == 0xff) { |
1104 | if ((chp->ch_flags & WDCF_ONESLAVE0x02)) { |
1105 | wdc_set_drive(chp, 1); |
1106 | chp->ch_status = status = |
1107 | CHP_READ_REG(chp, wdr_status)((chp)->_vtbl->read_reg)(chp, wdr_status); |
1108 | WDC_LOG_STATUS(chp, chp->ch_status); |
1109 | } |
1110 | } |
1111 | if ((status & WDCS_BSY0x80) == 0 && (status & mask) == bits) |
1112 | break; |
1113 | if (++time > timeout) { |
1114 | WDCDEBUG_PRINT(("wdcwait: timeout, status 0x%b " |
1115 | "error 0x%x\n", status, WDCS_BITS, |
1116 | CHP_READ_REG(chp, wdr_error)), |
1117 | DEBUG_STATUSX | DEBUG_STATUS); |
1118 | return -1; |
1119 | } |
1120 | delay(WDCDELAY)(*delay_func)(100); |
1121 | } |
1122 | if (status & WDCS_ERR0x01) { |
1123 | chp->ch_error = CHP_READ_REG(chp, wdr_error)((chp)->_vtbl->read_reg)(chp, wdr_error); |
1124 | WDC_LOG_ERROR(chp, chp->ch_error); |
1125 | |
1126 | WDCDEBUG_PRINT(("wdcwait: error %x\n", chp->ch_error), |
1127 | DEBUG_STATUSX | DEBUG_STATUS); |
1128 | } |
1129 | |
1130 | #ifdef WDCNDELAY_DEBUG |
1131 | /* After autoconfig, there should be no long delays. */ |
1132 | if (!cold && time > WDCNDELAY_DEBUG) { |
1133 | struct wdc_xfer *xfer = TAILQ_FIRST(&chp->ch_queue->sc_xfer)((&chp->ch_queue->sc_xfer)->tqh_first); |
1134 | if (xfer == NULL((void *)0)) |
1135 | printf("%s channel %d: warning: busy-wait took %dus\n", |
1136 | chp->wdc->sc_dev.dv_xname, chp->channel, |
1137 | WDCDELAY100 * time); |
1138 | else |
1139 | printf("%s:%d:%d: warning: busy-wait took %dus\n", |
1140 | chp->wdc->sc_dev.dv_xname, chp->channel, |
1141 | xfer->drive, |
1142 | WDCDELAY100 * time); |
1143 | } |
1144 | #endif /* WDCNDELAY_DEBUG */ |
1145 | return time; |
1146 | } |
1147 | |
1148 | /* |
1149 | * Busy-wait for DMA to complete |
1150 | */ |
1151 | int |
1152 | wdc_dmawait(struct channel_softc *chp, struct wdc_xfer *xfer, int timeout) |
1153 | { |
1154 | int time; |
1155 | for (time = 0; time < timeout * 1000 / WDCDELAY100; time++) { |
1156 | chp->wdc->dma_status = |
1157 | (*chp->wdc->dma_finish)(chp->wdc->dma_arg, |
1158 | chp->channel, xfer->drive, 0); |
1159 | if ((chp->wdc->dma_status & WDC_DMAST_NOIRQ0x01) == 0) |
1160 | return 0; |
1161 | if (chp->wdc->dma_status == 0xff) { |
1162 | chp->dying = 1; |
1163 | return -1; |
1164 | } |
1165 | delay(WDCDELAY)(*delay_func)(100); |
1166 | } |
1167 | /* timeout, force a DMA halt */ |
1168 | chp->wdc->dma_status = (*chp->wdc->dma_finish)(chp->wdc->dma_arg, |
1169 | chp->channel, xfer->drive, 1); |
1170 | return 1; |
1171 | } |
1172 | |
1173 | void |
1174 | wdctimeout(void *arg) |
1175 | { |
1176 | struct channel_softc *chp = (struct channel_softc *)arg; |
1177 | struct wdc_xfer *xfer; |
1178 | int s; |
1179 | |
1180 | WDCDEBUG_PRINT(("wdctimeout\n"), DEBUG_FUNCS); |
1181 | |
1182 | s = splbio()splraise(0x6); |
1183 | xfer = TAILQ_FIRST(&chp->ch_queue->sc_xfer)((&chp->ch_queue->sc_xfer)->tqh_first); |
1184 | |
1185 | /* Did we lose a race with the interrupt? */ |
1186 | if (xfer == NULL((void *)0) || |
1187 | !timeout_triggered(&chp->ch_timo)((&chp->ch_timo)->to_flags & 0x08)) { |
1188 | splx(s)spllower(s); |
1189 | return; |
1190 | } |
1191 | if ((chp->ch_flags & WDCF_IRQ_WAIT0x10) != 0) { |
1192 | __wdcerror(chp, "timeout"); |
1193 | printf("\ttype: %s\n", (xfer->c_flags & C_ATAPI0x0002) ? |
1194 | "atapi":"ata"); |
1195 | printf("\tc_bcount: %d\n", xfer->c_bcount); |
1196 | printf("\tc_skip: %d\n", xfer->c_skip); |
1197 | if (chp->ch_flags & WDCF_DMA_WAIT0x20) { |
1198 | chp->wdc->dma_status = |
1199 | (*chp->wdc->dma_finish)(chp->wdc->dma_arg, |
1200 | chp->channel, xfer->drive, 1); |
1201 | chp->ch_flags &= ~WDCF_DMA_WAIT0x20; |
1202 | } |
1203 | /* |
1204 | * Call the interrupt routine. If we just missed and interrupt, |
1205 | * it will do what's needed. Else, it will take the needed |
1206 | * action (reset the device). |
1207 | */ |
1208 | xfer->c_flags |= C_TIMEOU0x0004; |
1209 | chp->ch_flags &= ~WDCF_IRQ_WAIT0x10; |
1210 | xfer->c_intr(chp, xfer, 1); |
1211 | } else |
1212 | __wdcerror(chp, "missing untimeout"); |
1213 | splx(s)spllower(s); |
1214 | } |
1215 | |
1216 | /* |
1217 | * Probe drive's capabilities, for use by the controller later. |
1218 | * Assumes drvp points to an existing drive. |
1219 | * XXX this should be a controller-indep function |
1220 | */ |
1221 | void |
1222 | wdc_probe_caps(struct ata_drive_datas *drvp, struct ataparams *params) |
1223 | { |
1224 | struct channel_softc *chp = drvp->chnl_softc; |
1225 | struct wdc_softc *wdc = chp->wdc; |
1226 | int i, valid_mode_found; |
1227 | int cf_flags = drvp->cf_flags; |
1228 | |
1229 | if ((wdc->cap & (WDC_CAPABILITY_DATA160x0001 | WDC_CAPABILITY_DATA320x0002)) == |
1230 | (WDC_CAPABILITY_DATA160x0001 | WDC_CAPABILITY_DATA320x0002)) { |
1231 | struct ataparams params2; |
1232 | |
1233 | /* |
1234 | * Controller claims 16 and 32 bit transfers. |
1235 | * Re-do an IDENTIFY with 32-bit transfers, |
1236 | * and compare results. |
1237 | */ |
1238 | drvp->drive_flags |= DRIVE_CAP320x0008; |
1239 | ata_get_params(drvp, at_poll, ¶ms2); |
1240 | if (bcmp(params, ¶ms2, sizeof(struct ataparams)) != 0) { |
1241 | /* Not good. fall back to 16bits */ |
1242 | drvp->drive_flags &= ~DRIVE_CAP320x0008; |
1243 | } |
1244 | } |
1245 | #if 0 /* Some ultra-DMA drives claims to only support ATA-3. sigh */ |
1246 | if (params->atap_ata_major > 0x01 && |
1247 | params->atap_ata_major != 0xffff) { |
1248 | for (i = 14; i > 0; i--) { |
1249 | if (params->atap_ata_major & (1 << i)) { |
1250 | printf("%sATA version %d\n", sep, i); |
1251 | drvp->ata_vers = i; |
1252 | break; |
1253 | } |
1254 | } |
1255 | } else |
1256 | #endif /* 0 */ |
1257 | /* Use PIO mode 3 as a default value for ATAPI devices */ |
1258 | if (drvp->drive_flags & DRIVE_ATAPI0x0002) |
1259 | drvp->PIO_mode = 3; |
1260 | |
1261 | WDCDEBUG_PRINT(("wdc_probe_caps: wdc_cap 0x%x cf_flags 0x%x\n", |
1262 | wdc->cap, cf_flags), DEBUG_PROBE); |
1263 | |
1264 | valid_mode_found = 0; |
1265 | |
1266 | WDCDEBUG_PRINT(("%s: atap_oldpiotiming=%d\n", __func__, |
1267 | params->atap_oldpiotiming), DEBUG_PROBE); |
1268 | /* |
1269 | * ATA-4 compliant devices contain PIO mode |
1270 | * number in atap_oldpiotiming. |
1271 | */ |
1272 | if (params->atap_oldpiotiming <= 2) { |
1273 | drvp->PIO_cap = params->atap_oldpiotiming; |
1274 | valid_mode_found = 1; |
1275 | drvp->drive_flags |= DRIVE_MODE0x0040; |
1276 | } else if (params->atap_oldpiotiming > 180) { |
1277 | /* |
1278 | * ATA-2 compliant devices contain cycle |
1279 | * time in atap_oldpiotiming. |
1280 | * A device with a cycle time of 180ns |
1281 | * or less is at least PIO mode 3 and |
1282 | * should be reporting that in |
1283 | * atap_piomode_supp, so ignore it here. |
1284 | */ |
1285 | if (params->atap_oldpiotiming <= 240) { |
1286 | drvp->PIO_cap = 2; |
1287 | } else { |
1288 | drvp->PIO_cap = 1; |
1289 | } |
1290 | valid_mode_found = 1; |
1291 | drvp->drive_flags |= DRIVE_MODE0x0040; |
1292 | } |
1293 | if (valid_mode_found) |
1294 | drvp->PIO_mode = drvp->PIO_cap; |
1295 | |
1296 | WDCDEBUG_PRINT(("%s: atap_extensions=0x%x, atap_piomode_supp=0x%x, " |
1297 | "atap_dmamode_supp=0x%x, atap_udmamode_supp=0x%x\n", |
1298 | __func__, params->atap_extensions, params->atap_piomode_supp, |
1299 | params->atap_dmamode_supp, params->atap_udmamode_supp), |
1300 | DEBUG_PROBE); |
1301 | |
1302 | /* |
1303 | * It's not in the specs, but it seems that some drive |
1304 | * returns 0xffff in atap_extensions when this field is invalid |
1305 | */ |
1306 | if (params->atap_extensions != 0xffff && |
1307 | (params->atap_extensions & WDC_EXT_MODES0x0002)) { |
1308 | /* |
1309 | * XXX some drives report something wrong here (they claim to |
1310 | * support PIO mode 8 !). As mode is coded on 3 bits in |
1311 | * SET FEATURE, limit it to 7 (so limit i to 4). |
1312 | * If higher mode than 7 is found, abort. |
1313 | */ |
1314 | for (i = 7; i >= 0; i--) { |
1315 | if ((params->atap_piomode_supp & (1 << i)) == 0) |
1316 | continue; |
1317 | if (i > 4) |
1318 | return; |
1319 | |
1320 | valid_mode_found = 1; |
1321 | |
1322 | if ((wdc->cap & WDC_CAPABILITY_MODE0x0004) == 0) { |
1323 | drvp->PIO_cap = i + 3; |
1324 | continue; |
1325 | } |
1326 | |
1327 | /* |
1328 | * See if mode is accepted. |
1329 | * If the controller can't set its PIO mode, |
1330 | * assume the BIOS set it up correctly |
1331 | */ |
1332 | if (ata_set_mode(drvp, 0x08 | (i + 3), |
1333 | at_poll) != CMD_OK0) |
1334 | continue; |
1335 | |
1336 | /* |
1337 | * If controller's driver can't set its PIO mode, |
1338 | * set the highest one the controller supports |
1339 | */ |
1340 | if (wdc->PIO_cap >= i + 3) { |
1341 | drvp->PIO_mode = i + 3; |
1342 | drvp->PIO_cap = i + 3; |
1343 | break; |
1344 | } |
1345 | } |
1346 | if (!valid_mode_found) { |
1347 | /* |
1348 | * We didn't find a valid PIO mode. |
1349 | * Assume the values returned for DMA are buggy too |
1350 | */ |
1351 | return; |
1352 | } |
1353 | drvp->drive_flags |= DRIVE_MODE0x0040; |
1354 | |
1355 | /* Some controllers don't support ATAPI DMA */ |
1356 | if ((drvp->drive_flags & DRIVE_ATAPI0x0002) && |
1357 | (wdc->cap & WDC_CAPABILITY_NO_ATAPI_DMA0x1000)) |
1358 | return; |
1359 | |
1360 | valid_mode_found = 0; |
Value stored to 'valid_mode_found' is never read | |
1361 | for (i = 7; i >= 0; i--) { |
1362 | if ((params->atap_dmamode_supp & (1 << i)) == 0) |
1363 | continue; |
1364 | if ((wdc->cap & WDC_CAPABILITY_DMA0x0008) && |
1365 | (wdc->cap & WDC_CAPABILITY_MODE0x0004)) |
1366 | if (ata_set_mode(drvp, 0x20 | i, at_poll) |
1367 | != CMD_OK0) |
1368 | continue; |
1369 | |
1370 | valid_mode_found = 1; |
1371 | |
1372 | if (wdc->cap & WDC_CAPABILITY_DMA0x0008) { |
1373 | if ((wdc->cap & WDC_CAPABILITY_MODE0x0004) && |
1374 | wdc->DMA_cap < i) |
1375 | continue; |
1376 | drvp->DMA_mode = i; |
1377 | drvp->DMA_cap = i; |
1378 | drvp->drive_flags |= DRIVE_DMA0x0010; |
1379 | } |
1380 | break; |
1381 | } |
1382 | if (params->atap_extensions & WDC_EXT_UDMA_MODES0x0004) { |
1383 | for (i = 7; i >= 0; i--) { |
1384 | if ((params->atap_udmamode_supp & (1 << i)) |
1385 | == 0) |
1386 | continue; |
1387 | if ((wdc->cap & WDC_CAPABILITY_MODE0x0004) && |
1388 | (wdc->cap & WDC_CAPABILITY_UDMA0x0010)) |
1389 | if (ata_set_mode(drvp, 0x40 | i, |
1390 | at_poll) != CMD_OK0) |
1391 | continue; |
1392 | if (wdc->cap & WDC_CAPABILITY_UDMA0x0010) { |
1393 | if ((wdc->cap & WDC_CAPABILITY_MODE0x0004) && |
1394 | wdc->UDMA_cap < i) |
1395 | continue; |
1396 | drvp->UDMA_mode = i; |
1397 | drvp->UDMA_cap = i; |
1398 | drvp->drive_flags |= DRIVE_UDMA0x0020; |
1399 | } |
1400 | break; |
1401 | } |
1402 | } |
1403 | } |
1404 | |
1405 | /* Try to guess ATA version here, if it didn't get reported */ |
1406 | if (drvp->ata_vers == 0) { |
1407 | if (drvp->drive_flags & DRIVE_UDMA0x0020) |
1408 | drvp->ata_vers = 4; /* should be at last ATA-4 */ |
1409 | else if (drvp->PIO_cap > 2) |
1410 | drvp->ata_vers = 2; /* should be at last ATA-2 */ |
1411 | } |
1412 | if (cf_flags & ATA_CONFIG_PIO_SET0x0008) { |
1413 | drvp->PIO_mode = |
1414 | (cf_flags & ATA_CONFIG_PIO_MODES0x0007) >> ATA_CONFIG_PIO_OFF0; |
1415 | drvp->drive_flags |= DRIVE_MODE0x0040; |
1416 | } |
1417 | if ((wdc->cap & WDC_CAPABILITY_DMA0x0008) == 0) { |
1418 | /* don't care about DMA modes */ |
1419 | return; |
1420 | } |
1421 | if (cf_flags & ATA_CONFIG_DMA_SET0x0080) { |
1422 | if ((cf_flags & ATA_CONFIG_DMA_MODES0x0070) == |
1423 | ATA_CONFIG_DMA_DISABLE0x0070) { |
1424 | drvp->drive_flags &= ~DRIVE_DMA0x0010; |
1425 | } else { |
1426 | drvp->DMA_mode = (cf_flags & ATA_CONFIG_DMA_MODES0x0070) >> |
1427 | ATA_CONFIG_DMA_OFF4; |
1428 | drvp->drive_flags |= DRIVE_DMA0x0010 | DRIVE_MODE0x0040; |
1429 | } |
1430 | } |
1431 | if ((wdc->cap & WDC_CAPABILITY_UDMA0x0010) == 0) { |
1432 | /* don't care about UDMA modes */ |
1433 | return; |
1434 | } |
1435 | if (cf_flags & ATA_CONFIG_UDMA_SET0x0800) { |
1436 | if ((cf_flags & ATA_CONFIG_UDMA_MODES0x0700) == |
1437 | ATA_CONFIG_UDMA_DISABLE0x0700) { |
1438 | drvp->drive_flags &= ~DRIVE_UDMA0x0020; |
1439 | } else { |
1440 | drvp->UDMA_mode = (cf_flags & ATA_CONFIG_UDMA_MODES0x0700) >> |
1441 | ATA_CONFIG_UDMA_OFF8; |
1442 | drvp->drive_flags |= DRIVE_UDMA0x0020 | DRIVE_MODE0x0040; |
1443 | } |
1444 | } |
1445 | } |
1446 | |
1447 | void |
1448 | wdc_output_bytes(struct ata_drive_datas *drvp, void *bytes, unsigned int buflen) |
1449 | { |
1450 | struct channel_softc *chp = drvp->chnl_softc; |
1451 | unsigned int off = 0; |
1452 | unsigned int len = buflen, roundlen; |
1453 | |
1454 | if (drvp->drive_flags & DRIVE_CAP320x0008) { |
1455 | roundlen = len & ~3; |
1456 | |
1457 | CHP_WRITE_RAW_MULTI_4(chp,((chp)->_vtbl->write_raw_multi_4)(chp, (void *)((u_int8_t *)bytes + off), roundlen) |
1458 | (void *)((u_int8_t *)bytes + off), roundlen)((chp)->_vtbl->write_raw_multi_4)(chp, (void *)((u_int8_t *)bytes + off), roundlen); |
1459 | |
1460 | off += roundlen; |
1461 | len -= roundlen; |
1462 | } |
1463 | |
1464 | if (len > 0) { |
1465 | roundlen = (len + 1) & ~0x1; |
1466 | |
1467 | CHP_WRITE_RAW_MULTI_2(chp,((chp)->_vtbl->write_raw_multi_2)(chp, (void *)((u_int8_t *)bytes + off), roundlen) |
1468 | (void *)((u_int8_t *)bytes + off), roundlen)((chp)->_vtbl->write_raw_multi_2)(chp, (void *)((u_int8_t *)bytes + off), roundlen); |
1469 | } |
1470 | } |
1471 | |
1472 | void |
1473 | wdc_input_bytes(struct ata_drive_datas *drvp, void *bytes, unsigned int buflen) |
1474 | { |
1475 | struct channel_softc *chp = drvp->chnl_softc; |
1476 | unsigned int off = 0; |
1477 | unsigned int len = buflen, roundlen; |
1478 | |
1479 | if (drvp->drive_flags & DRIVE_CAP320x0008) { |
1480 | roundlen = len & ~3; |
1481 | |
1482 | CHP_READ_RAW_MULTI_4(chp,((chp)->_vtbl->read_raw_multi_4)(chp, (void *)((u_int8_t *)bytes + off), roundlen) |
1483 | (void *)((u_int8_t *)bytes + off), roundlen)((chp)->_vtbl->read_raw_multi_4)(chp, (void *)((u_int8_t *)bytes + off), roundlen); |
1484 | |
1485 | off += roundlen; |
1486 | len -= roundlen; |
1487 | } |
1488 | |
1489 | if (len > 0) { |
1490 | roundlen = (len + 1) & ~0x1; |
1491 | |
1492 | CHP_READ_RAW_MULTI_2(chp,((chp)->_vtbl->read_raw_multi_2)(chp, (void *)((u_int8_t *)bytes + off), roundlen) |
1493 | (void *)((u_int8_t *)bytes + off), roundlen)((chp)->_vtbl->read_raw_multi_2)(chp, (void *)((u_int8_t *)bytes + off), roundlen); |
1494 | } |
1495 | } |
1496 | |
1497 | void |
1498 | wdc_print_caps(struct ata_drive_datas *drvp) |
1499 | { |
1500 | /* This is actually a lie until we fix the _probe_caps |
1501 | algorithm. Don't print out lies */ |
1502 | #if 0 |
1503 | printf("%s: can use ", drvp->drive_name); |
1504 | |
1505 | if (drvp->drive_flags & DRIVE_CAP320x0008) { |
1506 | printf("32-bit"); |
1507 | } else |
1508 | printf("16-bit"); |
1509 | |
1510 | printf(", PIO mode %d", drvp->PIO_cap); |
1511 | |
1512 | if (drvp->drive_flags & DRIVE_DMA0x0010) { |
1513 | printf(", DMA mode %d", drvp->DMA_cap); |
1514 | } |
1515 | |
1516 | if (drvp->drive_flags & DRIVE_UDMA0x0020) { |
1517 | printf(", Ultra-DMA mode %d", drvp->UDMA_cap); |
1518 | } |
1519 | |
1520 | printf("\n"); |
1521 | #endif /* 0 */ |
1522 | } |
1523 | |
1524 | void |
1525 | wdc_print_current_modes(struct channel_softc *chp) |
1526 | { |
1527 | int drive; |
1528 | struct ata_drive_datas *drvp; |
1529 | |
1530 | for (drive = 0; drive < 2; drive++) { |
1531 | drvp = &chp->ch_drive[drive]; |
1532 | if ((drvp->drive_flags & DRIVE(0x0001|0x0002|0x0004)) == 0) |
1533 | continue; |
1534 | |
1535 | printf("%s(%s:%d:%d):", |
1536 | drvp->drive_name, |
1537 | chp->wdc->sc_dev.dv_xname, chp->channel, drive); |
1538 | |
1539 | if ((chp->wdc->cap & WDC_CAPABILITY_MODE0x0004) == 0 && |
1540 | !(drvp->cf_flags & ATA_CONFIG_PIO_SET0x0008)) |
1541 | printf(" using BIOS timings"); |
1542 | else |
1543 | printf(" using PIO mode %d", drvp->PIO_mode); |
1544 | if (drvp->drive_flags & DRIVE_DMA0x0010) |
1545 | printf(", DMA mode %d", drvp->DMA_mode); |
1546 | if (drvp->drive_flags & DRIVE_UDMA0x0020) |
1547 | printf(", Ultra-DMA mode %d", drvp->UDMA_mode); |
1548 | printf("\n"); |
1549 | } |
1550 | } |
1551 | |
1552 | /* |
1553 | * downgrade the transfer mode of a drive after an error. return 1 if |
1554 | * downgrade was possible, 0 otherwise. |
1555 | */ |
1556 | int |
1557 | wdc_downgrade_mode(struct ata_drive_datas *drvp) |
1558 | { |
1559 | struct channel_softc *chp = drvp->chnl_softc; |
1560 | struct wdc_softc *wdc = chp->wdc; |
1561 | int cf_flags = drvp->cf_flags; |
1562 | |
1563 | /* if drive or controller don't know its mode, we can't do much */ |
1564 | if ((drvp->drive_flags & DRIVE_MODE0x0040) == 0 || |
1565 | (wdc->cap & WDC_CAPABILITY_MODE0x0004) == 0) |
1566 | return 0; |
1567 | /* current drive mode was set by a config flag, let it this way */ |
1568 | if ((cf_flags & ATA_CONFIG_PIO_SET0x0008) || |
1569 | (cf_flags & ATA_CONFIG_DMA_SET0x0080) || |
1570 | (cf_flags & ATA_CONFIG_UDMA_SET0x0800)) |
1571 | return 0; |
1572 | |
1573 | /* |
1574 | * We'd ideally like to use an Ultra DMA mode since they have the |
1575 | * protection of a CRC. So we try each Ultra DMA mode and see if |
1576 | * we can find any working combo |
1577 | */ |
1578 | if ((drvp->drive_flags & DRIVE_UDMA0x0020) && drvp->UDMA_mode > 0) { |
1579 | drvp->UDMA_mode = drvp->UDMA_mode - 1; |
1580 | printf("%s: transfer error, downgrading to Ultra-DMA mode %d\n", |
1581 | drvp->drive_name, drvp->UDMA_mode); |
1582 | } else if ((drvp->drive_flags & DRIVE_UDMA0x0020) && |
1583 | (drvp->drive_flags & DRIVE_DMAERR0x0100) == 0) { |
1584 | /* |
1585 | * If we were using ultra-DMA, don't downgrade to |
1586 | * multiword DMA if we noticed a CRC error. It has |
1587 | * been noticed that CRC errors in ultra-DMA lead to |
1588 | * silent data corruption in multiword DMA. Data |
1589 | * corruption is less likely to occur in PIO mode. |
1590 | */ |
1591 | drvp->drive_flags &= ~DRIVE_UDMA0x0020; |
1592 | drvp->drive_flags |= DRIVE_DMA0x0010; |
1593 | drvp->DMA_mode = drvp->DMA_cap; |
1594 | printf("%s: transfer error, downgrading to DMA mode %d\n", |
1595 | drvp->drive_name, drvp->DMA_mode); |
1596 | } else if (drvp->drive_flags & (DRIVE_DMA0x0010 | DRIVE_UDMA0x0020)) { |
1597 | drvp->drive_flags &= ~(DRIVE_DMA0x0010 | DRIVE_UDMA0x0020); |
1598 | drvp->PIO_mode = drvp->PIO_cap; |
1599 | printf("%s: transfer error, downgrading to PIO mode %d\n", |
1600 | drvp->drive_name, drvp->PIO_mode); |
1601 | } else /* already using PIO, can't downgrade */ |
1602 | return 0; |
1603 | |
1604 | wdc->set_modes(chp); |
1605 | /* reset the channel, which will schedule all drives for setup */ |
1606 | wdc_reset_channel(drvp, 0); |
1607 | return 1; |
1608 | } |
1609 | |
1610 | int |
1611 | wdc_exec_command(struct ata_drive_datas *drvp, struct wdc_command *wdc_c) |
1612 | { |
1613 | struct channel_softc *chp = drvp->chnl_softc; |
1614 | struct wdc_xfer *xfer; |
1615 | int s, ret; |
1616 | |
1617 | WDCDEBUG_PRINT(("wdc_exec_command %s:%d:%d\n", |
1618 | chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive), |
1619 | DEBUG_FUNCS); |
1620 | |
1621 | /* set up an xfer and queue. Wait for completion */ |
1622 | xfer = wdc_get_xfer(wdc_c->flags & AT_WAIT0x0008 ? WDC_CANSLEEP0x00 : |
1623 | WDC_NOSLEEP0x01); |
1624 | if (xfer == NULL((void *)0)) { |
1625 | return WDC_TRY_AGAIN0x03; |
1626 | } |
1627 | |
1628 | if (wdc_c->flags & AT_POLL0x0010) |
1629 | xfer->c_flags |= C_POLL0x0020; |
1630 | xfer->drive = drvp->drive; |
1631 | xfer->databuf = wdc_c->data; |
1632 | xfer->c_bcount = wdc_c->bcount; |
1633 | xfer->cmd = wdc_c; |
1634 | xfer->c_start = __wdccommand_start; |
1635 | xfer->c_intr = __wdccommand_intr; |
1636 | xfer->c_kill_xfer = __wdccommand_done; |
1637 | |
1638 | s = splbio()splraise(0x6); |
1639 | wdc_exec_xfer(chp, xfer); |
1640 | #ifdef DIAGNOSTIC1 |
1641 | if ((wdc_c->flags & AT_POLL0x0010) != 0 && |
1642 | (wdc_c->flags & AT_DONE0x0020) == 0) |
1643 | panic("wdc_exec_command: polled command not done"); |
1644 | #endif /* DIAGNOSTIC */ |
1645 | if (wdc_c->flags & AT_DONE0x0020) { |
1646 | ret = WDC_COMPLETE0x01; |
1647 | } else { |
1648 | if (wdc_c->flags & AT_WAIT0x0008) { |
1649 | WDCDEBUG_PRINT(("wdc_exec_command sleeping\n"), |
1650 | DEBUG_FUNCS); |
1651 | |
1652 | while ((wdc_c->flags & AT_DONE0x0020) == 0) { |
1653 | tsleep_nsec(wdc_c, PRIBIO16, "wdccmd", INFSLP0xffffffffffffffffULL); |
1654 | } |
1655 | ret = WDC_COMPLETE0x01; |
1656 | } else { |
1657 | ret = WDC_QUEUED0x02; |
1658 | } |
1659 | } |
1660 | splx(s)spllower(s); |
1661 | return ret; |
1662 | } |
1663 | |
1664 | void |
1665 | __wdccommand_start(struct channel_softc *chp, struct wdc_xfer *xfer) |
1666 | { |
1667 | int drive = xfer->drive; |
1668 | struct wdc_command *wdc_c = xfer->cmd; |
1669 | |
1670 | WDCDEBUG_PRINT(("__wdccommand_start %s:%d:%d\n", |
1671 | chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive), |
1672 | DEBUG_FUNCS); |
1673 | |
1674 | /* |
1675 | * Disable interrupts if we're polling |
1676 | */ |
1677 | if (xfer->c_flags & C_POLL0x0020) { |
1678 | wdc_disable_intr(chp); |
1679 | } |
1680 | |
1681 | wdc_set_drive(chp, drive); |
1682 | DELAY(1)(*delay_func)(1); |
1683 | |
1684 | /* |
1685 | * For resets, we don't really care to make sure that |
1686 | * the bus is free |
1687 | */ |
1688 | if (wdc_c->r_command != ATAPI_SOFT_RESET0x08) { |
1689 | if (wdcwait(chp, wdc_c->r_st_bmask | WDCS_DRQ,((wdc_wait_for_status((chp), (wdc_c->r_st_bmask | 0x08), ( wdc_c->r_st_bmask), (wdc_c->timeout)) >= 0) ? 0 : -1 ) |
1690 | wdc_c->r_st_bmask, wdc_c->timeout)((wdc_wait_for_status((chp), (wdc_c->r_st_bmask | 0x08), ( wdc_c->r_st_bmask), (wdc_c->timeout)) >= 0) ? 0 : -1 ) != 0) { |
1691 | goto timeout; |
1692 | } |
1693 | } else |
1694 | DELAY(10)(*delay_func)(10); |
1695 | |
1696 | wdccommand(chp, drive, wdc_c->r_command, wdc_c->r_cyl, wdc_c->r_head, |
1697 | wdc_c->r_sector, wdc_c->r_count, wdc_c->r_features); |
1698 | |
1699 | if ((wdc_c->flags & AT_WRITE0x0002) == AT_WRITE0x0002) { |
1700 | /* wait at least 400ns before reading status register */ |
1701 | DELAY(10)(*delay_func)(10); |
1702 | if (wait_for_unbusy(chp, wdc_c->timeout)((wdc_wait_for_status(((chp)), (0), (0), ((wdc_c->timeout) )) >= 0) ? 0 : -1) != 0) |
1703 | goto timeout; |
1704 | |
1705 | if ((chp->ch_status & (WDCS_DRQ0x08 | WDCS_ERR0x01)) == WDCS_ERR0x01) { |
1706 | __wdccommand_done(chp, xfer); |
1707 | return; |
1708 | } |
1709 | |
1710 | if (wait_for_drq(chp, wdc_c->timeout)((wdc_wait_for_status(((chp)), (0x08), (0x08), ((wdc_c->timeout ))) >= 0) ? 0 : -1) != 0) |
1711 | goto timeout; |
1712 | |
1713 | wdc_output_bytes(&chp->ch_drive[drive], |
1714 | wdc_c->data, wdc_c->bcount); |
1715 | } |
1716 | |
1717 | if ((wdc_c->flags & AT_POLL0x0010) == 0) { |
1718 | chp->ch_flags |= WDCF_IRQ_WAIT0x10; /* wait for interrupt */ |
1719 | timeout_add_msec(&chp->ch_timo, wdc_c->timeout); |
1720 | return; |
1721 | } |
1722 | |
1723 | /* |
1724 | * Polled command. Wait for drive ready or drq. Done in intr(). |
1725 | * Wait for at last 400ns for status bit to be valid. |
1726 | */ |
1727 | delay(10)(*delay_func)(10); |
1728 | __wdccommand_intr(chp, xfer, 0); |
1729 | return; |
1730 | |
1731 | timeout: |
1732 | wdc_c->flags |= AT_TIMEOU0x0080; |
1733 | __wdccommand_done(chp, xfer); |
1734 | } |
1735 | |
1736 | int |
1737 | __wdccommand_intr(struct channel_softc *chp, struct wdc_xfer *xfer, int irq) |
1738 | { |
1739 | struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive]; |
1740 | struct wdc_command *wdc_c = xfer->cmd; |
1741 | int bcount = wdc_c->bcount; |
1742 | char *data = wdc_c->data; |
1743 | |
1744 | WDCDEBUG_PRINT(("__wdccommand_intr %s:%d:%d\n", |
1745 | chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive), DEBUG_INTR); |
1746 | if (wdcwait(chp, wdc_c->r_st_pmask, wdc_c->r_st_pmask,((wdc_wait_for_status((chp), (wdc_c->r_st_pmask), (wdc_c-> r_st_pmask), ((irq == 0) ? wdc_c->timeout : 0)) >= 0) ? 0 : -1) |
1747 | (irq == 0) ? wdc_c->timeout : 0)((wdc_wait_for_status((chp), (wdc_c->r_st_pmask), (wdc_c-> r_st_pmask), ((irq == 0) ? wdc_c->timeout : 0)) >= 0) ? 0 : -1)) { |
1748 | if (chp->dying) { |
1749 | __wdccommand_done(chp, xfer); |
1750 | return -1; |
1751 | } |
1752 | if (irq && (xfer->c_flags & C_TIMEOU0x0004) == 0) |
1753 | return 0; /* IRQ was not for us */ |
1754 | wdc_c->flags |= AT_TIMEOU0x0080; |
1755 | goto out; |
1756 | } |
1757 | if (chp->wdc->cap & WDC_CAPABILITY_IRQACK0x0400) |
1758 | chp->wdc->irqack(chp); |
1759 | if (wdc_c->flags & AT_READ0x0001) { |
1760 | if ((chp->ch_status & WDCS_DRQ0x08) == 0) { |
1761 | wdc_c->flags |= AT_TIMEOU0x0080; |
1762 | goto out; |
1763 | } |
1764 | wdc_input_bytes(drvp, data, bcount); |
1765 | /* Should we wait for device to indicate idle? */ |
1766 | } |
1767 | out: |
1768 | __wdccommand_done(chp, xfer); |
1769 | WDCDEBUG_PRINT(("__wdccommand_intr returned\n"), DEBUG_INTR); |
1770 | return 1; |
1771 | } |
1772 | |
1773 | void |
1774 | __wdccommand_done(struct channel_softc *chp, struct wdc_xfer *xfer) |
1775 | { |
1776 | struct wdc_command *wdc_c = xfer->cmd; |
1777 | |
1778 | WDCDEBUG_PRINT(("__wdccommand_done %s:%d:%d %02x\n", |
1779 | chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive, |
1780 | chp->ch_status), DEBUG_FUNCS); |
1781 | if (chp->dying) |
1782 | goto killit; |
1783 | if (chp->ch_status & WDCS_DWF0x20) |
1784 | wdc_c->flags |= AT_DF0x0100; |
1785 | if (chp->ch_status & WDCS_ERR0x01) { |
1786 | wdc_c->flags |= AT_ERROR0x0040; |
1787 | wdc_c->r_error = chp->ch_error; |
1788 | } |
1789 | wdc_c->flags |= AT_DONE0x0020; |
1790 | if ((wdc_c->flags & AT_READREG0x0200) != 0 && |
1791 | (wdc_c->flags & (AT_ERROR0x0040 | AT_DF0x0100)) == 0) { |
1792 | wdc_c->r_head = CHP_READ_REG(chp, wdr_sdh)((chp)->_vtbl->read_reg)(chp, wdr_sdh); |
1793 | wdc_c->r_cyl = CHP_READ_REG(chp, wdr_cyl_hi)((chp)->_vtbl->read_reg)(chp, wdr_cyl_hi) << 8; |
1794 | wdc_c->r_cyl |= CHP_READ_REG(chp, wdr_cyl_lo)((chp)->_vtbl->read_reg)(chp, wdr_cyl_lo); |
1795 | wdc_c->r_sector = CHP_READ_REG(chp, wdr_sector)((chp)->_vtbl->read_reg)(chp, wdr_sector); |
1796 | wdc_c->r_count = CHP_READ_REG(chp, wdr_seccnt)((chp)->_vtbl->read_reg)(chp, wdr_seccnt); |
1797 | wdc_c->r_error = CHP_READ_REG(chp, wdr_error)((chp)->_vtbl->read_reg)(chp, wdr_error); |
1798 | wdc_c->r_features = wdc_c->r_error; |
1799 | } |
1800 | |
1801 | killit: |
1802 | if (xfer->c_flags & C_POLL0x0020) { |
1803 | wdc_enable_intr(chp); |
1804 | } else |
1805 | timeout_del(&chp->ch_timo); |
1806 | |
1807 | wdc_free_xfer(chp, xfer); |
1808 | WDCDEBUG_PRINT(("__wdccommand_done before callback\n"), DEBUG_INTR); |
1809 | |
1810 | if (chp->dying) |
1811 | return; |
1812 | |
1813 | if (wdc_c->flags & AT_WAIT0x0008) |
1814 | wakeup(wdc_c); |
1815 | else |
1816 | if (wdc_c->callback) |
1817 | wdc_c->callback(wdc_c->callback_arg); |
1818 | wdcstart(chp); |
1819 | WDCDEBUG_PRINT(("__wdccommand_done returned\n"), DEBUG_INTR); |
1820 | } |
1821 | |
1822 | /* |
1823 | * Send a command. The drive should be ready. |
1824 | * Assumes interrupts are blocked. |
1825 | */ |
1826 | void |
1827 | wdccommand(struct channel_softc *chp, u_int8_t drive, u_int8_t command, |
1828 | u_int16_t cylin, u_int8_t head, u_int8_t sector, u_int8_t count, |
1829 | u_int8_t features) |
1830 | { |
1831 | WDCDEBUG_PRINT(("wdccommand %s:%d:%d: command=0x%x cylin=%d head=%d " |
1832 | "sector=%d count=%d features=%d\n", chp->wdc->sc_dev.dv_xname, |
1833 | chp->channel, drive, command, cylin, head, sector, count, features), |
1834 | DEBUG_FUNCS); |
1835 | WDC_LOG_ATA_CMDLONG(chp, head, features, cylin, cylin >> 8, sector, |
1836 | count, command); |
1837 | |
1838 | /* Select drive, head, and addressing mode. */ |
1839 | CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (drive << 4) | head)((chp)->_vtbl->write_reg)(chp, wdr_sdh, 0xa0 | (drive << 4) | head); |
1840 | |
1841 | /* Load parameters. */ |
1842 | CHP_WRITE_REG(chp, wdr_features, features)((chp)->_vtbl->write_reg)(chp, wdr_features, features); |
1843 | CHP_WRITE_REG(chp, wdr_cyl_lo, cylin)((chp)->_vtbl->write_reg)(chp, wdr_cyl_lo, cylin); |
1844 | CHP_WRITE_REG(chp, wdr_cyl_hi, cylin >> 8)((chp)->_vtbl->write_reg)(chp, wdr_cyl_hi, cylin >> 8); |
1845 | CHP_WRITE_REG(chp, wdr_sector, sector)((chp)->_vtbl->write_reg)(chp, wdr_sector, sector); |
1846 | CHP_WRITE_REG(chp, wdr_seccnt, count)((chp)->_vtbl->write_reg)(chp, wdr_seccnt, count); |
1847 | |
1848 | /* Send command. */ |
1849 | CHP_WRITE_REG(chp, wdr_command, command)((chp)->_vtbl->write_reg)(chp, wdr_command, command); |
1850 | } |
1851 | |
1852 | /* |
1853 | * Send a 48-bit addressing command. The drive should be ready. |
1854 | * Assumes interrupts are blocked. |
1855 | */ |
1856 | void |
1857 | wdccommandext(struct channel_softc *chp, u_int8_t drive, u_int8_t command, |
1858 | u_int64_t blkno, u_int16_t count) |
1859 | { |
1860 | WDCDEBUG_PRINT(("wdccommandext %s:%d:%d: command=0x%x blkno=%llu " |
1861 | "count=%d\n", chp->wdc->sc_dev.dv_xname, |
1862 | chp->channel, drive, command, blkno, count), |
1863 | DEBUG_FUNCS); |
1864 | WDC_LOG_ATA_CMDEXT(chp, blkno >> 40, blkno >> 16, blkno >> 32, |
1865 | blkno >> 8, blkno >> 24, blkno, count >> 8, count, command); |
1866 | |
1867 | /* Select drive and LBA mode. */ |
1868 | CHP_WRITE_REG(chp, wdr_sdh, (drive << 4) | WDSD_LBA)((chp)->_vtbl->write_reg)(chp, wdr_sdh, (drive << 4) | 0x40); |
1869 | |
1870 | /* Load parameters. */ |
1871 | CHP_LBA48_WRITE_REG(chp, wdr_lba_hi,((chp)->_vtbl->lba48_write_reg)(chp, wdr_lba_hi, ((blkno >> 32) & 0xff00) | ((blkno >> 16) & 0xff )) |
1872 | ((blkno >> 32) & 0xff00) | ((blkno >> 16) & 0xff))((chp)->_vtbl->lba48_write_reg)(chp, wdr_lba_hi, ((blkno >> 32) & 0xff00) | ((blkno >> 16) & 0xff )); |
1873 | CHP_LBA48_WRITE_REG(chp, wdr_lba_mi,((chp)->_vtbl->lba48_write_reg)(chp, wdr_lba_mi, ((blkno >> 24) & 0xff00) | ((blkno >> 8) & 0xff) ) |
1874 | ((blkno >> 24) & 0xff00) | ((blkno >> 8) & 0xff))((chp)->_vtbl->lba48_write_reg)(chp, wdr_lba_mi, ((blkno >> 24) & 0xff00) | ((blkno >> 8) & 0xff) ); |
1875 | CHP_LBA48_WRITE_REG(chp, wdr_lba_lo,((chp)->_vtbl->lba48_write_reg)(chp, wdr_lba_lo, ((blkno >> 16) & 0xff00) | (blkno & 0xff)) |
1876 | ((blkno >> 16) & 0xff00) | (blkno & 0xff))((chp)->_vtbl->lba48_write_reg)(chp, wdr_lba_lo, ((blkno >> 16) & 0xff00) | (blkno & 0xff)); |
1877 | CHP_LBA48_WRITE_REG(chp, wdr_seccnt, count)((chp)->_vtbl->lba48_write_reg)(chp, wdr_seccnt, count); |
1878 | |
1879 | /* Send command. */ |
1880 | CHP_WRITE_REG(chp, wdr_command, command)((chp)->_vtbl->write_reg)(chp, wdr_command, command); |
1881 | } |
1882 | |
1883 | /* |
1884 | * Simplified version of wdccommand(). Unbusy/ready/drq must be |
1885 | * tested by the caller. |
1886 | */ |
1887 | void |
1888 | wdccommandshort(struct channel_softc *chp, int drive, int command) |
1889 | { |
1890 | |
1891 | WDCDEBUG_PRINT(("wdccommandshort %s:%d:%d command 0x%x\n", |
1892 | chp->wdc->sc_dev.dv_xname, chp->channel, drive, command), |
1893 | DEBUG_FUNCS); |
1894 | WDC_LOG_ATA_CMDSHORT(chp, command); |
1895 | |
1896 | /* Select drive. */ |
1897 | CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (drive << 4))((chp)->_vtbl->write_reg)(chp, wdr_sdh, 0xa0 | (drive << 4)); |
1898 | CHP_WRITE_REG(chp, wdr_command, command)((chp)->_vtbl->write_reg)(chp, wdr_command, command); |
1899 | } |
1900 | |
1901 | /* Add a command to the queue and start controller. Must be called at splbio */ |
1902 | |
1903 | void |
1904 | wdc_exec_xfer(struct channel_softc *chp, struct wdc_xfer *xfer) |
1905 | { |
1906 | WDCDEBUG_PRINT(("wdc_exec_xfer %p flags 0x%x channel %d drive %d\n", |
1907 | xfer, xfer->c_flags, chp->channel, xfer->drive), DEBUG_XFERS); |
1908 | |
1909 | /* complete xfer setup */ |
1910 | xfer->chp = chp; |
1911 | |
1912 | /* |
1913 | * If we are a polled command, and the list is not empty, |
1914 | * we are doing a dump. Drop the list to allow the polled command |
1915 | * to complete, we're going to reboot soon anyway. |
1916 | */ |
1917 | if ((xfer->c_flags & C_POLL0x0020) != 0 && |
1918 | !TAILQ_EMPTY(&chp->ch_queue->sc_xfer)(((&chp->ch_queue->sc_xfer)->tqh_first) == ((void *)0))) { |
1919 | TAILQ_INIT(&chp->ch_queue->sc_xfer)do { (&chp->ch_queue->sc_xfer)->tqh_first = ((void *)0); (&chp->ch_queue->sc_xfer)->tqh_last = & (&chp->ch_queue->sc_xfer)->tqh_first; } while (0 ); |
1920 | } |
1921 | /* insert at the end of command list */ |
1922 | TAILQ_INSERT_TAIL(&chp->ch_queue->sc_xfer,xfer , c_xferchain)do { (xfer)->c_xferchain.tqe_next = ((void *)0); (xfer)-> c_xferchain.tqe_prev = (&chp->ch_queue->sc_xfer)-> tqh_last; *(&chp->ch_queue->sc_xfer)->tqh_last = (xfer); (&chp->ch_queue->sc_xfer)->tqh_last = & (xfer)->c_xferchain.tqe_next; } while (0); |
1923 | WDCDEBUG_PRINT(("wdcstart from wdc_exec_xfer, flags 0x%x\n", |
1924 | chp->ch_flags), DEBUG_XFERS); |
1925 | wdcstart(chp); |
1926 | } |
1927 | |
1928 | void * |
1929 | wdc_xfer_get(void *null) |
1930 | { |
1931 | return (pool_get(&wdc_xfer_pool, PR_NOWAIT0x0002 | PR_ZERO0x0008)); |
1932 | } |
1933 | |
1934 | void |
1935 | wdc_scrub_xfer(struct wdc_xfer *xfer) |
1936 | { |
1937 | memset(xfer, 0, sizeof(*xfer))__builtin_memset((xfer), (0), (sizeof(*xfer))); |
1938 | xfer->c_flags = C_SCSIXFER0x0800; |
1939 | } |
1940 | |
1941 | void |
1942 | wdc_xfer_put(void *null, void *xxfer) |
1943 | { |
1944 | struct wdc_xfer *xfer = xxfer; |
1945 | int put = 0; |
1946 | int s; |
1947 | |
1948 | s = splbio()splraise(0x6); |
1949 | if (ISSET(xfer->c_flags, C_SCSIXFER)((xfer->c_flags) & (0x0800))) |
1950 | CLR(xfer->c_flags, C_SCSIXFER)((xfer->c_flags) &= ~(0x0800)); |
1951 | else |
1952 | put = 1; |
1953 | splx(s)spllower(s); |
1954 | |
1955 | if (put) |
1956 | pool_put(&wdc_xfer_pool, xfer); |
1957 | } |
1958 | |
1959 | struct wdc_xfer * |
1960 | wdc_get_xfer(int flags) |
1961 | { |
1962 | return (scsi_io_get(&wdc_xfer_iopool, |
1963 | ISSET(flags, WDC_NOSLEEP)((flags) & (0x01)) ? SCSI_NOSLEEP0x00001 : 0)); |
1964 | } |
1965 | |
1966 | void |
1967 | wdc_free_xfer(struct channel_softc *chp, struct wdc_xfer *xfer) |
1968 | { |
1969 | int put = 0; |
1970 | int s; |
1971 | |
1972 | if (xfer->c_flags & C_PRIVATEXFER0x0400) { |
1973 | chp->ch_flags &= ~WDCF_ACTIVE0x01; |
1974 | TAILQ_REMOVE(&chp->ch_queue->sc_xfer, xfer, c_xferchain)do { if (((xfer)->c_xferchain.tqe_next) != ((void *)0)) (xfer )->c_xferchain.tqe_next->c_xferchain.tqe_prev = (xfer)-> c_xferchain.tqe_prev; else (&chp->ch_queue->sc_xfer )->tqh_last = (xfer)->c_xferchain.tqe_prev; *(xfer)-> c_xferchain.tqe_prev = (xfer)->c_xferchain.tqe_next; ((xfer )->c_xferchain.tqe_prev) = ((void *)-1); ((xfer)->c_xferchain .tqe_next) = ((void *)-1); } while (0); |
1975 | return; |
1976 | } |
1977 | |
1978 | s = splbio()splraise(0x6); |
1979 | chp->ch_flags &= ~WDCF_ACTIVE0x01; |
1980 | TAILQ_REMOVE(&chp->ch_queue->sc_xfer, xfer, c_xferchain)do { if (((xfer)->c_xferchain.tqe_next) != ((void *)0)) (xfer )->c_xferchain.tqe_next->c_xferchain.tqe_prev = (xfer)-> c_xferchain.tqe_prev; else (&chp->ch_queue->sc_xfer )->tqh_last = (xfer)->c_xferchain.tqe_prev; *(xfer)-> c_xferchain.tqe_prev = (xfer)->c_xferchain.tqe_next; ((xfer )->c_xferchain.tqe_prev) = ((void *)-1); ((xfer)->c_xferchain .tqe_next) = ((void *)-1); } while (0); |
1981 | if (ISSET(xfer->c_flags, C_SCSIXFER)((xfer->c_flags) & (0x0800))) |
1982 | CLR(xfer->c_flags, C_SCSIXFER)((xfer->c_flags) &= ~(0x0800)); |
1983 | else |
1984 | put = 1; |
1985 | splx(s)spllower(s); |
1986 | |
1987 | if (put) |
1988 | scsi_io_put(&wdc_xfer_iopool, xfer); |
1989 | } |
1990 | |
1991 | |
1992 | /* |
1993 | * Kill off all pending xfers for a channel_softc. |
1994 | * |
1995 | * Must be called at splbio(). |
1996 | */ |
1997 | void |
1998 | wdc_kill_pending(struct channel_softc *chp) |
1999 | { |
2000 | struct wdc_xfer *xfer; |
2001 | |
2002 | while ((xfer = TAILQ_FIRST(&chp->ch_queue->sc_xfer)((&chp->ch_queue->sc_xfer)->tqh_first)) != NULL((void *)0)) { |
2003 | chp = xfer->chp; |
2004 | (*xfer->c_kill_xfer)(chp, xfer); |
2005 | } |
2006 | } |
2007 | |
2008 | void |
2009 | __wdcerror(struct channel_softc *chp, char *msg) |
2010 | { |
2011 | struct wdc_xfer *xfer = TAILQ_FIRST(&chp->ch_queue->sc_xfer)((&chp->ch_queue->sc_xfer)->tqh_first); |
2012 | if (xfer == NULL((void *)0)) |
2013 | printf("%s:%d: %s\n", chp->wdc->sc_dev.dv_xname, chp->channel, |
2014 | msg); |
2015 | else |
2016 | printf("%s(%s:%d:%d): %s\n", |
2017 | chp->ch_drive[xfer->drive].drive_name, |
2018 | chp->wdc->sc_dev.dv_xname, |
2019 | chp->channel, xfer->drive, msg); |
2020 | } |
2021 | |
2022 | /* |
2023 | * the bit bucket |
2024 | */ |
2025 | void |
2026 | wdcbit_bucket(struct channel_softc *chp, int size) |
2027 | { |
2028 | CHP_READ_RAW_MULTI_2(chp, NULL, size)((chp)->_vtbl->read_raw_multi_2)(chp, ((void *)0), size ); |
2029 | } |
2030 | |
2031 | |
2032 | #include <sys/ataio.h> |
2033 | #include <sys/fcntl.h> |
2034 | |
2035 | int wdc_ioc_ata_cmd(struct ata_drive_datas *, atareq_t *); |
2036 | |
2037 | int |
2038 | wdc_ioc_ata_cmd(struct ata_drive_datas *drvp, atareq_t *atareq) |
2039 | { |
2040 | struct wdc_command wdc_c; |
2041 | int err = 0; |
2042 | |
2043 | /* |
2044 | * Make sure a timeout was supplied in the ioctl request |
2045 | */ |
2046 | if (atareq->timeout == 0) |
2047 | return (EINVAL22); |
2048 | |
2049 | if (atareq->datalen > MAXPHYS(64 * 1024)) |
2050 | return (EINVAL22); |
2051 | |
2052 | bzero(&wdc_c, sizeof(wdc_c))__builtin_bzero((&wdc_c), (sizeof(wdc_c))); |
2053 | |
2054 | if (atareq->datalen > 0) { |
2055 | wdc_c.data = dma_alloc(atareq->datalen, PR_NOWAIT0x0002 | PR_ZERO0x0008); |
2056 | if (wdc_c.data == NULL((void *)0)) { |
2057 | err = ENOMEM12; |
2058 | goto err; |
2059 | } |
2060 | wdc_c.bcount = atareq->datalen; |
2061 | } |
2062 | |
2063 | wdc_c.flags = AT_WAIT0x0008; |
2064 | if (atareq->flags & ATACMD_READ0x00000001) |
2065 | wdc_c.flags |= AT_READ0x0001; |
2066 | if (atareq->flags & ATACMD_WRITE0x00000002) { |
2067 | if (atareq->datalen > 0) { |
2068 | err = copyin(atareq->databuf, wdc_c.data, |
2069 | atareq->datalen); |
2070 | if (err != 0) |
2071 | goto err; |
2072 | } |
2073 | wdc_c.flags |= AT_WRITE0x0002; |
2074 | } |
2075 | if (atareq->flags & ATACMD_READREG0x00000004) |
2076 | wdc_c.flags |= AT_READREG0x0200; |
2077 | |
2078 | wdc_c.timeout = atareq->timeout; |
2079 | wdc_c.r_command = atareq->command; |
2080 | wdc_c.r_head = atareq->head & 0x0f; |
2081 | wdc_c.r_cyl = atareq->cylinder; |
2082 | wdc_c.r_sector = atareq->sec_num; |
2083 | wdc_c.r_count = atareq->sec_count; |
2084 | wdc_c.r_features = atareq->features; |
2085 | if (drvp->drive_flags & DRIVE_ATAPI0x0002) { |
2086 | if (wdc_c.r_command == WDCC_IDENTIFY0xec) |
2087 | wdc_c.r_command = ATAPI_IDENTIFY_DEVICE0xa1; |
2088 | } else { |
2089 | wdc_c.r_st_bmask = WDCS_DRDY0x40; |
2090 | wdc_c.r_st_pmask = WDCS_DRDY0x40; |
2091 | } |
2092 | |
2093 | if (wdc_exec_command(drvp, &wdc_c) != WDC_COMPLETE0x01) { |
2094 | atareq->retsts = ATACMD_ERROR0x02; |
2095 | goto copyout; |
2096 | } |
2097 | |
2098 | if (wdc_c.flags & (AT_ERROR0x0040 | AT_TIMEOU0x0080 | AT_DF0x0100)) { |
2099 | if (wdc_c.flags & AT_ERROR0x0040) { |
2100 | atareq->retsts = ATACMD_ERROR0x02; |
2101 | atareq->error = wdc_c.r_error; |
2102 | } else if (wdc_c.flags & AT_DF0x0100) |
2103 | atareq->retsts = ATACMD_DF0x03; |
2104 | else |
2105 | atareq->retsts = ATACMD_TIMEOUT0x01; |
2106 | } else { |
2107 | atareq->retsts = ATACMD_OK0x00; |
2108 | if (atareq->flags & ATACMD_READREG0x00000004) { |
2109 | atareq->head = wdc_c.r_head; |
2110 | atareq->cylinder = wdc_c.r_cyl; |
2111 | atareq->sec_num = wdc_c.r_sector; |
2112 | atareq->sec_count = wdc_c.r_count; |
2113 | atareq->features = wdc_c.r_features; |
2114 | atareq->error = wdc_c.r_error; |
2115 | } |
2116 | } |
2117 | |
2118 | copyout: |
2119 | if (atareq->datalen > 0 && atareq->flags & ATACMD_READ0x00000001) { |
2120 | err = copyout(wdc_c.data, atareq->databuf, atareq->datalen); |
2121 | if (err != 0) |
2122 | goto err; |
2123 | } |
2124 | |
2125 | err: |
2126 | if (wdc_c.data) |
2127 | dma_free(wdc_c.data, atareq->datalen); |
2128 | return (err); |
2129 | } |
2130 | |
2131 | int |
2132 | wdc_ioctl(struct ata_drive_datas *drvp, u_long xfer, caddr_t addr, int flag, |
2133 | struct proc *p) |
2134 | { |
2135 | int error = 0; |
2136 | |
2137 | switch (xfer) { |
2138 | #ifdef WDCDEBUG |
2139 | case ATAIOGETTRACE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct atagettrace) & 0x1fff) << 16) | ((('Q')) << 8) | ((27))): { |
2140 | atagettrace_t *agt = (atagettrace_t *)addr; |
2141 | unsigned int size = 0; |
2142 | char *log_to_copy; |
2143 | |
2144 | size = agt->buf_size; |
2145 | if (size > 65536) { |
2146 | size = 65536; |
2147 | } |
2148 | |
2149 | log_to_copy = wdc_get_log(&size, &agt->bytes_left); |
2150 | |
2151 | if (log_to_copy != NULL((void *)0)) { |
2152 | error = copyout(log_to_copy, agt->buf, size); |
2153 | free(log_to_copy, M_TEMP127, 0); |
2154 | } |
2155 | |
2156 | agt->bytes_copied = size; |
2157 | break; |
2158 | } |
2159 | #endif /* WDCDEBUG */ |
2160 | |
2161 | case ATAIOCCOMMAND(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (atareq_t) & 0x1fff) << 16) | ((('Q')) << 8) | ((8))): { |
2162 | atareq_t *atareq = (atareq_t *)addr; |
2163 | |
2164 | /* |
2165 | * Make sure this command is (relatively) safe first |
2166 | */ |
2167 | if ((flag & FWRITE0x0002) == 0 && atareq->flags & ATACMD_WRITE0x00000002) |
2168 | error = EPERM1; |
2169 | else |
2170 | error = wdc_ioc_ata_cmd(drvp, atareq); |
2171 | break; |
2172 | } |
2173 | |
2174 | default: |
2175 | error = ENOTTY25; |
2176 | goto exit; |
2177 | } |
2178 | |
2179 | exit: |
2180 | return (error); |
2181 | } |