1/* 2 * Copyright (c) 2014 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <barrelfish/barrelfish.h> 11 12#include <dma_internal.h> 13#include <dma_device_internal.h> 14#include <dma_channel_internal.h> 15#include <dma_request_internal.h> 16 17#include <debug.h> 18 19/* 20 * ============================================================================ 21 * Library Internal Interface 22 * ============================================================================ 23 */ 24 25/* 26 * ---------------------------------------------------------------------------- 27 * Request List Management 28 * ---------------------------------------------------------------------------- 29 */ 30 31/** 32 * \brief returns the first request on the submitted request queue of the channel 33 * 34 * \param chan DMA channel 35 * 36 * \returns pointer to the DMA request 37 * NULL if queue was empty 38 */ 39struct dma_request *dma_channel_deq_request_head(struct dma_channel *chan) 40{ 41 struct dma_request *req = chan->req_list.head; 42 if (req == NULL) { 43 assert(chan->req_list.count == 0); 44 return NULL; 45 } 46 47 chan->req_list.count--; 48 49 chan->req_list.head = dma_request_get_next(req); 50 if (chan->req_list.head == NULL) { 51 chan->req_list.tail = NULL; 52 assert(chan->req_list.count == 0); 53 } 54 55 DMACHAN_DEBUG("request : deq head [%016lx] count=%u\n", chan->id, 56 dma_request_get_id(req), chan->req_list.count); 57 58 return req; 59} 60 61/** 62 * \brief returns the request with the given request ID 63 * 64 * \param chan DMA channel 65 * \param id DMA request id 66 * 67 * \returns pointer to the DMA request 68 * NULL if queue was empty 69 */ 70struct dma_request *dma_channel_deq_request_by_id(struct dma_channel *chan, 71 dma_req_id_t id) 72{ 73 struct dma_request *req = chan->req_list.head; 74 if (req == NULL) { 75 assert(chan->req_list.count == 0); 76 return NULL; 77 } 78 while(req) { 79 if (req->id == id) { 80 if (req->prev != NULL) { 81 req->prev->next = req->next; 82 } 83 84 if (req->next != NULL) { 85 req->next->prev = req->prev; 86 } 87 chan->req_list.count--; 88 if (chan->req_list.count == 0) { 89 assert(chan->req_list.head == chan->req_list.tail); 90 chan->req_list.head = NULL; 91 chan->req_list.tail = NULL; 92 } 93 req->next = NULL; 94 req->prev = NULL; 95 return req; 96 } 97 req = req->next; 98 } 99 return NULL; 100} 101 102/** 103 * \brief inserts a request into the channels request list 104 * 105 * \param chan DMA channel 106 * \param req DMA request to be inserted 107 */ 108void dma_channel_enq_request_head(struct dma_channel *chan, 109 struct dma_request *req) 110{ 111 dma_request_set_next(req, chan->req_list.head); 112 113 chan->req_list.count++; 114 115 chan->req_list.head = req; 116 if (chan->req_list.tail == NULL) { 117 chan->req_list.tail = req; 118 assert(chan->req_list.count == 1); 119 } 120 121 DMACHAN_DEBUG("request : enq head [%016lx] count=%u\n", chan->id, 122 dma_request_get_id(req), chan->req_list.count); 123} 124 125/** 126 * \brief inserts a request at the end of the channels request list 127 * 128 * \param chan DMA channel 129 * \param req DMA request to be inserted 130 */ 131void dma_channel_enq_request_tail(struct dma_channel *chan, 132 struct dma_request *req) 133{ 134 dma_request_set_next(req, NULL); 135 136 if (chan->req_list.head == NULL) { 137 assert(chan->req_list.count == 0); 138 chan->req_list.head = req; 139 } else { 140 assert(chan->req_list.count > 0); 141 dma_request_set_next(chan->req_list.tail, req); 142 } 143 144 chan->req_list.tail = req; 145 146 chan->req_list.count++; 147 148 DMACHAN_DEBUG("request : enq tail [%016lx] count=%u\n", chan->id, 149 dma_request_get_id(req), chan->req_list.count); 150} 151 152/* 153 * ============================================================================ 154 * Public Interface 155 * ============================================================================ 156 */ 157 158/** 159 * \brief polls the DMA channel for completed events 160 * 161 * \param chan DMA Channel 162 * 163 * \returns SYS_ERR_OK if there was something processed 164 * DMA_ERR_CHAN_IDLE if there was no request on the channel 165 * DMA_ERR_REQUEST_UNFINISHED if the request has not been completed yet 166 * 167 */ 168inline errval_t dma_channel_poll(struct dma_channel *chan) 169{ 170 if (chan->f.poll) { 171 return chan->f.poll(chan); 172 } 173 return DMA_ERR_DEVICE_UNSUPPORTED; 174} 175 176/* 177 * ---------------------------------------------------------------------------- 178 * Getter / Setter Methods 179 * ---------------------------------------------------------------------------- 180 */ 181 182/** 183 * \brief gets the ID of the channel 184 * 185 * \param DMA channel 186 * 187 * \returns DMA channel ID 188 */ 189inline dma_chan_id_t dma_channel_get_id(struct dma_channel *chan) 190{ 191 return chan->id; 192} 193 194/** 195 * \brief gets the state of the channel 196 * 197 * \param DMA channel 198 * 199 * \returns DMA channel state 200 */ 201inline dma_chan_st_t dma_channel_get_state(struct dma_channel *chan) 202{ 203 return chan->state; 204} 205 206/** 207 * \brief gets the DMA device this channel belongs to 208 * 209 * \param DMA channel 210 * 211 * \returns DMA device 212 */ 213inline struct dma_device *dma_channel_get_device(struct dma_channel *chan) 214{ 215 return chan->device; 216} 217 218/** 219 * \brief gets the number of unfinished requests on this channel 220 * 221 * \param DMA channel 222 * 223 * \returns request count 224 */ 225inline uint32_t dma_channel_get_request_count(struct dma_channel *chan) 226{ 227 return chan->req_list.count; 228} 229 230/** 231 * \brief gets the address where the MMIO registers are mapped 232 * 233 * \param DMA channel 234 * 235 * \returns MMIO register vbase 236 */ 237inline lvaddr_t dma_channel_get_mmio_vbase(struct dma_channel *chan) 238{ 239 return chan->mmio.vaddr; 240} 241 242/** 243 * \brief gets the maximum transfer size of the channel 244 * 245 * \param DMA channel 246 * 247 * \returns maximum transfer size in bytes 248 */ 249inline uint32_t dma_channel_get_max_xfer_size(struct dma_channel *chan) 250{ 251 return chan->max_xfer_size; 252} 253