1/*
2 * Copyright 2002/03, Thomas Kurschel. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6/*!	Generic PCI bus mastering IDE driver. */
7
8#include <KernelExport.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include <ide_adapter.h>
13
14#define GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME "busses/ide/generic_ide_pci/driver_v1"
15#define GENERIC_IDE_PCI_CHANNEL_MODULE_NAME "busses/ide/generic_ide_pci/channel/v1"
16
17#define IDE_PCI_CONTROLLER_TYPE_NAME "ide pci controller"
18
19ide_for_controller_interface *ide;
20static ide_adapter_interface *ide_adapter;
21device_manager_info *pnp;
22
23
24static void
25set_channel(void *cookie, ide_channel channel)
26{
27	ide_adapter->set_channel((ide_adapter_channel_info *)cookie, channel);
28}
29
30
31static status_t
32write_command_block_regs(void *channel_cookie, ide_task_file *tf, ide_reg_mask mask)
33{
34	return ide_adapter->write_command_block_regs((ide_adapter_channel_info *)channel_cookie, tf, mask);
35}
36
37
38static status_t
39read_command_block_regs(void *channel_cookie, ide_task_file *tf, ide_reg_mask mask)
40{
41	return ide_adapter->read_command_block_regs((ide_adapter_channel_info *)channel_cookie, tf, mask);
42}
43
44
45static uint8
46get_altstatus(void *channel_cookie)
47{
48	return ide_adapter->get_altstatus((ide_adapter_channel_info *)channel_cookie);
49}
50
51
52static status_t
53write_device_control(void *channel_cookie, uint8 val)
54{
55	return ide_adapter->write_device_control((ide_adapter_channel_info *)channel_cookie, val);
56}
57
58
59static status_t
60write_pio(void *channel_cookie, uint16 *data, int count, bool force_16bit)
61{
62	return ide_adapter->write_pio((ide_adapter_channel_info *)channel_cookie, data, count, force_16bit);
63}
64
65
66static status_t
67read_pio(void *channel_cookie, uint16 *data, int count, bool force_16bit)
68{
69	return ide_adapter->read_pio((ide_adapter_channel_info *)channel_cookie, data, count, force_16bit);
70}
71
72
73static status_t
74prepare_dma(void *channel_cookie,
75	const physical_entry *sg_list, size_t sg_list_count,
76	bool to_device)
77{
78	return ide_adapter->prepare_dma((ide_adapter_channel_info *)channel_cookie, sg_list, sg_list_count, to_device);
79}
80
81
82static status_t
83start_dma(void *channel_cookie)
84{
85	return ide_adapter->start_dma((ide_adapter_channel_info *)channel_cookie);
86}
87
88
89static status_t
90finish_dma(void *channel_cookie)
91{
92	return ide_adapter->finish_dma((ide_adapter_channel_info *)channel_cookie);
93}
94
95
96static status_t
97init_channel(device_node *node, void **channel_cookie)
98{
99	return ide_adapter->init_channel(node,
100		(ide_adapter_channel_info **)channel_cookie,
101		sizeof(ide_adapter_channel_info), ide_adapter->inthand);
102}
103
104
105static void
106uninit_channel(void *channel_cookie)
107{
108	ide_adapter->uninit_channel((ide_adapter_channel_info *)channel_cookie);
109}
110
111
112static void
113channel_removed(void *channel_cookie)
114{
115	ide_adapter->channel_removed((ide_adapter_channel_info *)channel_cookie);
116}
117
118
119static status_t
120init_controller(device_node *node, ide_adapter_controller_info **cookie)
121{
122	return ide_adapter->init_controller(node, cookie,
123		sizeof( ide_adapter_controller_info));
124}
125
126
127static void
128uninit_controller(ide_adapter_controller_info *controller)
129{
130	ide_adapter->uninit_controller(controller);
131}
132
133
134static void
135controller_removed(ide_adapter_controller_info *controller)
136{
137	return ide_adapter->controller_removed(controller);
138}
139
140
141static status_t
142probe_controller(device_node *parent)
143{
144	return ide_adapter->probe_controller(parent,
145		GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME, "generic_ide_pci",
146		"Generic IDE PCI Controller",
147		GENERIC_IDE_PCI_CHANNEL_MODULE_NAME,
148		true,
149		true,					// assume that command queuing works
150		1,						// assume 16 bit alignment is enough
151		0xffff,					// boundary is on 64k according to spec
152		0x10000,				// up to 64k per S/G block according to spec
153		true);					// by default, compatibility mode is used
154}
155
156
157static float
158supports_device(device_node *parent)
159{
160	const char *bus;
161	uint16 baseClass, subClass;
162
163	// make sure parent is an PCI IDE mass storage host adapter device node
164	if (pnp->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK
165		|| pnp->get_attr_uint16(parent, B_DEVICE_TYPE, &baseClass, false) != B_OK
166		|| pnp->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subClass, false) != B_OK)
167		return -1;
168
169	if (strcmp(bus, "pci") || baseClass != PCI_mass_storage)
170		return 0.0f;
171
172	if (subClass == PCI_ide)
173		return 0.3f;
174
175	// vendor 105a: Promise Technology, Inc.; device 4d69: 20269 (Ultra133TX2)
176	// has subClass set to PCI_mass_storage_other, and there are others as well.
177	if (subClass == PCI_mass_storage_other)
178		return 0.3f;
179
180	return 0.0f;
181}
182
183
184module_dependency module_dependencies[] = {
185	{ IDE_FOR_CONTROLLER_MODULE_NAME, (module_info **)&ide },
186	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
187	{ IDE_ADAPTER_MODULE_NAME, (module_info **)&ide_adapter },
188	{}
189};
190
191
192// exported interface
193static ide_controller_interface channel_interface = {
194	{
195		{
196			GENERIC_IDE_PCI_CHANNEL_MODULE_NAME,
197			0,
198			NULL
199		},
200
201		NULL,	// supports device
202		NULL,	// register device
203		init_channel,
204		uninit_channel,
205		NULL,	// register child devices
206		NULL,	// rescan
207		channel_removed,
208	},
209
210	&set_channel,
211
212	&write_command_block_regs,
213	&read_command_block_regs,
214
215	&get_altstatus,
216	&write_device_control,
217
218	&write_pio,
219	&read_pio,
220
221	&prepare_dma,
222	&start_dma,
223	&finish_dma,
224};
225
226
227static driver_module_info controller_interface = {
228	{
229		GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME,
230		0,
231		NULL
232	},
233
234	supports_device,
235	probe_controller,
236	(status_t (*)(device_node *, void **))	init_controller,
237	(void (*)(void *))						uninit_controller,
238	NULL,	// register child devices
239	NULL,	// rescan
240	(void (*)(void *))						controller_removed,
241};
242
243module_info *modules[] = {
244	(module_info *)&controller_interface,
245	(module_info *)&channel_interface,
246	NULL
247};
248