📄 hif.c
字号:
/* * Copyright (c) 2004-2006 Atheros Communications Inc. * All rights reserved. * * 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 ------- */CF_PNP_INFO Ids[] = { { .CF_ManufacturerID = MANUFACTURER_ID_BASE | 0xB, .CF_ManufacturerCode = MANUFACTURER_CODE, .CF_FunctionClass = FUNCTION_CLASS, .CF_FunctionNo = 1 }, { .CF_ManufacturerID = MANUFACTURER_ID_BASE | 0xA, .CF_ManufacturerCode = MANUFACTURER_CODE, .CF_FunctionClass = FUNCTION_CLASS, .CF_FunctionNo = 1 }, { .CF_ManufacturerID = MANUFACTURER_ID_BASE | 0x9, .CF_ManufacturerCode = MANUFACTURER_CODE, .CF_FunctionClass = FUNCTION_CLASS, .CF_FunctionNo = 1 }, { .CF_ManufacturerID = MANUFACTURER_ID_BASE | 0x8, .CF_ManufacturerCode = MANUFACTURER_CODE, .CF_FunctionClass = FUNCTION_CLASS, .CF_FunctionNo = 1 }, { } //list is null termintaed};TARGET_FUNCTION_CONTEXT FunctionContext = { .function.pName = "cf_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];A_MUTEX_T lock;#ifdef DEBUGextern A_UINT32 debughif;extern A_UINT32 debugzonelevel;#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){ CF_STATUS status; /* 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.deviceInterruptDisabler = callbacks->deviceInterruptDisabler; htcCallbacks.deviceInterruptEnabler = callbacks->deviceInterruptEnabler; htcCallbacks.dsrHandler = callbacks->dsrHandler; A_MUTEX_INIT(&lock); /* Register with bus driver core */ status = CF_RegisterFunction(&FunctionContext.function); A_ASSERT(CF_SUCCESS(status));}/*Parameters:type - can be of the basic or extended. For SDIO it maps to using a CMD52 or CMD53. For wince SDIO it maps to SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED. For CF this paramter is unused.dmode - byte or block basis. For wince SDIO driver, it maps to SD_IO_BYTE_MODE and SD_IO_BLOCK_MODE. This mode is unused for CF.amode - type of addressing on the target (fixed/incremental). This maps to writing to a REGISTER or a FIFO for CF.*/A_STATUSHIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, HIF_REQUEST *request, void *context){ CFREQUEST cfrequest; CF_STATUS status; A_UINT32 remainingLen; A_UINT32 curPos; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); A_MEMZERO(&cfrequest, sizeof(CFREQUEST)); cfrequest.pDataBuffer = buffer; cfrequest.length = length; /* Changes made to compensate for the changes in htc. For all the mbox reads we are now passing the beginning of the address of the mailbox and the addressing mode is incremental - TODO */ if ((request->direction == HIF_READ) && HIF_IS_MBOX_ADDR(address)) { address += (HIF_MBOX_WIDTH - 1); request->amode = HIF_FIXED_ADDRESS; } if (request->emode == HIF_SYNCHRONOUS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Synchronous\n")); } else if (request->emode == HIF_ASYNCHRONOUS) { 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->direction == HIF_WRITE) { cfrequest.Flags |= CFREQ_FLAGS_DATA_WRITE; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Write\n")); } else if (request->direction == HIF_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) { cfrequest.Flags |= CFREQ_FLAGS_FIXED_ADDRESS; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Fixed\n")); } else if (request->amode == HIF_INCREMENTAL_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; } /* We need to do multiple writes in the case of CF interface * as the MBOX size is limited to 256 bytes */ if ( request->direction == HIF_WRITE && HIF_IS_MBOX_ADDR(address) ) { remainingLen = length;#define BLK_SZ (HIF_MBOX_WIDTH - 2) curPos = 0; while (remainingLen > BLK_SZ) { cfrequest.address = address; cfrequest.length = BLK_SZ; cfrequest.pDataBuffer = &buffer[curPos]; status = CFDEVICE_CALL_REQUESTW_FUNC(device->handle, &cfrequest); if (status != CF_STATUS_SUCCESS) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF Write failed\n")); return status; } curPos += BLK_SZ; remainingLen -= BLK_SZ; } cfrequest.pDataBuffer = &buffer[curPos]; cfrequest.address = address + HIF_MBOX_WIDTH - remainingLen; cfrequest.length = remainingLen; status = CFDEVICE_CALL_REQUESTW_FUNC(device->handle, &cfrequest); if (status != CF_STATUS_SUCCESS) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF Write failed\n")); return status; } } else if ( request->direction == HIF_READ && HIF_IS_MBOX_ADDR(address) ) { // Read from an even address cfrequest.address = address - 1; status = CFDEVICE_CALL_REQUESTW_FUNC(device->handle, &cfrequest); } else { cfrequest.address = address; status = CFDEVICE_CALL_REQUESTB_FUNC(device->handle, &cfrequest); } if (status == CF_STATUS_SUCCESS) { status = A_OK; } else { status = A_ERROR; } return status;}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_UINT32 count; CF_STATUS status = CF_STATUS_SUCCESS; /* Free the bus requests */ for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { busRequest[count].free = TRUE; } /* Unregister with bus driver core */ if (device == NULL) { status = CF_UnregisterFunction(&FunctionContext.function); } A_ASSERT(CF_SUCCESS(status));}voidhifISRHandler(void *context, A_BOOL *callDSR){ A_STATUS status; HIF_DEVICE *device; device = (HIF_DEVICE *)context; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); status = htcCallbacks.deviceInterruptDisabler(device, callDSR); A_ASSERT(status == A_OK);}voidhifDSRHandler(unsigned long context){ A_STATUS status; HIF_DEVICE *device; device = (HIF_DEVICE *)context; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); status = htcCallbacks.dsrHandler(device); A_ASSERT(status == A_OK);}static A_BOOLhifDeviceInserted(CFFUNCTION *function, PCFDEVICE handle){ A_UINT32 count; HIF_DEVICE *device; TARGET_FUNCTION_CONTEXT *functionContext; device = addHifDevice(handle); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); functionContext = (TARGET_FUNCTION_CONTEXT *)function->pContext; /* Allocate the bus requests to be used later */ for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { busRequest[count].free = TRUE; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("busRequest[%d].request = 0x%p, busRequest[%d].free = %d\n", count, &busRequest[count].request, count, busRequest[count].free)); } /* Inform HTC */ if ((htcCallbacks.deviceInsertedHandler(device)) != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device rejected\n")); return FALSE; } return TRUE;}voidHIFAckInterrupt(HIF_DEVICE *device){ htcCallbacks.deviceInterruptEnabler(device); return; /* enable interrupts */ //enable_irq(device->handle->irq);}voidHIFUnMaskInterrupt(HIF_DEVICE *device){ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("HIFUnMaskInterrupt")); CFDEVICE_SET_IRQ_HANDLER(device->handle, hifISRHandler, hifDSRHandler, device);}void HIFMaskInterrupt(HIF_DEVICE *device){ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("HIFMaskInterrupt")); CFDEVICE_SET_IRQ_HANDLER(device->handle, NULL, NULL, device);}static voidhifDeviceRemoved(CFFUNCTION *function, PCFDEVICE handle){ A_STATUS status; HIF_DEVICE *device; device = getHifDevice(handle); status = htcCallbacks.deviceRemovedHandler(device); delHifDevice(handle); A_ASSERT(status == A_OK);}static HIF_DEVICE *addHifDevice(PCFDEVICE handle){ hifDevice[0].handle = handle; return &hifDevice[0];}static HIF_DEVICE *getHifDevice(PCFDEVICE handle){ return &hifDevice[0];}static voiddelHifDevice(PCFDEVICE handle){ hifDevice[0].handle = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -