BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / busses / ide / silicon_image_3112 / silicon_image_3112.c
blob8e1b80a8268f18ee17badf14ae5cbafea6c1ae1b
1 /*
2 * Copyright 2006, Marcus Overhagen. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
6 #include <stdlib.h>
7 #include <string.h>
9 #include <KernelExport.h>
10 #include <device_manager.h>
11 #include <bus/IDE.h>
13 #include <ide_adapter.h>
15 #define TRACE(x...) dprintf("si-3112: " x)
16 //#define FLOW(x...) dprintf("si-3112: " x)
17 #define FLOW(x...)
20 #define DRIVER_PRETTY_NAME "Silicon Image SATA"
21 #define CONTROLLER_NAME DRIVER_PRETTY_NAME
22 #define CONTROLLER_MODULE_NAME "busses/ide/silicon_image_3112/driver_v1"
23 #define CHANNEL_MODULE_NAME "busses/ide/silicon_image_3112/channel/v1"
25 enum asic_type {
26 ASIC_SI3112 = 0,
27 ASIC_SI3114 = 1,
30 #if 0
31 static const char *adapter_asic_names[] = {
32 "si3112",
33 "si3114",
34 NULL
36 #endif
38 static const struct {
39 uint16 channel_count;
40 uint32 mmio_bar_size;
41 } kASICData[2] = {
42 { 2, 0x200 },
43 { 4, 0x400 },
46 static const struct {
47 uint16 cmd;
48 uint16 ctl;
49 uint16 bmdma;
50 uint16 sien;
51 uint16 stat;
52 const char *name;
53 } kControllerChannelData[] = {
54 { 0x80, 0x8A, 0x00, 0x148, 0xA0, "Primary Channel" },
55 { 0xC0, 0xCA, 0x08, 0x1C8, 0xE0, "Secondary Channel" },
56 { 0x280, 0x28A, 0x200, 0x348, 0x2A0, "Tertiary Channel" },
57 { 0x2C0, 0x2CA, 0x208, 0x3C8, 0x2E0, "Quaternary Channel" },
60 #define SI_SYSCFG 0x48
61 #define SI_BMDMA2 0x200
62 #define SI_INT_STEERING 0x02
63 #define SI_MASK_2PORT ((1 << 22) | (1 << 23))
64 #define SI_MASK_4PORT ((1 << 22) | (1 << 23) | (1 << 24) | (1 << 25))
66 struct channel_data;
68 typedef struct controller_data {
69 pci_device_module_info *pci;
70 pci_device *device;
72 device_node *node;
74 struct channel_data *channel[4]; // XXX only for interrupt workaround
75 int channel_count; // XXX only for interrupt workaround
77 uint32 asic_index;
78 uint32 int_num;
80 area_id mmio_area;
81 uint32 mmio_addr;
83 uint32 lost; // != 0 if device got removed, i.e. if it must not
84 // be accessed anymore
85 } controller_data;
88 typedef struct channel_data {
89 pci_device_module_info *pci;
90 device_node * node;
91 pci_device * device;
92 ide_channel ide_channel;
94 volatile uint8 * task_file;
95 volatile uint8 * control_block;
96 volatile uint8 * command_block;
97 volatile uint8 * dev_ctrl;
98 volatile uint8 * bm_status_reg;
99 volatile uint8 * bm_command_reg;
100 volatile uint32 * bm_prdt_address;
102 volatile uint32 * stat;
104 area_id prd_area;
105 prd_entry * prdt;
106 phys_addr_t prdt_phys;
107 uint32 dma_active;
108 uint32 lost;
109 } channel_data;
112 static ide_for_controller_interface * ide;
113 static ide_adapter_interface * ide_adapter;
114 static device_manager_info * dm;
116 static status_t device_control_write(void *channel_cookie, uint8 val);
117 static int32 handle_interrupt(void *arg);
120 static float
121 controller_supports(device_node *parent)
123 const char *bus;
124 uint16 vendorID;
125 uint16 deviceID;
127 // get the bus (should be PCI)
128 if (dm->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK
129 || strcmp(bus, "pci") != 0)
130 return B_ERROR;
132 // get vendor and device ID
133 if (dm->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, &vendorID, false) != B_OK
134 || dm->get_attr_uint16(parent, B_DEVICE_ID, &deviceID, false) != B_OK) {
135 return B_ERROR;
138 #define ID(v, d) (((v) << 16) | (d))
139 switch (ID(vendorID, deviceID)) {
140 case ID(0x1095, 0x0240):
141 case ID(0x1095, 0x3112):
142 case ID(0x1095, 0x3114):
143 case ID(0x1095, 0x3512):
144 case ID(0x1002, 0x436e): // ATI
145 case ID(0x1002, 0x4379): // ATI
146 case ID(0x1002, 0x437a): // ATI
147 break;
148 default:
149 return 0.0f;
152 TRACE("controller found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID);
154 return 0.8f;
158 static status_t
159 controller_probe(device_node *parent)
161 pci_device *device;
162 pci_device_module_info *pci;
163 uint32 mmioBase;
164 uint16 deviceID;
165 uint16 vendorID;
166 uint8 interruptNumber;
167 int asicIndex;
169 TRACE("controller_probe\n");
171 dm->get_driver(parent, (driver_module_info **)&pci, (void **)&device);
173 deviceID = pci->read_pci_config(device, PCI_device_id, 2);
174 vendorID = pci->read_pci_config(device, PCI_vendor_id, 2);
175 interruptNumber = pci->read_pci_config(device, PCI_interrupt_line, 1);
176 mmioBase = pci->read_pci_config(device, PCI_base_registers + 20, 4)
177 & PCI_address_io_mask;
179 switch (ID(vendorID, deviceID)) {
180 case ID(0x1095, 0x0240):
181 case ID(0x1095, 0x3112):
182 case ID(0x1095, 0x3512):
183 case ID(0x1002, 0x436e): // ATI
184 case ID(0x1002, 0x4379): // ATI
185 case ID(0x1002, 0x437a): // ATI
186 asicIndex = ASIC_SI3112;
187 break;
188 case ID(0x1095, 0x3114):
189 asicIndex = ASIC_SI3114;
190 break;
191 default:
192 TRACE("unsupported asic\n");
193 return B_ERROR;
196 if (!mmioBase) {
197 TRACE("mmio not configured\n");
198 return B_ERROR;
201 if (interruptNumber == 0 || interruptNumber == 0xff) {
202 TRACE("irq not configured\n");
203 return B_ERROR;
207 io_resource resources[2] = {
208 { B_IO_MEMORY, mmioBase, kASICData[asicIndex].mmio_bar_size },
211 device_attr attrs[] = {
212 // properties of this controller for ide bus manager
213 // there are always max. 2 devices
214 // (unless this is a Compact Flash Card with a built-in IDE controller,
215 // which has exactly 1 device)
216 { IDE_CONTROLLER_MAX_DEVICES_ITEM, B_UINT8_TYPE, { ui8: kASICData[asicIndex].channel_count }},
217 // of course we can DMA
218 { IDE_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: true }},
219 // command queuing always works
220 { IDE_CONTROLLER_CAN_CQ_ITEM, B_UINT8_TYPE, { ui8: true }},
221 // choose any name here
222 { IDE_CONTROLLER_CONTROLLER_NAME_ITEM, B_STRING_TYPE, { string: CONTROLLER_NAME }},
224 // DMA properties
225 // data must be word-aligned;
226 // warning: some controllers are more picky!
227 { B_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: 1}},
228 // one S/G block must not cross 64K boundary
229 { B_DMA_BOUNDARY, B_UINT32_TYPE, { ui32: 0xffff }},
230 // max size of S/G block is 16 bits with zero being 64K
231 { B_DMA_MAX_SEGMENT_BLOCKS, B_UINT32_TYPE, { ui32: 0x10000 }},
232 { B_DMA_MAX_SEGMENT_COUNT, B_UINT32_TYPE,
233 { ui32: IDE_ADAPTER_MAX_SG_COUNT }},
234 { B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { ui64: 0x100000000LL }},
236 // private data to find controller
237 { "silicon_image_3112/asic_index", B_UINT32_TYPE, { ui32: asicIndex }},
238 { "silicon_image_3112/mmio_base", B_UINT32_TYPE, { ui32: mmioBase }},
239 { "silicon_image_3112/int_num", B_UINT32_TYPE, { ui32: interruptNumber }},
240 { NULL }
243 TRACE("publishing controller\n");
245 return dm->register_node(parent, CONTROLLER_MODULE_NAME, attrs,
246 resources, NULL);
251 static status_t
252 controller_init(device_node *node, void **_controllerCookie)
254 controller_data *controller;
255 device_node *parent;
256 pci_device_module_info *pci;
257 pci_device *device;
258 uint32 asicIndex;
259 uint32 mmioBase;
260 uint32 mmioAddr;
261 area_id mmioArea;
262 uint32 interruptNumber;
263 status_t res;
264 uint32 temp;
265 int i;
267 TRACE("controller_init\n");
269 if (dm->get_attr_uint32(node, "silicon_image_3112/asic_index", &asicIndex, false) != B_OK)
270 return B_ERROR;
271 if (dm->get_attr_uint32(node, "silicon_image_3112/mmio_base", &mmioBase, false) != B_OK)
272 return B_ERROR;
273 if (dm->get_attr_uint32(node, "silicon_image_3112/int_num", &interruptNumber, false) != B_OK)
274 return B_ERROR;
276 controller = malloc(sizeof(controller_data));
277 if (!controller)
278 return B_NO_MEMORY;
280 FLOW("controller %p\n", controller);
282 mmioArea = map_physical_memory("Silicon Image SATA regs", mmioBase,
283 kASICData[asicIndex].mmio_bar_size, B_ANY_KERNEL_ADDRESS, 0,
284 (void **)&mmioAddr);
285 if (mmioArea < B_OK) {
286 TRACE("controller_init: mapping memory failed\n");
287 free(controller);
288 return B_ERROR;
291 parent = dm->get_parent_node(node);
292 dm->get_driver(parent, (driver_module_info **)&pci, (void **)&device);
293 dm->put_node(parent);
295 TRACE("asic %ld\n", asicIndex);
296 TRACE("int_num %ld\n", interruptNumber);
297 TRACE("mmio_addr %p\n", (void *)mmioAddr);
299 controller->pci = pci;
300 controller->device = device;
301 controller->node = node;
302 controller->asic_index = asicIndex;
303 controller->int_num = interruptNumber;
304 controller->mmio_area = mmioArea;
305 controller->mmio_addr = mmioAddr;
306 controller->lost = 0;
308 controller->channel_count = kASICData[asicIndex].channel_count;
309 for (i = 0; i < kASICData[asicIndex].channel_count; i++)
310 controller->channel[i] = 0;
312 if (asicIndex == ASIC_SI3114) {
313 // I put a magic spell on you
314 temp = *(volatile uint32 *)(mmioAddr + SI_BMDMA2);
315 *(volatile uint32 *)(mmioAddr + SI_BMDMA2) = temp | SI_INT_STEERING;
316 *(volatile uint32 *)(mmioAddr + SI_BMDMA2); // flush
319 // disable all sata phy interrupts
320 for (i = 0; i < kASICData[asicIndex].channel_count; i++)
321 *(volatile uint32 *)(mmioAddr + kControllerChannelData[i].sien) = 0;
322 *(volatile uint32 *)(mmioAddr + kControllerChannelData[0].sien); // flush
324 // install interrupt handler
325 res = install_io_interrupt_handler(interruptNumber, handle_interrupt,
326 controller, 0);
327 if (res < B_OK) {
328 TRACE("controller_init: installing interrupt handler failed\n");
329 delete_area(mmioArea);
330 free(controller);
331 return res;
334 // unmask interrupts
335 temp = *(volatile uint32 *)(mmioAddr + SI_SYSCFG);
336 temp &= (asicIndex == ASIC_SI3114) ? (~SI_MASK_4PORT) : (~SI_MASK_2PORT);
337 *(volatile uint32 *)(mmioAddr + SI_SYSCFG) = temp;
338 *(volatile uint32 *)(mmioAddr + SI_SYSCFG); // flush
340 *_controllerCookie = controller;
342 TRACE("controller_init success\n");
343 return B_OK;
347 static void
348 controller_uninit(void *controllerCookie)
350 controller_data *controller = controllerCookie;
351 uint32 temp;
353 TRACE("controller_uninit enter\n");
355 // disable interrupts
356 temp = *(volatile uint32 *)(controller->mmio_addr + SI_SYSCFG);
357 temp |= (controller->asic_index == ASIC_SI3114) ? SI_MASK_4PORT : SI_MASK_2PORT;
358 *(volatile uint32 *)(controller->mmio_addr + SI_SYSCFG) = temp;
359 *(volatile uint32 *)(controller->mmio_addr + SI_SYSCFG); // flush
361 remove_io_interrupt_handler(controller->int_num, handle_interrupt,
362 controller);
364 delete_area(controller->mmio_area);
365 free(controller);
367 TRACE("controller_uninit leave\n");
371 static status_t
372 controller_register_channels(void *cookie)
374 controller_data *controller = cookie;
375 int index;
377 // publish channel nodes
378 for (index = 0; index < kASICData[controller->asic_index].channel_count;
379 index++) {
380 device_attr attrs[] = {
381 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: DRIVER_PRETTY_NAME }},
382 // { PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: kControllerChannelData[channelIndex].name }},
383 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, { string: IDE_FOR_CONTROLLER_MODULE_NAME }},
385 // private data to identify channel
386 { IDE_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: true }},
387 { "silicon_image_3112/chan_index", B_UINT32_TYPE, { ui32: index }},
388 { NULL }
391 TRACE("publishing %s\n", kControllerChannelData[index].name);
393 dm->register_node(controller->node, CHANNEL_MODULE_NAME, attrs,
394 NULL, NULL);
397 return B_OK;
401 static void
402 controller_removed(void *controllerCookie)
404 controller_data *controller = controllerCookie;
405 controller->lost = 1;
409 // #pragma mark -
412 static status_t
413 channel_init(device_node *node, void **_channelCookie)
415 controller_data *controller;
416 device_node *parent;
417 channel_data *channel;
418 physical_entry entry;
419 size_t prdtSize;
420 uint32 channelIndex;
422 TRACE("channel_init enter\n");
424 channel = malloc(sizeof(channel_data));
425 if (!channel)
426 return B_NO_MEMORY;
428 if (dm->get_attr_uint32(node, "silicon_image_3112/chan_index", &channelIndex, false) != B_OK)
429 goto err;
431 #if 0
432 if (1 /* debug */){
433 uint8 bus, device, function;
434 uint16 vendorID, deviceID;
435 dm->get_attr_uint8(node, PCI_DEVICE_BUS_ITEM, &bus, true);
436 dm->get_attr_uint8(node, PCI_DEVICE_DEVICE_ITEM, &device, true);
437 dm->get_attr_uint8(node, PCI_DEVICE_FUNCTION_ITEM, &function, true);
438 dm->get_attr_uint16(node, PCI_DEVICE_VENDOR_ID_ITEM, &vendorID, true);
439 dm->get_attr_uint16(node, PCI_DEVICE_DEVICE_ID_ITEM, &deviceID, true);
440 TRACE("bus %3d, device %2d, function %2d: vendor %04x, device %04x\n",
441 bus, device, function, vendorID, deviceID);
443 #endif
445 TRACE("channel_index %ld\n", channelIndex);
446 TRACE("channel name: %s\n", kControllerChannelData[channelIndex].name);
448 TRACE("channel %p\n", channel);
450 parent = dm->get_parent_node(node);
451 dm->get_driver(parent, NULL, (void **)&controller);
452 dm->put_node(parent);
454 TRACE("controller %p\n", controller);
455 TRACE("mmio_addr %p\n", (void *)controller->mmio_addr);
457 // PRDT must be contiguous, dword-aligned and must not cross 64K boundary
458 // TODO: Where's the handling for the 64 K boundary? create_area_etc() can be
459 // used.
460 prdtSize = (IDE_ADAPTER_MAX_SG_COUNT * sizeof(prd_entry) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1);
461 channel->prd_area = create_area("prd", (void **)&channel->prdt,
462 B_ANY_KERNEL_ADDRESS, prdtSize, B_32_BIT_CONTIGUOUS, 0);
463 if (channel->prd_area < B_OK) {
464 TRACE("creating prd_area failed\n");
465 goto err;
468 get_memory_map(channel->prdt, prdtSize, &entry, 1);
469 channel->prdt_phys = entry.address;
471 channel->pci = controller->pci;
472 channel->device = controller->device;
473 channel->node = node;
474 channel->ide_channel = NULL;
476 channel->task_file = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].cmd + 1);
477 channel->control_block = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].ctl);
478 channel->command_block = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].cmd);
479 channel->dev_ctrl = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].ctl);
480 channel->bm_prdt_address = (volatile uint32 *)(controller->mmio_addr + kControllerChannelData[channelIndex].bmdma + IDE_BM_PRDT_ADDRESS);
481 channel->bm_status_reg = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].bmdma + IDE_BM_STATUS_REG);
482 channel->bm_command_reg = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].bmdma + IDE_BM_COMMAND_REG);
483 channel->stat = (volatile uint32 *)(controller->mmio_addr + kControllerChannelData[channelIndex].stat);
485 channel->lost = 0;
486 channel->dma_active = 0;
488 controller->channel[channelIndex] = channel;
490 // enable interrupts so the channel is ready to run
491 device_control_write(channel, ide_devctrl_bit3);
493 *_channelCookie = channel;
495 TRACE("channel_init leave\n");
496 return B_OK;
498 err:
499 free(channel);
500 return B_ERROR;
504 static void
505 channel_uninit(void *channelCookie)
507 channel_data *channel = channelCookie;
509 TRACE("channel_uninit enter\n");
511 // disable IRQs
512 device_control_write(channel, ide_devctrl_bit3 | ide_devctrl_nien);
514 // catch spurious interrupt
515 // (some controllers generate an IRQ when you _disable_ interrupts,
516 // they are delayed by less then 40 µs, so 1 ms is safe)
517 snooze(1000);
519 delete_area(channel->prd_area);
520 free(channel);
522 TRACE("channel_uninit leave\n");
526 static void
527 channel_removed(void *channelCookie)
529 channel_data *channel = channelCookie;
530 channel->lost = 1;
534 static void
535 set_channel(void *channelCookie, ide_channel ideChannel)
537 channel_data *channel = channelCookie;
538 channel->ide_channel = ideChannel;
542 static status_t
543 task_file_write(void *channelCookie, ide_task_file *tf, ide_reg_mask mask)
545 channel_data *channel = channelCookie;
546 int i;
548 FLOW("task_file_write\n");
550 if (channel->lost)
551 return B_ERROR;
553 for (i = 0; i < 7; i++) {
554 if( ((1 << (i+7)) & mask) != 0 ) {
555 FLOW("%x->HI(%x)\n", tf->raw.r[i + 7], i );
556 channel->task_file[i] = tf->raw.r[i + 7];
559 if (((1 << i) & mask) != 0) {
560 FLOW("%x->LO(%x)\n", tf->raw.r[i], i );
561 channel->task_file[i] = tf->raw.r[i];
564 *channel->dev_ctrl; // read altstatus to flush
566 return B_OK;
570 static status_t
571 task_file_read(void *channelCookie, ide_task_file *tf, ide_reg_mask mask)
573 channel_data *channel = channelCookie;
574 int i;
576 FLOW("task_file_read\n");
578 if (channel->lost)
579 return B_ERROR;
581 for (i = 0; i < 7; i++) {
582 if (((1 << i) & mask) != 0) {
583 tf->raw.r[i] = channel->task_file[i];
584 FLOW("%x: %x\n", i, (int)tf->raw.r[i] );
588 return B_OK;
592 static uint8
593 altstatus_read(void *channelCookie)
595 channel_data *channel = channelCookie;
597 FLOW("altstatus_read\n");
599 if (channel->lost)
600 return 0x01; // Error bit
602 return *channel->dev_ctrl;
606 static status_t
607 device_control_write(void *channelCookie, uint8 val)
609 channel_data *channel = channelCookie;
611 FLOW("device_control_write 0x%x\n", val);
613 if (channel->lost)
614 return B_ERROR;
616 *channel->dev_ctrl = val;
617 *channel->dev_ctrl; // read altstatus to flush
619 return B_OK;
623 static status_t
624 pio_write(void *channelCookie, uint16 *data, int count, bool force_16bit)
626 channel_data *channel = channelCookie;
627 if (channel->lost)
628 return B_ERROR;
630 FLOW("pio_write force_16bit = %d, (count & 1) = %d\n", force_16bit, (count & 1));
632 // The data port is only 8 bit wide in the command register block.
634 if ((count & 1) != 0 || force_16bit) {
635 volatile uint16 * base = (volatile uint16 *)channel->command_block;
636 for ( ; count > 0; --count)
637 *base = *(data++);
638 } else {
639 volatile uint32 * base = (volatile uint32 *)channel->command_block;
640 uint32 *cur_data = (uint32 *)data;
642 for ( ; count > 0; count -= 2 )
643 *base = *(cur_data++);
645 *channel->dev_ctrl; // read altstatus to flush
647 return B_OK;
651 static status_t
652 pio_read(void *channelCookie, uint16 *data, int count, bool force_16bit)
654 channel_data *channel = channelCookie;
655 if (channel->lost)
656 return B_ERROR;
658 FLOW("pio_read force_16bit = %d, (count & 1) = %d\n", force_16bit, (count & 1));
660 // The data port is only 8 bit wide in the command register block.
661 // We are memory mapped and read using 16 or 32 bit access from this 8 bit location.
663 if ((count & 1) != 0 || force_16bit) {
664 volatile uint16 * base = (volatile uint16 *)channel->command_block;
665 for ( ; count > 0; --count)
666 *(data++) = *base;
667 } else {
668 volatile uint32 * base = (volatile uint32 *)channel->command_block;
669 uint32 *cur_data = (uint32 *)data;
671 for ( ; count > 0; count -= 2 )
672 *(cur_data++) = *base;
675 return B_OK;
679 static status_t
680 dma_prepare(void *channelCookie, const physical_entry *sg_list,
681 size_t sg_list_count, bool write)
683 channel_data *channel = channelCookie;
684 pci_device_module_info *pci = channel->pci;
685 pci_device *device = channel->device;
686 prd_entry *prd = channel->prdt;
687 uint8 command;
688 uint8 status;
689 uint32 temp;
690 int i;
692 FLOW("dma_prepare enter\n");
694 for (i = sg_list_count - 1, prd = channel->prdt; i >= 0;
695 --i, ++prd, ++sg_list ) {
696 prd->address = B_HOST_TO_LENDIAN_INT32(pci->ram_address(device,
697 (void*)(addr_t)sg_list->address));
699 // 0 means 64K - this is done automatically by discarding upper 16 bits
700 prd->count = B_HOST_TO_LENDIAN_INT16((uint16)sg_list->size);
701 prd->EOT = i == 0;
703 FLOW("%x, %x, %d\n", (int)prd->address, prd->count, prd->EOT);
706 // XXX move this to chan init?
707 temp = (*channel->bm_prdt_address) & 3;
708 temp |= B_HOST_TO_LENDIAN_INT32(pci->ram_address(device,
709 (void *)(addr_t)channel->prdt_phys)) & ~3;
710 *channel->bm_prdt_address = temp;
712 *channel->dev_ctrl; // read altstatus to flush
714 // reset interrupt and error signal
715 status = *channel->bm_status_reg | IDE_BM_STATUS_INTERRUPT
716 | IDE_BM_STATUS_ERROR;
717 *channel->bm_status_reg = status;
719 *channel->dev_ctrl; // read altstatus to flush
721 // set data direction
722 command = *channel->bm_command_reg;
723 if (write)
724 command &= ~IDE_BM_COMMAND_READ_FROM_DEVICE;
725 else
726 command |= IDE_BM_COMMAND_READ_FROM_DEVICE;
728 *channel->bm_command_reg = command;
730 *channel->dev_ctrl; // read altstatus to flush
732 FLOW("dma_prepare leave\n");
734 return B_OK;
738 static status_t
739 dma_start(void *channelCookie)
741 channel_data *channel = channelCookie;
742 uint8 command;
744 FLOW("dma_start enter\n");
746 command = *channel->bm_command_reg | IDE_BM_COMMAND_START_STOP;
747 channel->dma_active = true;
748 *channel->bm_command_reg = command;
750 *channel->dev_ctrl; // read altstatus to flush
752 FLOW("dma_start leave\n");
754 return B_OK;
758 static status_t
759 dma_finish(void *channelCookie)
761 channel_data *channel = channelCookie;
762 uint8 command;
763 uint8 status;
765 FLOW("dma_finish enter\n");
767 command = *channel->bm_command_reg & ~IDE_BM_COMMAND_START_STOP;
768 channel->dma_active = false;
770 *channel->bm_command_reg = command;
772 status = *channel->bm_status_reg;
774 *channel->bm_status_reg = status | IDE_BM_STATUS_INTERRUPT
775 | IDE_BM_STATUS_ERROR;
777 *channel->dev_ctrl; // read altstatus to flush
779 if ((status & IDE_BM_STATUS_ERROR) != 0) {
780 FLOW("dma_finish: failed\n");
781 return B_ERROR;
784 if ((status & IDE_BM_STATUS_INTERRUPT) == 0) {
785 if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
786 TRACE("dma_finish: transfer aborted\n");
787 return B_ERROR;
788 } else {
789 TRACE("dma_finish: buffer underrun\n");
790 return B_DEV_DATA_UNDERRUN;
792 } else {
793 if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
794 TRACE("dma_finish: buffer too large\n");
795 return B_DEV_DATA_OVERRUN;
796 } else {
797 FLOW("dma_finish leave\n");
798 return B_OK;
804 static int32
805 handle_interrupt(void *arg)
807 controller_data *controller = arg;
808 uint8 status;
809 int32 result, ret;
810 int i;
812 // FLOW("handle_interrupt\n");
814 result = B_UNHANDLED_INTERRUPT;
816 for (i = 0; i < controller->channel_count; i++) {
817 channel_data *channel = controller->channel[i];
818 if (!channel || channel->lost)
819 continue;
821 if (channel->dma_active) {
822 if ((*channel->bm_status_reg & IDE_BM_STATUS_INTERRUPT) == 0)
823 continue;
824 } else {
825 // for PIO, read the "Task File Configuration + Status" Interrupt
826 // status
827 if (!(*channel->stat & (1 << 11)))
828 continue;
831 // acknowledge IRQ
832 status = *(channel->command_block + 7);
833 ret = ide->irq_handler(channel->ide_channel, status);
834 if (ret == B_INVOKE_SCHEDULER || result == B_UNHANDLED_INTERRUPT)
835 result = ret;
838 return result;
842 module_dependency module_dependencies[] = {
843 { IDE_FOR_CONTROLLER_MODULE_NAME, (module_info **)&ide },
844 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&dm },
845 { IDE_ADAPTER_MODULE_NAME, (module_info **)&ide_adapter },
850 static ide_controller_interface sChannelInterface = {
853 CHANNEL_MODULE_NAME,
855 NULL
858 .supports_device = NULL,
859 .register_device = NULL,
860 .init_driver = &channel_init,
861 .uninit_driver = &channel_uninit,
862 .register_child_devices = NULL,
863 .device_removed = &channel_removed,
866 .set_channel = &set_channel,
867 .write_command_block_regs = &task_file_write,
868 .read_command_block_regs = &task_file_read,
869 .get_altstatus = &altstatus_read,
870 .write_device_control = &device_control_write,
871 .write_pio = &pio_write,
872 .read_pio = &pio_read,
873 .prepare_dma = &dma_prepare,
874 .start_dma = &dma_start,
875 .finish_dma = &dma_finish,
879 static driver_module_info sControllerInterface = {
881 CONTROLLER_MODULE_NAME,
883 NULL
886 .supports_device = &controller_supports,
887 .register_device = &controller_probe,
888 .init_driver = &controller_init,
889 .uninit_driver = &controller_uninit,
890 .register_child_devices = &controller_register_channels,
891 .device_removed = &controller_removed,
894 module_info *modules[] = {
895 (module_info *)&sControllerInterface,
896 (module_info *)&sChannelInterface,
897 NULL