4 * @abstract: HIF layer reference implementation for Atheros SDIO stack
6 * @notice: Copyright (c) 2004-2006 Atheros Communications Inc.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation;
13 * Software distributed under the License is distributed on an "AS
14 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15 * implied. See the License for the specific language governing
16 * rights and limitations under the License.
22 #include "hif_internal.h"
24 /* ------ Static Variables ------ */
26 /* ------ Global Variable Declarations ------- */
29 .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xB,
30 .SDIO_ManufacturerCode = MANUFACTURER_CODE,
31 .SDIO_FunctionClass = FUNCTION_CLASS,
35 .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xA,
36 .SDIO_ManufacturerCode = MANUFACTURER_CODE,
37 .SDIO_FunctionClass = FUNCTION_CLASS,
41 .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x9,
42 .SDIO_ManufacturerCode = MANUFACTURER_CODE,
43 .SDIO_FunctionClass = FUNCTION_CLASS,
47 .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x8,
48 .SDIO_ManufacturerCode = MANUFACTURER_CODE,
49 .SDIO_FunctionClass = FUNCTION_CLASS,
53 .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x0,
54 .SDIO_ManufacturerCode = MANUFACTURER_CODE,
55 .SDIO_FunctionClass = FUNCTION_CLASS,
59 .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x1,
60 .SDIO_ManufacturerCode = MANUFACTURER_CODE,
61 .SDIO_FunctionClass = FUNCTION_CLASS,
65 } //list is null termintaed
68 TARGET_FUNCTION_CONTEXT FunctionContext = {
69 .function.Version = CT_SDIO_STACK_VERSION_CODE,
70 .function.pName = "sdio_wlan",
71 .function.MaxDevices = 1,
72 .function.NumDevices = 0,
74 .function.pProbe = hifDeviceInserted,
75 .function.pRemove = hifDeviceRemoved,
76 .function.pSuspend = NULL,
77 .function.pResume = NULL,
78 .function.pWake = NULL,
79 .function.pContext = &FunctionContext,
82 HIF_DEVICE hifDevice[HIF_MAX_DEVICES];
83 HTC_CALLBACKS htcCallbacks;
84 BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM];
85 static BUS_REQUEST *s_busRequestFreeQueue = NULL;
86 OS_CRITICALSECTION lock;
87 extern A_UINT32 onebitmode;
88 extern A_UINT32 busspeedlow;
91 extern A_UINT32 debughif;
92 #define ATH_DEBUG_ERROR 1
93 #define ATH_DEBUG_WARN 2
94 #define ATH_DEBUG_TRACE 3
95 #define _AR_DEBUG_PRINTX_ARG(arg...) arg
96 #define AR_DEBUG_PRINTF(lvl, args)\
97 {if (lvl <= debughif)\
98 A_PRINTF(KERN_ALERT _AR_DEBUG_PRINTX_ARG args);\
101 #define AR_DEBUG_PRINTF(lvl, args)
104 static BUS_REQUEST *hifAllocateBusRequest(void);
105 static void hifFreeBusRequest(BUS_REQUEST *busrequest);
106 static THREAD_RETURN insert_helper_func(POSKERNEL_HELPER pHelper);
107 static void ResetAllCards(void);
109 /* ------ Functions ------ */
110 int HIFInit(HTC_CALLBACKS *callbacks)
113 DBG_ASSERT(callbacks != NULL);
115 /* Store the callback and event handlers */
116 htcCallbacks.deviceInsertedHandler = callbacks->deviceInsertedHandler;
117 htcCallbacks.deviceRemovedHandler = callbacks->deviceRemovedHandler;
118 htcCallbacks.deviceSuspendHandler = callbacks->deviceSuspendHandler;
119 htcCallbacks.deviceResumeHandler = callbacks->deviceResumeHandler;
120 htcCallbacks.deviceWakeupHandler = callbacks->deviceWakeupHandler;
121 htcCallbacks.rwCompletionHandler = callbacks->rwCompletionHandler;
122 htcCallbacks.dsrHandler = callbacks->dsrHandler;
124 CriticalSectionInit(&lock);
126 /* Register with bus driver core */
127 status = SDIO_RegisterFunction(&FunctionContext.function);
128 DBG_ASSERT(SDIO_SUCCESS(status));
134 HIFReadWrite(HIF_DEVICE *device,
146 SDREQUEST *sdrequest;
147 SDIO_STATUS sdiostatus;
148 BUS_REQUEST *busrequest;
149 A_STATUS status = A_OK;
151 DBG_ASSERT(device != NULL);
152 DBG_ASSERT(device->handle != NULL);
154 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device));
157 busrequest = hifAllocateBusRequest();
158 if (busrequest == NULL) {
159 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF Unable to allocate bus request\n"));
160 status = A_NO_RESOURCE;
164 sdrequest = busrequest->request;
165 busrequest->context = context;
167 sdrequest->pDataBuffer = buffer;
168 if (request & HIF_SYNCHRONOUS) {
169 sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS;
170 sdrequest->pCompleteContext = NULL;
171 sdrequest->pCompletion = NULL;
172 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Synchronous\n"));
173 } else if (request & HIF_ASYNCHRONOUS) {
174 sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS |
175 SDREQ_FLAGS_TRANS_ASYNC;
176 sdrequest->pCompleteContext = busrequest;
177 sdrequest->pCompletion = hifRWCompletionHandler;
178 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Asynchronous\n"));
180 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
181 ("Invalid execution mode: 0x%08x\n", request));
186 if (request & HIF_EXTENDED_IO) {
187 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Command type: CMD53\n"));
188 sdrequest->Command = CMD53;
190 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
191 ("Invalid command type: 0x%08x\n", request));
196 if (request & HIF_BLOCK_BASIS) {
197 mode = CMD53_BLOCK_BASIS;
198 sdrequest->BlockLen = HIF_MBOX_BLOCK_SIZE;
199 sdrequest->BlockCount = length / HIF_MBOX_BLOCK_SIZE;
200 count = sdrequest->BlockCount;
201 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
202 ("Block mode (BlockLen: %d, BlockCount: %d)\n",
203 sdrequest->BlockLen, sdrequest->BlockCount));
204 } else if (request & HIF_BYTE_BASIS) {
205 mode = CMD53_BYTE_BASIS;
206 sdrequest->BlockLen = length;
207 sdrequest->BlockCount = 1;
208 count = sdrequest->BlockLen;
209 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
210 ("Byte mode (BlockLen: %d, BlockCount: %d)\n",
211 sdrequest->BlockLen, sdrequest->BlockCount));
213 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
214 ("Invalid data mode: 0x%08x\n", request));
220 /* useful for checking register accesses */
222 A_PRINTF(KERN_ALERT"HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n",
223 request & HIF_WRITE ? "write":"read", address, length);
227 if ((address >= HIF_MBOX_START_ADDR(0)) &&
228 (address <= HIF_MBOX_END_ADDR(3)))
231 DBG_ASSERT(length <= HIF_MBOX_WIDTH);
234 * Mailbox write. Adjust the address so that the last byte
235 * falls on the EOM address.
237 address += (HIF_MBOX_WIDTH - length);
242 if (request & HIF_WRITE) {
244 sdrequest->Flags |= SDREQ_FLAGS_DATA_WRITE;
245 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Write\n"));
246 } else if (request & HIF_READ) {
248 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Read\n"));
250 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
251 ("Invalid direction: 0x%08x\n", request));
256 if (request & HIF_FIXED_ADDRESS) {
257 opcode = CMD53_FIXED_ADDRESS;
258 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Fixed\n"));
259 } else if (request & HIF_INCREMENTAL_ADDRESS) {
260 opcode = CMD53_INCR_ADDRESS;
261 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Incremental\n"));
263 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
264 ("Invalid address mode: 0x%08x\n", request));
269 funcNo = SDDEVICE_GET_SDIO_FUNCNO(device->handle);
270 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Function number: %d\n", funcNo));
271 SDIO_SET_CMD53_ARG(sdrequest->Argument, rw, funcNo,
272 mode, opcode, address, count);
274 /* Send the command out */
275 sdiostatus = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest);
277 if (!SDIO_SUCCESS(sdiostatus)) {
283 if (A_FAILED(status) || (request & HIF_SYNCHRONOUS)) {
284 if (busrequest != NULL) {
285 hifFreeBusRequest(busrequest);
289 if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
290 /* call back async handler on failure */
291 htcCallbacks.rwCompletionHandler(context, status);
298 HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
299 void *config, A_UINT32 configLen)
304 case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
305 ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
306 ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
307 ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
308 ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
311 case HIF_DEVICE_GET_MBOX_ADDR:
312 for (count = 0; count < 4; count ++) {
313 ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count);
316 case HIF_DEVICE_GET_IRQ_PROC_MODE:
317 /* the SDIO stack allows the interrupts to be processed either way, ASYNC or SYNC */
318 *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_ASYNC_SYNC;
321 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
322 ("Unsupported configuration opcode: %d\n", opcode));
330 HIFShutDownDevice(HIF_DEVICE *device)
335 SDCONFIG_BUS_MODE_DATA busSettings;
336 SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData;
338 if (device != NULL) {
339 DBG_ASSERT(device->handle != NULL);
341 /* Remove the allocated current if any */
342 status = SDLIB_IssueConfig(device->handle,
343 SDCONFIG_FUNC_FREE_SLOT_CURRENT, NULL, 0);
344 DBG_ASSERT(SDIO_SUCCESS(status));
346 /* Disable the card */
347 fData.EnableFlags = SDCONFIG_DISABLE_FUNC;
349 status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ENABLE_DISABLE,
350 &fData, sizeof(fData));
351 DBG_ASSERT(SDIO_SUCCESS(status));
353 /* Perform a soft I/O reset */
354 data = SDIO_IO_RESET;
355 status = SDLIB_IssueCMD52(device->handle, 0, SDIO_IO_ABORT_REG,
357 DBG_ASSERT(SDIO_SUCCESS(status));
360 * WAR - Codetelligence driver does not seem to shutdown correctly in 1
361 * bit mode. By default it configures the HC in the 4 bit. Its later in
362 * our driver that we switch to 1 bit mode. If we try to shutdown, the
363 * driver hangs so we revert to 4 bit mode, to be transparent to the
364 * underlying bus driver.
367 ZERO_OBJECT(busSettings);
368 busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(device->handle);
369 SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags,
370 SDCONFIG_BUS_WIDTH_4_BIT);
372 /* Issue config request to change the bus width to 4 bit */
373 status = SDLIB_IssueConfig(device->handle, SDCONFIG_BUS_MODE_CTRL,
375 sizeof(SDCONFIG_BUS_MODE_DATA));
376 DBG_ASSERT(SDIO_SUCCESS(status));
379 /* Free the bus requests */
380 for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
381 SDDeviceFreeRequest(device->handle, busRequest[count].request);
383 /* Clean up the queue */
384 s_busRequestFreeQueue = NULL;
386 /* since we are unloading the driver anyways, reset all cards in case the SDIO card
387 * is externally powered and we are unloading the SDIO stack. This avoids the problem when
388 * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already
391 /* Unregister with bus driver core */
392 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
393 ("Unregistering with the bus driver\n"));
394 status = SDIO_UnregisterFunction(&FunctionContext.function);
395 DBG_ASSERT(SDIO_SUCCESS(status));
400 hifRWCompletionHandler(SDREQUEST *request)
404 BUS_REQUEST *busrequest;
406 if (SDIO_SUCCESS(request->Status)) {
412 DBG_ASSERT(status == A_OK);
413 busrequest = (BUS_REQUEST *) request->pCompleteContext;
414 context = (void *) busrequest->context;
415 /* free the request before calling the callback, in case the
416 * callback submits another request, this guarantees that
417 * there is at least 1 free request available everytime the callback
419 hifFreeBusRequest(busrequest);
420 htcCallbacks.rwCompletionHandler(context, status);
424 hifIRQHandler(void *context)
429 device = (HIF_DEVICE *)context;
430 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device));
431 status = htcCallbacks.dsrHandler(device->htc_handle);
432 DBG_ASSERT(status == A_OK);
436 hifDeviceInserted(SDFUNCTION *function, SDDEVICE *handle)
444 A_UINT16 maxBlockSize;
445 SDCONFIG_BUS_MODE_DATA busSettings;
446 SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData;
447 TARGET_FUNCTION_CONTEXT *functionContext;
448 SDCONFIG_FUNC_SLOT_CURRENT_DATA slotCurrent;
449 SD_BUSCLOCK_RATE currentBusClock;
451 DBG_ASSERT(function != NULL);
452 DBG_ASSERT(handle != NULL);
454 device = addHifDevice(handle);
455 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device));
456 functionContext = (TARGET_FUNCTION_CONTEXT *)function->pContext;
459 * Issue commands to get the manufacturer ID and stuff and compare it
460 * against the rev Id derived from the ID registered during the
461 * initialization process. Report the device only in the case there
462 * is a match. In the case od SDIO, the bus driver has already queried
463 * these details so we just need to use their data structures to get the
464 * relevant values. Infact, the driver has already matched it against
465 * the Ids that we registered with it so we dont need to the step here.
468 /* Configure the SDIO Bus Width */
470 data = SDIO_BUS_WIDTH_1_BIT;
471 status = SDLIB_IssueCMD52(handle, 0, SDIO_BUS_IF_REG, &data, 1, 1);
472 if (!SDIO_SUCCESS(status)) {
473 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
474 ("Unable to set the bus width to 1 bit\n"));
479 /* Get current bus flags */
480 ZERO_OBJECT(busSettings);
482 busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(handle);
484 SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags,
485 SDCONFIG_BUS_WIDTH_1_BIT);
488 /* get the current operating clock, the bus driver sets us up based
489 * on what our CIS reports and what the host controller can handle
490 * we can use this to determine whether we want to drop our clock rate
492 currentBusClock = SDDEVICE_GET_OPER_CLOCK(handle);
493 busSettings.ClockRate = currentBusClock;
495 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
496 ("HIF currently running at: %d \n",currentBusClock));
498 /* see if HIF wants to run at a lower clock speed, we may already be
499 * at that lower clock speed */
500 if (currentBusClock > (SDIO_CLOCK_FREQUENCY_DEFAULT >> busspeedlow)) {
501 busSettings.ClockRate = SDIO_CLOCK_FREQUENCY_DEFAULT >> busspeedlow;
502 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
503 ("HIF overriding clock to %d \n",busSettings.ClockRate));
506 /* Issue config request to override clock rate */
507 status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_CHANGE_BUS_MODE, &busSettings,
508 sizeof(SDCONFIG_BUS_MODE_DATA));
509 if (!SDIO_SUCCESS(status)) {
510 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
511 ("Unable to configure the host clock\n"));
514 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
515 ("Configured clock: %d, Maximum clock: %d\n",
516 busSettings.ActualClockRate,
517 SDDEVICE_GET_MAX_CLOCK(handle)));
521 * Check if the target supports block mode. This result of this check
522 * can be used to implement the HIFReadWrite API.
524 if (SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle)) {
525 /* Limit block size to operational block limit or card function
527 maxBlockSize = min(SDDEVICE_GET_OPER_BLOCK_LEN(handle),
528 SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle));
530 /* check if the card support multi-block transfers */
531 if (!(SDDEVICE_GET_SDIOCARD_CAPS(handle) & SDIO_CAPS_MULTI_BLOCK)) {
532 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Byte basis only\n"));
534 /* Limit block size to max byte basis */
535 maxBlockSize = min(maxBlockSize,
536 (A_UINT16)SDIO_MAX_LENGTH_BYTE_BASIS);
539 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Multi-block capable\n"));
540 maxBlocks = SDDEVICE_GET_OPER_BLOCKS(handle);
541 status = SDLIB_SetFunctionBlockSize(handle, HIF_MBOX_BLOCK_SIZE);
542 if (!SDIO_SUCCESS(status)) {
543 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
544 ("Failed to set block size. Err:%d\n", status));
549 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
550 ("Bytes Per Block: %d bytes, Block Count:%d \n",
551 maxBlockSize, maxBlocks));
553 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
554 ("Function does not support Block Mode!\n"));
558 /* Allocate the slot current */
559 status = SDLIB_GetDefaultOpCurrent(handle, &slotCurrent.SlotCurrent);
560 if (SDIO_SUCCESS(status)) {
561 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Allocating Slot current: %d mA\n",
562 slotCurrent.SlotCurrent));
563 status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ALLOC_SLOT_CURRENT,
564 &slotCurrent, sizeof(slotCurrent));
565 if (!SDIO_SUCCESS(status)) {
566 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
567 ("Failed to allocate slot current %d\n", status));
572 /* Enable the dragon function */
576 fData.EnableFlags = SDCONFIG_ENABLE_FUNC;
577 while ((count++ < SDWLAN_ENABLE_DISABLE_TIMEOUT) && !enabled)
580 status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ENABLE_DISABLE,
581 &fData, sizeof(fData));
582 if (!SDIO_SUCCESS(status)) {
583 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
584 ("Attempting to enable the card again\n"));
588 /* Mark the status as enabled */
592 /* Check if we were succesful in enabling the target */
594 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
595 ("Failed to communicate with the target\n"));
599 /* Allocate the bus requests to be used later */
600 A_MEMZERO(busRequest, sizeof(busRequest));
601 for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
602 if ((busRequest[count].request = SDDeviceAllocRequest(handle)) == NULL){
603 AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate memory\n"));
604 /* TODO: Free the memory that has already been allocated */
607 hifFreeBusRequest(&busRequest[count]);
609 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
610 ("0x%08x = busRequest[%d].request = 0x%08x\n",
611 (unsigned int) &busRequest[count], count,
612 (unsigned int) busRequest[count].request));
615 /* Schedule a worker to handle device inserted, this is a temporary workaround
616 * to fix a deadlock if the device fails to intialize in the insertion handler
617 * The failure causes the instance to shutdown the HIF layer and unregister the
618 * function driver within the busdriver probe context which can deadlock
620 * NOTE: we cannot use the default work queue because that would block
621 * SD bus request processing for all synchronous I/O. We must use a kernel
622 * thread that is creating using the helper library.
625 if (SDIO_SUCCESS(SDLIB_OSCreateHelper(&device->insert_helper,
628 device->helper_started = TRUE;
634 static THREAD_RETURN insert_helper_func(POSKERNEL_HELPER pHelper)
638 * Adding a wait of around a second before we issue the very first
639 * command to dragon. During the process of loading/unloading the
640 * driver repeatedly it was observed that we get a data timeout
641 * while accessing function 1 registers in the chip. The theory at
642 * this point is that some initialization delay in dragon is
643 * causing the SDIO state in dragon core to be not ready even after
644 * the ready bit indicates that function 1 is ready. Accomodating
645 * for this behavior by adding some delay in the driver before it
646 * issues the first command after switching on dragon. Need to
647 * investigate this a bit more - TODO
652 if ((htcCallbacks.deviceInsertedHandler(SD_GET_OS_HELPER_CONTEXT(pHelper))) != A_OK) {
653 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device rejected\n"));
660 HIFAckInterrupt(HIF_DEVICE *device)
663 DBG_ASSERT(device != NULL);
664 DBG_ASSERT(device->handle != NULL);
666 /* Acknowledge our function IRQ */
667 status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ACK_IRQ,
669 DBG_ASSERT(SDIO_SUCCESS(status));
673 HIFUnMaskInterrupt(HIF_DEVICE *device)
677 DBG_ASSERT(device != NULL);
678 DBG_ASSERT(device->handle != NULL);
680 /* Register the IRQ Handler */
681 SDDEVICE_SET_IRQ_HANDLER(device->handle, hifIRQHandler, device);
683 /* Unmask our function IRQ */
684 status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_UNMASK_IRQ,
686 DBG_ASSERT(SDIO_SUCCESS(status));
689 void HIFMaskInterrupt(HIF_DEVICE *device)
692 DBG_ASSERT(device != NULL);
693 DBG_ASSERT(device->handle != NULL);
695 /* Mask our function IRQ */
696 status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_MASK_IRQ,
698 DBG_ASSERT(SDIO_SUCCESS(status));
700 /* Unregister the IRQ Handler */
701 SDDEVICE_SET_IRQ_HANDLER(device->handle, NULL, NULL);
704 static BUS_REQUEST *hifAllocateBusRequest(void)
706 BUS_REQUEST *busrequest;
709 CriticalSectionAcquire(&lock);
711 /* Remove first in list */
712 if((busrequest = s_busRequestFreeQueue) != NULL)
714 s_busRequestFreeQueue = busrequest->next;
718 CriticalSectionRelease(&lock);
724 hifFreeBusRequest(BUS_REQUEST *busrequest)
726 DBG_ASSERT(busrequest != NULL);
729 CriticalSectionAcquire(&lock);
731 /* Insert first in list */
732 busrequest->next = s_busRequestFreeQueue;
733 s_busRequestFreeQueue = busrequest;
736 CriticalSectionRelease(&lock);
740 hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *handle)
744 DBG_ASSERT(function != NULL);
745 DBG_ASSERT(handle != NULL);
747 device = getHifDevice(handle);
748 status = htcCallbacks.deviceRemovedHandler(device->htc_handle, A_OK);
750 /* cleanup the helper thread */
751 if (device->helper_started) {
752 SDLIB_OSDeleteHelper(&device->insert_helper);
753 device->helper_started = FALSE;
756 delHifDevice(handle);
757 DBG_ASSERT(status == A_OK);
761 addHifDevice(SDDEVICE *handle)
763 DBG_ASSERT(handle != NULL);
764 hifDevice[0].handle = handle;
765 return &hifDevice[0];
769 getHifDevice(SDDEVICE *handle)
771 DBG_ASSERT(handle != NULL);
772 return &hifDevice[0];
776 delHifDevice(SDDEVICE *handle)
778 DBG_ASSERT(handle != NULL);
779 hifDevice[0].handle = NULL;
783 HIFGetOSDevice(HIF_DEVICE *device)
785 return &device->handle->Device->dev;
788 static void ResetAllCards(void)
794 data = SDIO_IO_RESET;
796 /* set the I/O CARD reset bit:
797 * NOTE: we are exploiting a "feature" of the SDIO core that resets the core when you
798 * set the RES bit in the SDIO_IO_ABORT register. This bit however "normally" resets the
799 * I/O functions leaving the SDIO core in the same state (as per SDIO spec).
800 * In this design, this reset can be used to reset the SDIO core itself */
801 for (i = 0; i < HIF_MAX_DEVICES; i++) {
802 if (hifDevice[i].handle != NULL) {
803 AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
804 ("Issuing I/O Card reset for instance: %d \n",i));
805 /* set the I/O Card reset bit */
806 status = SDLIB_IssueCMD52(hifDevice[i].handle,
807 0, /* function 0 space */
817 void HIFSetHandle(void *hif_handle, void *handle)
819 HIF_DEVICE *device = (HIF_DEVICE *) hif_handle;
821 device->htc_handle = handle;