📄 ar6000_drv.c
字号:
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 + -