4 * @Abstract: DMA engine for Magpie
8 * Copyright (c) 2008 Atheros Communications Inc.
18 //#include <HIF_api.h>
19 #include <dma_engine_api.h>
20 #include <Magpie_api.h>
21 #include <vdesc_api.h>
22 #include <adf_os_mem.h>
23 #include <adf_os_io.h>
25 //#include "HIF_usb.h"
27 //HIF_USB_CONTEXT g_hifUSBCtx;
29 #define VDESC_TO_USBDESC(vdesc) (struct zsDmaDesc *)((vdesc)->hw_desc_buf)
31 static void relinkUSBDescToVdesc(VBUF *buf, struct zsDmaDesc* desc);
32 static void config_queue(struct zsDmaQueue *q, VDESC *desc_list);
34 #if ENABLE_SW_SWAP_DATA_MODE
35 static void swapData(struct zsDmaDesc* usbDesc);
38 static void init_usb_desc(struct zsDmaDesc *usbDesc)
40 usbDesc->status = ZM_OWN_BITS_SW;
42 usbDesc->dataSize = 0;
43 usbDesc->totalLen = 0;
44 usbDesc->lastAddr = 0;
45 usbDesc->dataAddr = 0;
46 usbDesc->nextAddr = 0;
49 void _DMAengine_init()
54 void _DMAengine_init_rx_queue(struct zsDmaQueue *q)
57 struct zsDmaDesc *usbDesc;
59 desc = VDESC_alloc_vdesc();
61 usbDesc = VDESC_TO_USBDESC(desc);
62 init_usb_desc(usbDesc);
64 q->head = q->terminator = usbDesc;
68 void _DMAengine_init_tx_queue(struct zsTxDmaQueue *q)
70 _DMAengine_init_rx_queue((struct zsDmaQueue *)q);
71 q->xmited_buf_head = NULL;
72 q->xmited_buf_tail = NULL;
75 #if ENABLE_SW_SWAP_DATA_MODE
77 static void swapData(struct zsDmaDesc* usbDesc)
79 int len = (usbDesc->dataSize & 0xfffffffc) >> 2;
81 A_UINT32 *dataAddr = (A_UINT32 *)usbDesc->dataAddr;
84 if ( ( usbDesc->dataSize & 3 ) != 0 ) {
88 for ( i = 0; i < len; i++ ) {
91 dataAddr[i] = __bswap32(data);
97 void _DMAengine_return_recv_buf(struct zsDmaQueue *q, VBUF *buf)
99 /* Re-link the VDESC of buf into USB descriptor list & queue the descriptors
102 config_queue(q, buf->desc_list);
106 static void config_queue(struct zsDmaQueue *q, VDESC *desc_list)
109 struct zsDmaDesc *usbDesc;
110 struct zsDmaDesc* prevUsbDesc = NULL;
111 struct zsDmaDesc* headUsbDesc;
114 while ( theDesc != NULL ) {
115 usbDesc = (struct zsDmaDesc *)VDESC_get_hw_desc(theDesc);
116 init_usb_desc(usbDesc);
118 theDesc->data_offset = 0; //RAY 0723
119 usbDesc->dataAddr = (volatile u32_t)(theDesc->buf_addr + theDesc->data_offset);
120 usbDesc->dataSize = theDesc->buf_size;
122 if ( prevUsbDesc == NULL ) {
123 headUsbDesc = usbDesc;
124 prevUsbDesc = usbDesc;
126 prevUsbDesc->nextAddr = usbDesc;
127 prevUsbDesc = usbDesc;
130 theDesc = theDesc->next_desc;
133 headUsbDesc->lastAddr = prevUsbDesc;
134 DMA_Engine_reclaim_packet(q, headUsbDesc);
139 //#define MAX_TX_BUF_SIZE ZM_BLOCK_SIZE
140 //#define MAX_TX_BUF_SIZE 1600
142 void _DMAengine_config_rx_queue(struct zsDmaQueue *q, int num_desc, int buf_size)
148 for(i=0; i < num_desc; i++)
150 desc = VDESC_alloc_vdesc();
152 adf_os_assert(desc != NULL);
154 desc->buf_addr = (A_UINT8 *)adf_os_mem_alloc(buf_size);
155 desc->buf_size = buf_size;
156 desc->next_desc = NULL;
157 desc->data_offset = 0;
167 desc->next_desc = head;
172 config_queue(q, head);
175 void _DMAengine_xmit_buf(struct zsTxDmaQueue *q, VBUF *buf)
178 struct zsDmaDesc* usbDesc;
179 struct zsDmaDesc* prevUsbDesc = NULL;
180 struct zsDmaDesc* headUsbDesc;
182 /* Re-link the VDESC of buf into USB descriptor list & queue the descriptors
185 currVdesc = (VDESC *)buf->desc_list;
186 while(currVdesc != NULL) {
188 usbDesc = (struct zsDmaDesc *)currVdesc->hw_desc_buf;
190 init_usb_desc(usbDesc);
191 usbDesc->dataSize = currVdesc->data_size;
192 usbDesc->dataAddr = (volatile u32_t)(currVdesc->buf_addr + currVdesc->data_offset);
196 #if ENABLE_SW_SWAP_DATA_MODE && ENABLE_SWAP_DATA_MODE == 0
200 if ( prevUsbDesc == NULL ) {
201 headUsbDesc = usbDesc;
203 usbDesc->ctrl |= ZM_FS_BIT;
205 // how to get the total len???
206 usbDesc->totalLen = buf->buf_length;
207 prevUsbDesc = usbDesc;
210 prevUsbDesc->nextAddr = usbDesc;
211 prevUsbDesc = usbDesc;
214 currVdesc = currVdesc->next_desc;
217 usbDesc->ctrl |= ZM_LS_BIT;
218 headUsbDesc->lastAddr = usbDesc;
220 if ( q->xmited_buf_head == NULL && q->xmited_buf_tail == NULL ) {
221 q->xmited_buf_head = buf;
222 q->xmited_buf_tail = buf;
223 q->xmited_buf_head->next_buf = q->xmited_buf_tail;
226 q->xmited_buf_tail->next_buf = buf;
227 q->xmited_buf_tail = buf;
230 DMA_Engine_put_packet((struct zsDmaQueue *)q, headUsbDesc);
233 void _DMAengine_flush_xmit(struct zsDmaQueue *q)
237 int _DMAengine_has_compl_packets(struct zsDmaQueue *q)
239 int has_compl_pkts = 0;
241 if ((q->head != q->terminator) &&
242 ((q->head->status & ZM_OWN_BITS_MASK) != ZM_OWN_BITS_HW)) {
246 return has_compl_pkts;
249 VBUF* _DMAengine_reap_recv_buf(struct zsDmaQueue *q)
251 struct zsDmaDesc* desc;
254 //u8_t *tbuf = (u8_t *)desc->dataAddr;
256 desc = DMA_Engine_get_packet(q);
261 #if ENABLE_SW_SWAP_DATA_MODE && ENABLE_SWAP_DATA_MODE == 0
265 buf = VBUF_alloc_vbuf();
266 adf_os_assert(buf != NULL);
268 relinkUSBDescToVdesc(buf, desc);
272 VBUF* _DMAengine_reap_xmited_buf(struct zsTxDmaQueue *q)
274 struct zsDmaDesc* desc;
277 desc = DMA_Engine_get_packet((struct zsDmaQueue *)q);
282 // assert g_hifUSBCtx.upVbufQ.head is not null
283 // assert g_hifUSBCtx.upVbufQ.tail is not null
284 sentBuf = q->xmited_buf_head;
285 if ( q->xmited_buf_head == q->xmited_buf_tail ) {
286 q->xmited_buf_head = NULL;
287 q->xmited_buf_tail = NULL;
289 q->xmited_buf_head = q->xmited_buf_head->next_buf;
292 sentBuf->next_buf = NULL;
293 relinkUSBDescToVdesc(sentBuf, desc);
297 void _DMAengine_desc_dump(struct zsDmaQueue *q)
300 struct zsDmaDesc* tmpDesc;
305 if( tmpDesc == q->terminator )
307 #ifdef DESC_DUMP_BOTH_DESCnDATA
308 A_PRINTF("0x%08x(0x%08x,T)]", tmpDesc, tmpDesc->dataAddr);
310 A_PRINTF("0x%08x(T)]", tmpDesc);
315 #ifdef DESC_DUMP_BOTH_DESCnDATA
316 A_PRINTF("0x%08x(0x%08x,%c)->", tmpDesc, tmpDesc->dataAddr, (tmpDesc->status&ZM_OWN_BITS_HW)?'H':'S');
318 A_PRINTF("0x%08x(%c)->", tmpDesc, (tmpDesc->status&ZM_OWN_BITS_HW)?'H':'S');
326 tmpDesc = tmpDesc->nextAddr;
331 /* the exported entry point into this module. All apis are accessed through
332 * function pointers */
333 void dma_engine_module_install(struct dma_engine_api *apis)
336 apis->_init = _DMAengine_init;
337 apis->_config_rx_queue = _DMAengine_config_rx_queue;
338 apis->_xmit_buf = _DMAengine_xmit_buf;
339 apis->_flush_xmit = _DMAengine_flush_xmit;
340 apis->_reap_recv_buf = _DMAengine_reap_recv_buf;
341 apis->_return_recv_buf = _DMAengine_return_recv_buf;
342 apis->_reap_xmited_buf = _DMAengine_reap_xmited_buf;
343 apis->_swap_data = swapData;
344 apis->_has_compl_packets = _DMAengine_has_compl_packets;
345 apis->_init_rx_queue = _DMAengine_init_rx_queue;
346 apis->_init_tx_queue = _DMAengine_init_tx_queue;
347 apis->_desc_dump = _DMAengine_desc_dump;
348 apis->_get_packet = zfDmaGetPacket;
349 apis->_reclaim_packet = zfDmaReclaimPacket;
350 apis->_put_packet = zfDmaPutPacket;
352 /* save ptr to the ptr to the context for external code to inspect/modify internal module state */
353 //apis->pReserved = &g_pMboxHWContext;
356 static void relinkUSBDescToVdesc(VBUF *buf, struct zsDmaDesc* desc)
359 VDESC *prevVdesc = NULL;
360 struct zsDmaDesc *currDesc = desc;
362 vdesc = VDESC_HW_TO_VDESC(currDesc);
363 buf->desc_list = vdesc;
364 buf->buf_length = currDesc->totalLen;
366 while(currDesc != NULL) {
367 vdesc->data_size = currDesc->dataSize;
368 //vdesc->data_offset = 0; // TODO: bad!!
370 if ( prevVdesc == NULL ) {
373 prevVdesc->next_desc = vdesc;
377 if ( currDesc->ctrl & ZM_LS_BIT ) {
378 vdesc->next_desc = NULL;
382 currDesc = currDesc->nextAddr;
383 vdesc = VDESC_HW_TO_VDESC(currDesc);