2 * Copyright 2007, Marcus Overhagen. All rights reserved.
3 * Distributed under the terms of the MIT License.
12 #define TRACE(a...) dprintf("ahci: " a)
13 //#define FLOW(a...) dprintf("ahci: " a)
16 #define AHCI_ID_GENERATOR "ahci/id"
17 #define AHCI_ID_ITEM "ahci/id"
18 #define AHCI_BRIDGE_PRETTY_NAME "AHCI Bridge"
19 #define AHCI_CONTROLLER_PRETTY_NAME "AHCI Controller"
22 const device_info kSupportedDevices
[] = {
23 { 0x1002, 0x4380, "ATI SB600" },
24 { 0x1002, 0x4390, "ATI SB700/800" },
25 { 0x1002, 0x4391, "ATI IXP700" },
26 { 0x1002, 0x4392, "ATI SB700/800" },
27 { 0x1002, 0x4393, "ATI SB700/800" },
28 { 0x1002, 0x4394, "ATI SB700/800" },
29 { 0x1002, 0x4395, "ATI SB700/800" },
30 { 0x1039, 0x1184, "SiS 966" },
31 { 0x1039, 0x1185, "SiS 966" },
32 { 0x1039, 0x0186, "SiS 968" },
33 { 0x10b9, 0x5288, "Acer Labs M5288" },
34 { 0x10de, 0x044c, "NVIDIA MCP65" },
35 { 0x10de, 0x044d, "NVIDIA MCP65" },
36 { 0x10de, 0x044e, "NVIDIA MCP65" },
37 { 0x10de, 0x044f, "NVIDIA MCP65" },
38 { 0x10de, 0x045c, "NVIDIA MCP65" },
39 { 0x10de, 0x045d, "NVIDIA MCP65" },
40 { 0x10de, 0x045e, "NVIDIA MCP65" },
41 { 0x10de, 0x045f, "NVIDIA MCP65" },
42 { 0x10de, 0x0550, "NVIDIA MCP67" },
43 { 0x10de, 0x0551, "NVIDIA MCP67" },
44 { 0x10de, 0x0552, "NVIDIA MCP67" },
45 { 0x10de, 0x0553, "NVIDIA MCP67" },
46 { 0x10de, 0x0554, "NVIDIA MCP67" },
47 { 0x10de, 0x0555, "NVIDIA MCP67" },
48 { 0x10de, 0x0556, "NVIDIA MCP67" },
49 { 0x10de, 0x0557, "NVIDIA MCP67" },
50 { 0x10de, 0x0558, "NVIDIA MCP67" },
51 { 0x10de, 0x0559, "NVIDIA MCP67" },
52 { 0x10de, 0x055a, "NVIDIA MCP67" },
53 { 0x10de, 0x055b, "NVIDIA MCP67" },
54 { 0x10de, 0x07f0, "NVIDIA MCP73" },
55 { 0x10de, 0x07f1, "NVIDIA MCP73" },
56 { 0x10de, 0x07f2, "NVIDIA MCP73" },
57 { 0x10de, 0x07f3, "NVIDIA MCP73" },
58 { 0x10de, 0x07f4, "NVIDIA MCP73" },
59 { 0x10de, 0x07f5, "NVIDIA MCP73" },
60 { 0x10de, 0x07f6, "NVIDIA MCP73" },
61 { 0x10de, 0x07f7, "NVIDIA MCP73" },
62 { 0x10de, 0x07f8, "NVIDIA MCP73" },
63 { 0x10de, 0x07f9, "NVIDIA MCP73" },
64 { 0x10de, 0x07fa, "NVIDIA MCP73" },
65 { 0x10de, 0x07fb, "NVIDIA MCP73" },
66 { 0x10de, 0x0ad0, "NVIDIA MCP77" },
67 { 0x10de, 0x0ad1, "NVIDIA MCP77" },
68 { 0x10de, 0x0ad2, "NVIDIA MCP77" },
69 { 0x10de, 0x0ad3, "NVIDIA MCP77" },
70 { 0x10de, 0x0ad4, "NVIDIA MCP77" },
71 { 0x10de, 0x0ad5, "NVIDIA MCP77" },
72 { 0x10de, 0x0ad6, "NVIDIA MCP77" },
73 { 0x10de, 0x0ad7, "NVIDIA MCP77" },
74 { 0x10de, 0x0ad8, "NVIDIA MCP77" },
75 { 0x10de, 0x0ad9, "NVIDIA MCP77" },
76 { 0x10de, 0x0ada, "NVIDIA MCP77" },
77 { 0x10de, 0x0adb, "NVIDIA MCP77" },
78 { 0x10de, 0x0ab4, "NVIDIA MCP79" },
79 { 0x10de, 0x0ab5, "NVIDIA MCP79" },
80 { 0x10de, 0x0ab6, "NVIDIA MCP79" },
81 { 0x10de, 0x0ab7, "NVIDIA MCP79" },
82 { 0x10de, 0x0ab8, "NVIDIA MCP79" },
83 { 0x10de, 0x0ab9, "NVIDIA MCP79" },
84 { 0x10de, 0x0aba, "NVIDIA MCP79" },
85 { 0x10de, 0x0abb, "NVIDIA MCP79" },
86 { 0x10de, 0x0abc, "NVIDIA MCP79" },
87 { 0x10de, 0x0abd, "NVIDIA MCP79" },
88 { 0x10de, 0x0abe, "NVIDIA MCP79" },
89 { 0x10de, 0x0abf, "NVIDIA MCP79" },
90 { 0x10de, 0x0d84, "NVIDIA MCP89" },
91 { 0x10de, 0x0d85, "NVIDIA MCP89" },
92 { 0x10de, 0x0d86, "NVIDIA MCP89" },
93 { 0x10de, 0x0d87, "NVIDIA MCP89" },
94 { 0x10de, 0x0d88, "NVIDIA MCP89" },
95 { 0x10de, 0x0d89, "NVIDIA MCP89" },
96 { 0x10de, 0x0d8a, "NVIDIA MCP89" },
97 { 0x10de, 0x0d8b, "NVIDIA MCP89" },
98 { 0x10de, 0x0d8c, "NVIDIA MCP89" },
99 { 0x10de, 0x0d8d, "NVIDIA MCP89" },
100 { 0x10de, 0x0d8e, "NVIDIA MCP89" },
101 { 0x10de, 0x0d8f, "NVIDIA MCP89" },
102 { 0x1106, 0x3349, "VIA VT8251" },
103 { 0x1106, 0x6287, "VIA VT8251" },
104 { 0x11ab, 0x6121, "Marvell 6121" },
105 { 0x11ab, 0x6145, "Marvell 6145" },
106 { 0x197b, 0x2360, "JMicron JMB360" },
107 { 0x197b, 0x2361, "JMicron JMB361" },
108 { 0x197b, 0x2362, "JMicron JMB362" },
109 { 0x197b, 0x2363, "JMicron JMB363" },
110 { 0x197b, 0x2366, "JMicron JMB366" },
111 { 0x8086, 0x2652, "Intel ICH6R" },
112 { 0x8086, 0x2653, "Intel ICH6-M" },
113 { 0x8086, 0x2681, "Intel 63xxESB" },
114 { 0x8086, 0x2682, "Intel ESB2" },
115 { 0x8086, 0x2683, "Intel ESB2" },
116 { 0x8086, 0x27c1, "Intel ICH7R (AHCI mode)" },
117 { 0x8086, 0x27c3, "Intel ICH7R (RAID mode)" },
118 { 0x8086, 0x27c5, "Intel ICH7-M (AHCI mode)" },
119 { 0x8086, 0x27c6, "Intel ICH7-M DH (RAID mode)" },
120 { 0x8086, 0x2821, "Intel ICH8 (AHCI mode)" },
121 { 0x8086, 0x2822, "Intel ICH8R / ICH9 (RAID mode)" },
122 { 0x8086, 0x2824, "Intel ICH8 (AHCI mode)" },
123 { 0x8086, 0x2829, "Intel ICH8M (AHCI mode)" },
124 { 0x8086, 0x282a, "Intel ICH8M (RAID mode)" },
125 { 0x8086, 0x2922, "Intel ICH9 (AHCI mode)" },
126 { 0x8086, 0x2923, "Intel ICH9 (AHCI mode)" },
127 { 0x8086, 0x2924, "Intel ICH9" },
128 { 0x8086, 0x2925, "Intel ICH9" },
129 { 0x8086, 0x2927, "Intel ICH9" },
130 { 0x8086, 0x2929, "Intel ICH9M" },
131 { 0x8086, 0x292a, "Intel ICH9M" },
132 { 0x8086, 0x292b, "Intel ICH9M" },
133 { 0x8086, 0x292c, "Intel ICH9M" },
134 { 0x8086, 0x292f, "Intel ICH9M" },
135 { 0x8086, 0x294d, "Intel ICH9" },
136 { 0x8086, 0x294e, "Intel ICH9M" },
137 { 0x8086, 0x3a05, "Intel ICH10" },
138 { 0x8086, 0x3a22, "Intel ICH10" },
139 { 0x8086, 0x3a25, "Intel ICH10" },
144 device_manager_info
*gDeviceManager
;
145 scsi_for_sim_interface
*gSCSI
;
146 pci_x86_module_info
* gPCIx86Module
;
150 get_device_info(uint16 vendorID
, uint16 deviceID
, const char **name
,
153 const device_info
*info
;
154 for (info
= kSupportedDevices
; info
->vendor
; info
++) {
155 if (info
->vendor
== vendorID
&& info
->device
== deviceID
) {
159 *flags
= info
->flags
;
168 register_sim(device_node
*parent
)
170 int32 id
= gDeviceManager
->create_id(AHCI_ID_GENERATOR
);
175 device_attr attrs
[] = {
176 { B_DEVICE_FIXED_CHILD
, B_STRING_TYPE
,
177 { string
: SCSI_FOR_SIM_MODULE_NAME
}},
178 { B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
,
179 { string
: AHCI_CONTROLLER_PRETTY_NAME
}},
181 { SCSI_DESCRIPTION_CONTROLLER_NAME
, B_STRING_TYPE
,
182 { string
: AHCI_DEVICE_MODULE_NAME
}},
183 { B_DMA_MAX_TRANSFER_BLOCKS
, B_UINT32_TYPE
, { ui32
: 255 }},
184 { AHCI_ID_ITEM
, B_UINT32_TYPE
, { ui32
: (uint32
)id
}},
185 // { PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE,
186 // { string: AHCI_ID_GENERATOR }},
187 // { PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: id }},
192 status_t status
= gDeviceManager
->register_node(parent
,
193 AHCI_SIM_MODULE_NAME
, attrs
, NULL
, NULL
);
195 gDeviceManager
->free_id(AHCI_ID_GENERATOR
, id
);
206 ahci_supports_device(device_node
*parent
)
208 uint16 baseClass
, subClass
, classAPI
;
214 FLOW("ahci_supports_device\n");
216 if (gDeviceManager
->get_attr_string(parent
, B_DEVICE_BUS
, &bus
, false)
220 if (strcmp(bus
, "pci"))
223 if (gDeviceManager
->get_attr_uint16(parent
, B_DEVICE_TYPE
, &baseClass
,
225 || gDeviceManager
->get_attr_uint16(parent
, B_DEVICE_SUB_TYPE
, &subClass
,
227 || gDeviceManager
->get_attr_uint16(parent
, B_DEVICE_INTERFACE
,
228 &classAPI
, false) < B_OK
229 || gDeviceManager
->get_attr_uint16(parent
, B_DEVICE_VENDOR_ID
,
230 &vendorID
, false) < B_OK
231 || gDeviceManager
->get_attr_uint16(parent
, B_DEVICE_ID
, &deviceID
,
235 if (get_device_info(vendorID
, deviceID
, &name
, NULL
) < B_OK
) {
236 if (baseClass
!= PCI_mass_storage
|| subClass
!= PCI_sata
237 || classAPI
!= PCI_sata_ahci
)
239 TRACE("generic AHCI controller found! vendor 0x%04x, device 0x%04x\n", vendorID
, deviceID
);
243 if (vendorID
== PCI_VENDOR_JMICRON
) {
244 // JMicron uses the same device ID for SATA and PATA controllers,
245 // check if BAR5 exists to determine if it's a AHCI controller
246 pci_device_module_info
*pci
;
250 gDeviceManager
->get_driver(parent
, (driver_module_info
**)&pci
,
252 pci
->get_pci_info(device
, &info
);
254 if (info
.u
.h0
.base_register_sizes
[5] == 0)
258 TRACE("AHCI controller %s found!\n", name
);
264 ahci_register_device(device_node
*parent
)
266 device_attr attrs
[] = {
267 { SCSI_DEVICE_MAX_TARGET_COUNT
, B_UINT32_TYPE
,
269 { B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
,
270 { string
: AHCI_BRIDGE_PRETTY_NAME
}},
273 // data must be word-aligned;
274 { B_DMA_ALIGNMENT
, B_UINT32_TYPE
, { ui32
: 1 }},
275 // one S/G block must not cross 64K boundary
276 { B_DMA_BOUNDARY
, B_UINT32_TYPE
, { ui32
: 0xffff }},
277 // max size of S/G block is 16 bits with zero being 64K
278 { B_DMA_MAX_SEGMENT_BLOCKS
, B_UINT32_TYPE
, { ui32
: 0x10000 }},
279 { B_DMA_MAX_SEGMENT_COUNT
, B_UINT32_TYPE
,
280 { ui32
: 32 /* whatever... */ }},
281 { B_DMA_HIGH_ADDRESS
, B_UINT64_TYPE
, { ui64
: 0x100000000LL
}},
282 // TODO: We don't know at this point whether 64 bit addressing is
283 // supported. That's indicated by a capability flag. Play it safe
288 TRACE("ahci_register_device\n");
290 return gDeviceManager
->register_node(parent
, AHCI_DEVICE_MODULE_NAME
,
296 ahci_init_driver(device_node
*node
, void **_cookie
)
298 TRACE("ahci_init_driver\n");
305 ahci_uninit_driver(void *cookie
)
307 TRACE("ahci_uninit_driver, cookie %p\n", cookie
);
312 ahci_register_child_devices(void *cookie
)
314 device_node
*node
= (device_node
*)cookie
;
316 // TODO: register SIM for every controller we find!
317 return register_sim(node
);
322 ahci_device_removed(void *cookie
)
324 TRACE("ahci_device_removed, cookie %p\n", cookie
);
329 std_ops(int32 op
, ...)
333 if (get_module(B_PCI_X86_MODULE_NAME
,
334 (module_info
**)&gPCIx86Module
) != B_OK
) {
335 TRACE("failed to get pci x86 module\n");
336 gPCIx86Module
= NULL
;
339 case B_MODULE_UNINIT
:
340 if (gPCIx86Module
!= NULL
) {
341 put_module(B_PCI_X86_MODULE_NAME
);
342 gPCIx86Module
= NULL
;
352 driver_module_info sAHCIDevice
= {
354 AHCI_DEVICE_MODULE_NAME
,
358 ahci_supports_device
,
359 ahci_register_device
,
362 ahci_register_child_devices
,
368 module_dependency module_dependencies
[] = {
369 { B_DEVICE_MANAGER_MODULE_NAME
, (module_info
**)&gDeviceManager
},
370 { SCSI_FOR_SIM_MODULE_NAME
, (module_info
**)&gSCSI
},
375 module_info
*modules
[] = {
376 (module_info
*)&sAHCIDevice
,
377 (module_info
*)&gAHCISimInterface
,