3 * Copyright (c) 2004-2007 Atheros Communications Inc.
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;
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.
20 #include "ar6000_drv.h"
22 #ifdef HTC_RAW_INTERFACE
25 ar6000_htc_raw_read_cb(void *Context
, HTC_PACKET
*pPacket
)
27 AR_SOFTC_T
*ar
= (AR_SOFTC_T
*)Context
;
29 HTC_RAW_STREAM_ID streamID
;
31 busy
= (raw_htc_buffer
*)pPacket
->pPktContext
;
32 A_ASSERT(busy
!= NULL
);
34 if (pPacket
->Status
== A_ECANCELED
) {
36 * HTC provides A_ECANCELED status when it doesn't want to be refilled
37 * (probably due to a shutdown)
42 streamID
= arEndpoint2RawStreamID(ar
,pPacket
->Endpoint
);
43 A_ASSERT(streamID
!= HTC_RAW_STREAM_NOT_MAPPED
);
46 if (down_trylock(&ar
->raw_htc_read_sem
[streamID
])) {
48 if (down_interruptible(&ar
->raw_htc_read_sem
[streamID
])) {
50 AR_DEBUG2_PRINTF("Unable to down the semaphore\n");
53 A_ASSERT((pPacket
->Status
!= A_OK
) ||
54 (pPacket
->pBuffer
== (busy
->data
+ HTC_HEADER_LEN
)));
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
]);
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
]);
68 ar6000_htc_raw_write_cb(void *Context
, HTC_PACKET
*pPacket
)
70 AR_SOFTC_T
*ar
= (AR_SOFTC_T
*)Context
;
72 HTC_RAW_STREAM_ID streamID
;
74 free
= (raw_htc_buffer
*)pPacket
->pPktContext
;
75 A_ASSERT(free
!= NULL
);
77 if (pPacket
->Status
== A_ECANCELED
) {
79 * HTC provides A_ECANCELED status when it doesn't want to be refilled
80 * (probably due to a shutdown)
85 streamID
= arEndpoint2RawStreamID(ar
,pPacket
->Endpoint
);
86 A_ASSERT(streamID
!= HTC_RAW_STREAM_NOT_MAPPED
);
89 if (down_trylock(&ar
->raw_htc_write_sem
[streamID
])) {
91 if (down_interruptible(&ar
->raw_htc_write_sem
[streamID
])) {
93 AR_DEBUG2_PRINTF("Unable to down the semaphore\n");
96 A_ASSERT(pPacket
->pBuffer
== (free
->data
+ HTC_HEADER_LEN
));
99 ar
->write_buffer_available
[streamID
] = TRUE
;
100 up(&ar
->raw_htc_write_sem
[streamID
]);
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
]);
107 /* connect to a service */
108 static A_STATUS
ar6000_connect_raw_service(AR_SOFTC_T
*ar
,
109 HTC_RAW_STREAM_ID StreamID
)
112 HTC_SERVICE_CONNECT_RESP response
;
114 HTC_SERVICE_CONNECT_REQ connect
;
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
;
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
;
137 A_MEMZERO(&response
,sizeof(response
));
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
,
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");
153 /* set endpoint mapping for the RAW HTC streams */
154 arSetRawStream2EndpointIDMap(ar
,StreamID
,response
.Endpoint
);
156 AR_DEBUG_PRINTF("HTC RAW : stream ID: %d, endpoint: %d\n",
157 StreamID
, arRawStream2EndpointID(ar
,StreamID
));
164 int ar6000_htc_raw_open(AR_SOFTC_T
*ar
)
167 int streamID
, endPt
, count2
;
168 raw_htc_buffer
*buffer
;
169 HTC_SERVICE_ID servicepriority
;
171 A_ASSERT(ar
->arHtcTarget
!= NULL
);
173 /* wait for target */
174 status
= HTCWaitTarget(ar
->arHtcTarget
);
176 if (A_FAILED(status
)) {
177 AR_DEBUG_PRINTF("HTCWaitTarget failed (%d)\n", status
);
181 for (endPt
= 0; endPt
< ENDPOINT_MAX
; endPt
++) {
182 ar
->arEp2RawMapping
[endPt
] = HTC_RAW_STREAM_NOT_MAPPED
;
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
]);
192 /* try to connect to the raw service */
193 status
= ar6000_connect_raw_service(ar
,streamID
);
195 if (A_FAILED(status
)) {
199 if (arRawStream2EndpointID(ar
,streamID
) == 0) {
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
));
210 SET_HTC_PACKET_INFO_RX_REFILL(&buffer
->HTCPacket
,
214 arRawStream2EndpointID(ar
,streamID
));
216 /* Queue buffers to HTC for receive */
217 if ((status
= HTCAddReceivePkt(ar
->arHtcTarget
, &buffer
->HTCPacket
)) != A_OK
)
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
));
230 ar
->read_buffer_available
[streamID
] = FALSE
;
231 ar
->write_buffer_available
[streamID
] = TRUE
;
234 if (A_FAILED(status
)) {
238 AR_DEBUG_PRINTF("HTC RAW, number of streams the target supports: %d \n", streamID
);
240 servicepriority
= HTC_RAW_STREAMS_SVC
; /* only 1 */
242 /* set callbacks and priority list */
243 HTCSetCreditDistribution(ar
->arHtcTarget
,
245 NULL
, /* use default */
246 NULL
, /* use default */
250 /* Start the HTC component */
251 if ((status
= HTCStart(ar
->arHtcTarget
)) != A_OK
) {
256 (ar
)->arRawIfInit
= TRUE
;
261 int ar6000_htc_raw_close(AR_SOFTC_T
*ar
)
263 A_PRINTF("ar6000_htc_raw_close called \n");
264 HTCStop(ar
->arHtcTarget
);
266 /* reset the device */
267 ar6000_reset_device(ar
->arHifDevice
, ar
->arTargetType
);
268 /* Initialize the BMI component */
275 get_filled_buffer(AR_SOFTC_T
*ar
, HTC_RAW_STREAM_ID StreamID
)
278 raw_htc_buffer
*busy
;
281 for (count
= 0; count
< RAW_HTC_READ_BUFFERS_NUM
; count
++) {
282 busy
= ar
->raw_htc_read_buffer
[StreamID
][count
];
288 ar
->read_buffer_available
[StreamID
] = TRUE
;
290 ar
->read_buffer_available
[StreamID
] = FALSE
;
296 ssize_t
ar6000_htc_raw_read(AR_SOFTC_T
*ar
, HTC_RAW_STREAM_ID StreamID
,
297 char __user
*buffer
, size_t length
)
300 raw_htc_buffer
*busy
;
302 if (arRawStream2EndpointID(ar
,StreamID
) == 0) {
303 AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID
);
307 if (down_interruptible(&ar
->raw_htc_read_sem
[StreamID
])) {
311 busy
= get_filled_buffer(ar
,StreamID
);
312 while (!ar
->read_buffer_available
[StreamID
]) {
313 up(&ar
->raw_htc_read_sem
[StreamID
]);
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
]))
322 if (down_interruptible(&ar
->raw_htc_read_sem
[StreamID
])) {
325 busy
= get_filled_buffer(ar
,StreamID
);
329 readPtr
= busy
->currPtr
;
330 if (length
> busy
->length
- HTC_HEADER_LEN
) {
331 length
= busy
->length
- HTC_HEADER_LEN
;
333 if (copy_to_user(buffer
, &busy
->data
[readPtr
], length
)) {
334 up(&ar
->raw_htc_read_sem
[StreamID
]);
338 busy
->currPtr
+= length
;
340 //AR_DEBUG_PRINTF("raw read ioctl: currPTR : 0x%X 0x%X \n", busy->currPtr,busy->length);
342 if (busy
->currPtr
== busy
->length
)
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
);
350 ar
->read_buffer_available
[StreamID
] = FALSE
;
351 up(&ar
->raw_htc_read_sem
[StreamID
]);
356 static raw_htc_buffer
*
357 get_free_buffer(AR_SOFTC_T
*ar
, HTC_ENDPOINT_ID StreamID
)
360 raw_htc_buffer
*free
;
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) {
370 ar
->write_buffer_available
[StreamID
] = TRUE
;
372 ar
->write_buffer_available
[StreamID
] = FALSE
;
378 ssize_t
ar6000_htc_raw_write(AR_SOFTC_T
*ar
, HTC_RAW_STREAM_ID StreamID
,
379 char __user
*buffer
, size_t length
)
382 raw_htc_buffer
*free
;
384 if (arRawStream2EndpointID(ar
,StreamID
) == 0) {
385 AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID
);
389 if (down_interruptible(&ar
->raw_htc_write_sem
[StreamID
])) {
393 /* Search for a free buffer */
394 free
= get_free_buffer(ar
,StreamID
);
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
]);
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
]))
407 if (down_interruptible(&ar
->raw_htc_write_sem
[StreamID
])) {
410 free
= get_free_buffer(ar
,StreamID
);
414 writePtr
= HTC_HEADER_LEN
;
415 if (length
> (AR6000_BUFFER_SIZE
- HTC_HEADER_LEN
)) {
416 length
= AR6000_BUFFER_SIZE
- HTC_HEADER_LEN
;
419 if (copy_from_user(&free
->data
[writePtr
], buffer
, length
)) {
420 up(&ar
->raw_htc_read_sem
[StreamID
]);
424 free
->length
= length
;
426 SET_HTC_PACKET_INFO_TX(&free
->HTCPacket
,
428 &free
->data
[writePtr
],
430 arRawStream2EndpointID(ar
,StreamID
),
433 HTCSendPkt(ar
->arHtcTarget
,&free
->HTCPacket
);
435 ar
->write_buffer_available
[StreamID
] = FALSE
;
436 up(&ar
->raw_htc_write_sem
[StreamID
]);
440 #endif /* HTC_RAW_INTERFACE */