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