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