1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 // All rights reserved.
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.
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.
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
24 #include "ar6000_drv.h"
26 #ifdef HTC_RAW_INTERFACE
29 ar6000_htc_raw_read_cb(void *Context
, struct htc_packet
*pPacket
)
31 struct ar6_softc
*ar
= (struct ar6_softc
*)Context
;
33 HTC_RAW_STREAM_ID streamID
;
34 AR_RAW_HTC_T
*arRaw
= ar
->arRawHtc
;
36 busy
= (raw_htc_buffer
*)pPacket
->pPktContext
;
37 A_ASSERT(busy
!= NULL
);
39 if (pPacket
->Status
== A_ECANCELED
) {
41 * HTC provides A_ECANCELED status when it doesn't want to be refilled
42 * (probably due to a shutdown)
47 streamID
= arEndpoint2RawStreamID(ar
,pPacket
->Endpoint
);
48 A_ASSERT(streamID
!= HTC_RAW_STREAM_NOT_MAPPED
);
51 if (down_trylock(&arRaw
->raw_htc_read_sem
[streamID
])) {
53 if (down_interruptible(&arRaw
->raw_htc_read_sem
[streamID
])) {
55 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Unable to down the semaphore\n"));
58 A_ASSERT((pPacket
->Status
!= 0) ||
59 (pPacket
->pBuffer
== (busy
->data
+ HTC_HEADER_LEN
)));
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
]);
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
]);
73 ar6000_htc_raw_write_cb(void *Context
, struct htc_packet
*pPacket
)
75 struct ar6_softc
*ar
= (struct ar6_softc
*)Context
;
77 HTC_RAW_STREAM_ID streamID
;
78 AR_RAW_HTC_T
*arRaw
= ar
->arRawHtc
;
80 free
= (raw_htc_buffer
*)pPacket
->pPktContext
;
81 A_ASSERT(free
!= NULL
);
83 if (pPacket
->Status
== A_ECANCELED
) {
85 * HTC provides A_ECANCELED status when it doesn't want to be refilled
86 * (probably due to a shutdown)
91 streamID
= arEndpoint2RawStreamID(ar
,pPacket
->Endpoint
);
92 A_ASSERT(streamID
!= HTC_RAW_STREAM_NOT_MAPPED
);
95 if (down_trylock(&arRaw
->raw_htc_write_sem
[streamID
])) {
97 if (down_interruptible(&arRaw
->raw_htc_write_sem
[streamID
])) {
99 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Unable to down the semaphore\n"));
102 A_ASSERT(pPacket
->pBuffer
== (free
->data
+ HTC_HEADER_LEN
));
105 arRaw
->write_buffer_available
[streamID
] = true;
106 up(&arRaw
->raw_htc_write_sem
[streamID
]);
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
]);
113 /* connect to a service */
114 static int ar6000_connect_raw_service(struct ar6_softc
*ar
,
115 HTC_RAW_STREAM_ID StreamID
)
118 struct htc_service_connect_resp response
;
120 struct htc_service_connect_req connect
;
124 A_MEMZERO(&connect
,sizeof(connect
));
125 /* pass the stream ID as meta data to the RAW streams service */
126 streamNo
= (u8
)StreamID
;
127 connect
.pMetaData
= &streamNo
;
128 connect
.MetaDataLength
= sizeof(u8
);
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
;
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
;
142 A_MEMZERO(&response
,sizeof(response
));
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
,
151 if (response
.ConnectRespCode
== HTC_SERVICE_NO_MORE_EP
) {
152 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("HTC RAW , No more streams allowed \n"));
158 /* set endpoint mapping for the RAW HTC streams */
159 arSetRawStream2EndpointIDMap(ar
,StreamID
,response
.Endpoint
);
161 AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW
,("HTC RAW : stream ID: %d, endpoint: %d\n",
162 StreamID
, arRawStream2EndpointID(ar
,StreamID
)));
169 int ar6000_htc_raw_open(struct ar6_softc
*ar
)
172 int streamID
, endPt
, count2
;
173 raw_htc_buffer
*buffer
;
174 HTC_SERVICE_ID servicepriority
;
175 AR_RAW_HTC_T
*arRaw
= ar
->arRawHtc
;
177 arRaw
= ar
->arRawHtc
= A_MALLOC(sizeof(AR_RAW_HTC_T
));
179 A_MEMZERO(arRaw
, sizeof(AR_RAW_HTC_T
));
182 A_ASSERT(ar
->arHtcTarget
!= NULL
);
184 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("Faile to allocate memory for HTC RAW interface\n"));
187 /* wait for target */
188 status
= HTCWaitTarget(ar
->arHtcTarget
);
191 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("HTCWaitTarget failed (%d)\n", status
));
195 for (endPt
= 0; endPt
< ENDPOINT_MAX
; endPt
++) {
196 arRaw
->arEp2RawMapping
[endPt
] = HTC_RAW_STREAM_NOT_MAPPED
;
199 for (streamID
= HTC_RAW_STREAM_0
; streamID
< HTC_RAW_STREAM_NUM_MAX
; streamID
++) {
200 /* Initialize the data structures */
201 sema_init(&arRaw
->raw_htc_read_sem
[streamID
], 1);
202 sema_init(&arRaw
->raw_htc_write_sem
[streamID
], 1);
203 init_waitqueue_head(&arRaw
->raw_htc_read_queue
[streamID
]);
204 init_waitqueue_head(&arRaw
->raw_htc_write_queue
[streamID
]);
206 /* try to connect to the raw service */
207 status
= ar6000_connect_raw_service(ar
,streamID
);
213 if (arRawStream2EndpointID(ar
,streamID
) == 0) {
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
));
224 SET_HTC_PACKET_INFO_RX_REFILL(&buffer
->HTCPacket
,
228 arRawStream2EndpointID(ar
,streamID
));
230 /* Queue buffers to HTC for receive */
231 if ((status
= HTCAddReceivePkt(ar
->arHtcTarget
, &buffer
->HTCPacket
)) != 0)
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
));
244 arRaw
->read_buffer_available
[streamID
] = false;
245 arRaw
->write_buffer_available
[streamID
] = true;
252 AR_DEBUG_PRINTF(ATH_DEBUG_INFO
,("HTC RAW, number of streams the target supports: %d \n", streamID
));
254 servicepriority
= HTC_RAW_STREAMS_SVC
; /* only 1 */
256 /* set callbacks and priority list */
257 HTCSetCreditDistribution(ar
->arHtcTarget
,
259 NULL
, /* use default */
260 NULL
, /* use default */
264 /* Start the HTC component */
265 if ((status
= HTCStart(ar
->arHtcTarget
)) != 0) {
270 (ar
)->arRawIfInit
= true;
275 int ar6000_htc_raw_close(struct ar6_softc
*ar
)
277 A_PRINTF("ar6000_htc_raw_close called \n");
278 HTCStop(ar
->arHtcTarget
);
280 /* reset the device */
281 ar6000_reset_device(ar
->arHifDevice
, ar
->arTargetType
, true, false);
282 /* Initialize the BMI component */
289 get_filled_buffer(struct ar6_softc
*ar
, HTC_RAW_STREAM_ID StreamID
)
292 raw_htc_buffer
*busy
;
293 AR_RAW_HTC_T
*arRaw
= ar
->arRawHtc
;
296 for (count
= 0; count
< RAW_HTC_READ_BUFFERS_NUM
; count
++) {
297 busy
= &arRaw
->raw_htc_read_buffer
[StreamID
][count
];
303 arRaw
->read_buffer_available
[StreamID
] = true;
305 arRaw
->read_buffer_available
[StreamID
] = false;
311 ssize_t
ar6000_htc_raw_read(struct ar6_softc
*ar
, HTC_RAW_STREAM_ID StreamID
,
312 char __user
*buffer
, size_t length
)
315 raw_htc_buffer
*busy
;
316 AR_RAW_HTC_T
*arRaw
= ar
->arRawHtc
;
318 if (arRawStream2EndpointID(ar
,StreamID
) == 0) {
319 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("StreamID(%d) not connected! \n", StreamID
));
323 if (down_interruptible(&arRaw
->raw_htc_read_sem
[StreamID
])) {
327 busy
= get_filled_buffer(ar
,StreamID
);
328 while (!arRaw
->read_buffer_available
[StreamID
]) {
329 up(&arRaw
->raw_htc_read_sem
[StreamID
]);
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
]))
338 if (down_interruptible(&arRaw
->raw_htc_read_sem
[StreamID
])) {
341 busy
= get_filled_buffer(ar
,StreamID
);
345 readPtr
= busy
->currPtr
;
346 if (length
> busy
->length
- HTC_HEADER_LEN
) {
347 length
= busy
->length
- HTC_HEADER_LEN
;
349 if (copy_to_user(buffer
, &busy
->data
[readPtr
], length
)) {
350 up(&arRaw
->raw_htc_read_sem
[StreamID
]);
354 busy
->currPtr
+= length
;
356 if (busy
->currPtr
== busy
->length
)
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
);
364 arRaw
->read_buffer_available
[StreamID
] = false;
365 up(&arRaw
->raw_htc_read_sem
[StreamID
]);
370 static raw_htc_buffer
*
371 get_free_buffer(struct ar6_softc
*ar
, HTC_ENDPOINT_ID StreamID
)
374 raw_htc_buffer
*free
;
375 AR_RAW_HTC_T
*arRaw
= ar
->arRawHtc
;
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) {
385 arRaw
->write_buffer_available
[StreamID
] = true;
387 arRaw
->write_buffer_available
[StreamID
] = false;
393 ssize_t
ar6000_htc_raw_write(struct ar6_softc
*ar
, HTC_RAW_STREAM_ID StreamID
,
394 char __user
*buffer
, size_t length
)
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
));
404 if (down_interruptible(&arRaw
->raw_htc_write_sem
[StreamID
])) {
408 /* Search for a free buffer */
409 free
= get_free_buffer(ar
,StreamID
);
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
]);
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
]))
422 if (down_interruptible(&arRaw
->raw_htc_write_sem
[StreamID
])) {
425 free
= get_free_buffer(ar
,StreamID
);
429 writePtr
= HTC_HEADER_LEN
;
430 if (length
> (HTC_RAW_BUFFER_SIZE
- HTC_HEADER_LEN
)) {
431 length
= HTC_RAW_BUFFER_SIZE
- HTC_HEADER_LEN
;
434 if (copy_from_user(&free
->data
[writePtr
], buffer
, length
)) {
435 up(&arRaw
->raw_htc_read_sem
[StreamID
]);
439 free
->length
= length
;
441 SET_HTC_PACKET_INFO_TX(&free
->HTCPacket
,
443 &free
->data
[writePtr
],
445 arRawStream2EndpointID(ar
,StreamID
),
448 HTCSendPkt(ar
->arHtcTarget
,&free
->HTCPacket
);
450 arRaw
->write_buffer_available
[StreamID
] = false;
451 up(&arRaw
->raw_htc_write_sem
[StreamID
]);
455 #endif /* HTC_RAW_INTERFACE */