xref: /haiku/src/add-ons/kernel/busses/scsi/ahci/ahci.c (revision 1026b0a1a76dc88927bb8175c470f638dc5464ee)
1 /*
2  * Copyright 2007, Marcus Overhagen. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "ahci_defs.h"
7 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 
12 #define TRACE(a...) dprintf("ahci: " a)
13 #define FLOW(a...)	dprintf("ahci: " a)
14 
15 #define AHCI_ID_GENERATOR "ahci/id"
16 #define AHCI_ID_ITEM "ahci/id"
17 #define AHCI_BRIDGE_PRETTY_NAME "AHCI Bridge"
18 #define AHCI_CONTROLLER_PRETTY_NAME "AHCI Controller"
19 
20 
21 const device_info kSupportedDevices[] = {
22 	{ 0x1002, 0x4380, "ATI SB600" },
23 	{ 0x1002, 0x4390, "ATI SB700/800" },
24 	{ 0x1002, 0x4391, "ATI IXP700" },
25 	{ 0x1002, 0x4392, "ATI SB700/800" },
26 	{ 0x1002, 0x4393, "ATI SB700/800" },
27 	{ 0x1002, 0x4394, "ATI SB700/800" },
28 	{ 0x1002, 0x4395, "ATI SB700/800" },
29 	{ 0x1039, 0x1184, "SiS 966" },
30 	{ 0x1039, 0x1185, "SiS 966" },
31 	{ 0x1039, 0x0186, "SiS 968" },
32 	{ 0x10b9, 0x5288, "Acer Labs M5288" },
33 	{ 0x10de, 0x044c, "NVIDIA MCP65" },
34 	{ 0x10de, 0x044d, "NVIDIA MCP65" },
35 	{ 0x10de, 0x044e, "NVIDIA MCP65" },
36 	{ 0x10de, 0x044f, "NVIDIA MCP65" },
37 	{ 0x10de, 0x045c, "NVIDIA MCP65" },
38 	{ 0x10de, 0x045d, "NVIDIA MCP65" },
39 	{ 0x10de, 0x045e, "NVIDIA MCP65" },
40 	{ 0x10de, 0x045f, "NVIDIA MCP65" },
41 	{ 0x10de, 0x0550, "NVIDIA MCP67" },
42 	{ 0x10de, 0x0551, "NVIDIA MCP67" },
43 	{ 0x10de, 0x0552, "NVIDIA MCP67" },
44 	{ 0x10de, 0x0553, "NVIDIA MCP67" },
45 	{ 0x10de, 0x0554, "NVIDIA MCP67" },
46 	{ 0x10de, 0x0555, "NVIDIA MCP67" },
47 	{ 0x10de, 0x0556, "NVIDIA MCP67" },
48 	{ 0x10de, 0x0557, "NVIDIA MCP67" },
49 	{ 0x10de, 0x0558, "NVIDIA MCP67" },
50 	{ 0x10de, 0x0559, "NVIDIA MCP67" },
51 	{ 0x10de, 0x055a, "NVIDIA MCP67" },
52 	{ 0x10de, 0x055b, "NVIDIA MCP67" },
53 	{ 0x10de, 0x07f0, "NVIDIA MCP73" },
54 	{ 0x10de, 0x07f1, "NVIDIA MCP73" },
55 	{ 0x10de, 0x07f2, "NVIDIA MCP73" },
56 	{ 0x10de, 0x07f3, "NVIDIA MCP73" },
57 	{ 0x10de, 0x07f4, "NVIDIA MCP73" },
58 	{ 0x10de, 0x07f5, "NVIDIA MCP73" },
59 	{ 0x10de, 0x07f6, "NVIDIA MCP73" },
60 	{ 0x10de, 0x07f7, "NVIDIA MCP73" },
61 	{ 0x10de, 0x07f8, "NVIDIA MCP73" },
62 	{ 0x10de, 0x07f9, "NVIDIA MCP73" },
63 	{ 0x10de, 0x07fa, "NVIDIA MCP73" },
64 	{ 0x10de, 0x07fb, "NVIDIA MCP73" },
65 	{ 0x10de, 0x0ad0, "NVIDIA MCP77" },
66 	{ 0x10de, 0x0ad1, "NVIDIA MCP77" },
67 	{ 0x10de, 0x0ad2, "NVIDIA MCP77" },
68 	{ 0x10de, 0x0ad3, "NVIDIA MCP77" },
69 	{ 0x10de, 0x0ad4, "NVIDIA MCP77" },
70 	{ 0x10de, 0x0ad5, "NVIDIA MCP77" },
71 	{ 0x10de, 0x0ad6, "NVIDIA MCP77" },
72 	{ 0x10de, 0x0ad7, "NVIDIA MCP77" },
73 	{ 0x10de, 0x0ad8, "NVIDIA MCP77" },
74 	{ 0x10de, 0x0ad9, "NVIDIA MCP77" },
75 	{ 0x10de, 0x0ada, "NVIDIA MCP77" },
76 	{ 0x10de, 0x0adb, "NVIDIA MCP77" },
77 	{ 0x10de, 0x0ab4, "NVIDIA MCP79" },
78 	{ 0x10de, 0x0ab5, "NVIDIA MCP79" },
79 	{ 0x10de, 0x0ab6, "NVIDIA MCP79" },
80 	{ 0x10de, 0x0ab7, "NVIDIA MCP79" },
81 	{ 0x10de, 0x0ab8, "NVIDIA MCP79" },
82 	{ 0x10de, 0x0ab9, "NVIDIA MCP79" },
83 	{ 0x10de, 0x0aba, "NVIDIA MCP79" },
84 	{ 0x10de, 0x0abb, "NVIDIA MCP79" },
85 	{ 0x10de, 0x0abc, "NVIDIA MCP79" },
86 	{ 0x10de, 0x0abd, "NVIDIA MCP79" },
87 	{ 0x10de, 0x0abe, "NVIDIA MCP79" },
88 	{ 0x10de, 0x0abf, "NVIDIA MCP79" },
89 	{ 0x10de, 0x0d84, "NVIDIA MCP89" },
90 	{ 0x10de, 0x0d85, "NVIDIA MCP89" },
91 	{ 0x10de, 0x0d86, "NVIDIA MCP89" },
92 	{ 0x10de, 0x0d87, "NVIDIA MCP89" },
93 	{ 0x10de, 0x0d88, "NVIDIA MCP89" },
94 	{ 0x10de, 0x0d89, "NVIDIA MCP89" },
95 	{ 0x10de, 0x0d8a, "NVIDIA MCP89" },
96 	{ 0x10de, 0x0d8b, "NVIDIA MCP89" },
97 	{ 0x10de, 0x0d8c, "NVIDIA MCP89" },
98 	{ 0x10de, 0x0d8d, "NVIDIA MCP89" },
99 	{ 0x10de, 0x0d8e, "NVIDIA MCP89" },
100 	{ 0x10de, 0x0d8f, "NVIDIA MCP89" },
101 	{ 0x1106, 0x3349, "VIA VT8251" },
102 	{ 0x1106, 0x6287, "VIA VT8251" },
103 	{ 0x11ab, 0x6121, "Marvell 6121" },
104 	{ 0x11ab, 0x6145, "Marvell 6145" },
105 	{ 0x197b, 0x2360, "JMicron JMB360" },
106 	{ 0x197b, 0x2361, "JMicron JMB361" },
107 	{ 0x197b, 0x2362, "JMicron JMB362" },
108 	{ 0x197b, 0x2363, "JMicron JMB363" },
109 	{ 0x197b, 0x2366, "JMicron JMB366" },
110 	{ 0x8086, 0x2652, "Intel ICH6R" },
111 	{ 0x8086, 0x2653, "Intel ICH6-M" },
112 	{ 0x8086, 0x2681, "Intel 63xxESB" },
113 	{ 0x8086, 0x2682, "Intel ESB2" },
114 	{ 0x8086, 0x2683, "Intel ESB2" },
115 	{ 0x8086, 0x27c1, "Intel ICH7R (AHCI mode)" },
116 	{ 0x8086, 0x27c3, "Intel ICH7R (RAID mode)" },
117 	{ 0x8086, 0x27c5, "Intel ICH7-M (AHCI mode)" },
118 	{ 0x8086, 0x27c6, "Intel ICH7-M DH (RAID mode)" },
119 	{ 0x8086, 0x2821, "Intel ICH8 (AHCI mode)" },
120 	{ 0x8086, 0x2822, "Intel ICH8R / ICH9 (RAID mode)" },
121 	{ 0x8086, 0x2824, "Intel ICH8 (AHCI mode)" },
122 	{ 0x8086, 0x2829, "Intel ICH8M (AHCI mode)" },
123 	{ 0x8086, 0x282a, "Intel ICH8M (RAID mode)" },
124 	{ 0x8086, 0x2922, "Intel ICH9 (AHCI mode)" },
125 	{ 0x8086, 0x2923, "Intel ICH9 (AHCI mode)" },
126 	{ 0x8086, 0x2924, "Intel ICH9" },
127 	{ 0x8086, 0x2925, "Intel ICH9" },
128 	{ 0x8086, 0x2927, "Intel ICH9" },
129 	{ 0x8086, 0x2929, "Intel ICH9M" },
130 	{ 0x8086, 0x292a, "Intel ICH9M" },
131 	{ 0x8086, 0x292b, "Intel ICH9M" },
132 	{ 0x8086, 0x292c, "Intel ICH9M" },
133 	{ 0x8086, 0x292f, "Intel ICH9M" },
134 	{ 0x8086, 0x294d, "Intel ICH9" },
135 	{ 0x8086, 0x294e, "Intel ICH9M" },
136 	{ 0x8086, 0x3a05, "Intel ICH10" },
137 	{ 0x8086, 0x3a22, "Intel ICH10" },
138 	{ 0x8086, 0x3a25, "Intel ICH10" },
139 	{}
140 };
141 
142 
143 device_manager_info *gDeviceManager;
144 scsi_for_sim_interface *gSCSI;
145 
146 
147 status_t
148 get_device_info(uint16 vendorID, uint16 deviceID, const char **name,
149 	uint32 *flags)
150 {
151 	const device_info *info;
152 	for (info = kSupportedDevices; info->vendor; info++) {
153 		if (info->vendor == vendorID && info->device == deviceID) {
154 			if (name)
155 				*name = info->name;
156 			if (flags)
157 				*flags = info->flags;
158 			return B_OK;
159 		}
160 	}
161 	return B_ERROR;
162 }
163 
164 
165 static status_t
166 register_sim(device_node *parent)
167 {
168 	int32 id = gDeviceManager->create_id(AHCI_ID_GENERATOR);
169 	if (id < 0)
170 		return id;
171 
172 	{
173 		device_attr attrs[] = {
174 			{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
175 				{ string: SCSI_FOR_SIM_MODULE_NAME }},
176 			{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
177 				{ string: AHCI_CONTROLLER_PRETTY_NAME }},
178 
179 			{ SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE,
180 				{ string: AHCI_DEVICE_MODULE_NAME }},
181 			{ B_DMA_MAX_TRANSFER_BLOCKS, B_UINT32_TYPE, { ui32: 255 }},
182 			{ AHCI_ID_ITEM, B_UINT32_TYPE, { ui32: id }},
183 //			{ PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE,
184 //				{ string: AHCI_ID_GENERATOR }},
185 //			{ PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: id }},
186 
187 			{ NULL }
188 		};
189 
190 		status_t status = gDeviceManager->register_node(parent,
191 			AHCI_SIM_MODULE_NAME, attrs, NULL, NULL);
192 		if (status < B_OK)
193 			gDeviceManager->free_id(AHCI_ID_GENERATOR, id);
194 
195 		return status;
196 	}
197 }
198 
199 
200 //	#pragma mark -
201 
202 
203 static float
204 ahci_supports_device(device_node *parent)
205 {
206 	uint16 baseClass, subClass, classAPI;
207 	uint16 vendorID;
208 	uint16 deviceID;
209 	const char *name;
210 	const char *bus;
211 
212 	TRACE("ahci_supports_device\n");
213 
214 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
215 			< B_OK)
216 		return 0.0f;
217 
218 	if (strcmp(bus, "pci"))
219 		return 0.0f;
220 
221 	if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &baseClass,
222 				false) < B_OK
223 		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subClass,
224 				false) < B_OK
225 		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_INTERFACE,
226 				&classAPI, false) < B_OK
227 		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID,
228 				&vendorID, false) < B_OK
229 		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID,
230 				false) < B_OK)
231 		return 0.0f;
232 
233 	if (get_device_info(vendorID, deviceID, &name, NULL) < B_OK) {
234 		if (baseClass != PCI_mass_storage || subClass != PCI_sata
235 			|| classAPI != PCI_sata_ahci)
236 			return 0.0f;
237 		TRACE("generic AHCI controller found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID);
238 		return 0.8f;
239 	}
240 
241 	if (vendorID == PCI_VENDOR_JMICRON) {
242 		// JMicron uses the same device ID for SATA and PATA controllers,
243 		// check if BAR5 exists to determine if it's a AHCI controller
244 		pci_device_module_info *pci;
245 		pci_device *device;
246 		pci_info info;
247 
248 		gDeviceManager->get_driver(parent, (driver_module_info **)&pci,
249 			(void **)&device);
250 		pci->get_pci_info(device, &info);
251 
252 		if (info.u.h0.base_register_sizes[5] == 0)
253 			return 0.0f;
254 	}
255 
256 	TRACE("AHCI controller %s found!\n", name);
257 	return 1.0f;
258 }
259 
260 
261 static status_t
262 ahci_register_device(device_node *parent)
263 {
264 	device_attr attrs[] = {
265 		{ SCSI_DEVICE_MAX_TARGET_COUNT, B_UINT32_TYPE,
266 			{ ui32: 33 }},
267 		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
268 			{ string: AHCI_BRIDGE_PRETTY_NAME }},
269 
270 		// DMA properties
271 		// data must be word-aligned;
272 		{ B_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: 1 }},
273 		// one S/G block must not cross 64K boundary
274 		{ B_DMA_BOUNDARY, B_UINT32_TYPE, { ui32: 0xffff }},
275 		// max size of S/G block is 16 bits with zero being 64K
276 		{ B_DMA_MAX_SEGMENT_BLOCKS, B_UINT32_TYPE, { ui32: 0x10000 }},
277 		{ B_DMA_MAX_SEGMENT_COUNT, B_UINT32_TYPE,
278 			{ ui32: 32 /* whatever... */ }},
279 		{ B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { ui64: 0x100000000LL }},
280 			// TODO: We don't know at this point whether 64 bit addressing is
281 			// supported. That's indicated by a capability flag. Play it safe
282 			// for now.
283 		{ NULL }
284 	};
285 
286 	TRACE("ahci_register_device\n");
287 
288 	return gDeviceManager->register_node(parent, AHCI_DEVICE_MODULE_NAME,
289 		attrs, NULL, NULL);
290 }
291 
292 
293 static status_t
294 ahci_init_driver(device_node *node, void **_cookie)
295 {
296 	TRACE("ahci_init_driver\n");
297 	*_cookie = node;
298 	return B_OK;
299 }
300 
301 
302 static void
303 ahci_uninit_driver(void *cookie)
304 {
305 	TRACE("ahci_uninit_driver, cookie %p\n", cookie);
306 }
307 
308 
309 static status_t
310 ahci_register_child_devices(void *cookie)
311 {
312 	device_node *node = (device_node *)cookie;
313 
314 	// TODO: register SIM for every controller we find!
315 	return register_sim(node);
316 }
317 
318 
319 static void
320 ahci_device_removed(void *cookie)
321 {
322 	TRACE("ahci_device_removed, cookie %p\n", cookie);
323 }
324 
325 
326 static status_t
327 std_ops(int32 op, ...)
328 {
329 	switch (op) {
330 		case B_MODULE_INIT:
331 		case B_MODULE_UNINIT:
332 			return B_OK;
333 
334 		default:
335 			return B_ERROR;
336 	}
337 }
338 
339 
340 driver_module_info sAHCIDevice = {
341 	{
342 		AHCI_DEVICE_MODULE_NAME,
343 		0,
344 		std_ops
345 	},
346 	ahci_supports_device,
347 	ahci_register_device,
348 	ahci_init_driver,
349 	ahci_uninit_driver,
350 	ahci_register_child_devices,
351 	NULL,	// rescan
352 	ahci_device_removed
353 };
354 
355 
356 module_dependency module_dependencies[] = {
357 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
358 	{ SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSI },
359 	{}
360 };
361 
362 
363 module_info *modules[] = {
364 	(module_info *)&sAHCIDevice,
365 	(module_info *)&gAHCISimInterface,
366 	NULL
367 };
368