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