| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ahcisata_core.c,v 1.90 2020/12/27 15:13:07 jmcneill Exp $ */ | | 1 | /* $NetBSD: ahcisata_core.c,v 1.91 2020/12/28 11:05:54 jmcneill Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2006 Manuel Bouyer. | | 4 | * Copyright (c) 2006 Manuel Bouyer. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
| @@ -16,27 +16,27 @@ | | | @@ -16,27 +16,27 @@ |
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | * | | 25 | * |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | #include <sys/cdefs.h> | | 28 | #include <sys/cdefs.h> |
29 | __KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.90 2020/12/27 15:13:07 jmcneill Exp $"); | | 29 | __KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.91 2020/12/28 11:05:54 jmcneill Exp $"); |
30 | | | 30 | |
31 | #include <sys/types.h> | | 31 | #include <sys/types.h> |
32 | #include <sys/malloc.h> | | 32 | #include <sys/malloc.h> |
33 | #include <sys/param.h> | | 33 | #include <sys/param.h> |
34 | #include <sys/kernel.h> | | 34 | #include <sys/kernel.h> |
35 | #include <sys/systm.h> | | 35 | #include <sys/systm.h> |
36 | #include <sys/disklabel.h> | | 36 | #include <sys/disklabel.h> |
37 | #include <sys/proc.h> | | 37 | #include <sys/proc.h> |
38 | #include <sys/buf.h> | | 38 | #include <sys/buf.h> |
39 | | | 39 | |
40 | #include <dev/ata/atareg.h> | | 40 | #include <dev/ata/atareg.h> |
41 | #include <dev/ata/satavar.h> | | 41 | #include <dev/ata/satavar.h> |
42 | #include <dev/ata/satareg.h> | | 42 | #include <dev/ata/satareg.h> |
| @@ -74,26 +74,27 @@ static void ahci_cmd_abort(struct ata_ch | | | @@ -74,26 +74,27 @@ static void ahci_cmd_abort(struct ata_ch |
74 | static void ahci_cmd_done(struct ata_channel *, struct ata_xfer *); | | 74 | static void ahci_cmd_done(struct ata_channel *, struct ata_xfer *); |
75 | static void ahci_cmd_done_end(struct ata_channel *, struct ata_xfer *); | | 75 | static void ahci_cmd_done_end(struct ata_channel *, struct ata_xfer *); |
76 | static void ahci_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | | 76 | static void ahci_cmd_kill_xfer(struct ata_channel *, struct ata_xfer *, int); |
77 | static int ahci_bio_start(struct ata_channel *, struct ata_xfer *); | | 77 | static int ahci_bio_start(struct ata_channel *, struct ata_xfer *); |
78 | static void ahci_bio_poll(struct ata_channel *, struct ata_xfer *); | | 78 | static void ahci_bio_poll(struct ata_channel *, struct ata_xfer *); |
79 | static void ahci_bio_abort(struct ata_channel *, struct ata_xfer *); | | 79 | static void ahci_bio_abort(struct ata_channel *, struct ata_xfer *); |
80 | static int ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int); | | 80 | static int ahci_bio_complete(struct ata_channel *, struct ata_xfer *, int); |
81 | static void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ; | | 81 | static void ahci_bio_kill_xfer(struct ata_channel *, struct ata_xfer *, int) ; |
82 | static void ahci_channel_stop(struct ahci_softc *, struct ata_channel *, int); | | 82 | static void ahci_channel_stop(struct ahci_softc *, struct ata_channel *, int); |
83 | static void ahci_channel_start(struct ahci_softc *, struct ata_channel *, | | 83 | static void ahci_channel_start(struct ahci_softc *, struct ata_channel *, |
84 | int, int); | | 84 | int, int); |
85 | static void ahci_channel_recover(struct ata_channel *, int, uint32_t); | | 85 | static void ahci_channel_recover(struct ata_channel *, int, uint32_t); |
86 | static int ahci_dma_setup(struct ata_channel *, int, void *, size_t, int); | | 86 | static int ahci_dma_setup(struct ata_channel *, int, void *, size_t, int); |
| | | 87 | static int ahci_intr_port_common(struct ata_channel *); |
87 | | | 88 | |
88 | #if NATAPIBUS > 0 | | 89 | #if NATAPIBUS > 0 |
89 | static void ahci_atapibus_attach(struct atabus_softc *); | | 90 | static void ahci_atapibus_attach(struct atabus_softc *); |
90 | static void ahci_atapi_kill_pending(struct scsipi_periph *); | | 91 | static void ahci_atapi_kill_pending(struct scsipi_periph *); |
91 | static void ahci_atapi_minphys(struct buf *); | | 92 | static void ahci_atapi_minphys(struct buf *); |
92 | static void ahci_atapi_scsipi_request(struct scsipi_channel *, | | 93 | static void ahci_atapi_scsipi_request(struct scsipi_channel *, |
93 | scsipi_adapter_req_t, void *); | | 94 | scsipi_adapter_req_t, void *); |
94 | static int ahci_atapi_start(struct ata_channel *, struct ata_xfer *); | | 95 | static int ahci_atapi_start(struct ata_channel *, struct ata_xfer *); |
95 | static void ahci_atapi_poll(struct ata_channel *, struct ata_xfer *); | | 96 | static void ahci_atapi_poll(struct ata_channel *, struct ata_xfer *); |
96 | static void ahci_atapi_abort(struct ata_channel *, struct ata_xfer *); | | 97 | static void ahci_atapi_abort(struct ata_channel *, struct ata_xfer *); |
97 | static int ahci_atapi_complete(struct ata_channel *, struct ata_xfer *, int); | | 98 | static int ahci_atapi_complete(struct ata_channel *, struct ata_xfer *, int); |
98 | static void ahci_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int); | | 99 | static void ahci_atapi_kill_xfer(struct ata_channel *, struct ata_xfer *, int); |
99 | static void ahci_atapi_probe_device(struct atapibus_softc *, int); | | 100 | static void ahci_atapi_probe_device(struct atapibus_softc *, int); |
| @@ -592,52 +593,66 @@ int | | | @@ -592,52 +593,66 @@ int |
592 | ahci_intr(void *v) | | 593 | ahci_intr(void *v) |
593 | { | | 594 | { |
594 | struct ahci_softc *sc = v; | | 595 | struct ahci_softc *sc = v; |
595 | uint32_t is, ports; | | 596 | uint32_t is, ports; |
596 | int bit, r = 0; | | 597 | int bit, r = 0; |
597 | | | 598 | |
598 | while ((is = AHCI_READ(sc, AHCI_IS))) { | | 599 | while ((is = AHCI_READ(sc, AHCI_IS))) { |
599 | AHCIDEBUG_PRINT(("%s ahci_intr 0x%x\n", AHCINAME(sc), is), | | 600 | AHCIDEBUG_PRINT(("%s ahci_intr 0x%x\n", AHCINAME(sc), is), |
600 | DEBUG_INTR); | | 601 | DEBUG_INTR); |
601 | r = 1; | | 602 | r = 1; |
602 | ports = is; | | 603 | ports = is; |
603 | while ((bit = ffs(ports)) != 0) { | | 604 | while ((bit = ffs(ports)) != 0) { |
604 | bit--; | | 605 | bit--; |
605 | ahci_intr_port(&sc->sc_channels[bit]); | | 606 | ahci_intr_port_common(&sc->sc_channels[bit].ata_channel); |
606 | ports &= ~(1U << bit); | | 607 | ports &= ~(1U << bit); |
607 | } | | 608 | } |
608 | AHCI_WRITE(sc, AHCI_IS, is); | | 609 | AHCI_WRITE(sc, AHCI_IS, is); |
609 | } | | 610 | } |
610 | | | 611 | |
611 | return r; | | 612 | return r; |
612 | } | | 613 | } |
613 | | | 614 | |
614 | int | | 615 | int |
615 | ahci_intr_port(void *v) | | 616 | ahci_intr_port(void *v) |
616 | { | | 617 | { |
617 | struct ahci_channel *achp = v; | | 618 | struct ahci_channel *achp = v; |
618 | struct ata_channel *chp = &achp->ata_channel; | | 619 | struct ata_channel *chp = &achp->ata_channel; |
619 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; | | 620 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; |
| | | 621 | int ret; |
| | | 622 | |
| | | 623 | ret = ahci_intr_port_common(chp); |
| | | 624 | if (ret) { |
| | | 625 | AHCI_WRITE(sc, AHCI_IS, 1U << chp->ch_channel); |
| | | 626 | } |
| | | 627 | |
| | | 628 | return ret; |
| | | 629 | } |
| | | 630 | |
| | | 631 | static int |
| | | 632 | ahci_intr_port_common(struct ata_channel *chp) |
| | | 633 | { |
| | | 634 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; |
620 | uint32_t is, tfd, sact; | | 635 | uint32_t is, tfd, sact; |
621 | struct ata_xfer *xfer; | | 636 | struct ata_xfer *xfer; |
622 | int slot = -1; | | 637 | int slot = -1; |
623 | bool recover = false; | | 638 | bool recover = false; |
624 | uint32_t aslots; | | 639 | uint32_t aslots; |
625 | | | 640 | |
626 | is = AHCI_READ(sc, AHCI_P_IS(chp->ch_channel)); | | 641 | is = AHCI_READ(sc, AHCI_P_IS(chp->ch_channel)); |
627 | AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), is); | | 642 | AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), is); |
628 | | | 643 | |
629 | AHCIDEBUG_PRINT(( | | 644 | AHCIDEBUG_PRINT(("ahci_intr_port_common %s port %d " |
630 | "ahci_intr_port %s port %d is 0x%x CI 0x%x SACT 0x%x TFD 0x%x\n", | | 645 | "is 0x%x CI 0x%x SACT 0x%x TFD 0x%x\n", |
631 | AHCINAME(sc), | | 646 | AHCINAME(sc), |
632 | chp->ch_channel, is, | | 647 | chp->ch_channel, is, |
633 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel)), | | 648 | AHCI_READ(sc, AHCI_P_CI(chp->ch_channel)), |
634 | AHCI_READ(sc, AHCI_P_SACT(chp->ch_channel)), | | 649 | AHCI_READ(sc, AHCI_P_SACT(chp->ch_channel)), |
635 | AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel))), | | 650 | AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel))), |
636 | DEBUG_INTR); | | 651 | DEBUG_INTR); |
637 | | | 652 | |
638 | if ((chp->ch_flags & ATACH_NCQ) == 0) { | | 653 | if ((chp->ch_flags & ATACH_NCQ) == 0) { |
639 | /* Non-NCQ operation */ | | 654 | /* Non-NCQ operation */ |
640 | sact = AHCI_READ(sc, AHCI_P_CI(chp->ch_channel)); | | 655 | sact = AHCI_READ(sc, AHCI_P_CI(chp->ch_channel)); |
641 | } else { | | 656 | } else { |
642 | /* NCQ operation */ | | 657 | /* NCQ operation */ |
643 | sact = AHCI_READ(sc, AHCI_P_SACT(chp->ch_channel)); | | 658 | sact = AHCI_READ(sc, AHCI_P_SACT(chp->ch_channel)); |