| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: wdc.c,v 1.264 2011/08/28 09:32:21 christos Exp $ */ | | 1 | /* $NetBSD: wdc.c,v 1.265 2011/08/28 10:21:41 bouyer Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved. | | 4 | * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved. |
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 | * |
| @@ -48,27 +48,27 @@ | | | @@ -48,27 +48,27 @@ |
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 | /* | | 56 | /* |
57 | * CODE UNTESTED IN THE CURRENT REVISION: | | 57 | * CODE UNTESTED IN THE CURRENT REVISION: |
58 | */ | | 58 | */ |
59 | | | 59 | |
60 | #include <sys/cdefs.h> | | 60 | #include <sys/cdefs.h> |
61 | __KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.264 2011/08/28 09:32:21 christos Exp $"); | | 61 | __KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.265 2011/08/28 10:21:41 bouyer Exp $"); |
62 | | | 62 | |
63 | #include "opt_ata.h" | | 63 | #include "opt_ata.h" |
64 | #include "opt_wdc.h" | | 64 | #include "opt_wdc.h" |
65 | | | 65 | |
66 | #include <sys/param.h> | | 66 | #include <sys/param.h> |
67 | #include <sys/systm.h> | | 67 | #include <sys/systm.h> |
68 | #include <sys/kernel.h> | | 68 | #include <sys/kernel.h> |
69 | #include <sys/conf.h> | | 69 | #include <sys/conf.h> |
70 | #include <sys/buf.h> | | 70 | #include <sys/buf.h> |
71 | #include <sys/device.h> | | 71 | #include <sys/device.h> |
72 | #include <sys/malloc.h> | | 72 | #include <sys/malloc.h> |
73 | #include <sys/syslog.h> | | 73 | #include <sys/syslog.h> |
74 | #include <sys/proc.h> | | 74 | #include <sys/proc.h> |
| @@ -289,29 +289,27 @@ wdc_drvprobe(struct ata_channel *chp) | | | @@ -289,29 +289,27 @@ wdc_drvprobe(struct ata_channel *chp) |
289 | { | | 289 | { |
290 | struct ataparams params; /* XXX: large struct */ | | 290 | struct ataparams params; /* XXX: large struct */ |
291 | struct atac_softc *atac = chp->ch_atac; | | 291 | struct atac_softc *atac = chp->ch_atac; |
292 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | | 292 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); |
293 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | | 293 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; |
294 | u_int8_t st0 = 0, st1 = 0; | | 294 | u_int8_t st0 = 0, st1 = 0; |
295 | int i, j, error, s; | | 295 | int i, j, error, s; |
296 | | | 296 | |
297 | if (wdcprobe1(chp, 0) == 0) { | | 297 | if (wdcprobe1(chp, 0) == 0) { |
298 | /* No drives, abort the attach here. */ | | 298 | /* No drives, abort the attach here. */ |
299 | return; | | 299 | return; |
300 | } | | 300 | } |
301 | | | 301 | |
302 | #ifndef WDC_NO_IDS | | | |
303 | s = splbio(); | | 302 | s = splbio(); |
304 | #endif | | | |
305 | /* for ATA/OLD drives, wait for DRDY, 3s timeout */ | | 303 | /* for ATA/OLD drives, wait for DRDY, 3s timeout */ |
306 | for (i = 0; i < mstohz(3000); i++) { | | 304 | for (i = 0; i < mstohz(3000); i++) { |
307 | /* | | 305 | /* |
308 | * select drive 1 first, so that master is selected on | | 306 | * select drive 1 first, so that master is selected on |
309 | * exit from the loop | | 307 | * exit from the loop |
310 | */ | | 308 | */ |
311 | if (chp->ch_drive[1].drive_flags & (DRIVE_ATA|DRIVE_OLD)) { | | 309 | if (chp->ch_drive[1].drive_flags & (DRIVE_ATA|DRIVE_OLD)) { |
312 | if (wdc->select) | | 310 | if (wdc->select) |
313 | wdc->select(chp,1); | | 311 | wdc->select(chp,1); |
314 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], | | 312 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], |
315 | 0, WDSD_IBM | 0x10); | | 313 | 0, WDSD_IBM | 0x10); |
316 | delay(10); /* 400ns delay */ | | 314 | delay(10); /* 400ns delay */ |
317 | st1 = bus_space_read_1(wdr->cmd_iot, | | 315 | st1 = bus_space_read_1(wdr->cmd_iot, |
| @@ -330,32 +328,30 @@ wdc_drvprobe(struct ata_channel *chp) | | | @@ -330,32 +328,30 @@ wdc_drvprobe(struct ata_channel *chp) |
330 | | | 328 | |
331 | if (((chp->ch_drive[0].drive_flags & (DRIVE_ATA|DRIVE_OLD)) | | 329 | if (((chp->ch_drive[0].drive_flags & (DRIVE_ATA|DRIVE_OLD)) |
332 | == 0 || | | 330 | == 0 || |
333 | (st0 & WDCS_DRDY)) && | | 331 | (st0 & WDCS_DRDY)) && |
334 | ((chp->ch_drive[1].drive_flags & (DRIVE_ATA|DRIVE_OLD)) | | 332 | ((chp->ch_drive[1].drive_flags & (DRIVE_ATA|DRIVE_OLD)) |
335 | == 0 || | | 333 | == 0 || |
336 | (st1 & WDCS_DRDY))) | | 334 | (st1 & WDCS_DRDY))) |
337 | break; | | 335 | break; |
338 | #ifdef WDC_NO_IDS | | 336 | #ifdef WDC_NO_IDS |
339 | /* cannot tsleep here (can't enable IPL_BIO interrups), | | 337 | /* cannot tsleep here (can't enable IPL_BIO interrups), |
340 | * delay instead | | 338 | * delay instead |
341 | */ | | 339 | */ |
342 | delay(1000000 / hz); | | 340 | delay(1000000 / hz); |
343 | } | | | |
344 | #else | | 341 | #else |
345 | tsleep(¶ms, PRIBIO, "atadrdy", 1); | | 342 | tsleep(¶ms, PRIBIO, "atadrdy", 1); |
346 | } | | | |
347 | s = splbio(); | | | |
348 | #endif | | 343 | #endif |
| | | 344 | } |
349 | if ((st0 & WDCS_DRDY) == 0) | | 345 | if ((st0 & WDCS_DRDY) == 0) |
350 | chp->ch_drive[0].drive_flags &= ~(DRIVE_ATA|DRIVE_OLD); | | 346 | chp->ch_drive[0].drive_flags &= ~(DRIVE_ATA|DRIVE_OLD); |
351 | if ((st1 & WDCS_DRDY) == 0) | | 347 | if ((st1 & WDCS_DRDY) == 0) |
352 | chp->ch_drive[1].drive_flags &= ~(DRIVE_ATA|DRIVE_OLD); | | 348 | chp->ch_drive[1].drive_flags &= ~(DRIVE_ATA|DRIVE_OLD); |
353 | splx(s); | | 349 | splx(s); |
354 | | | 350 | |
355 | ATADEBUG_PRINT(("%s:%d: wait DRDY st0 0x%x st1 0x%x\n", | | 351 | ATADEBUG_PRINT(("%s:%d: wait DRDY st0 0x%x st1 0x%x\n", |
356 | device_xname(atac->atac_dev), | | 352 | device_xname(atac->atac_dev), |
357 | chp->ch_channel, st0, st1), DEBUG_PROBE); | | 353 | chp->ch_channel, st0, st1), DEBUG_PROBE); |
358 | | | 354 | |
359 | /* Wait a bit, some devices are weird just after a reset. */ | | 355 | /* Wait a bit, some devices are weird just after a reset. */ |
360 | delay(5000); | | 356 | delay(5000); |
361 | | | 357 | |
| @@ -1089,27 +1085,26 @@ wdc_do_reset(struct ata_channel *chp, in | | | @@ -1089,27 +1085,26 @@ wdc_do_reset(struct ata_channel *chp, in |
1089 | } | | 1085 | } |
1090 | | | 1086 | |
1091 | static int | | 1087 | static int |
1092 | __wdcwait_reset(struct ata_channel *chp, int drv_mask, int poll) | | 1088 | __wdcwait_reset(struct ata_channel *chp, int drv_mask, int poll) |
1093 | { | | 1089 | { |
1094 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); | | 1090 | struct wdc_softc *wdc = CHAN_TO_WDC(chp); |
1095 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; | | 1091 | struct wdc_regs *wdr = &wdc->regs[chp->ch_channel]; |
1096 | int timeout, nloop; | | 1092 | int timeout, nloop; |
1097 | u_int8_t st0 = 0, st1 = 0; | | 1093 | u_int8_t st0 = 0, st1 = 0; |
1098 | #ifdef ATADEBUG | | 1094 | #ifdef ATADEBUG |
1099 | u_int8_t sc0 = 0, sn0 = 0, cl0 = 0, ch0 = 0; | | 1095 | u_int8_t sc0 = 0, sn0 = 0, cl0 = 0, ch0 = 0; |
1100 | u_int8_t sc1 = 0, sn1 = 0, cl1 = 0, ch1 = 0; | | 1096 | u_int8_t sc1 = 0, sn1 = 0, cl1 = 0, ch1 = 0; |
1101 | #endif | | 1097 | #endif |
1102 | KASSERT(poll == RESET_POLL); | | | |
1103 | if (poll) | | 1098 | if (poll) |
1104 | nloop = WDCNDELAY_RST; | | 1099 | nloop = WDCNDELAY_RST; |
1105 | else | | 1100 | else |
1106 | nloop = WDC_RESET_WAIT * hz / 1000; | | 1101 | nloop = WDC_RESET_WAIT * hz / 1000; |
1107 | /* wait for BSY to deassert */ | | 1102 | /* wait for BSY to deassert */ |
1108 | for (timeout = 0; timeout < nloop; timeout++) { | | 1103 | for (timeout = 0; timeout < nloop; timeout++) { |
1109 | if ((drv_mask & 0x01) != 0) { | | 1104 | if ((drv_mask & 0x01) != 0) { |
1110 | if (wdc->select) | | 1105 | if (wdc->select) |
1111 | wdc->select(chp,0); | | 1106 | wdc->select(chp,0); |
1112 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], | | 1107 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], |
1113 | 0, WDSD_IBM); /* master */ | | 1108 | 0, WDSD_IBM); /* master */ |
1114 | delay(10); | | 1109 | delay(10); |
1115 | st0 = bus_space_read_1(wdr->cmd_iot, | | 1110 | st0 = bus_space_read_1(wdr->cmd_iot, |
| @@ -1498,33 +1493,36 @@ __wdccommand_intr(struct ata_channel *ch | | | @@ -1498,33 +1493,36 @@ __wdccommand_intr(struct ata_channel *ch |
1498 | * Historically it's what we have always done so keeping it | | 1493 | * Historically it's what we have always done so keeping it |
1499 | * here ensure binary backward compatibility. | | 1494 | * here ensure binary backward compatibility. |
1500 | */ | | 1495 | */ |
1501 | drive_flags = DRIVE_NOSTREAM | | | 1496 | drive_flags = DRIVE_NOSTREAM | |
1502 | chp->ch_drive[xfer->c_drive].drive_flags; | | 1497 | chp->ch_drive[xfer->c_drive].drive_flags; |
1503 | } else { | | 1498 | } else { |
1504 | /* | | 1499 | /* |
1505 | * Other data structure are opaque and should be transfered | | 1500 | * Other data structure are opaque and should be transfered |
1506 | * as is. | | 1501 | * as is. |
1507 | */ | | 1502 | */ |
1508 | drive_flags = chp->ch_drive[xfer->c_drive].drive_flags; | | 1503 | drive_flags = chp->ch_drive[xfer->c_drive].drive_flags; |
1509 | } | | 1504 | } |
1510 | | | 1505 | |
1511 | #ifndef WDC_NO_IDS | | 1506 | #ifdef WDC_NO_IDS |
| | | 1507 | wflags = AT_POLL; |
| | | 1508 | #else |
1512 | if ((ata_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL)) { | | 1509 | if ((ata_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL)) { |
1513 | /* both wait and poll, we can tsleep here */ | | 1510 | /* both wait and poll, we can tsleep here */ |
1514 | wflags = AT_WAIT | AT_POLL; | | 1511 | wflags = AT_WAIT | AT_POLL; |
1515 | } else | | 1512 | } else { |
1516 | #endif | | | |
1517 | wflags = AT_POLL; | | 1513 | wflags = AT_POLL; |
| | | 1514 | } |
| | | 1515 | #endif |
1518 | | | 1516 | |
1519 | again: | | 1517 | again: |
1520 | ATADEBUG_PRINT(("__wdccommand_intr %s:%d:%d\n", | | 1518 | ATADEBUG_PRINT(("__wdccommand_intr %s:%d:%d\n", |
1521 | device_xname(chp->ch_atac->atac_dev), chp->ch_channel, | | 1519 | device_xname(chp->ch_atac->atac_dev), chp->ch_channel, |
1522 | xfer->c_drive), DEBUG_INTR); | | 1520 | xfer->c_drive), DEBUG_INTR); |
1523 | /* | | 1521 | /* |
1524 | * after a ATAPI_SOFT_RESET, the device will have released the bus. | | 1522 | * after a ATAPI_SOFT_RESET, the device will have released the bus. |
1525 | * Reselect again, it doesn't hurt for others commands, and the time | | 1523 | * Reselect again, it doesn't hurt for others commands, and the time |
1526 | * penalty for the extra regiter write is acceptable, | | 1524 | * penalty for the extra regiter write is acceptable, |
1527 | * wdc_exec_command() isn't called often (mosly for autoconfig) | | 1525 | * wdc_exec_command() isn't called often (mosly for autoconfig) |
1528 | */ | | 1526 | */ |
1529 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0, | | 1527 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0, |
1530 | WDSD_IBM | (xfer->c_drive << 4)); | | 1528 | WDSD_IBM | (xfer->c_drive << 4)); |