4443bb2673314f2c6299379d199fe91b796854f7
[openwrt/staging/yousong.git] / target / linux / s3c24xx / files-2.6.31 / 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 */