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

📄 ar6000_drv.c

📁 Linux下SDIO设备的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
                      HIF_INCREMENTAL_ADDRESS);    status = HIFReadWrite(hifDevice,                          WINDOW_DATA_ADDRESS,                          (A_UCHAR *)data,                          sizeof(A_UINT32),                          &request,                          NULL);    if (status != A_OK) {        AR_DEBUG_PRINTF("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data);        return status;    }    status = HIFReadWrite(hifDevice,                          WINDOW_WRITE_ADDR_ADDRESS+1,                          ((A_UCHAR *)(address))+1,                          sizeof(A_UINT32)-1,                          &request,                          NULL);    if (status != A_OK) {        AR_DEBUG_PRINTF("Cannot write initial bytes of 0x%x to WINDOW_WRITE_ADDR_ADDRESS\n", *address);        return status;    }    status = HIFReadWrite(hifDevice,                          WINDOW_WRITE_ADDR_ADDRESS,                          (A_UCHAR *)address,                          sizeof(A_UINT8),                          &request,                          NULL);    if (status != A_OK) {        AR_DEBUG_PRINTF("Cannot write 0x%x to WINDOW_WRITE_ADDR_ADDRESS\n", *address);        return status;    }    return status;}/* * HTC Event handlers */static voidar6000_avail_ev(HTC_TARGET *htcTarget, HTC_ENDPOINT_ID eid, HTC_EVENT_ID event,                HTC_EVENT_INFO *evInfo,                void *arg){    int i;    struct net_device *dev;    AR_SOFTC_T *ar;    int device_index = 0;    AR_DEBUG_PRINTF("ar6000_available\n");    for (i=0; i < MAX_AR6000; i++) {        if (ar6000_devices[i] == NULL) {            break;        }    }    if (i == MAX_AR6000) {        AR_DEBUG_PRINTF("ar6000_available: max devices reached\n");        return;    }    /* Save this. It gives a bit better readability especially since */    /* we use another local "i" variable below.                      */    device_index = i;    A_ASSERT(htcTarget != NULL);    A_ASSERT(event == HTC_TARGET_AVAILABLE);    dev = alloc_etherdev(sizeof(AR_SOFTC_T));    if (dev == NULL) {        AR_DEBUG_PRINTF("ar6000_available: can't alloc etherdev\n");        return;    }    SET_MODULE_OWNER(dev);    ether_setup(dev);    if (dev->priv == NULL) {        printk(KERN_CRIT "ar6000_available: Could not allocate memory\n");        return;    }    A_MEMZERO(dev->priv, sizeof(AR_SOFTC_T));    ar                       = (AR_SOFTC_T *)dev->priv;    ar->arNetDev             = dev;    ar->arHtcTarget          = htcTarget;    ar->arHifDevice          = evInfo->buffer;    ar->arWlanState          = WLAN_ENABLED;    ar6000_init_control_info(ar);    init_waitqueue_head(&arEvent);    sema_init(&ar->arSem, 1);    /*     * If requested, perform some magic which requires no cooperation from     * the Target.  It causes the Target to ignore flash and execute the     * OS from ROM.     *     * This code uses the Diagnostic Window to remap instructions at     * the start of ROM in such a way that on the next CPU reset, the     * ROM code avoids using flash.  Then it uses the Diagnostic     * Window to force a CPU Warm Reset.     *     * This is intended to support recovery from a corrupted flash.     */    if (skipflash)    {        int i;        static struct {                A_UINT32 addr;                A_UINT32 data;        } ForceROM[] = {                /* NB: This is ROM-version dependent. */                {0x00001ff0, 0x175b0027}, /* jump instruction at 0xa0001ff0 */                {0x00001ff4, 0x00000000}, /* nop instruction at 0xa0001ff4 */                {MC_REMAP_TARGET_ADDRESS, 0x00001ff0}, /* remap to 0xa0001ff0 */                {MC_REMAP_COMPARE_ADDRESS, 0x01000040},/* ...from 0xbfc00040 */                {MC_REMAP_SIZE_ADDRESS, 0x00000000},   /* ...1 cache line */                {MC_REMAP_VALID_ADDRESS, 0x00000001},  /* ...remap is valid */                {LOCAL_COUNT_ADDRESS+0x10, 0}, /* clear BMI credit counter */                {RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},        };        AR_DEBUG_PRINTF("Force Target to execute from ROM....\n");        for (i=0; i<sizeof(ForceROM)/sizeof(*ForceROM); i++) {            if (ar6000_WriteRegDiag(ar->arHifDevice,                &ForceROM[i].addr,                &ForceROM[i].data) != A_OK)            {                AR_DEBUG_PRINTF("Cannot force Target to execute ROM!\n");                break;            }        }    }    BMIInit();    if ((BMIGetTargetId(ar->arHifDevice, &ar->arVersion.target_ver)) != A_OK) {        return;    }    spin_lock_init(&ar->arLock);    /* Don't install the init function if BMI is requested */    if(!bmienable)    {        dev->init = ar6000_init;    }    dev->open = &ar6000_open;    dev->stop = &ar6000_close;    dev->hard_start_xmit = &ar6000_data_tx;    dev->get_stats = &ar6000_get_stats;    dev->get_wireless_stats = ar6000_get_iwstats; /*Displayed via proc fs */    /* dev->tx_timeout = ar6000_tx_timeout; */    dev->do_ioctl = &ar6000_ioctl;    dev->watchdog_timeo = AR6000_TX_TIMEOUT;    ar6000_ioctl_iwsetup(&ath_iw_handler_def);    dev->wireless_handlers = &ath_iw_handler_def;    /*     * We need the OS to provide us with more headroom in order to     * perform dix to 802.3, WMI header encap, and the HTC header     */    dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) +        sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN;    /* This runs the init function */    if (register_netdev(dev)) {        AR_DEBUG_PRINTF("ar6000_avail: register_netdev failed\n");        ar6000_destroy(dev);        return;    }    /* We only register the device in the global list if we succeed. */    /* If the device is in the global list, it will be destroyed     */    /* when the module is unloaded.                                  */    ar6000_devices[device_index] = dev;    AR_DEBUG_PRINTF("ar6000_avail: name=%s htcTarget=0x%x, dev=0x%x (%d), ar=0x%x\n",                    dev->name, (A_UINT32)htcTarget, (A_UINT32)dev, device_index,                    (A_UINT32)ar);}static voidar6000_unavail_ev(HTC_TARGET *htcTarget, HTC_ENDPOINT_ID eid,                  HTC_EVENT_ID event, HTC_EVENT_INFO *evInfo, void *arg){    int i;    AR_SOFTC_T *ar;    struct net_device *ar6000_netdev;    for (i=0; i < MAX_AR6000; i++) {        if (ar6000_devices[i] != NULL) {            ar = (AR_SOFTC_T *)ar6000_devices[i]->priv;            if (ar && ar->arHtcTarget == htcTarget) {                ar6000_netdev = ar6000_devices[i];                ar6000_devices[i] = NULL;                ar6000_destroy(ar6000_netdev);            }        }    }}static voidar6000_destroy(struct net_device *dev){    AR_SOFTC_T *ar;    if((dev == NULL) || ((ar = netdev_priv(dev)) == NULL))    {        AR_DEBUG_PRINTF("%s(): Failed to get device structure.\n", __func__);        return;    }    /* Stop the transmit queues */    netif_stop_queue(dev);    /* Disable the target and the interrupts associated with it */    if (ar->arWmiReady == TRUE)    {        if (!bypasswmi)        {            if (ar->arConnected == TRUE || ar->arConnectPending == TRUE)            {                AR_DEBUG_PRINTF("%s(): Disconnect\n", __func__);                AR6000_SPIN_LOCK(&ar->arLock, 0);                ar6000_init_profile_info(ar);                wmi_disconnect_cmd(ar->arWmi);                AR6000_SPIN_UNLOCK(&ar->arLock, 0);            }            /* It's necessary to wait for the tx pending cleaning */            wait_event_interruptible(arEvent,                ar->arTxPending[WMI_CONTROL_MBOX]==0);            ar->arWmiReady  = FALSE;            ar->arConnected = FALSE;            ar->arConnectPending = FALSE;            wmi_shutdown(ar->arWmi);            ar->arWmiEnabled = FALSE;            ar->arWmi = NULL;            ar->arWlanState = WLAN_ENABLED;        }        /* It's necessary to wait for the tx pending cleaning */        wait_event_interruptible(arEvent,            ar->arTxPending[WMI_CONTROL_MBOX]==0);        HTCStop(ar->arHtcTarget);        /* It's necessary to wait for the tx pending cleaning */        wait_event_interruptible(arEvent,            ar->arTxPending[WMI_CONTROL_MBOX]==0);        AR_DEBUG_PRINTF("%s(): WMI and HTC stopped\n", __func__);    }    else    {        AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n",            __func__, (unsigned int) ar, (unsigned int) ar->arWmi);        /* Shut down WMI if we have started it */        if(ar->arWmiEnabled == TRUE)        {            AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__);            wmi_shutdown(ar->arWmi);            ar->arWmiEnabled = FALSE;            ar->arWmi = NULL;        }        /* It's necessary to wait for the tx pending cleaning */        wait_event_interruptible(arEvent,            ar->arTxPending[WMI_CONTROL_MBOX]==0);        HTCStop(ar->arHtcTarget);        /* It's necessary to wait for the tx pending cleaning */        wait_event_interruptible(arEvent,            ar->arTxPending[WMI_CONTROL_MBOX]==0);    }    BMIInit();    /* Done with cookies */    ar6000_cookie_cleanup(ar);    /* Free up the device data structure */    HTCShutDown(ar->arHtcTarget);    unregister_netdev(dev);#ifdef mvlcee31_2_4_20_omap2420_gsm_gprs    kfree(dev);#else    free_netdev(dev);#endif}static voidar6000_init_profile_info(AR_SOFTC_T *ar){    ar->arSsidLen            = 0;    A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));    ar->arNetworkType        = INFRA_NETWORK;    ar->arDot11AuthMode      = OPEN_AUTH;    ar->arAuthMode           = NONE_AUTH;    ar->arPairwiseCrypto     = NONE_CRYPT;    ar->arPairwiseCryptoLen  = 0;    ar->arGroupCrypto        = NONE_CRYPT;    ar->arGroupCryptoLen     = 0;    A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));    A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));    A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));    ar->arBssChannel = 0;}static voidar6000_init_control_info(AR_SOFTC_T *ar){    ar->arWmiEnabled         = FALSE;    ar6000_init_profile_info(ar);    ar->arDefTxKeyIndex      = 0;    A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));    ar->arChannelHint        = 0;    ar->arListenInterval     = MAX_LISTEN_INTERVAL;    ar->arVersion.host_ver   = AR6000_SW_VERSION;    ar->arRssi               = 0;    ar->arTxPwr              = 0;    ar->arTxPwrSet           = FALSE;    ar->arBitRate            = 0;    ar->arMaxRetries         = 0;}static intar6000_open(struct net_device *dev){    /* Wake up the queues */    netif_wake_queue(dev);    return 0;}static intar6000_close(struct net_device *dev){    netif_stop_queue(dev);    return 0;}/* This function does one time initialization for the lifetime of the device */static intar6000_init(struct net_device *dev){    int i;    AR_SOFTC_T *ar;    int endpoint[] = { ENDPOINT1, ENDPOINT2, ENDPOINT3, ENDPOINT4 };    A_STATUS    status;    A_INT32     timeleft;    if((ar = netdev_priv(dev)) == NULL)    {        return(-EIO);    }    /* Do we need to finish the BMI phase */    if(BMIDone(ar->arHifDevice) != A_OK)    {        return -EIO;    }    if (!bypasswmi)    {        if (ar->arVersion.host_ver != ar->arVersion.target_ver) {            A_PRINTF("WARNING: Host version 0x%x does not match Target "                    " version 0x%x!\n",                    ar->arVersion.host_ver, ar->arVersion.target_ver);        }        /* Indicate that WMI is enabled (although not ready yet) */        ar->arWmiEnabled = TRUE;        if ((ar->arWmi = wmi_init((void *) ar)) == NULL)        {            AR_DEBUG_PRINTF("%s() Failed to initialize WMI.\n", __func__);            return(-EIO);        }        AR_DEBUG_PRINTF("%s() Got WMI @ 0x%08x.\n", __func__,            (unsigned int) ar->arWmi);    }    /* Install event handlers for each end point */    for(i = 0; i < (sizeof(endpoint) / sizeof(int)); i++)    {        if(HTCEventReg(ar->arHtcTarget, endpoint[i], HTC_BUFFER_RECEIVED,            ar6000_rx, ar) != A_OK)        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -