📄 hif.c
字号:
/* * Copyright (c) 2004-2005 Atheros Communications Inc. * * Wireless Network driver for Atheros AR6001 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * * This file contains the routines handling the interaction with the SDIO * driver */#include "hif_internal.h"/* ------ Static Variables ------ *//* ------ Global Variable Declarations ------- */SD_PNP_INFO Ids[] = { { .SDIO_ManufacturerID = MANUFACTURER_ID_BASE | 0xB, .SDIO_ManufacturerCode = MANUFACTURER_CODE, .SDIO_FunctionClass = FUNCTION_CLASS, .SDIO_FunctionNo = 1 }, { .SDIO_ManufacturerID = MANUFACTURER_ID_BASE | 0xA, .SDIO_ManufacturerCode = MANUFACTURER_CODE, .SDIO_FunctionClass = FUNCTION_CLASS, .SDIO_FunctionNo = 1 }, { .SDIO_ManufacturerID = MANUFACTURER_ID_BASE | 0x9, .SDIO_ManufacturerCode = MANUFACTURER_CODE, .SDIO_FunctionClass = FUNCTION_CLASS, .SDIO_FunctionNo = 1 }, { .SDIO_ManufacturerID = MANUFACTURER_ID_BASE | 0x8, .SDIO_ManufacturerCode = MANUFACTURER_CODE, .SDIO_FunctionClass = FUNCTION_CLASS, .SDIO_FunctionNo = 1 }, { } //list is null termintaed};TARGET_FUNCTION_CONTEXT FunctionContext = { .function.Version = CT_SDIO_STACK_VERSION_CODE, .function.pName = "sdio_wlan", .function.MaxDevices = 1, .function.NumDevices = 0, .function.pIds = Ids, .function.pProbe = hifDeviceInserted, .function.pRemove = hifDeviceRemoved, .function.pSuspend = NULL, .function.pResume = NULL, .function.pWake = NULL, .function.pContext = &FunctionContext,};HIF_DEVICE hifDevice[HIF_MAX_DEVICES];HTC_CALLBACKS htcCallbacks;BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM];OS_CRITICALSECTION lock;extern A_UINT32 onebitmode;extern A_UINT32 busspeedlow;extern A_UINT32 debughif;#ifdef DEBUG#define ATH_DEBUG_ERROR 1#define ATH_DEBUG_WARN 2#define ATH_DEBUG_TRACE 3#define _AR_DEBUG_PRINTX_ARG(arg...) arg#define AR_DEBUG_PRINTF(lvl, args)\ {if (lvl <= debughif)\ A_PRINTF(KERN_ALERT _AR_DEBUG_PRINTX_ARG args);\ }#else#define AR_DEBUG_PRINTF(lvl, args)#endif/* ------ Functions ------ */voidHIFRegisterCallbacks(HTC_CALLBACKS *callbacks){ SDIO_STATUS status; DBG_ASSERT(callbacks != NULL); /* Store the callback and event handlers */ htcCallbacks.deviceInsertedHandler = callbacks->deviceInsertedHandler; htcCallbacks.deviceRemovedHandler = callbacks->deviceRemovedHandler; htcCallbacks.deviceSuspendHandler = callbacks->deviceSuspendHandler; htcCallbacks.deviceResumeHandler = callbacks->deviceResumeHandler; htcCallbacks.deviceWakeupHandler = callbacks->deviceWakeupHandler; htcCallbacks.rwCompletionHandler = callbacks->rwCompletionHandler; htcCallbacks.dsrHandler = callbacks->dsrHandler; CriticalSectionInit(&lock); /* Register with bus driver core */ status = SDIO_RegisterFunction(&FunctionContext.function); DBG_ASSERT(SDIO_SUCCESS(status));}A_STATUSHIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, HIF_REQUEST *request, void *context){ A_UINT8 rw; A_UINT8 mode; A_UINT8 funcNo; A_UINT8 opcode; A_UINT16 count; SDREQUEST *sdrequest; SDIO_STATUS status; DBG_ASSERT(device != NULL); DBG_ASSERT(device->handle != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); sdrequest = hifAllocateDeviceRequest(device->handle); if (sdrequest == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate bus request\n")); return A_ERROR; } sdrequest->pDataBuffer = buffer; if (request->emode == HIF_SYNCHRONOUS) { sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS; sdrequest->pCompleteContext = NULL; sdrequest->pCompletion = NULL; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Synchronous\n")); } else if (request->emode == HIF_ASYNCHRONOUS) { sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS | SDREQ_FLAGS_TRANS_ASYNC; sdrequest->pCompleteContext = context; sdrequest->pCompletion = hifRWCompletionHandler; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Asynchronous\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid execution mode: %d\n", request->emode)); return A_ERROR; } if (request->type == HIF_EXTENDED_IO) { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Command type: CMD53\n")); sdrequest->Command = CMD53; } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid command type: %d\n", request->type)); return A_ERROR; } if (request->dmode == HIF_BLOCK_BASIS) { mode = CMD53_BLOCK_BASIS; sdrequest->BlockLen = HIF_MBOX_BLOCK_SIZE; sdrequest->BlockCount = length / HIF_MBOX_BLOCK_SIZE; count = sdrequest->BlockCount; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Block mode (BlockLen: %d, BlockCount: %d)\n", sdrequest->BlockLen, sdrequest->BlockCount)); } else if (request->dmode == HIF_BYTE_BASIS) { mode = CMD53_BYTE_BASIS; sdrequest->BlockLen = length; sdrequest->BlockCount = 1; count = sdrequest->BlockLen; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Byte mode (BlockLen: %d, BlockCount: %d)\n", sdrequest->BlockLen, sdrequest->BlockCount)); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid data mode: %d\n", request->dmode)); return A_ERROR; } if ((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3))) { /* * Mailbox write. Adjust the address so that the last byte * falls on the EOM address. */ address += (HIF_MBOX_WIDTH - length); } if (request->direction == HIF_WRITE) { rw = CMD53_WRITE; sdrequest->Flags |= SDREQ_FLAGS_DATA_WRITE; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Write\n")); } else if (request->direction == HIF_READ) { rw = CMD53_READ; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Read\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid direction: %d\n", request->direction)); return A_ERROR; } if (request->amode == HIF_FIXED_ADDRESS) { opcode = CMD53_FIXED_ADDRESS; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Fixed\n")); } else if (request->amode == HIF_INCREMENTAL_ADDRESS) { opcode = CMD53_INCR_ADDRESS; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Incremental\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid address mode: %d\n", request->amode)); return A_ERROR; } funcNo = SDDEVICE_GET_SDIO_FUNCNO(device->handle); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Function number: %d\n", funcNo)); SDIO_SET_CMD53_ARG(sdrequest->Argument, rw, funcNo, mode, opcode, address, count); /* Send the command out */ status = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest); if (status == SDIO_STATUS_PENDING) { DBG_ASSERT(request->emode == HIF_ASYNCHRONOUS); return A_OK; } else if (status == SDIO_STATUS_SUCCESS) { DBG_ASSERT(request->emode == HIF_SYNCHRONOUS); hifFreeDeviceRequest(sdrequest); return A_OK; } return A_ERROR;}A_STATUSHIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen){ A_UINT32 count; switch(opcode) { case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; break; case HIF_DEVICE_GET_MBOX_ADDR: for (count = 0; count < 4; count ++) { ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); } break; default: AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid configuration opcode: %d\n", opcode)); return A_ERROR; } return A_OK;}voidHIFShutDownDevice(HIF_DEVICE *device){ A_UINT8 data; A_UINT32 count; SDIO_STATUS status; SDCONFIG_BUS_MODE_DATA busSettings; SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData; if (device != NULL) { DBG_ASSERT(device->handle != NULL); /* Remove the allocated current if any */ status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_FREE_SLOT_CURRENT, NULL, 0); DBG_ASSERT(SDIO_SUCCESS(status)); /* Disable the card */ fData.EnableFlags = SDCONFIG_DISABLE_FUNC; fData.TimeOut = 1; status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ENABLE_DISABLE, &fData, sizeof(fData)); DBG_ASSERT(SDIO_SUCCESS(status)); /* Perform a soft I/O reset */ data = SDIO_IO_RESET; status = SDLIB_IssueCMD52(device->handle, 0, SDIO_IO_ABORT_REG, &data, 1, 1); DBG_ASSERT(SDIO_SUCCESS(status)); /* * WAR - Codetelligence driver does not seem to shutdown correctly in 1 * bit mode. By default it configures the HC in the 4 bit. Its later in * our driver that we switch to 1 bit mode. If we try to shutdown, the * driver hangs so we revert to 4 bit mode, to be transparent to the * underlying bus driver. */ if (onebitmode) { ZERO_OBJECT(busSettings); busSettings.BusModeFlags = device->handle->pHcd->CardProperties.BusMode; SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags, SDCONFIG_BUS_WIDTH_4_BIT); /* Issue config request to change the bus width to 4 bit */ status = SDLIB_IssueConfig(device->handle, SDCONFIG_BUS_MODE_CTRL, &busSettings, sizeof(SDCONFIG_BUS_MODE_DATA)); DBG_ASSERT(SDIO_SUCCESS(status)); } /* Free the bus requests */ for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { SDDeviceFreeRequest(device->handle, busRequest[count].request); busRequest[count].free = FALSE; } } else { /* Unregister with bus driver core */ status = SDIO_UnregisterFunction(&FunctionContext.function); DBG_ASSERT(SDIO_SUCCESS(status)); }}voidhifRWCompletionHandler(SDREQUEST *request){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -