2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted (subject to the limitations in the
7 * disclaimer below) provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
17 * * Neither the name of Qualcomm Atheros nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
22 * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
23 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
33 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * @Abstract: DMA engine for Magpie
48 //#include <HIF_api.h>
49 #include <dma_engine_api.h>
50 #include <Magpie_api.h>
51 #include <vdesc_api.h>
52 #include <adf_os_mem.h>
53 #include <adf_os_io.h>
55 //#include "HIF_usb.h"
57 //HIF_USB_CONTEXT g_hifUSBCtx;
59 #define VDESC_TO_USBDESC(vdesc) (struct zsDmaDesc *)((vdesc)->hw_desc_buf)
61 static void relinkUSBDescToVdesc(VBUF *buf, struct zsDmaDesc* desc);
62 static void config_queue(struct zsDmaQueue *q, VDESC *desc_list);
64 #if ENABLE_SW_SWAP_DATA_MODE
65 static void swapData(struct zsDmaDesc* usbDesc);
68 static void init_usb_desc(struct zsDmaDesc *usbDesc)
70 usbDesc->status = ZM_OWN_BITS_SW;
72 usbDesc->dataSize = 0;
73 usbDesc->totalLen = 0;
74 usbDesc->lastAddr = 0;
75 usbDesc->dataAddr = 0;
76 usbDesc->nextAddr = 0;
79 void _DMAengine_init()
84 void _DMAengine_init_rx_queue(struct zsDmaQueue *q)
87 struct zsDmaDesc *usbDesc;
89 desc = VDESC_alloc_vdesc();
91 usbDesc = VDESC_TO_USBDESC(desc);
92 init_usb_desc(usbDesc);
94 q->head = q->terminator = usbDesc;
98 void _DMAengine_init_tx_queue(struct zsTxDmaQueue *q)
100 _DMAengine_init_rx_queue((struct zsDmaQueue *)q);
101 q->xmited_buf_head = NULL;
102 q->xmited_buf_tail = NULL;
105 #if ENABLE_SW_SWAP_DATA_MODE
107 static void swapData(struct zsDmaDesc* usbDesc)
109 int len = (usbDesc->dataSize & 0xfffffffc) >> 2;
111 A_UINT32 *dataAddr = (A_UINT32 *)usbDesc->dataAddr;
114 if ( ( usbDesc->dataSize & 3 ) != 0 ) {
118 for ( i = 0; i < len; i++ ) {
121 dataAddr[i] = __bswap32(data);
127 void _DMAengine_return_recv_buf(struct zsDmaQueue *q, VBUF *buf)
129 /* Re-link the VDESC of buf into USB descriptor list & queue the descriptors
132 config_queue(q, buf->desc_list);
136 static void config_queue(struct zsDmaQueue *q, VDESC *desc_list)
139 struct zsDmaDesc *usbDesc;
140 struct zsDmaDesc* prevUsbDesc = NULL;
141 struct zsDmaDesc* headUsbDesc;
144 while ( theDesc != NULL ) {
145 usbDesc = (struct zsDmaDesc *)VDESC_get_hw_desc(theDesc);
146 init_usb_desc(usbDesc);
148 theDesc->data_offset = 0; //RAY 0723
149 usbDesc->dataAddr = (volatile u32_t)(theDesc->buf_addr + theDesc->data_offset);
150 usbDesc->dataSize = theDesc->buf_size;
152 if ( prevUsbDesc == NULL ) {
153 headUsbDesc = usbDesc;
154 prevUsbDesc = usbDesc;
156 prevUsbDesc->nextAddr = usbDesc;
157 prevUsbDesc = usbDesc;
160 theDesc = theDesc->next_desc;
163 headUsbDesc->lastAddr = prevUsbDesc;
164 DMA_Engine_reclaim_packet(q, headUsbDesc);
169 //#define MAX_TX_BUF_SIZE ZM_BLOCK_SIZE
170 //#define MAX_TX_BUF_SIZE 1600
172 void _DMAengine_config_rx_queue(struct zsDmaQueue *q, int num_desc, int buf_size)
178 for(i=0; i < num_desc; i++)
180 desc = VDESC_alloc_vdesc();
182 adf_os_assert(desc != NULL);
184 desc->buf_addr = (A_UINT8 *)adf_os_mem_alloc(buf_size);
185 desc->buf_size = buf_size;
186 desc->next_desc = NULL;
187 desc->data_offset = 0;
197 desc->next_desc = head;
202 config_queue(q, head);
205 void _DMAengine_xmit_buf(struct zsTxDmaQueue *q, VBUF *buf)
208 struct zsDmaDesc* usbDesc;
209 struct zsDmaDesc* prevUsbDesc = NULL;
210 struct zsDmaDesc* headUsbDesc;
212 /* Re-link the VDESC of buf into USB descriptor list & queue the descriptors
215 currVdesc = (VDESC *)buf->desc_list;
216 while(currVdesc != NULL) {
218 usbDesc = (struct zsDmaDesc *)currVdesc->hw_desc_buf;
220 init_usb_desc(usbDesc);
221 usbDesc->dataSize = currVdesc->data_size;
222 usbDesc->dataAddr = (volatile u32_t)(currVdesc->buf_addr + currVdesc->data_offset);
226 #if ENABLE_SW_SWAP_DATA_MODE && ENABLE_SWAP_DATA_MODE == 0
230 if ( prevUsbDesc == NULL ) {
231 headUsbDesc = usbDesc;
233 usbDesc->ctrl |= ZM_FS_BIT;
235 // how to get the total len???
236 usbDesc->totalLen = buf->buf_length;
237 prevUsbDesc = usbDesc;
240 prevUsbDesc->nextAddr = usbDesc;
241 prevUsbDesc = usbDesc;
244 currVdesc = currVdesc->next_desc;
247 usbDesc->ctrl |= ZM_LS_BIT;
248 headUsbDesc->lastAddr = usbDesc;
250 if ( q->xmited_buf_head == NULL && q->xmited_buf_tail == NULL ) {
251 q->xmited_buf_head = buf;
252 q->xmited_buf_tail = buf;
253 q->xmited_buf_head->next_buf = q->xmited_buf_tail;
256 q->xmited_buf_tail->next_buf = buf;
257 q->xmited_buf_tail = buf;
260 DMA_Engine_put_packet((struct zsDmaQueue *)q, headUsbDesc);
263 void _DMAengine_flush_xmit(struct zsDmaQueue *q)
267 int _DMAengine_has_compl_packets(struct zsDmaQueue *q)
269 int has_compl_pkts = 0;
271 if ((q->head != q->terminator) &&
272 ((q->head->status & ZM_OWN_BITS_MASK) != ZM_OWN_BITS_HW)) {
276 return has_compl_pkts;
279 VBUF* _DMAengine_reap_recv_buf(struct zsDmaQueue *q)
281 struct zsDmaDesc* desc;
284 //u8_t *tbuf = (u8_t *)desc->dataAddr;
286 desc = DMA_Engine_get_packet(q);
291 #if ENABLE_SW_SWAP_DATA_MODE && ENABLE_SWAP_DATA_MODE == 0
295 buf = VBUF_alloc_vbuf();
296 adf_os_assert(buf != NULL);
298 relinkUSBDescToVdesc(buf, desc);
302 VBUF* _DMAengine_reap_xmited_buf(struct zsTxDmaQueue *q)
304 struct zsDmaDesc* desc;
307 desc = DMA_Engine_get_packet((struct zsDmaQueue *)q);
312 // assert g_hifUSBCtx.upVbufQ.head is not null
313 // assert g_hifUSBCtx.upVbufQ.tail is not null
314 sentBuf = q->xmited_buf_head;
315 if ( q->xmited_buf_head == q->xmited_buf_tail ) {
316 q->xmited_buf_head = NULL;
317 q->xmited_buf_tail = NULL;
319 q->xmited_buf_head = q->xmited_buf_head->next_buf;
322 sentBuf->next_buf = NULL;
323 relinkUSBDescToVdesc(sentBuf, desc);
327 void _DMAengine_desc_dump(struct zsDmaQueue *q)
330 struct zsDmaDesc* tmpDesc;
335 if( tmpDesc == q->terminator )
337 #ifdef DESC_DUMP_BOTH_DESCnDATA
338 A_PRINTF("0x%08x(0x%08x,T)]", tmpDesc, tmpDesc->dataAddr);
340 A_PRINTF("0x%08x(T)]", tmpDesc);
345 #ifdef DESC_DUMP_BOTH_DESCnDATA
346 A_PRINTF("0x%08x(0x%08x,%c)->", tmpDesc, tmpDesc->dataAddr, (tmpDesc->status&ZM_OWN_BITS_HW)?'H':'S');
348 A_PRINTF("0x%08x(%c)->", tmpDesc, (tmpDesc->status&ZM_OWN_BITS_HW)?'H':'S');
356 tmpDesc = tmpDesc->nextAddr;
361 /* the exported entry point into this module. All apis are accessed through
362 * function pointers */
363 void dma_engine_module_install(struct dma_engine_api *apis)
366 apis->_init = _DMAengine_init;
367 apis->_config_rx_queue = _DMAengine_config_rx_queue;
368 apis->_xmit_buf = _DMAengine_xmit_buf;
369 apis->_flush_xmit = _DMAengine_flush_xmit;
370 apis->_reap_recv_buf = _DMAengine_reap_recv_buf;
371 apis->_return_recv_buf = _DMAengine_return_recv_buf;
372 apis->_reap_xmited_buf = _DMAengine_reap_xmited_buf;
373 apis->_swap_data = swapData;
374 apis->_has_compl_packets = _DMAengine_has_compl_packets;
375 apis->_init_rx_queue = _DMAengine_init_rx_queue;
376 apis->_init_tx_queue = _DMAengine_init_tx_queue;
377 apis->_desc_dump = _DMAengine_desc_dump;
378 apis->_get_packet = zfDmaGetPacket;
379 apis->_reclaim_packet = zfDmaReclaimPacket;
380 apis->_put_packet = zfDmaPutPacket;
382 /* save ptr to the ptr to the context for external code to inspect/modify internal module state */
383 //apis->pReserved = &g_pMboxHWContext;
386 static void relinkUSBDescToVdesc(VBUF *buf, struct zsDmaDesc* desc)
389 VDESC *prevVdesc = NULL;
390 struct zsDmaDesc *currDesc = desc;
392 vdesc = VDESC_HW_TO_VDESC(currDesc);
393 buf->desc_list = vdesc;
394 buf->buf_length = currDesc->totalLen;
396 while(currDesc != NULL) {
397 vdesc->data_size = currDesc->dataSize;
398 //vdesc->data_offset = 0; // TODO: bad!!
400 if ( prevVdesc == NULL ) {
403 prevVdesc->next_desc = vdesc;
407 if ( currDesc->ctrl & ZM_LS_BIT ) {
408 vdesc->next_desc = NULL;
412 currDesc = currDesc->nextAddr;
413 vdesc = VDESC_HW_TO_VDESC(currDesc);