⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hif.c

📁 linux下的SDIO 驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -