Initial cut of the open ath9k htc firmware.
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / build / magpie_1_1 / sboot / dma_engine / src / dma_engine.c
1 /*
2  * @File: dma_engine.c
3  * 
4  * @Abstract: DMA engine for Magpie
5  * 
6  * @Notes:
7  * 
8  * Copyright (c) 2008 Atheros Communications Inc.
9  * All rights reserved.
10  *
11  */
12 #include "sys_cfg.h"
13 #include "dt_defs.h"
14 #include "reg_defs.h"
15 #include "desc.h"
16
17 #include <osapi.h>
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>
24
25 //#include "HIF_usb.h"
26
27 //HIF_USB_CONTEXT g_hifUSBCtx;
28
29 #define VDESC_TO_USBDESC(vdesc)     (struct zsDmaDesc *)((vdesc)->hw_desc_buf)
30
31 static void relinkUSBDescToVdesc(VBUF *buf, struct zsDmaDesc* desc);
32 static void config_queue(struct zsDmaQueue *q, VDESC *desc_list);
33
34 #if ENABLE_SW_SWAP_DATA_MODE
35 static void swapData(struct zsDmaDesc* usbDesc);
36 #endif
37
38 static void init_usb_desc(struct zsDmaDesc *usbDesc)
39 {
40     usbDesc->status = ZM_OWN_BITS_SW;
41     usbDesc->ctrl = 0;
42     usbDesc->dataSize = 0;
43     usbDesc->totalLen = 0;
44     usbDesc->lastAddr = 0;
45     usbDesc->dataAddr = 0;
46     usbDesc->nextAddr = 0;    
47 }
48
49 void _DMAengine_init() 
50 {
51
52 }
53
54 void _DMAengine_init_rx_queue(struct zsDmaQueue *q) 
55 {
56     VDESC *desc;
57     struct zsDmaDesc *usbDesc;
58     
59     desc = VDESC_alloc_vdesc();
60     if ( desc != NULL ) {
61         usbDesc = VDESC_TO_USBDESC(desc);
62         init_usb_desc(usbDesc);
63         
64         q->head = q->terminator = usbDesc;
65     }   
66 }
67
68 void _DMAengine_init_tx_queue(struct zsTxDmaQueue *q) 
69 {
70     _DMAengine_init_rx_queue((struct zsDmaQueue *)q);
71     q->xmited_buf_head = NULL;
72     q->xmited_buf_tail = NULL;     
73 }
74
75 #if ENABLE_SW_SWAP_DATA_MODE
76
77 static void swapData(struct zsDmaDesc* usbDesc)
78 {
79     int len = (usbDesc->dataSize & 0xfffffffc) >> 2;
80     int i;
81     A_UINT32 *dataAddr = (A_UINT32 *)usbDesc->dataAddr;
82     A_UINT32 data;
83     
84     if ( ( usbDesc->dataSize & 3 ) != 0 ) {
85         len += 1;
86     }
87     
88     for ( i = 0; i < len; i++ ) {
89         data = dataAddr[i];
90         
91         dataAddr[i] = __bswap32(data);
92     }    
93 }
94
95 #endif
96
97 void _DMAengine_return_recv_buf(struct zsDmaQueue *q, VBUF *buf)
98 {    
99     /* Re-link the VDESC of buf into USB descriptor list & queue the descriptors 
100        into downQ
101      */     
102     config_queue(q, buf->desc_list);   
103     VBUF_free_vbuf(buf);              
104 }
105
106 static void config_queue(struct zsDmaQueue *q, VDESC *desc_list)
107 {   
108     VDESC *theDesc;
109     struct zsDmaDesc *usbDesc;
110     struct zsDmaDesc* prevUsbDesc = NULL;
111     struct zsDmaDesc* headUsbDesc;
112         
113     theDesc = desc_list;
114     while ( theDesc != NULL ) {            
115         usbDesc = (struct zsDmaDesc *)VDESC_get_hw_desc(theDesc);
116         init_usb_desc(usbDesc);
117        
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;
121         
122         if ( prevUsbDesc == NULL ) {
123             headUsbDesc = usbDesc;
124             prevUsbDesc = usbDesc;
125         } else {
126             prevUsbDesc->nextAddr = usbDesc;
127             prevUsbDesc = usbDesc;
128         }                
129         
130         theDesc = theDesc->next_desc;
131     }
132     
133     headUsbDesc->lastAddr = prevUsbDesc;
134     DMA_Engine_reclaim_packet(q, headUsbDesc);   
135                     
136     return;
137 }
138
139 //#define MAX_TX_BUF_SIZE            ZM_BLOCK_SIZE
140 //#define MAX_TX_BUF_SIZE            1600
141
142 void _DMAengine_config_rx_queue(struct zsDmaQueue *q, int num_desc, int buf_size)
143 {
144     int i;
145     VDESC *desc;
146     VDESC *head = NULL;
147         
148     for(i=0; i < num_desc; i++)
149     {
150         desc = VDESC_alloc_vdesc();
151         
152         adf_os_assert(desc != NULL);
153         
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;
158         desc->data_size = 0;
159         desc->control = 0;
160                
161         if ( head == NULL )
162         {
163             head = desc;
164         }
165         else
166         {
167             desc->next_desc = head;
168             head = desc;
169         }
170     }         
171     
172     config_queue(q, head);          
173 }
174
175 void _DMAengine_xmit_buf(struct zsTxDmaQueue *q, VBUF *buf)
176 {
177     VDESC *currVdesc;
178     struct zsDmaDesc* usbDesc;
179     struct zsDmaDesc* prevUsbDesc = NULL;
180     struct zsDmaDesc* headUsbDesc;   
181         
182     /* Re-link the VDESC of buf into USB descriptor list & queue the descriptors 
183        into upQ
184      */
185     currVdesc = (VDESC *)buf->desc_list;
186     while(currVdesc != NULL) {
187         
188         usbDesc = (struct zsDmaDesc *)currVdesc->hw_desc_buf;
189                 
190         init_usb_desc(usbDesc);
191         usbDesc->dataSize = currVdesc->data_size;
192         usbDesc->dataAddr = (volatile u32_t)(currVdesc->buf_addr + currVdesc->data_offset);
193         usbDesc->ctrl = 0;
194         usbDesc->status = 0;
195
196 #if ENABLE_SW_SWAP_DATA_MODE && ENABLE_SWAP_DATA_MODE == 0
197         swapData(usbDesc);
198 #endif
199
200         if ( prevUsbDesc == NULL ) {
201             headUsbDesc = usbDesc;
202             
203             usbDesc->ctrl |= ZM_FS_BIT;
204             
205             // how to get the total len???
206             usbDesc->totalLen = buf->buf_length;
207             prevUsbDesc = usbDesc;
208         }
209         else {
210             prevUsbDesc->nextAddr = usbDesc;
211             prevUsbDesc = usbDesc;
212         }
213              
214         currVdesc = currVdesc->next_desc;
215     }
216
217     usbDesc->ctrl |= ZM_LS_BIT;
218     headUsbDesc->lastAddr = usbDesc;
219
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;
224     }
225     else {
226         q->xmited_buf_tail->next_buf = buf;
227         q->xmited_buf_tail = buf;
228     }
229
230     DMA_Engine_put_packet((struct zsDmaQueue *)q, headUsbDesc); 
231 }
232     
233 void _DMAengine_flush_xmit(struct zsDmaQueue *q)
234 {
235 }
236
237 int _DMAengine_has_compl_packets(struct zsDmaQueue *q)
238 {
239     int has_compl_pkts = 0;
240     
241     if ((q->head != q->terminator) && 
242         ((q->head->status & ZM_OWN_BITS_MASK) != ZM_OWN_BITS_HW)) {
243         has_compl_pkts = 1;            
244     }
245     
246     return has_compl_pkts;
247 }
248     
249 VBUF* _DMAengine_reap_recv_buf(struct zsDmaQueue *q)
250 {
251     struct zsDmaDesc* desc;
252     VBUF *buf;
253     //int i;
254     //u8_t *tbuf = (u8_t *)desc->dataAddr;
255             
256     desc = DMA_Engine_get_packet(q);            
257     
258     if(!desc)
259        return NULL;
260
261 #if ENABLE_SW_SWAP_DATA_MODE && ENABLE_SWAP_DATA_MODE == 0
262     swapData(desc);
263 #endif
264     
265     buf = VBUF_alloc_vbuf();
266     adf_os_assert(buf != NULL);
267     
268     relinkUSBDescToVdesc(buf, desc);
269     return buf;
270 }
271     
272 VBUF* _DMAengine_reap_xmited_buf(struct zsTxDmaQueue *q)
273 {
274     struct zsDmaDesc* desc;
275     VBUF *sentBuf;
276     
277     desc = DMA_Engine_get_packet((struct zsDmaQueue *)q);
278     
279     if(!desc)
280        return NULL;
281
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;
288     } else {        
289         q->xmited_buf_head = q->xmited_buf_head->next_buf;       
290     }
291     
292     sentBuf->next_buf = NULL;
293     relinkUSBDescToVdesc(sentBuf, desc);
294     return sentBuf;
295 }
296
297 void _DMAengine_desc_dump(struct zsDmaQueue *q)
298 {
299     u32_t i=0;
300     struct zsDmaDesc* tmpDesc;
301         
302     tmpDesc = q->head;
303
304     do {
305         if( tmpDesc == q->terminator )
306         {
307 #ifdef DESC_DUMP_BOTH_DESCnDATA
308             A_PRINTF("0x%08x(0x%08x,T)]", tmpDesc, tmpDesc->dataAddr);
309 #else
310             A_PRINTF("0x%08x(T)]", tmpDesc);
311 #endif
312             break;
313         }
314         else
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');
317 #else
318             A_PRINTF("0x%08x(%c)->", tmpDesc, (tmpDesc->status&ZM_OWN_BITS_HW)?'H':'S');
319 #endif
320         
321         if( (++i%5)==0 ) 
322         {
323             A_PRINTF("\n\r   ");
324         }   
325         
326         tmpDesc = tmpDesc->nextAddr;            
327     }while(1);   
328     A_PRINTF("\n\r"); 
329 }
330     
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)
334 {    
335         /* hook in 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;
351     
352         /* save ptr to the ptr to the context for external code to inspect/modify internal module state */
353     //apis->pReserved = &g_pMboxHWContext;
354 }
355  
356 static void relinkUSBDescToVdesc(VBUF *buf, struct zsDmaDesc* desc)
357 {
358     VDESC *vdesc;
359     VDESC *prevVdesc = NULL;
360     struct zsDmaDesc *currDesc = desc;
361                  
362     vdesc = VDESC_HW_TO_VDESC(currDesc);          
363     buf->desc_list = vdesc;
364     buf->buf_length = currDesc->totalLen;        
365     
366     while(currDesc != NULL) {      
367         vdesc->data_size = currDesc->dataSize;                   
368         //vdesc->data_offset = 0; // TODO: bad!!
369         
370         if ( prevVdesc == NULL ) {
371             prevVdesc = vdesc;
372         } else {
373             prevVdesc->next_desc = vdesc;
374             prevVdesc = vdesc;
375         }
376         
377         if ( currDesc->ctrl & ZM_LS_BIT ) {
378             vdesc->next_desc = NULL;
379             currDesc = NULL;
380             break;
381         } else {
382             currDesc = currDesc->nextAddr;
383             vdesc = VDESC_HW_TO_VDESC(currDesc);
384         }
385     }        
386 }