xref: /haiku/src/add-ons/kernel/busses/ata/highpoint_ide_pci/highpoint_ide_pci.cpp (revision a2b91af97b0b10c13af98b357e754833a5db80cc)
1 /*
2  * Copyright 2017, Alexander Coers. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 #include "highpoint_ata.h"
6 
7 #include <ata_adapter.h>
8 #include <malloc.h>
9 #include <KernelExport.h>
10 
11 #include <stdlib.h>
12 #include <string.h>
13 
14 
15 #define INFO(a...)			dprintf("Highpoint-IDE: " a)
16 
17 //#define TRACE_HIGHPOINT
18 #ifdef TRACE_HIGHPOINT
19 #define TRACE(a...)		dprintf("Highpoint-IDE: " a)
20 #define TRACE_ONLY
21 #else
22 #define TRACE(a...)
23 #define TRACE_ONLY __attribute__((unused))
24 #endif
25 
26 
27 #define HIGHPOINT_IDE_PCI_CONTROLLER_MODULE_NAME "busses/ata/highpoint_ide_pci/driver_v1"
28 #define HIGHPOINT_IDE_PCI_CHANNEL_MODULE_NAME    "busses/ata/highpoint_ide_pci/channel/v1"
29 
30 
31 static ata_for_controller_interface *sATA;
32 static ata_adapter_interface *sATAAdapter;
33 static device_manager_info *sDeviceManager;
34 
35 struct HPT_controller_info *HPT_info;
36 
37 
38 // #pragma mark - helper functions
39 
40 
41 static void
set_channel(void * cookie,ata_channel channel)42 set_channel(void *cookie, ata_channel channel)
43 {
44 	TRACE("set_channel()\n");
45 
46 	sATAAdapter->set_channel((ata_adapter_channel_info *)cookie, channel);
47 }
48 
49 
50 static status_t
write_command_block_regs(void * channel_cookie,ata_task_file * tf,ata_reg_mask mask)51 write_command_block_regs(void *channel_cookie, ata_task_file *tf,
52 	ata_reg_mask mask)
53 {
54 	TRACE("write_command_block_regs()\n");
55 
56 	return sATAAdapter->write_command_block_regs(
57 		(ata_adapter_channel_info *)channel_cookie, tf, mask);
58 }
59 
60 
61 static status_t
read_command_block_regs(void * channel_cookie,ata_task_file * tf,ata_reg_mask mask)62 read_command_block_regs(void *channel_cookie, ata_task_file *tf,
63 	ata_reg_mask mask)
64 {
65 	TRACE("read_command_block_regs()\n");
66 
67 	return sATAAdapter->read_command_block_regs(
68 		(ata_adapter_channel_info *)channel_cookie, tf, mask);
69 }
70 
71 
72 static uint8
get_altstatus(void * channel_cookie)73 get_altstatus(void *channel_cookie)
74 {
75 	TRACE("get_altstatus()\n");
76 
77 	return sATAAdapter->get_altstatus(
78 		(ata_adapter_channel_info *)channel_cookie);
79 }
80 
81 
82 static status_t
write_device_control(void * channel_cookie,uint8 val)83 write_device_control(void *channel_cookie, uint8 val)
84 {
85 	TRACE("write_device_control()\n");
86 
87 	return sATAAdapter->write_device_control(
88 		(ata_adapter_channel_info *)channel_cookie, val);
89 }
90 
91 
92 static status_t
write_pio(void * channel_cookie,uint16 * data,int count,bool force_16bit)93 write_pio(void *channel_cookie, uint16 *data, int count, bool force_16bit)
94 {
95 	TRACE("write_pio()\n");
96 
97 	return sATAAdapter->write_pio((ata_adapter_channel_info *)channel_cookie,
98 		data, count, force_16bit);
99 }
100 
101 
102 static status_t
read_pio(void * channel_cookie,uint16 * data,int count,bool force_16bit)103 read_pio(void *channel_cookie, uint16 *data, int count, bool force_16bit)
104 {
105 	TRACE("read_pio()\n");
106 
107 	return sATAAdapter->read_pio((ata_adapter_channel_info *)channel_cookie,
108 		data, count, force_16bit);
109 }
110 
111 
112 static status_t
prepare_dma(void * channel_cookie,const physical_entry * sg_list,size_t sg_list_count,bool to_device)113 prepare_dma(void *channel_cookie, const physical_entry *sg_list,
114 	size_t sg_list_count, bool to_device)
115 {
116 	TRACE("prepare_dma()\n");
117 
118 	return sATAAdapter->prepare_dma((ata_adapter_channel_info *)channel_cookie,
119 		sg_list, sg_list_count, to_device);
120 }
121 
122 
123 static status_t
start_dma(void * channel_cookie)124 start_dma(void *channel_cookie)
125 {
126 	TRACE("start_dma()\n");
127 
128 	return sATAAdapter->start_dma((ata_adapter_channel_info *)channel_cookie);
129 }
130 
131 
132 static status_t
finish_dma(void * channel_cookie)133 finish_dma(void *channel_cookie)
134 {
135 	TRACE("finish_dma()\n");
136 
137 	return sATAAdapter->finish_dma((ata_adapter_channel_info *)channel_cookie);
138 }
139 
140 
141 static status_t
init_channel(device_node * node,void ** channel_cookie)142 init_channel(device_node *node, void **channel_cookie)
143 {
144 	status_t result;
145 	uint8 channel_index;
146 
147 	TRACE("init_channel(): node: %p, cookie: %p\n", node, channel_cookie);
148 
149 #if 0 /* debug */
150 	uint8 bus = 0, device = 0, function = 0;
151 	uint16 vendorID=0xffff, deviceID=0xffff;
152 	sDeviceManager->get_attr_uint16(node, B_DEVICE_VENDOR_ID, &vendorID, true);
153 	sDeviceManager->get_attr_uint16(node, B_DEVICE_ID, &deviceID, true);
154 	TRACE("init_channel():init_channel(): bus %3d, device %2d, function %2d: vendor %04x, device %04x\n",
155 		bus, device, function, vendorID, deviceID);
156 	if (vendorID != ATA_HIGHPOINT_ID) {
157 		TRACE ("unsupported! Vendor ID: %x\n",vendorID);
158 		return B_ERROR;
159 	}
160 #endif
161 
162 	result = sATAAdapter->init_channel(node,
163 		(ata_adapter_channel_info **)channel_cookie,
164 		sizeof(ata_adapter_channel_info), sATAAdapter->inthand);
165 	// from here we have valid channel...
166 	ata_adapter_channel_info *channel TRACE_ONLY = NULL;
167 	channel = (ata_adapter_channel_info *)*channel_cookie;
168 
169 	if (sDeviceManager->get_attr_uint8(node, ATA_ADAPTER_CHANNEL_INDEX,
170 			&channel_index, false) != B_OK)  {
171 		TRACE("init_channel(): channel not set, strange!\n");
172 		return B_ERROR;
173 	}
174 
175 	TRACE("init_channel(): channel command %x, control %x, result: %d \n",
176 		channel->command_block_base,
177 		channel->control_block_base, (int)result);
178 	TRACE("init_channel(): index #%d done. HPT_info deviceID: %04x, config option %x, "
179 		"revision %2d, function %2d \n", channel_index, HPT_info->deviceID,
180 		HPT_info->configOption, HPT_info->revisionID, HPT_info->function);
181 	return result;
182 }
183 
184 
185 static void
uninit_channel(void * channel_cookie)186 uninit_channel(void *channel_cookie)
187 {
188 	TRACE("uninit_channel()\n");
189 
190 	sATAAdapter->uninit_channel((ata_adapter_channel_info *)channel_cookie);
191 }
192 
193 
194 static void
channel_removed(void * channel_cookie)195 channel_removed(void *channel_cookie)
196 {
197 	TRACE("channel_removed()\n");
198 
199 	sATAAdapter->channel_removed((ata_adapter_channel_info *)channel_cookie);
200 }
201 
202 
203 static status_t
init_controller(device_node * node,ata_adapter_controller_info ** cookie)204 init_controller(device_node *node, ata_adapter_controller_info **cookie)
205 {
206 	pci_device_module_info *pci;
207 	pci_device *pci_device;
208 	pci_info info;
209 	uint16 devID = 0xffff;
210 	uint8 revisionID = 0xff;
211 	uint8 function = 0xff;
212 
213 	status_t result;
214 
215 	// we need some our info structure here
216 	HPT_info = (struct HPT_controller_info *) malloc(sizeof(HPT_controller_info));
217 	if (HPT_info == NULL)
218 		return B_NO_MEMORY;
219 
220 	result = sATAAdapter->init_controller(node, cookie,
221 		sizeof(ata_adapter_controller_info));
222 
223 	if (result == B_OK) {
224 		// get device info
225 		device_node *parent = sDeviceManager->get_parent_node(node);
226 		sDeviceManager->get_driver(parent, (driver_module_info **)&pci, (void **)&pci_device);
227 		// read registers
228 		pci->get_pci_info(pci_device,&info);
229 		devID = info.device_id;
230 		revisionID = info.revision;
231 		function = info.function;
232 
233 		HPT_info->deviceID = devID;
234 		HPT_info->revisionID = revisionID;
235 		HPT_info->function = function;
236 
237 		INFO("found: device: %x, revision: %x, function: %x\n",devID,revisionID,function);
238 
239 		// setting different config options
240 		if (devID == ATA_HPT366) {
241 			switch (revisionID) {
242 			case 0:
243 				HPT_info->configOption = CFG_HPT366_OLD;
244 				HPT_info->maxDMA = ATA_ULTRA_DMA4;
245 				break;
246 			case 1:
247 			case 2:
248 				HPT_info->configOption = CFG_HPT366;
249 				HPT_info->maxDMA = ATA_ULTRA_DMA4;
250 				break;
251 			case 3:
252 				HPT_info->configOption = CFG_HPT370;
253 				HPT_info->maxDMA = ATA_ULTRA_DMA5;
254 				break;
255 			case 5:
256 				HPT_info->configOption = CFG_HPT372;
257 				HPT_info->maxDMA = ATA_ULTRA_DMA6;
258 				break;
259 			default:
260 				HPT_info->configOption = CFG_HPTUnknown;
261 				HPT_info->maxDMA = ATA_ULTRA_DMA0;
262 			}
263 		} else {
264 			if (devID == ATA_HPT374) {
265 				HPT_info->configOption = CFG_HPT374;
266 				HPT_info->maxDMA = ATA_ULTRA_DMA6;
267 			} else {
268 				// all other versions use this config
269 				HPT_info->configOption = CFG_HPT372;
270 				HPT_info->maxDMA = ATA_ULTRA_DMA6;
271 			}
272 		}
273 
274 		if (HPT_info->configOption == CFG_HPT366_OLD) {
275 			/* disable interrupt prediction */
276 			pci->write_pci_config(pci_device, 0x51, 1, (pci->read_pci_config(pci_device, 0x51, 1) & ~0x80));
277 			INFO("Highpoint-ATA: old revision found.\n");
278 	    } else {
279 			/* disable interrupt prediction */
280 			pci->write_pci_config(pci_device, 0x51, 1, (pci->read_pci_config(pci_device, 0x51, 1) & ~0x03));
281 			pci->write_pci_config(pci_device, 0x55, 1, (pci->read_pci_config(pci_device, 0x55, 1) & ~0x03));
282 
283 			/* enable interrupts */
284 			pci->write_pci_config(pci_device, 0x5a, 1, (pci->read_pci_config(pci_device, 0x5a, 1) & ~0x10));
285 
286 			/* set clocks etc */
287 			if (HPT_info->configOption < CFG_HPT372) {
288     			pci->write_pci_config(pci_device, 0x5b, 1, 0x22);
289 	    	} else {
290     			pci->write_pci_config(pci_device, 0x5b, 1,
291 		     		(pci->read_pci_config(pci_device, 0x5b, 1) & 0x01) | 0x20);
292 	    	}
293 		}
294 	}
295 	return result;
296 }
297 
298 
299 static void
uninit_controller(ata_adapter_controller_info * controller)300 uninit_controller(ata_adapter_controller_info *controller)
301 {
302 	TRACE("uninit_controller()\n");
303 	free(HPT_info);
304 	sATAAdapter->uninit_controller(controller);
305 }
306 
307 
308 static void
controller_removed(ata_adapter_controller_info * controller)309 controller_removed(ata_adapter_controller_info *controller)
310 {
311 	TRACE("controller_removed()\n");
312 
313 	return sATAAdapter->controller_removed(controller);
314 }
315 
316 
317 static status_t
probe_controller(device_node * parent)318 probe_controller(device_node *parent)
319 {
320 	status_t result;
321 	result = sATAAdapter->probe_controller(parent,
322 		HIGHPOINT_IDE_PCI_CONTROLLER_MODULE_NAME, "highpoint_ide_pci",
323 		"Highpoint IDE PCI Controller",
324 		HIGHPOINT_IDE_PCI_CHANNEL_MODULE_NAME,
325 		true,
326 		true,					// assume that command queuing works
327 		1,						// assume 16 bit alignment is enough
328 		0xffff,					// boundary is on 64k according to spec
329 		0x10000,				// up to 64k per S/G block according to spec
330 		false);					// by default, compatibility mode is used, not for HPT!
331 
332 	TRACE("probe_controller(): probe result: %x\n",(int)result);
333 	return result;
334 }
335 
336 
337 static float
supports_device(device_node * parent)338 supports_device(device_node *parent)
339 {
340 	TRACE("supports_device()\n");
341 
342 	const char *bus;
343 	uint16 baseClass, subClass;
344 	uint16 vendorID;
345 	uint16 deviceID;
346 	float result = -1.0f;
347 
348 	// make sure parent is an PCI IDE mass storage host adapter device node
349 	if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK
350 		|| sDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &baseClass, false) != B_OK
351 		|| sDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subClass, false) != B_OK
352 		|| sDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, &vendorID, false) != B_OK
353 		|| sDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID, false) != B_OK)
354 		return -1.0f;
355 
356 	// No PCI bus OR no mass storage OR no Highpoint device = bail out
357 	if (vendorID != ATA_HIGHPOINT_ID) {
358 		TRACE("supports_device(): unsupported device: vendor ID: %x, deviceID: %x\n",vendorID, deviceID);
359 		return 0.0f;
360 	}
361 
362 	// check if mass storage controller
363 	if ((subClass == PCI_ide) || (subClass == PCI_mass_storage_other)) {
364 		switch (deviceID) {
365  		case ATA_HPT302:
366  			// UDMA 6
367  		case ATA_HPT366:
368  			// UDMA 4, Rev 0 & 2
369  			// UDMA 5, Rev 3
370  		 	// UDMA 6, Rev 5
371  		case ATA_HPT371:
372  		case ATA_HPT372:
373  		case ATA_HPT374:
374  			// UDMA 6
375 			result = 1.0f;
376 			break;
377 		default:
378 			// device not supported, should be covered by generic ata driver
379 			result = 0.0f;
380 		}
381 	}
382 	INFO("supporting device Vendor ID: %x, deviceID: %x, result %f\n", vendorID, deviceID, result);
383 	return result;
384 }
385 
386 // #pragma mark - module dependencies
387 
388 module_dependency module_dependencies[] = {
389 	{ ATA_FOR_CONTROLLER_MODULE_NAME, (module_info **)&sATA },
390 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
391 	{ ATA_ADAPTER_MODULE_NAME, (module_info **)&sATAAdapter },
392 	{}
393 };
394 
395 
396 static ata_controller_interface channel_interface = {
397 	{
398 		{
399 			HIGHPOINT_IDE_PCI_CHANNEL_MODULE_NAME,
400 			0,
401 			NULL
402 		},
403 
404 		NULL,	// supports device
405 		NULL,	// register device
406 		init_channel,
407 		uninit_channel,
408 		NULL,	// register child devices
409 		NULL,	// rescan
410 		channel_removed,
411 	},
412 
413 	&set_channel,
414 
415 	&write_command_block_regs,
416 	&read_command_block_regs,
417 
418 	&get_altstatus,
419 	&write_device_control,
420 
421 	&write_pio,
422 	&read_pio,
423 
424 	&prepare_dma,
425 	&start_dma,
426 	&finish_dma,
427 };
428 
429 
430 static driver_module_info controller_interface = {
431 	{
432 		HIGHPOINT_IDE_PCI_CONTROLLER_MODULE_NAME,
433 		0,
434 		NULL
435 	},
436 
437 	supports_device,
438 	probe_controller,
439 	(status_t (*)(device_node *, void **))	init_controller,
440 	(void (*)(void *))						uninit_controller,
441 	NULL,	// register child devices
442 	NULL,	// rescan
443 	(void (*)(void *))						controller_removed,
444 };
445 
446 module_info *modules[] = {
447 	(module_info *)&controller_interface,
448 	(module_info *)&channel_interface,
449 	NULL
450 };
451