BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / bus_managers / ide / dma.c
blobffe1fd36079087f90dbe58346565787051e014be
1 /*
2 * Copyright 2004-2007, Haiku, Inc. All RightsReserved.
3 * Copyright 2002/03, Thomas Kurschel. All rights reserved.
5 * Distributed under the terms of the MIT License.
6 */
8 //! DMA helper functions
11 #include "ide_internal.h"
13 #define CHECK_DEV_DMA_MODE(infoblock, elem, mode, this_mode, num_modes ) \
14 if( infoblock->elem ) { \
15 mode = this_mode; \
16 ++num_modes; \
20 int
21 get_device_dma_mode(ide_device_info *device)
23 ide_device_infoblock *infoblock = &device->infoblock;
25 int num_modes, mode;
27 mode = 0;
28 num_modes = 0;
30 if (!infoblock->DMA_supported)
31 return -1;
33 CHECK_DEV_DMA_MODE(infoblock, MDMA0_selected, mode, 0, num_modes);
34 CHECK_DEV_DMA_MODE(infoblock, MDMA1_selected, mode, 1, num_modes);
35 CHECK_DEV_DMA_MODE(infoblock, MDMA2_selected, mode, 2, num_modes);
37 if (infoblock->_88_valid) {
38 CHECK_DEV_DMA_MODE(infoblock, UDMA0_selected, mode, 0x10, num_modes);
39 CHECK_DEV_DMA_MODE(infoblock, UDMA1_selected, mode, 0x11, num_modes);
40 CHECK_DEV_DMA_MODE(infoblock, UDMA2_selected, mode, 0x12, num_modes);
41 CHECK_DEV_DMA_MODE(infoblock, UDMA3_selected, mode, 0x13, num_modes);
42 CHECK_DEV_DMA_MODE(infoblock, UDMA4_selected, mode, 0x14, num_modes);
43 CHECK_DEV_DMA_MODE(infoblock, UDMA5_selected, mode, 0x15, num_modes);
44 CHECK_DEV_DMA_MODE(infoblock, UDMA6_selected, mode, 0x16, num_modes);
47 if (num_modes != 1)
48 return -1;
50 SHOW_FLOW(3, "%x", mode);
52 return mode;
56 bool
57 configure_dma(ide_device_info *device)
59 if (get_device_dma_mode(device) != -1) {
60 device->DMA_enabled = device->DMA_supported = device->bus->can_DMA;
61 if (device->DMA_enabled) {
62 dprintf("IDE: enabling DMA\n");
63 } else {
64 dprintf("IDE: disabling DMA (failsafe option selected)\n");
66 } else {
67 device->DMA_enabled = false;
68 dprintf("IDE: DMA not possible, disabling\n");
71 return true;
75 /*! Abort DMA transmission
76 must be called _before_ start_dma_wait
78 void
79 abort_dma(ide_device_info *device, ide_qrequest *qrequest)
81 ide_bus_info *bus = device->bus;
83 SHOW_FLOW0(0, "");
85 bus->controller->finish_dma(bus->channel_cookie);
89 /*! Prepare DMA transmission
90 on return, DMA engine waits for device to transmit data
91 warning: doesn't set sense data on error
93 bool
94 prepare_dma(ide_device_info *device, ide_qrequest *qrequest)
96 ide_bus_info *bus = device->bus;
97 scsi_ccb *request = qrequest->request;
98 status_t res;
100 res = bus->controller->prepare_dma(bus->channel_cookie, request->sg_list,
101 request->sg_count, qrequest->is_write);
102 if (res != B_OK)
103 return false;
105 return true;
109 /*! Start waiting for DMA to be finished */
110 void
111 start_dma_wait(ide_device_info *device, ide_qrequest *qrequest)
113 ide_bus_info *bus = device->bus;
115 bus->controller->start_dma(bus->channel_cookie);
117 start_waiting(bus, qrequest->request->timeout > 0 ?
118 qrequest->request->timeout : IDE_STD_TIMEOUT, ide_state_async_waiting);
122 /*! Start waiting for DMA to be finished with bus lock not hold */
123 void
124 start_dma_wait_no_lock(ide_device_info *device, ide_qrequest *qrequest)
126 ide_bus_info *bus = device->bus;
128 IDE_LOCK(bus);
129 start_dma_wait(device, qrequest);
133 /*! Finish dma transmission after device has fired IRQ */
134 bool
135 finish_dma(ide_device_info *device)
137 ide_bus_info *bus = device->bus;
138 status_t dma_res;
140 dma_res = bus->controller->finish_dma(bus->channel_cookie);
142 return dma_res == B_OK || dma_res == B_DEV_DATA_OVERRUN;