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