Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/ahci/ahci_pci.c
39536 views
1
/*-
2
* Copyright (c) 2009-2012 Alexander Motin <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer,
10
* without modification, immediately at the beginning of the file.
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
#include <sys/param.h>
28
#include <sys/module.h>
29
#include <sys/systm.h>
30
#include <sys/kernel.h>
31
#include <sys/bus.h>
32
#include <sys/conf.h>
33
#include <sys/endian.h>
34
#include <sys/malloc.h>
35
#include <sys/lock.h>
36
#include <sys/mutex.h>
37
#include <sys/stdarg.h>
38
#include <sys/sysctl.h>
39
#include <sys/taskqueue.h>
40
#include <sys/tree.h>
41
#include <machine/resource.h>
42
#include <machine/bus.h>
43
#include <sys/rman.h>
44
#include <dev/pci/pcivar.h>
45
#include <dev/pci/pcireg.h>
46
#include <dev/iommu/iommu.h>
47
#include "ahci.h"
48
49
static int force_ahci = 1;
50
TUNABLE_INT("hw.ahci.force", &force_ahci);
51
52
static const struct {
53
uint32_t id;
54
uint8_t rev;
55
const char *name;
56
int quirks;
57
} ahci_ids[] = {
58
{0x43801002, 0x00, "AMD SB600",
59
AHCI_Q_NOMSI | AHCI_Q_ATI_PMP_BUG | AHCI_Q_MAXIO_64K},
60
{0x43901002, 0x00, "AMD SB7x0/SB8x0/SB9x0",
61
AHCI_Q_ATI_PMP_BUG | AHCI_Q_1MSI},
62
{0x43911002, 0x00, "AMD SB7x0/SB8x0/SB9x0",
63
AHCI_Q_ATI_PMP_BUG | AHCI_Q_1MSI},
64
{0x43921002, 0x00, "AMD SB7x0/SB8x0/SB9x0",
65
AHCI_Q_ATI_PMP_BUG | AHCI_Q_1MSI},
66
{0x43931002, 0x00, "AMD SB7x0/SB8x0/SB9x0",
67
AHCI_Q_ATI_PMP_BUG | AHCI_Q_1MSI},
68
{0x43941002, 0x00, "AMD SB7x0/SB8x0/SB9x0",
69
AHCI_Q_ATI_PMP_BUG | AHCI_Q_1MSI},
70
/* Not sure SB8x0/SB9x0 needs this quirk. Be conservative though */
71
{0x43951002, 0x00, "AMD SB8x0/SB9x0", AHCI_Q_ATI_PMP_BUG},
72
{0x43b61022, 0x00, "AMD X399", 0},
73
{0x43b51022, 0x00, "AMD 300 Series", 0}, /* X370 */
74
{0x43b71022, 0x00, "AMD 300 Series", 0}, /* B350 */
75
{0x43c81022, 0x00, "AMD 400 Series", 0}, /* B450 */
76
{0x43eb1022, 0x00, "AMD 500 Series", 0},
77
{0x43f61022, 0x00, "AMD 600 Series", 0}, /* X670 */
78
{0x78001022, 0x00, "AMD Hudson-2", 0},
79
{0x78011022, 0x00, "AMD Hudson-2", 0},
80
{0x78021022, 0x00, "AMD Hudson-2", 0},
81
{0x78031022, 0x00, "AMD Hudson-2", 0},
82
{0x78041022, 0x00, "AMD Hudson-2", 0},
83
{0x79001022, 0x00, "AMD KERNCZ", 0},
84
{0x79011022, 0x00, "AMD KERNCZ", 0},
85
{0x79021022, 0x00, "AMD KERNCZ", 0},
86
{0x79031022, 0x00, "AMD KERNCZ", 0},
87
{0x79041022, 0x00, "AMD KERNCZ", 0},
88
{0x79161022, 0x00, "AMD KERNCZ (RAID)", 0},
89
{0x06011b21, 0x00, "ASMedia ASM1060", AHCI_Q_NOCCS|AHCI_Q_NOAUX},
90
{0x06021b21, 0x00, "ASMedia ASM1060", AHCI_Q_NOCCS|AHCI_Q_NOAUX},
91
{0x06111b21, 0x00, "ASMedia ASM1061", AHCI_Q_NOCCS|AHCI_Q_NOAUX},
92
{0x06121b21, 0x00, "ASMedia ASM1062", AHCI_Q_NOCCS|AHCI_Q_NOAUX},
93
{0x06201b21, 0x00, "ASMedia ASM106x", AHCI_Q_NOCCS|AHCI_Q_NOAUX},
94
{0x06211b21, 0x00, "ASMedia ASM106x", AHCI_Q_NOCCS|AHCI_Q_NOAUX},
95
{0x06221b21, 0x00, "ASMedia ASM106x", AHCI_Q_NOCCS|AHCI_Q_NOAUX},
96
{0x06241b21, 0x00, "ASMedia ASM106x", AHCI_Q_NOCCS|AHCI_Q_NOAUX},
97
{0x06251b21, 0x00, "ASMedia ASM106x", AHCI_Q_NOCCS|AHCI_Q_NOAUX},
98
{0x10621b21, 0x00, "ASMedia ASM116x", 0},
99
{0x10641b21, 0x00, "ASMedia ASM116x", 0},
100
{0x11641b21, 0x00, "ASMedia ASM116x", 0},
101
{0x11651b21, 0x00, "ASMedia ASM116x", 0},
102
{0x11661b21, 0x00, "ASMedia ASM116x", 0},
103
{0x79011d94, 0x00, "Hygon KERNCZ", 0},
104
{0x0f228086, 0x00, "Intel BayTrail", 0},
105
{0x0f238086, 0x00, "Intel BayTrail", 0},
106
{0x26528086, 0x00, "Intel ICH6", AHCI_Q_NOFORCE},
107
{0x26538086, 0x00, "Intel ICH6M", AHCI_Q_NOFORCE},
108
{0x26818086, 0x00, "Intel ESB2", 0},
109
{0x26828086, 0x00, "Intel ESB2", 0},
110
{0x26838086, 0x00, "Intel ESB2", 0},
111
{0x27c18086, 0x00, "Intel ICH7", 0},
112
{0x27c38086, 0x00, "Intel ICH7", 0},
113
{0x27c58086, 0x00, "Intel ICH7M", 0},
114
{0x27c68086, 0x00, "Intel ICH7M", 0},
115
{0x28218086, 0x00, "Intel ICH8", 0},
116
{0x28228086, 0x00, "Intel ICH8+ (RAID)", 0},
117
{0x28248086, 0x00, "Intel ICH8", 0},
118
{0x28298086, 0x00, "Intel ICH8M", 0},
119
{0x282a8086, 0x00, "Intel ICH8M+ (RAID)", 0},
120
{0x29228086, 0x00, "Intel ICH9", 0},
121
{0x29238086, 0x00, "Intel ICH9", 0},
122
{0x29248086, 0x00, "Intel ICH9", 0},
123
{0x29258086, 0x00, "Intel ICH9", 0},
124
{0x29278086, 0x00, "Intel ICH9", 0},
125
{0x29298086, 0x00, "Intel ICH9M", 0},
126
{0x292a8086, 0x00, "Intel ICH9M", 0},
127
{0x292b8086, 0x00, "Intel ICH9M", 0},
128
{0x292c8086, 0x00, "Intel ICH9M", 0},
129
{0x292f8086, 0x00, "Intel ICH9M", 0},
130
{0x294d8086, 0x00, "Intel ICH9", 0},
131
{0x294e8086, 0x00, "Intel ICH9M", 0},
132
{0x3a028086, 0x00, "Intel ICH10", 0},
133
{0x3a058086, 0x00, "Intel ICH10 (RAID)", 0},
134
{0x3a228086, 0x00, "Intel ICH10", 0},
135
{0x3a258086, 0x00, "Intel ICH10 (RAID)", 0},
136
{0x3b228086, 0x00, "Intel Ibex Peak", 0},
137
{0x3b238086, 0x00, "Intel Ibex Peak", 0},
138
{0x3b258086, 0x00, "Intel Ibex Peak (RAID)", 0},
139
{0x3b298086, 0x00, "Intel Ibex Peak-M", 0},
140
{0x3b2c8086, 0x00, "Intel Ibex Peak-M (RAID)", 0},
141
{0x3b2f8086, 0x00, "Intel Ibex Peak-M", 0},
142
{0x06d68086, 0x00, "Intel Comet Lake (RAID)", 0},
143
{0x19b08086, 0x00, "Intel Denverton", 0},
144
{0x19b18086, 0x00, "Intel Denverton", 0},
145
{0x19b28086, 0x00, "Intel Denverton", 0},
146
{0x19b38086, 0x00, "Intel Denverton", 0},
147
{0x19b48086, 0x00, "Intel Denverton", 0},
148
{0x19b58086, 0x00, "Intel Denverton", 0},
149
{0x19b68086, 0x00, "Intel Denverton", 0},
150
{0x19b78086, 0x00, "Intel Denverton", 0},
151
{0x19be8086, 0x00, "Intel Denverton", 0},
152
{0x19bf8086, 0x00, "Intel Denverton", 0},
153
{0x19c08086, 0x00, "Intel Denverton", 0},
154
{0x19c18086, 0x00, "Intel Denverton", 0},
155
{0x19c28086, 0x00, "Intel Denverton", 0},
156
{0x19c38086, 0x00, "Intel Denverton", 0},
157
{0x19c48086, 0x00, "Intel Denverton", 0},
158
{0x19c58086, 0x00, "Intel Denverton", 0},
159
{0x19c68086, 0x00, "Intel Denverton", 0},
160
{0x19c78086, 0x00, "Intel Denverton", 0},
161
{0x19ce8086, 0x00, "Intel Denverton", 0},
162
{0x19cf8086, 0x00, "Intel Denverton", 0},
163
{0x1c028086, 0x00, "Intel Cougar Point", 0},
164
{0x1c038086, 0x00, "Intel Cougar Point", 0},
165
{0x1c048086, 0x00, "Intel Cougar Point (RAID)", 0},
166
{0x1c058086, 0x00, "Intel Cougar Point (RAID)", 0},
167
{0x1c068086, 0x00, "Intel Cougar Point (RAID)", 0},
168
{0x1d028086, 0x00, "Intel Patsburg", 0},
169
{0x1d048086, 0x00, "Intel Patsburg", 0},
170
{0x1d068086, 0x00, "Intel Patsburg", 0},
171
{0x28268086, 0x00, "Intel Patsburg+ (RAID)", 0},
172
{0x1e028086, 0x00, "Intel Panther Point", 0},
173
{0x1e038086, 0x00, "Intel Panther Point", 0},
174
{0x1e048086, 0x00, "Intel Panther Point (RAID)", 0},
175
{0x1e058086, 0x00, "Intel Panther Point (RAID)", 0},
176
{0x1e068086, 0x00, "Intel Panther Point (RAID)", 0},
177
{0x1e078086, 0x00, "Intel Panther Point (RAID)", 0},
178
{0x1e0e8086, 0x00, "Intel Panther Point (RAID)", 0},
179
{0x1e0f8086, 0x00, "Intel Panther Point (RAID)", 0},
180
{0x1f228086, 0x00, "Intel Avoton", 0},
181
{0x1f238086, 0x00, "Intel Avoton", 0},
182
{0x1f248086, 0x00, "Intel Avoton (RAID)", 0},
183
{0x1f258086, 0x00, "Intel Avoton (RAID)", 0},
184
{0x1f268086, 0x00, "Intel Avoton (RAID)", 0},
185
{0x1f278086, 0x00, "Intel Avoton (RAID)", 0},
186
{0x1f2e8086, 0x00, "Intel Avoton (RAID)", 0},
187
{0x1f2f8086, 0x00, "Intel Avoton (RAID)", 0},
188
{0x1f328086, 0x00, "Intel Avoton", 0},
189
{0x1f338086, 0x00, "Intel Avoton", 0},
190
{0x1f348086, 0x00, "Intel Avoton (RAID)", 0},
191
{0x1f358086, 0x00, "Intel Avoton (RAID)", 0},
192
{0x1f368086, 0x00, "Intel Avoton (RAID)", 0},
193
{0x1f378086, 0x00, "Intel Avoton (RAID)", 0},
194
{0x1f3e8086, 0x00, "Intel Avoton (RAID)", 0},
195
{0x1f3f8086, 0x00, "Intel Avoton (RAID)", 0},
196
{0x23a38086, 0x00, "Intel Coleto Creek", 0},
197
{0x31e38086, 0x00, "Intel Gemini Lake", 0},
198
{0x4b638086, 0x00, "Intel Elkhart Lake", 0},
199
{0x5ae38086, 0x00, "Intel Apollo Lake", 0},
200
{0x7ae28086, 0x00, "Intel Alder Lake", 0},
201
{0x8c028086, 0x00, "Intel Lynx Point", 0},
202
{0x8c038086, 0x00, "Intel Lynx Point", 0},
203
{0x8c048086, 0x00, "Intel Lynx Point (RAID)", 0},
204
{0x8c058086, 0x00, "Intel Lynx Point (RAID)", 0},
205
{0x8c068086, 0x00, "Intel Lynx Point (RAID)", 0},
206
{0x8c078086, 0x00, "Intel Lynx Point (RAID)", 0},
207
{0x8c0e8086, 0x00, "Intel Lynx Point (RAID)", 0},
208
{0x8c0f8086, 0x00, "Intel Lynx Point (RAID)", 0},
209
{0x8c828086, 0x00, "Intel Wildcat Point", 0},
210
{0x8c838086, 0x00, "Intel Wildcat Point", 0},
211
{0x8c848086, 0x00, "Intel Wildcat Point (RAID)", 0},
212
{0x8c858086, 0x00, "Intel Wildcat Point (RAID)", 0},
213
{0x8c868086, 0x00, "Intel Wildcat Point (RAID)", 0},
214
{0x8c878086, 0x00, "Intel Wildcat Point (RAID)", 0},
215
{0x8c8e8086, 0x00, "Intel Wildcat Point (RAID)", 0},
216
{0x8c8f8086, 0x00, "Intel Wildcat Point (RAID)", 0},
217
{0x8d028086, 0x00, "Intel Wellsburg", 0},
218
{0x8d048086, 0x00, "Intel Wellsburg (RAID)", 0},
219
{0x8d068086, 0x00, "Intel Wellsburg (RAID)", 0},
220
{0x8d628086, 0x00, "Intel Wellsburg", 0},
221
{0x8d648086, 0x00, "Intel Wellsburg (RAID)", 0},
222
{0x8d668086, 0x00, "Intel Wellsburg (RAID)", 0},
223
{0x8d6e8086, 0x00, "Intel Wellsburg (RAID)", 0},
224
{0x28238086, 0x00, "Intel Wellsburg+ (RAID)", 0},
225
{0x28278086, 0x00, "Intel Wellsburg+ (RAID)", 0},
226
{0x9c028086, 0x00, "Intel Lynx Point-LP", 0},
227
{0x9c038086, 0x00, "Intel Lynx Point-LP", 0},
228
{0x9c048086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
229
{0x9c058086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
230
{0x9c068086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
231
{0x9c078086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
232
{0x9c0e8086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
233
{0x9c0f8086, 0x00, "Intel Lynx Point-LP (RAID)", 0},
234
{0x9c838086, 0x00, "Intel Wildcat Point-LP", 0},
235
{0x9c858086, 0x00, "Intel Wildcat Point-LP (RAID)", 0},
236
{0x9c878086, 0x00, "Intel Wildcat Point-LP (RAID)", 0},
237
{0x9c8f8086, 0x00, "Intel Wildcat Point-LP (RAID)", 0},
238
{0x9d038086, 0x00, "Intel Sunrise Point-LP", 0},
239
{0x9d058086, 0x00, "Intel Sunrise Point-LP (RAID)", 0},
240
{0x9d078086, 0x00, "Intel Sunrise Point-LP (RAID)", 0},
241
{0xa1028086, 0x00, "Intel Sunrise Point", 0},
242
{0xa1038086, 0x00, "Intel Sunrise Point", 0},
243
{0xa1058086, 0x00, "Intel Sunrise Point (RAID)", 0},
244
{0xa1068086, 0x00, "Intel Sunrise Point (RAID)", 0},
245
{0xa1078086, 0x00, "Intel Sunrise Point (RAID)", 0},
246
{0xa10f8086, 0x00, "Intel Sunrise Point (RAID)", 0},
247
{0xa1828086, 0x00, "Intel Lewisburg", 0},
248
{0xa1868086, 0x00, "Intel Lewisburg (RAID)", 0},
249
{0xa1d28086, 0x00, "Intel Lewisburg", 0},
250
{0xa1d68086, 0x00, "Intel Lewisburg (RAID)", 0},
251
{0xa2028086, 0x00, "Intel Lewisburg", 0},
252
{0xa2068086, 0x00, "Intel Lewisburg (RAID)", 0},
253
{0xa2528086, 0x00, "Intel Lewisburg", 0},
254
{0xa2568086, 0x00, "Intel Lewisburg (RAID)", 0},
255
{0xa2828086, 0x00, "Intel Union Point", 0},
256
{0xa2868086, 0x00, "Intel Union Point (RAID)", 0},
257
{0xa28e8086, 0x00, "Intel Union Point (RAID)", 0},
258
{0xa3528086, 0x00, "Intel Cannon Lake", 0},
259
{0xa3538086, 0x00, "Intel Cannon Lake", 0},
260
{0x23238086, 0x00, "Intel DH89xxCC", 0},
261
{0x2360197b, 0x00, "JMicron JMB360", 0},
262
{0x2361197b, 0x00, "JMicron JMB361", AHCI_Q_NOFORCE | AHCI_Q_1CH},
263
{0x2362197b, 0x00, "JMicron JMB362", 0},
264
{0x2363197b, 0x00, "JMicron JMB363", AHCI_Q_NOFORCE},
265
{0x2365197b, 0x00, "JMicron JMB365", AHCI_Q_NOFORCE},
266
{0x2366197b, 0x00, "JMicron JMB366", AHCI_Q_NOFORCE},
267
{0x2368197b, 0x00, "JMicron JMB368", AHCI_Q_NOFORCE},
268
{0x2392197b, 0x00, "JMicron JMB388", AHCI_Q_IOMMU_BUSWIDE},
269
{0x0585197b, 0x00, "JMicron JMB58x", 0},
270
{0x01221c28, 0x00, "Lite-On Plextor M6E (Marvell 88SS9183)",
271
AHCI_Q_IOMMU_BUSWIDE},
272
{0x611111ab, 0x00, "Marvell 88SE6111", AHCI_Q_NOFORCE | AHCI_Q_NOPMP |
273
AHCI_Q_1CH | AHCI_Q_EDGEIS},
274
{0x612111ab, 0x00, "Marvell 88SE6121", AHCI_Q_NOFORCE | AHCI_Q_NOPMP |
275
AHCI_Q_2CH | AHCI_Q_EDGEIS | AHCI_Q_NONCQ | AHCI_Q_NOCOUNT},
276
{0x614111ab, 0x00, "Marvell 88SE6141", AHCI_Q_NOFORCE | AHCI_Q_NOPMP |
277
AHCI_Q_4CH | AHCI_Q_EDGEIS | AHCI_Q_NONCQ | AHCI_Q_NOCOUNT},
278
{0x614511ab, 0x00, "Marvell 88SE6145", AHCI_Q_NOFORCE | AHCI_Q_NOPMP |
279
AHCI_Q_4CH | AHCI_Q_EDGEIS | AHCI_Q_NONCQ | AHCI_Q_NOCOUNT},
280
{0x91201b4b, 0x00, "Marvell 88SE912x", AHCI_Q_EDGEIS |
281
AHCI_Q_IOMMU_BUSWIDE},
282
{0x91231b4b, 0x11, "Marvell 88SE912x", AHCI_Q_ALTSIG |
283
AHCI_Q_IOMMU_BUSWIDE},
284
{0x91231b4b, 0x00, "Marvell 88SE912x", AHCI_Q_EDGEIS | AHCI_Q_SATA2 |
285
AHCI_Q_IOMMU_BUSWIDE},
286
{0x91251b4b, 0x00, "Marvell 88SE9125", 0},
287
{0x91281b4b, 0x00, "Marvell 88SE9128", AHCI_Q_ALTSIG |
288
AHCI_Q_IOMMU_BUSWIDE},
289
{0x91301b4b, 0x00, "Marvell 88SE9130", AHCI_Q_ALTSIG |
290
AHCI_Q_IOMMU_BUSWIDE},
291
{0x91701b4b, 0x00, "Marvell 88SE9170", AHCI_Q_IOMMU_BUSWIDE},
292
{0x91721b4b, 0x00, "Marvell 88SE9172", AHCI_Q_IOMMU_BUSWIDE},
293
{0x917a1b4b, 0x00, "Marvell 88SE917A", AHCI_Q_IOMMU_BUSWIDE},
294
{0x91821b4b, 0x00, "Marvell 88SE9182", AHCI_Q_IOMMU_BUSWIDE},
295
{0x91831b4b, 0x00, "Marvell 88SS9183", AHCI_Q_IOMMU_BUSWIDE},
296
{0x91a01b4b, 0x00, "Marvell 88SE91Ax", AHCI_Q_IOMMU_BUSWIDE},
297
{0x92151b4b, 0x00, "Marvell 88SE9215", 0},
298
{0x92201b4b, 0x00, "Marvell 88SE9220", AHCI_Q_ALTSIG |
299
AHCI_Q_IOMMU_BUSWIDE},
300
{0x92301b4b, 0x00, "Marvell 88SE9230", AHCI_Q_ALTSIG |
301
AHCI_Q_IOMMU_BUSWIDE | AHCI_Q_SLOWDEV},
302
{0x92351b4b, 0x00, "Marvell 88SE9235", 0},
303
{0x06201103, 0x00, "HighPoint RocketRAID 620", 0},
304
{0x06201b4b, 0x00, "HighPoint RocketRAID 620", 0},
305
{0x06221103, 0x00, "HighPoint RocketRAID 622", 0},
306
{0x06221b4b, 0x00, "HighPoint RocketRAID 622", 0},
307
{0x06401103, 0x00, "HighPoint RocketRAID 640", 0},
308
{0x06401b4b, 0x00, "HighPoint RocketRAID 640", 0},
309
{0x06441103, 0x00, "HighPoint RocketRAID 644", 0},
310
{0x06441b4b, 0x00, "HighPoint RocketRAID 644", 0},
311
{0x06411103, 0x00, "HighPoint RocketRAID 640L", 0},
312
{0x06421103, 0x00, "HighPoint RocketRAID 642L", AHCI_Q_IOMMU_BUSWIDE},
313
{0x06451103, 0x00, "HighPoint RocketRAID 644L", AHCI_Q_IOMMU_BUSWIDE},
314
{0x044c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
315
{0x044d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
316
{0x044e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
317
{0x044f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
318
{0x045c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
319
{0x045d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
320
{0x045e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
321
{0x045f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
322
{0x055010de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
323
{0x055110de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
324
{0x055210de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
325
{0x055310de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
326
{0x055410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
327
{0x055510de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
328
{0x055610de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
329
{0x055710de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
330
{0x055810de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
331
{0x055910de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
332
{0x055A10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
333
{0x055B10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
334
{0x058410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
335
{0x07f010de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
336
{0x07f110de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
337
{0x07f210de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
338
{0x07f310de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
339
{0x07f410de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
340
{0x07f510de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
341
{0x07f610de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
342
{0x07f710de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
343
{0x07f810de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
344
{0x07f910de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
345
{0x07fa10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
346
{0x07fb10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
347
{0x0ad010de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
348
{0x0ad110de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
349
{0x0ad210de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
350
{0x0ad310de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
351
{0x0ad410de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
352
{0x0ad510de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
353
{0x0ad610de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
354
{0x0ad710de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
355
{0x0ad810de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
356
{0x0ad910de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
357
{0x0ada10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
358
{0x0adb10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
359
{0x0ab410de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
360
{0x0ab510de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
361
{0x0ab610de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
362
{0x0ab710de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
363
{0x0ab810de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
364
{0x0ab910de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
365
{0x0aba10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
366
{0x0abb10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
367
{0x0abc10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
368
{0x0abd10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
369
{0x0abe10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
370
{0x0abf10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
371
{0x0d8410de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
372
{0x0d8510de, 0x00, "NVIDIA MCP89", AHCI_Q_NOFORCE|AHCI_Q_NOAA},
373
{0x0d8610de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
374
{0x0d8710de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
375
{0x0d8810de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
376
{0x0d8910de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
377
{0x0d8a10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
378
{0x0d8b10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
379
{0x0d8c10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
380
{0x0d8d10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
381
{0x0d8e10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
382
{0x0d8f10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
383
{0x3781105a, 0x00, "Promise TX8660", 0},
384
{0x33491106, 0x00, "VIA VT8251", AHCI_Q_NOPMP|AHCI_Q_NONCQ},
385
{0x62871106, 0x00, "VIA VT8251", AHCI_Q_NOPMP|AHCI_Q_NONCQ},
386
{0x11841039, 0x00, "SiS 966", 0},
387
{0x11851039, 0x00, "SiS 968", 0},
388
{0x01861039, 0x00, "SiS 968", 0},
389
{0xa01c177d, 0x00, "ThunderX", AHCI_Q_ABAR0|AHCI_Q_1MSI},
390
{0x00311c36, 0x00, "Annapurna", AHCI_Q_FORCE_PI|AHCI_Q_RESTORE_CAP|AHCI_Q_NOMSIX},
391
{0x1600144d, 0x00, "Samsung", AHCI_Q_NOMSI},
392
{0x07e015ad, 0x00, "VMware", 0},
393
{0x00000000, 0x00, NULL, 0}
394
};
395
396
static int
397
ahci_pci_ctlr_reset(device_t dev)
398
{
399
400
return(ahci_ctlr_reset(dev));
401
}
402
403
static int
404
ahci_probe(device_t dev)
405
{
406
int i, valid = 0;
407
uint32_t devid = pci_get_devid(dev);
408
uint8_t revid = pci_get_revid(dev);
409
410
/*
411
* Ensure it is not a PCI bridge (some vendors use
412
* the same PID and VID in PCI bridge and AHCI cards).
413
*/
414
if (pci_get_class(dev) == PCIC_BRIDGE)
415
return (ENXIO);
416
417
/* Is this a possible AHCI candidate? */
418
if (pci_get_class(dev) == PCIC_STORAGE &&
419
pci_get_subclass(dev) == PCIS_STORAGE_SATA &&
420
pci_get_progif(dev) == PCIP_STORAGE_SATA_AHCI_1_0)
421
valid = 1;
422
else if (pci_get_class(dev) == PCIC_STORAGE &&
423
pci_get_subclass(dev) == PCIS_STORAGE_RAID)
424
valid = 2;
425
/* Is this a known AHCI chip? */
426
for (i = 0; ahci_ids[i].id != 0; i++) {
427
if (ahci_ids[i].id == devid &&
428
ahci_ids[i].rev <= revid &&
429
(valid || (force_ahci == 1 &&
430
!(ahci_ids[i].quirks & AHCI_Q_NOFORCE)))) {
431
/* Do not attach JMicrons with single PCI function. */
432
if (pci_get_vendor(dev) == 0x197b &&
433
(ahci_ids[i].quirks & AHCI_Q_NOFORCE) &&
434
(pci_read_config(dev, 0xdf, 1) & 0x40) == 0)
435
return (ENXIO);
436
device_set_descf(dev, "%s AHCI SATA controller",
437
ahci_ids[i].name);
438
return (BUS_PROBE_DEFAULT);
439
}
440
}
441
if (valid != 1)
442
return (ENXIO);
443
device_set_desc(dev, "AHCI SATA controller");
444
return (BUS_PROBE_DEFAULT);
445
}
446
447
static int
448
ahci_ata_probe(device_t dev)
449
{
450
int i;
451
uint32_t devid = pci_get_devid(dev);
452
uint8_t revid = pci_get_revid(dev);
453
454
if ((intptr_t)device_get_ivars(dev) >= 0)
455
return (ENXIO);
456
/* Is this a known AHCI chip? */
457
for (i = 0; ahci_ids[i].id != 0; i++) {
458
if (ahci_ids[i].id == devid &&
459
ahci_ids[i].rev <= revid) {
460
device_set_descf(dev, "%s AHCI SATA controller",
461
ahci_ids[i].name);
462
return (BUS_PROBE_DEFAULT);
463
}
464
}
465
device_set_desc(dev, "AHCI SATA controller");
466
return (BUS_PROBE_DEFAULT);
467
}
468
469
static int
470
ahci_pci_read_msix_bars(device_t dev, uint8_t *table_bar, uint8_t *pba_bar)
471
{
472
int cap_offset = 0, ret;
473
uint32_t val;
474
475
if ((table_bar == NULL) || (pba_bar == NULL))
476
return (EINVAL);
477
478
ret = pci_find_cap(dev, PCIY_MSIX, &cap_offset);
479
if (ret != 0)
480
return (EINVAL);
481
482
val = pci_read_config(dev, cap_offset + PCIR_MSIX_TABLE, 4);
483
*table_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
484
485
val = pci_read_config(dev, cap_offset + PCIR_MSIX_PBA, 4);
486
*pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
487
488
return (0);
489
}
490
491
static int
492
ahci_pci_attach(device_t dev)
493
{
494
struct ahci_controller *ctlr = device_get_softc(dev);
495
int error, i;
496
uint32_t devid = pci_get_devid(dev);
497
uint8_t revid = pci_get_revid(dev);
498
int msi_count, msix_count;
499
uint8_t table_bar = 0, pba_bar = 0;
500
uint32_t caps, pi;
501
502
msi_count = pci_msi_count(dev);
503
msix_count = pci_msix_count(dev);
504
505
i = 0;
506
while (ahci_ids[i].id != 0 &&
507
(ahci_ids[i].id != devid ||
508
ahci_ids[i].rev > revid))
509
i++;
510
ctlr->quirks = ahci_ids[i].quirks;
511
512
if (ctlr->quirks & AHCI_Q_IOMMU_BUSWIDE) {
513
/*
514
* The controller issues DMA requests from PCI function 1,
515
* but the device is not multifunction.
516
* Ref: https://bugzilla.kernel.org/show_bug.cgi?id=42679
517
*/
518
bus_dma_iommu_set_buswide(dev);
519
}
520
521
/* Limit speed for my onboard JMicron external port.
522
* It is not eSATA really, limit to SATA 1 */
523
if (pci_get_devid(dev) == 0x2363197b &&
524
pci_get_subvendor(dev) == 0x1043 &&
525
pci_get_subdevice(dev) == 0x81e4)
526
ctlr->quirks |= AHCI_Q_SATA1_UNIT0;
527
resource_int_value(device_get_name(dev), device_get_unit(dev),
528
"quirks", &ctlr->quirks);
529
ctlr->vendorid = pci_get_vendor(dev);
530
ctlr->deviceid = pci_get_device(dev);
531
ctlr->subvendorid = pci_get_subvendor(dev);
532
ctlr->subdeviceid = pci_get_subdevice(dev);
533
534
/* Default AHCI Base Address is BAR(5), Cavium uses BAR(0) */
535
if (ctlr->quirks & AHCI_Q_ABAR0)
536
ctlr->r_rid = PCIR_BAR(0);
537
else
538
ctlr->r_rid = PCIR_BAR(5);
539
if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
540
&ctlr->r_rid, RF_ACTIVE)))
541
return ENXIO;
542
543
/*
544
* Intel RAID hardware can remap NVMe devices inside its BAR.
545
* Try to detect this. Either we have to add the device
546
* here, or the user has to change the mode in the BIOS
547
* from RST to AHCI.
548
*/
549
if (pci_get_vendor(dev) == 0x8086) {
550
uint32_t vscap;
551
552
vscap = ATA_INL(ctlr->r_mem, AHCI_VSCAP);
553
if (vscap & 1) {
554
uint32_t cap = ATA_INL(ctlr->r_mem, 0x800); /* Intel's REMAP CAP */
555
int i;
556
557
ctlr->remap_offset = 0x4000;
558
ctlr->remap_size = 0x4000;
559
560
/*
561
* Check each of the devices that might be remapped to
562
* make sure they are an nvme device. At the present,
563
* nvme are the only known devices remapped.
564
*/
565
for (i = 0; i < 3; i++) {
566
if (cap & (1 << i) &&
567
(ATA_INL(ctlr->r_mem, 0x880 + i * 0x80) ==
568
((PCIC_STORAGE << 16) |
569
(PCIS_STORAGE_NVM << 8) |
570
PCIP_STORAGE_NVM_ENTERPRISE_NVMHCI_1_0))) {
571
ctlr->remapped_devices++;
572
}
573
}
574
575
/* If we have any remapped device, disable MSI */
576
if (ctlr->remapped_devices > 0) {
577
device_printf(dev, "Detected %d nvme remapped devices\n",
578
ctlr->remapped_devices);
579
ctlr->quirks |= (AHCI_Q_NOMSIX | AHCI_Q_NOMSI);
580
}
581
}
582
}
583
584
if (ctlr->quirks & AHCI_Q_NOMSIX)
585
msix_count = 0;
586
587
/* Read MSI-x BAR IDs if supported */
588
if (msix_count > 0) {
589
error = ahci_pci_read_msix_bars(dev, &table_bar, &pba_bar);
590
if (error == 0) {
591
ctlr->r_msix_tab_rid = table_bar;
592
ctlr->r_msix_pba_rid = pba_bar;
593
} else {
594
/* Failed to read BARs, disable MSI-x */
595
msix_count = 0;
596
}
597
}
598
599
/* Allocate resources for MSI-x table and PBA */
600
if (msix_count > 0) {
601
/*
602
* Allocate new MSI-x table only if not
603
* allocated before.
604
*/
605
ctlr->r_msix_table = NULL;
606
if (ctlr->r_msix_tab_rid != ctlr->r_rid) {
607
/* Separate BAR for MSI-x */
608
ctlr->r_msix_table = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
609
&ctlr->r_msix_tab_rid, RF_ACTIVE);
610
if (ctlr->r_msix_table == NULL) {
611
ahci_free_mem(dev);
612
return (ENXIO);
613
}
614
}
615
616
/*
617
* Allocate new PBA table only if not
618
* allocated before.
619
*/
620
ctlr->r_msix_pba = NULL;
621
if ((ctlr->r_msix_pba_rid != ctlr->r_msix_tab_rid) &&
622
(ctlr->r_msix_pba_rid != ctlr->r_rid)) {
623
/* Separate BAR for PBA */
624
ctlr->r_msix_pba = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
625
&ctlr->r_msix_pba_rid, RF_ACTIVE);
626
if (ctlr->r_msix_pba == NULL) {
627
ahci_free_mem(dev);
628
return (ENXIO);
629
}
630
}
631
}
632
633
pci_enable_busmaster(dev);
634
/* Reset controller */
635
if ((error = ahci_pci_ctlr_reset(dev)) != 0) {
636
ahci_free_mem(dev);
637
return (error);
638
}
639
640
/* Setup interrupts. */
641
642
/* Setup MSI register parameters */
643
/* Process hints. */
644
caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
645
pi = ATA_INL(ctlr->r_mem, AHCI_PI);
646
if (ctlr->quirks & AHCI_Q_NOMSI)
647
ctlr->msi = 0;
648
else if ((ctlr->quirks & AHCI_Q_1MSI) ||
649
((caps & (AHCI_CAP_NPMASK | AHCI_CAP_CCCS)) == 0 && pi == 1))
650
ctlr->msi = 1;
651
else
652
ctlr->msi = 2;
653
resource_int_value(device_get_name(dev),
654
device_get_unit(dev), "msi", &ctlr->msi);
655
ctlr->numirqs = 1;
656
if (msi_count == 0 && msix_count == 0)
657
ctlr->msi = 0;
658
if (ctlr->msi < 0)
659
ctlr->msi = 0;
660
else if (ctlr->msi == 1) {
661
msi_count = min(1, msi_count);
662
msix_count = min(1, msix_count);
663
} else if (ctlr->msi > 1)
664
ctlr->msi = 2;
665
666
/* Allocate MSI/MSI-x if needed/present. */
667
if (ctlr->msi > 0) {
668
error = ENXIO;
669
670
/* Try to allocate MSI-x first */
671
if (msix_count > 0) {
672
error = pci_alloc_msix(dev, &msix_count);
673
if (error == 0)
674
ctlr->numirqs = msix_count;
675
}
676
677
/*
678
* Try to allocate MSI if msi_count is greater than 0
679
* and if MSI-x allocation failed.
680
*/
681
if ((error != 0) && (msi_count > 0)) {
682
error = pci_alloc_msi(dev, &msi_count);
683
if (error == 0)
684
ctlr->numirqs = msi_count;
685
}
686
687
/* Both MSI and MSI-x allocations failed */
688
if (error != 0) {
689
ctlr->msi = 0;
690
device_printf(dev, "Failed to allocate MSI/MSI-x, "
691
"falling back to INTx\n");
692
}
693
}
694
695
error = ahci_attach(dev);
696
if (error != 0) {
697
if (ctlr->msi > 0)
698
pci_release_msi(dev);
699
ahci_free_mem(dev);
700
}
701
return error;
702
}
703
704
static int
705
ahci_pci_detach(device_t dev)
706
{
707
708
ahci_detach(dev);
709
pci_release_msi(dev);
710
return (0);
711
}
712
713
static int
714
ahci_pci_suspend(device_t dev)
715
{
716
struct ahci_controller *ctlr = device_get_softc(dev);
717
718
bus_generic_suspend(dev);
719
/* Disable interupts, so the state change(s) doesn't trigger */
720
ATA_OUTL(ctlr->r_mem, AHCI_GHC,
721
ATA_INL(ctlr->r_mem, AHCI_GHC) & (~AHCI_GHC_IE));
722
return 0;
723
}
724
725
static int
726
ahci_pci_resume(device_t dev)
727
{
728
int res;
729
730
if ((res = ahci_pci_ctlr_reset(dev)) != 0)
731
return (res);
732
ahci_ctlr_setup(dev);
733
return (bus_generic_resume(dev));
734
}
735
736
static device_method_t ahci_methods[] = {
737
DEVMETHOD(device_probe, ahci_probe),
738
DEVMETHOD(device_attach, ahci_pci_attach),
739
DEVMETHOD(device_detach, ahci_pci_detach),
740
DEVMETHOD(device_suspend, ahci_pci_suspend),
741
DEVMETHOD(device_resume, ahci_pci_resume),
742
DEVMETHOD(bus_print_child, ahci_print_child),
743
DEVMETHOD(bus_alloc_resource, ahci_alloc_resource),
744
DEVMETHOD(bus_release_resource, ahci_release_resource),
745
DEVMETHOD(bus_setup_intr, ahci_setup_intr),
746
DEVMETHOD(bus_teardown_intr,ahci_teardown_intr),
747
DEVMETHOD(bus_child_location, ahci_child_location),
748
DEVMETHOD(bus_get_dma_tag, ahci_get_dma_tag),
749
DEVMETHOD_END
750
};
751
752
static driver_t ahci_driver = {
753
"ahci",
754
ahci_methods,
755
sizeof(struct ahci_controller)
756
};
757
758
DRIVER_MODULE(ahci, pci, ahci_driver, NULL, NULL);
759
/* Also matches class / subclass / progid XXX need to add when we have masking support */
760
MODULE_PNP_INFO("W32:vendor/device", pci, ahci, ahci_ids,
761
nitems(ahci_ids) - 1);
762
763
static device_method_t ahci_ata_methods[] = {
764
DEVMETHOD(device_probe, ahci_ata_probe),
765
DEVMETHOD(device_attach, ahci_pci_attach),
766
DEVMETHOD(device_detach, ahci_pci_detach),
767
DEVMETHOD(device_suspend, ahci_pci_suspend),
768
DEVMETHOD(device_resume, ahci_pci_resume),
769
DEVMETHOD(bus_print_child, ahci_print_child),
770
DEVMETHOD(bus_alloc_resource, ahci_alloc_resource),
771
DEVMETHOD(bus_release_resource, ahci_release_resource),
772
DEVMETHOD(bus_setup_intr, ahci_setup_intr),
773
DEVMETHOD(bus_teardown_intr,ahci_teardown_intr),
774
DEVMETHOD(bus_child_location, ahci_child_location),
775
DEVMETHOD_END
776
};
777
778
static driver_t ahci_ata_driver = {
779
"ahci",
780
ahci_ata_methods,
781
sizeof(struct ahci_controller)
782
};
783
784
DRIVER_MODULE(ahci, atapci, ahci_ata_driver, NULL, NULL);
785
786