| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ahcisata_core.c,v 1.104 2021/11/10 17:19:30 msaitoh Exp $ */ | | 1 | /* $NetBSD: ahcisata_core.c,v 1.105 2021/11/19 23:46:55 rin 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.104 2021/11/10 17:19:30 msaitoh Exp $"); | | 29 | __KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.105 2021/11/19 23:46:55 rin 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> |
| @@ -105,26 +105,41 @@ static const struct scsipi_bustype ahci_ | | | @@ -105,26 +105,41 @@ static const struct scsipi_bustype ahci_ |
105 | .bustype_type = SCSIPI_BUSTYPE_ATAPI, | | 105 | .bustype_type = SCSIPI_BUSTYPE_ATAPI, |
106 | .bustype_cmd = atapi_scsipi_cmd, | | 106 | .bustype_cmd = atapi_scsipi_cmd, |
107 | .bustype_interpret_sense = atapi_interpret_sense, | | 107 | .bustype_interpret_sense = atapi_interpret_sense, |
108 | .bustype_printaddr = atapi_print_addr, | | 108 | .bustype_printaddr = atapi_print_addr, |
109 | .bustype_kill_pending = ahci_atapi_kill_pending, | | 109 | .bustype_kill_pending = ahci_atapi_kill_pending, |
110 | .bustype_async_event_xfer_mode = NULL, | | 110 | .bustype_async_event_xfer_mode = NULL, |
111 | }; | | 111 | }; |
112 | #endif /* NATAPIBUS */ | | 112 | #endif /* NATAPIBUS */ |
113 | | | 113 | |
114 | #define ATA_DELAY 10000 /* 10s for a drive I/O */ | | 114 | #define ATA_DELAY 10000 /* 10s for a drive I/O */ |
115 | #define ATA_RESET_DELAY 31000 /* 31s for a drive reset */ | | 115 | #define ATA_RESET_DELAY 31000 /* 31s for a drive reset */ |
116 | #define AHCI_RST_WAIT (ATA_RESET_DELAY / 10) | | 116 | #define AHCI_RST_WAIT (ATA_RESET_DELAY / 10) |
117 | | | 117 | |
| | | 118 | #ifndef AHCISATA_EXTRA_DELAY_MS |
| | | 119 | #define AHCISATA_EXTRA_DELAY_MS 500 /* XXX need to adjust */ |
| | | 120 | #endif |
| | | 121 | |
| | | 122 | #ifdef AHCISATA_EXTRA_DELAY |
| | | 123 | #define AHCISATA_DO_EXTRA_DELAY(sc, chp, msg, flags) \ |
| | | 124 | ata_delay(chp, AHCISATA_EXTRA_DELAY_MS, msg, flags) |
| | | 125 | #else |
| | | 126 | #define AHCISATA_DO_EXTRA_DELAY(sc, chp, msg, flags) \ |
| | | 127 | do { \ |
| | | 128 | if ((sc)->sc_ahci_quirks & AHCI_QUIRK_EXTRA_DELAY) \ |
| | | 129 | ata_delay(chp, AHCISATA_EXTRA_DELAY_MS, msg, flags); \ |
| | | 130 | } while (0) |
| | | 131 | #endif |
| | | 132 | |
118 | const struct ata_bustype ahci_ata_bustype = { | | 133 | const struct ata_bustype ahci_ata_bustype = { |
119 | .bustype_type = SCSIPI_BUSTYPE_ATA, | | 134 | .bustype_type = SCSIPI_BUSTYPE_ATA, |
120 | .ata_bio = ahci_ata_bio, | | 135 | .ata_bio = ahci_ata_bio, |
121 | .ata_reset_drive = ahci_reset_drive, | | 136 | .ata_reset_drive = ahci_reset_drive, |
122 | .ata_reset_channel = ahci_reset_channel, | | 137 | .ata_reset_channel = ahci_reset_channel, |
123 | .ata_exec_command = ahci_exec_command, | | 138 | .ata_exec_command = ahci_exec_command, |
124 | .ata_get_params = ata_get_params, | | 139 | .ata_get_params = ata_get_params, |
125 | .ata_addref = ahci_ata_addref, | | 140 | .ata_addref = ahci_ata_addref, |
126 | .ata_delref = ahci_ata_delref, | | 141 | .ata_delref = ahci_ata_delref, |
127 | .ata_killpending = ahci_killpending, | | 142 | .ata_killpending = ahci_killpending, |
128 | .ata_recovery = ahci_channel_recover, | | 143 | .ata_recovery = ahci_channel_recover, |
129 | }; | | 144 | }; |
130 | | | 145 | |
| @@ -960,55 +975,51 @@ again: | | | @@ -960,55 +975,51 @@ again: |
960 | AHCINAME(sc), sig); | | 975 | AHCINAME(sc), sig); |
961 | goto end; | | 976 | goto end; |
962 | } | | 977 | } |
963 | AHCIDEBUG_PRINT(("%s: BSY took %d ms\n", AHCINAME(sc), i * 10), | | 978 | AHCIDEBUG_PRINT(("%s: BSY took %d ms\n", AHCINAME(sc), i * 10), |
964 | DEBUG_PROBE); | | 979 | DEBUG_PROBE); |
965 | sig = AHCI_READ(sc, AHCI_P_SIG(chp->ch_channel)); | | 980 | sig = AHCI_READ(sc, AHCI_P_SIG(chp->ch_channel)); |
966 | if (sigp) | | 981 | if (sigp) |
967 | *sigp = sig; | | 982 | *sigp = sig; |
968 | AHCIDEBUG_PRINT(("%s: port %d: sig=0x%x CMD=0x%x\n", | | 983 | AHCIDEBUG_PRINT(("%s: port %d: sig=0x%x CMD=0x%x\n", |
969 | AHCINAME(sc), chp->ch_channel, sig, | | 984 | AHCINAME(sc), chp->ch_channel, sig, |
970 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel))), DEBUG_PROBE); | | 985 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel))), DEBUG_PROBE); |
971 | end: | | 986 | end: |
972 | ahci_channel_stop(sc, chp, flags); | | 987 | ahci_channel_stop(sc, chp, flags); |
973 | #ifdef AHCISATA_EXTRA_DELAY | | 988 | AHCISATA_DO_EXTRA_DELAY(sc, chp, "ahcirst", flags); |
974 | ata_delay(chp, 500, "ahcirst", flags); | | | |
975 | #endif | | | |
976 | /* clear port interrupt register */ | | 989 | /* clear port interrupt register */ |
977 | AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff); | | 990 | AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff); |
978 | ahci_channel_start(sc, chp, flags, | | 991 | ahci_channel_start(sc, chp, flags, |
979 | (sc->sc_ahci_cap & AHCI_CAP_CLO) ? 1 : 0); | | 992 | (sc->sc_ahci_cap & AHCI_CAP_CLO) ? 1 : 0); |
980 | return error; | | 993 | return error; |
981 | } | | 994 | } |
982 | | | 995 | |
983 | static void | | 996 | static void |
984 | ahci_reset_channel(struct ata_channel *chp, int flags) | | 997 | ahci_reset_channel(struct ata_channel *chp, int flags) |
985 | { | | 998 | { |
986 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; | | 999 | struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; |
987 | struct ahci_channel *achp = (struct ahci_channel *)chp; | | 1000 | struct ahci_channel *achp = (struct ahci_channel *)chp; |
988 | int i, tfd; | | 1001 | int i, tfd; |
989 | | | 1002 | |
990 | ata_channel_lock_owned(chp); | | 1003 | ata_channel_lock_owned(chp); |
991 | | | 1004 | |
992 | ahci_channel_stop(sc, chp, flags); | | 1005 | ahci_channel_stop(sc, chp, flags); |
993 | if (sata_reset_interface(chp, sc->sc_ahcit, achp->ahcic_scontrol, | | 1006 | if (sata_reset_interface(chp, sc->sc_ahcit, achp->ahcic_scontrol, |
994 | achp->ahcic_sstatus, flags) != SStatus_DET_DEV) { | | 1007 | achp->ahcic_sstatus, flags) != SStatus_DET_DEV) { |
995 | printf("%s: port %d reset failed\n", AHCINAME(sc), chp->ch_channel); | | 1008 | printf("%s: port %d reset failed\n", AHCINAME(sc), chp->ch_channel); |
996 | /* XXX and then ? */ | | 1009 | /* XXX and then ? */ |
997 | } | | 1010 | } |
998 | ata_kill_active(chp, KILL_RESET, flags); | | 1011 | ata_kill_active(chp, KILL_RESET, flags); |
999 | #ifdef AHCISATA_EXTRA_DELAY | | 1012 | AHCISATA_DO_EXTRA_DELAY(sc, chp, "ahcirst", flags); |
1000 | ata_delay(chp, 500, "ahcirst", flags); | | | |
1001 | #endif | | | |
1002 | /* clear port interrupt register */ | | 1013 | /* clear port interrupt register */ |
1003 | AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff); | | 1014 | AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff); |
1004 | /* clear SErrors and start operations */ | | 1015 | /* clear SErrors and start operations */ |
1005 | ahci_channel_start(sc, chp, flags, | | 1016 | ahci_channel_start(sc, chp, flags, |
1006 | (sc->sc_ahci_cap & AHCI_CAP_CLO) ? 1 : 0); | | 1017 | (sc->sc_ahci_cap & AHCI_CAP_CLO) ? 1 : 0); |
1007 | /* wait 31s for BSY to clear */ | | 1018 | /* wait 31s for BSY to clear */ |
1008 | for (i = 0; i < AHCI_RST_WAIT; i++) { | | 1019 | for (i = 0; i < AHCI_RST_WAIT; i++) { |
1009 | tfd = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel)); | | 1020 | tfd = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel)); |
1010 | if ((AHCI_TFD_ST(tfd) & WDCS_BSY) == 0) | | 1021 | if ((AHCI_TFD_ST(tfd) & WDCS_BSY) == 0) |
1011 | break; | | 1022 | break; |
1012 | ata_delay(chp, 10, "ahcid2h", flags); | | 1023 | ata_delay(chp, 10, "ahcid2h", flags); |
1013 | } | | 1024 | } |
1014 | if ((AHCI_TFD_ST(tfd) & WDCS_BSY) != 0) | | 1025 | if ((AHCI_TFD_ST(tfd) & WDCS_BSY) != 0) |
| @@ -1058,29 +1069,27 @@ ahci_probe_drive(struct ata_channel *chp | | | @@ -1058,29 +1069,27 @@ ahci_probe_drive(struct ata_channel *chp |
1058 | __func__, chp->ch_channel); | | 1069 | __func__, chp->ch_channel); |
1059 | ata_channel_unlock(chp); | | 1070 | ata_channel_unlock(chp); |
1060 | return; | | 1071 | return; |
1061 | } | | 1072 | } |
1062 | | | 1073 | |
1063 | /* bring interface up, accept FISs, power up and spin up device */ | | 1074 | /* bring interface up, accept FISs, power up and spin up device */ |
1064 | AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel), | | 1075 | AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel), |
1065 | AHCI_P_CMD_ICC_AC | AHCI_P_CMD_FRE | | | 1076 | AHCI_P_CMD_ICC_AC | AHCI_P_CMD_FRE | |
1066 | AHCI_P_CMD_POD | AHCI_P_CMD_SUD); | | 1077 | AHCI_P_CMD_POD | AHCI_P_CMD_SUD); |
1067 | /* reset the PHY and bring online */ | | 1078 | /* reset the PHY and bring online */ |
1068 | switch (sata_reset_interface(chp, sc->sc_ahcit, achp->ahcic_scontrol, | | 1079 | switch (sata_reset_interface(chp, sc->sc_ahcit, achp->ahcic_scontrol, |
1069 | achp->ahcic_sstatus, AT_WAIT)) { | | 1080 | achp->ahcic_sstatus, AT_WAIT)) { |
1070 | case SStatus_DET_DEV: | | 1081 | case SStatus_DET_DEV: |
1071 | #ifdef AHCISATA_EXTRA_DELAY | | 1082 | AHCISATA_DO_EXTRA_DELAY(sc, chp, "ahcidv", AT_WAIT); |
1072 | ata_delay(chp, 500, "ahcidv", AT_WAIT); | | | |
1073 | #endif | | | |
1074 | | | 1083 | |
1075 | /* Initial value, used in case the soft reset fails */ | | 1084 | /* Initial value, used in case the soft reset fails */ |
1076 | sig = AHCI_READ(sc, AHCI_P_SIG(chp->ch_channel)); | | 1085 | sig = AHCI_READ(sc, AHCI_P_SIG(chp->ch_channel)); |
1077 | | | 1086 | |
1078 | if (sc->sc_ahci_cap & AHCI_CAP_SPM) { | | 1087 | if (sc->sc_ahci_cap & AHCI_CAP_SPM) { |
1079 | error = ahci_do_reset_drive(chp, PMP_PORT_CTL, AT_WAIT, | | 1088 | error = ahci_do_reset_drive(chp, PMP_PORT_CTL, AT_WAIT, |
1080 | &sig, c_slot); | | 1089 | &sig, c_slot); |
1081 | | | 1090 | |
1082 | /* If probe for PMP failed, just fallback to drive 0 */ | | 1091 | /* If probe for PMP failed, just fallback to drive 0 */ |
1083 | if (error) { | | 1092 | if (error) { |
1084 | aprint_error("%s port %d: drive %d reset " | | 1093 | aprint_error("%s port %d: drive %d reset " |
1085 | "failed, disabling PMP\n", | | 1094 | "failed, disabling PMP\n", |
1086 | AHCINAME(sc), chp->ch_channel, | | 1095 | AHCINAME(sc), chp->ch_channel, |
| @@ -1099,30 +1108,31 @@ ahci_probe_drive(struct ata_channel *chp | | | @@ -1099,30 +1108,31 @@ ahci_probe_drive(struct ata_channel *chp |
1099 | AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel), | | 1108 | AHCI_WRITE(sc, AHCI_P_CMD(chp->ch_channel), |
1100 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) | | | 1109 | AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) | |
1101 | AHCI_P_CMD_PMA); | | 1110 | AHCI_P_CMD_PMA); |
1102 | } | | 1111 | } |
1103 | /* clear port interrupt register */ | | 1112 | /* clear port interrupt register */ |
1104 | AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff); | | 1113 | AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff); |
1105 | | | 1114 | |
1106 | /* and enable interrupts */ | | 1115 | /* and enable interrupts */ |
1107 | AHCI_WRITE(sc, AHCI_P_IE(chp->ch_channel), | | 1116 | AHCI_WRITE(sc, AHCI_P_IE(chp->ch_channel), |
1108 | AHCI_P_IX_TFES | AHCI_P_IX_HBFS | AHCI_P_IX_HBDS | | | 1117 | AHCI_P_IX_TFES | AHCI_P_IX_HBFS | AHCI_P_IX_HBDS | |
1109 | AHCI_P_IX_IFS | | | 1118 | AHCI_P_IX_IFS | |
1110 | AHCI_P_IX_OFS | AHCI_P_IX_DPS | AHCI_P_IX_UFS | | | 1119 | AHCI_P_IX_OFS | AHCI_P_IX_DPS | AHCI_P_IX_UFS | |
1111 | AHCI_P_IX_PSS | AHCI_P_IX_DHRS | AHCI_P_IX_SDBS); | | 1120 | AHCI_P_IX_PSS | AHCI_P_IX_DHRS | AHCI_P_IX_SDBS); |
1112 | #ifdef AHCISATA_EXTRA_DELAY | | 1121 | /* |
1113 | /* wait 500ms before actually starting operations */ | | 1122 | * optionally, wait AHCISATA_EXTRA_DELAY_MS msec before |
1114 | ata_delay(chp, 500, "ahciprb", AT_WAIT); | | 1123 | * actually starting operations |
1115 | #endif | | 1124 | */ |
| | | 1125 | AHCISATA_DO_EXTRA_DELAY(sc, chp, "ahciprb", AT_WAIT); |
1116 | break; | | 1126 | break; |
1117 | | | 1127 | |
1118 | default: | | 1128 | default: |
1119 | break; | | 1129 | break; |
1120 | } | | 1130 | } |
1121 | | | 1131 | |
1122 | ata_queue_free_slot(chp, c_slot); | | 1132 | ata_queue_free_slot(chp, c_slot); |
1123 | | | 1133 | |
1124 | ata_channel_unlock(chp); | | 1134 | ata_channel_unlock(chp); |
1125 | } | | 1135 | } |
1126 | | | 1136 | |
1127 | static void | | 1137 | static void |
1128 | ahci_setup_channel(struct ata_channel *chp) | | 1138 | ahci_setup_channel(struct ata_channel *chp) |