Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelv...
[pandora-kernel.git] / drivers / staging / ath6kl / os / linux / ar6000_raw_if.c
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 // All rights reserved.
4 //
5 // 
6 //
7 // Permission to use, copy, modify, and/or distribute this software for any
8 // purpose with or without fee is hereby granted, provided that the above
9 // copyright notice and this permission notice appear in all copies.
10 //
11 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 //
19 //
20 //
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
23
24 #include "ar6000_drv.h"
25
26 #ifdef HTC_RAW_INTERFACE
27
28 static void
29 ar6000_htc_raw_read_cb(void *Context, HTC_PACKET *pPacket)
30 {
31     AR_SOFTC_T        *ar = (AR_SOFTC_T *)Context;
32     raw_htc_buffer    *busy;
33     HTC_RAW_STREAM_ID streamID; 
34     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
35
36     busy = (raw_htc_buffer *)pPacket->pPktContext;
37     A_ASSERT(busy != NULL);
38
39     if (pPacket->Status == A_ECANCELED) {
40         /*
41          * HTC provides A_ECANCELED status when it doesn't want to be refilled
42          * (probably due to a shutdown)
43          */
44         return;
45     }
46
47     streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint);
48     A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED);
49     
50 #ifdef CF
51    if (down_trylock(&arRaw->raw_htc_read_sem[streamID])) {
52 #else
53     if (down_interruptible(&arRaw->raw_htc_read_sem[streamID])) {
54 #endif /* CF */
55         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n"));
56     }
57
58     A_ASSERT((pPacket->Status != A_OK) || 
59              (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN)));
60
61     busy->length = pPacket->ActualLength + HTC_HEADER_LEN;
62     busy->currPtr = HTC_HEADER_LEN;
63     arRaw->read_buffer_available[streamID] = TRUE;
64     //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("raw read cb:  0x%X 0x%X \n", busy->currPtr,busy->length);
65     up(&arRaw->raw_htc_read_sem[streamID]);
66
67     /* Signal the waiting process */
68     AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) read process\n", streamID));
69     wake_up_interruptible(&arRaw->raw_htc_read_queue[streamID]);
70 }
71
72 static void
73 ar6000_htc_raw_write_cb(void *Context, HTC_PACKET *pPacket)
74 {
75     AR_SOFTC_T          *ar = (AR_SOFTC_T  *)Context;
76     raw_htc_buffer      *free;
77     HTC_RAW_STREAM_ID   streamID;
78     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
79     
80     free = (raw_htc_buffer *)pPacket->pPktContext;
81     A_ASSERT(free != NULL);
82
83     if (pPacket->Status == A_ECANCELED) {
84         /*
85          * HTC provides A_ECANCELED status when it doesn't want to be refilled
86          * (probably due to a shutdown)
87          */
88         return;
89     }
90
91     streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint);
92     A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED);
93     
94 #ifdef CF
95     if (down_trylock(&arRaw->raw_htc_write_sem[streamID])) {
96 #else
97     if (down_interruptible(&arRaw->raw_htc_write_sem[streamID])) {
98 #endif
99         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n"));
100     }
101
102     A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN));
103
104     free->length = 0;
105     arRaw->write_buffer_available[streamID] = TRUE;
106     up(&arRaw->raw_htc_write_sem[streamID]);
107
108     /* Signal the waiting process */
109     AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Waking up the StreamID(%d) write process\n", streamID));
110     wake_up_interruptible(&arRaw->raw_htc_write_queue[streamID]);
111 }
112
113 /* connect to a service */
114 static A_STATUS ar6000_connect_raw_service(AR_SOFTC_T        *ar,
115                                            HTC_RAW_STREAM_ID StreamID)
116 {
117     A_STATUS                 status;
118     HTC_SERVICE_CONNECT_RESP response;
119     A_UINT8                  streamNo;
120     HTC_SERVICE_CONNECT_REQ  connect;
121     
122     do {      
123         
124         A_MEMZERO(&connect,sizeof(connect));
125             /* pass the stream ID as meta data to the RAW streams service */
126         streamNo = (A_UINT8)StreamID;
127         connect.pMetaData = &streamNo;
128         connect.MetaDataLength = sizeof(A_UINT8);
129             /* these fields are the same for all endpoints */
130         connect.EpCallbacks.pContext = ar;
131         connect.EpCallbacks.EpTxComplete = ar6000_htc_raw_write_cb;   
132         connect.EpCallbacks.EpRecv = ar6000_htc_raw_read_cb;   
133             /* simple interface, we don't need these optional callbacks */      
134         connect.EpCallbacks.EpRecvRefill = NULL;
135         connect.EpCallbacks.EpSendFull = NULL;
136         connect.MaxSendQueueDepth = RAW_HTC_WRITE_BUFFERS_NUM;  
137         
138             /* connect to the raw streams service, we may be able to get 1 or more
139              * connections, depending on WHAT is running on the target */
140         connect.ServiceID = HTC_RAW_STREAMS_SVC;
141         
142         A_MEMZERO(&response,sizeof(response));
143         
144             /* try to connect to the raw stream, it is okay if this fails with 
145              * status HTC_SERVICE_NO_MORE_EP */
146         status = HTCConnectService(ar->arHtcTarget, 
147                                    &connect,
148                                    &response);
149         
150         if (A_FAILED(status)) {
151             if (response.ConnectRespCode == HTC_SERVICE_NO_MORE_EP) {
152                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC RAW , No more streams allowed \n"));
153                 status = A_OK;    
154             }
155             break;    
156         }
157
158             /* set endpoint mapping for the RAW HTC streams */
159         arSetRawStream2EndpointIDMap(ar,StreamID,response.Endpoint);
160
161         AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("HTC RAW : stream ID: %d, endpoint: %d\n", 
162                         StreamID, arRawStream2EndpointID(ar,StreamID)));
163         
164     } while (FALSE);
165     
166     return status;
167 }
168
169 int ar6000_htc_raw_open(AR_SOFTC_T *ar)
170 {
171     A_STATUS status;
172     int streamID, endPt, count2;
173     raw_htc_buffer *buffer;
174     HTC_SERVICE_ID servicepriority;
175     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
176     if (!arRaw) {
177         arRaw = ar->arRawHtc = A_MALLOC(sizeof(AR_RAW_HTC_T));
178         if (arRaw) {
179             A_MEMZERO(arRaw, sizeof(AR_RAW_HTC_T));
180         }
181     }
182     A_ASSERT(ar->arHtcTarget != NULL);
183     if (!arRaw) {
184         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Faile to allocate memory for HTC RAW interface\n"));
185         return -ENOMEM;
186     }
187     /* wait for target */
188     status = HTCWaitTarget(ar->arHtcTarget);
189         
190     if (A_FAILED(status)) {
191         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTCWaitTarget failed (%d)\n", status));
192         return -ENODEV;  
193     }
194     
195     for (endPt = 0; endPt < ENDPOINT_MAX; endPt++) {
196         arRaw->arEp2RawMapping[endPt] = HTC_RAW_STREAM_NOT_MAPPED;
197     }
198         
199     for (streamID = HTC_RAW_STREAM_0; streamID < HTC_RAW_STREAM_NUM_MAX; streamID++) {
200         /* Initialize the data structures */
201         init_MUTEX(&arRaw->raw_htc_read_sem[streamID]);
202         init_MUTEX(&arRaw->raw_htc_write_sem[streamID]);
203         init_waitqueue_head(&arRaw->raw_htc_read_queue[streamID]);
204         init_waitqueue_head(&arRaw->raw_htc_write_queue[streamID]);
205
206             /* try to connect to the raw service */
207         status = ar6000_connect_raw_service(ar,streamID);
208         
209         if (A_FAILED(status)) {
210             break;    
211         }
212         
213         if (arRawStream2EndpointID(ar,streamID) == 0) {
214             break;    
215         }
216         
217         for (count2 = 0; count2 < RAW_HTC_READ_BUFFERS_NUM; count2 ++) {
218             /* Initialize the receive buffers */
219             buffer = &arRaw->raw_htc_write_buffer[streamID][count2];
220             memset(buffer, 0, sizeof(raw_htc_buffer));
221             buffer = &arRaw->raw_htc_read_buffer[streamID][count2];
222             memset(buffer, 0, sizeof(raw_htc_buffer));
223             
224             SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket,
225                                           buffer,
226                                           buffer->data,
227                                           HTC_RAW_BUFFER_SIZE,
228                                           arRawStream2EndpointID(ar,streamID));
229             
230             /* Queue buffers to HTC for receive */
231             if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != A_OK)
232             {
233                 BMIInit();
234                 return -EIO;
235             }
236         }
237
238         for (count2 = 0; count2 < RAW_HTC_WRITE_BUFFERS_NUM; count2 ++) {
239             /* Initialize the receive buffers */
240             buffer = &arRaw->raw_htc_write_buffer[streamID][count2];
241             memset(buffer, 0, sizeof(raw_htc_buffer));
242         }
243
244         arRaw->read_buffer_available[streamID] = FALSE;
245         arRaw->write_buffer_available[streamID] = TRUE;
246     }
247     
248     if (A_FAILED(status)) {
249         return -EIO;    
250     }
251     
252     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("HTC RAW, number of streams the target supports: %d \n", streamID));
253             
254     servicepriority = HTC_RAW_STREAMS_SVC;  /* only 1 */
255     
256         /* set callbacks and priority list */
257     HTCSetCreditDistribution(ar->arHtcTarget,
258                              ar,
259                              NULL,  /* use default */
260                              NULL,  /* use default */
261                              &servicepriority,
262                              1);
263
264     /* Start the HTC component */
265     if ((status = HTCStart(ar->arHtcTarget)) != A_OK) {
266         BMIInit();
267         return -EIO;
268     }
269
270     (ar)->arRawIfInit = TRUE;
271     
272     return 0;
273 }
274
275 int ar6000_htc_raw_close(AR_SOFTC_T *ar)
276 {
277     A_PRINTF("ar6000_htc_raw_close called \n");
278     HTCStop(ar->arHtcTarget);
279     
280         /* reset the device */
281     ar6000_reset_device(ar->arHifDevice, ar->arTargetType, TRUE, FALSE);
282     /* Initialize the BMI component */
283     BMIInit();
284
285     return 0;
286 }
287
288 raw_htc_buffer *
289 get_filled_buffer(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID)
290 {
291     int count;
292     raw_htc_buffer *busy;
293     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
294
295     /* Check for data */
296     for (count = 0; count < RAW_HTC_READ_BUFFERS_NUM; count ++) {
297         busy = &arRaw->raw_htc_read_buffer[StreamID][count];
298         if (busy->length) {
299             break;
300         }
301     }
302     if (busy->length) {
303         arRaw->read_buffer_available[StreamID] = TRUE;
304     } else {
305         arRaw->read_buffer_available[StreamID] = FALSE;
306     }
307
308     return busy;
309 }
310
311 ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID, 
312                             char __user *buffer, size_t length)
313 {
314     int readPtr;
315     raw_htc_buffer *busy;
316     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
317
318     if (arRawStream2EndpointID(ar,StreamID) == 0) {
319         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID));
320         return -EFAULT;    
321     }
322     
323     if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) {
324         return -ERESTARTSYS;
325     }
326
327     busy = get_filled_buffer(ar,StreamID);
328     while (!arRaw->read_buffer_available[StreamID]) {
329         up(&arRaw->raw_htc_read_sem[StreamID]);
330
331         /* Wait for the data */
332         AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) read process\n", StreamID));
333         if (wait_event_interruptible(arRaw->raw_htc_read_queue[StreamID],
334                                      arRaw->read_buffer_available[StreamID]))
335         {
336             return -EINTR;
337         }
338         if (down_interruptible(&arRaw->raw_htc_read_sem[StreamID])) {
339             return -ERESTARTSYS;
340         }
341         busy = get_filled_buffer(ar,StreamID);
342     }
343
344     /* Read the data */
345     readPtr = busy->currPtr;
346     if (length > busy->length - HTC_HEADER_LEN) {
347         length = busy->length - HTC_HEADER_LEN;
348     }
349     if (copy_to_user(buffer, &busy->data[readPtr], length)) {
350         up(&arRaw->raw_htc_read_sem[StreamID]);
351         return -EFAULT;
352     }
353
354     busy->currPtr += length;
355         
356     if (busy->currPtr == busy->length)
357     {    
358         busy->currPtr = 0;
359         busy->length = 0;        
360         HTC_PACKET_RESET_RX(&busy->HTCPacket);                                          
361         //AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("raw read ioctl:  ep for packet:%d \n", busy->HTCPacket.Endpoint));
362         HTCAddReceivePkt(ar->arHtcTarget, &busy->HTCPacket);
363     }
364     arRaw->read_buffer_available[StreamID] = FALSE;
365     up(&arRaw->raw_htc_read_sem[StreamID]);
366
367     return length;
368 }
369
370 static raw_htc_buffer *
371 get_free_buffer(AR_SOFTC_T *ar, HTC_ENDPOINT_ID StreamID)
372 {
373     int count;
374     raw_htc_buffer *free;
375     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
376
377     free = NULL;
378     for (count = 0; count < RAW_HTC_WRITE_BUFFERS_NUM; count ++) {
379         free = &arRaw->raw_htc_write_buffer[StreamID][count];
380         if (free->length == 0) {
381             break;
382         }
383     }
384     if (!free->length) {
385         arRaw->write_buffer_available[StreamID] = TRUE;
386     } else {
387         arRaw->write_buffer_available[StreamID] = FALSE;
388     }
389
390     return free;
391 }
392
393 ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
394                      char __user *buffer, size_t length)
395 {
396     int writePtr;
397     raw_htc_buffer *free;
398     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
399     if (arRawStream2EndpointID(ar,StreamID) == 0) {
400         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID));
401         return -EFAULT;    
402     }
403     
404     if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) {
405         return -ERESTARTSYS;
406     }
407
408     /* Search for a free buffer */
409     free = get_free_buffer(ar,StreamID);
410
411     /* Check if there is space to write else wait */
412     while (!arRaw->write_buffer_available[StreamID]) {
413         up(&arRaw->raw_htc_write_sem[StreamID]);
414
415         /* Wait for buffer to become free */
416         AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) write process\n", StreamID));
417         if (wait_event_interruptible(arRaw->raw_htc_write_queue[StreamID],
418                                      arRaw->write_buffer_available[StreamID]))
419         {
420             return -EINTR;
421         }
422         if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) {
423             return -ERESTARTSYS;
424         }
425         free = get_free_buffer(ar,StreamID);
426     }
427
428     /* Send the data */
429     writePtr = HTC_HEADER_LEN;
430     if (length > (HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN)) {
431         length = HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN;
432     }
433
434     if (copy_from_user(&free->data[writePtr], buffer, length)) {
435         up(&arRaw->raw_htc_read_sem[StreamID]);
436         return -EFAULT;
437     }
438
439     free->length = length;
440         
441     SET_HTC_PACKET_INFO_TX(&free->HTCPacket,
442                            free,
443                            &free->data[writePtr],
444                            length,
445                            arRawStream2EndpointID(ar,StreamID),
446                            AR6K_DATA_PKT_TAG);
447     
448     HTCSendPkt(ar->arHtcTarget,&free->HTCPacket);
449     
450     arRaw->write_buffer_available[StreamID] = FALSE;
451     up(&arRaw->raw_htc_write_sem[StreamID]);
452
453     return length;
454 }
455 #endif /* HTC_RAW_INTERFACE */