Ticket #13819: highpoint_ide_pci.cpp

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