1/* 2* Bcmnet.c 3* 4*Copyright (C) 2010 Beceem Communications, Inc. 5* 6*This program is free software: you can redistribute it and/or modify 7*it under the terms of the GNU General Public License version 2 as 8*published by the Free Software Foundation. 9* 10*This program is distributed in the hope that it will be useful,but 11*WITHOUT ANY WARRANTY; without even the implied warranty of 12*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13*See the GNU General Public License for more details. 14* 15*You should have received a copy of the GNU General Public License 16*along with this program. If not, write to the Free Software Foundation, Inc., 17*51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18* 19*/ 20 21 22#include<headers.h> 23 24static INT bcm_notify_event(struct notifier_block *nb, ULONG event, PVOID dev) 25{ 26 struct net_device *ndev = (struct net_device*)dev; 27 PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); 28 //PMINI_ADAPTER Adapter = (PMINI_ADAPTER)ndev->priv; 29 if(strncmp(ndev->name,gblpnetdev->name,5)==0) 30 { 31 switch(event) 32 { 33 case NETDEV_CHANGEADDR: 34 case NETDEV_GOING_DOWN: 35 /*ignore this */ 36 break; 37 case NETDEV_DOWN: 38 break; 39 40 case NETDEV_UP: 41 break; 42 43 case NETDEV_REGISTER: 44 /* Increment the Reference Count for "veth0" */ 45 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Register RefCount: %x\n", 46 atomic_read(&ndev->refcnt)); 47 atomic_inc(&ndev->refcnt); 48 break; 49 50 case NETDEV_UNREGISTER: 51 /* Decrement the Reference Count for "veth0" */ 52 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unregister RefCnt: %x\n", 53 atomic_read(&ndev->refcnt)); 54 atomic_dec(&ndev->refcnt); 55 if((int)atomic_read(&ndev->refcnt) < 0) 56 atomic_set(&ndev->refcnt, 0); 57 break; 58 }; 59 } 60 return NOTIFY_DONE; 61} 62 63/* Notifier block to receive netdevice events */ 64static struct notifier_block bcm_notifier_block = 65{ 66 .notifier_call = bcm_notify_event, 67}; 68 69struct net_device *gblpnetdev; 70/***************************************************************************************/ 71/* proto-type of lower function */ 72#ifdef BCM_SHM_INTERFACE 73const char *bcmVirtDeviceName="bcmeth"; 74#endif 75 76static INT bcm_open(struct net_device *dev) 77{ 78 PMINI_ADAPTER Adapter = NULL ; //(PMINI_ADAPTER)dev->priv; 79 Adapter = GET_BCM_ADAPTER(dev); 80 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "======>"); 81 if(Adapter->fw_download_done==FALSE) 82 return -EINVAL; 83 Adapter->if_up=1; 84 if(Adapter->LinkUpStatus == 1){ 85 if(netif_queue_stopped(Adapter->dev)){ 86 netif_carrier_on(Adapter->dev); 87 netif_start_queue(Adapter->dev); 88 } 89 } 90 91 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "<======"); 92 return 0; 93} 94 95static INT bcm_close(struct net_device *dev) 96{ 97 PMINI_ADAPTER Adapter = NULL ;//gpadapter ; 98 Adapter = GET_BCM_ADAPTER(dev); 99 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "=====>"); 100 Adapter->if_up=0; 101 if(!netif_queue_stopped(dev)) { 102 netif_carrier_off(dev); 103 netif_stop_queue(dev); 104 } 105 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"<====="); 106 return 0; 107} 108 109static struct net_device_stats *bcm_get_stats(struct net_device *dev) 110{ 111 PLINUX_DEP_DATA pLinuxData=NULL; 112 PMINI_ADAPTER Adapter = NULL ;// gpadapter ; 113 Adapter = GET_BCM_ADAPTER(dev); 114 pLinuxData = (PLINUX_DEP_DATA)(Adapter->pvOsDepData); 115 116 //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Dev = %p, pLinuxData = %p", dev, pLinuxData); 117 pLinuxData->netstats.rx_packets=atomic_read(&Adapter->RxRollOverCount)*64*1024+Adapter->PrevNumRecvDescs; 118 pLinuxData->netstats.rx_bytes=atomic_read(&Adapter->GoodRxByteCount)+atomic_read(&Adapter->BadRxByteCount); 119 pLinuxData->netstats.rx_dropped=atomic_read(&Adapter->RxPacketDroppedCount); 120 pLinuxData->netstats.rx_errors=atomic_read(&Adapter->RxPacketDroppedCount); 121 pLinuxData->netstats.rx_length_errors=0; 122 pLinuxData->netstats.rx_frame_errors=0; 123 pLinuxData->netstats.rx_crc_errors=0; 124 pLinuxData->netstats.tx_bytes=atomic_read(&Adapter->GoodTxByteCount); 125 pLinuxData->netstats.tx_packets=atomic_read(&Adapter->TxTotalPacketCount); 126 pLinuxData->netstats.tx_dropped=atomic_read(&Adapter->TxDroppedPacketCount); 127 128 return &(pLinuxData->netstats); 129} 130 131 132#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) 133static const struct net_device_ops bcm_netdev_ops = { 134.ndo_open = bcm_open, 135.ndo_stop = bcm_close, 136.ndo_get_stats = bcm_get_stats, 137.ndo_start_xmit = bcm_transmit, 138}; 139#endif 140 141 142/** 143@ingroup init_functions 144Register other driver entry points with the kernel 145*/ 146int register_networkdev(PMINI_ADAPTER Adapter) 147{ 148 int result=0, reg_to_os = TRUE; 149#ifdef BCM_SHM_INTERFACE 150 int value = 0; 151#endif 152 153#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) 154 int *temp = NULL ; 155#endif 156 Adapter->dev = alloc_etherdev(sizeof(PMINI_ADAPTER)); 157 if(!Adapter->dev) 158 { 159 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "ERR: No Dev"); 160 return -ENOMEM; 161 } 162 gblpnetdev = Adapter->dev; 163#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 164 Adapter->dev->priv = Adapter; 165#else 166 temp = netdev_priv(Adapter->dev); 167 *temp = (UINT)Adapter; 168#endif 169 //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "init adapterptr: %x %x\n", (UINT)Adapter, temp); 170#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) 171 Adapter->dev->open = bcm_open; 172 Adapter->dev->stop = bcm_close; 173 Adapter->dev->get_stats = bcm_get_stats; 174 Adapter->dev->hard_start_xmit = bcm_transmit; 175#else 176 Adapter->dev->netdev_ops = &bcm_netdev_ops; 177#endif 178 179 Adapter->dev->hard_header_len = ETH_HLEN + LEADER_SIZE; 180 Adapter->dev->mtu = MTU_SIZE; 181 182 /* Read the MAC Address from EEPROM */ 183 ReadMacAddressFromNVM(Adapter); 184 185 186#ifndef BCM_SHM_INTERFACE 187 188 /* Register the notifier block for getting netdevice events */ 189 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Registering netdevice notifier\n"); 190 result = register_netdevice_notifier(&bcm_notifier_block); 191 if(result) 192 { 193 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM Notifier Block did not get registered"); 194 Adapter->bNetdeviceNotifierRegistered = FALSE; 195 return result; 196 } 197 else 198 { 199 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM Notifier got Registered"); 200 Adapter->bNetdeviceNotifierRegistered = TRUE; 201 } 202 203#else 204 205 strcpy(Adapter->dev->name, bcmVirtDeviceName); //Copy the device name 206 rdmalt(Adapter,VEOSHM_OLD_SCHEME_START, &value, sizeof(value)); 207 208 if((Adapter->CPUId == WP_CPU_ID) && (value != CPE_O_SCHEME_MAGIC_PATTERN)) 209 reg_to_os = FALSE; 210 211#endif 212 213 if(reg_to_os == FALSE) 214 { 215 printk("Not registering to OS\n"); 216 Adapter->if_up = 1; 217 } 218 else 219 { 220 result = register_netdev(Adapter->dev); 221 if (!result) 222 { 223 Adapter->bNetworkInterfaceRegistered = TRUE ; 224 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Beceem Network device name is %s!", Adapter->dev->name); 225 } 226 else 227 { 228 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Network device can not be registered!"); 229 Adapter->bNetworkInterfaceRegistered = FALSE ; 230 return result; 231 } 232 } 233#if 0 234 Adapter->stDebugState.debug_level = DBG_LVL_CURR; 235 Adapter->stDebugState.type =(UINT)0xffffffff; 236 Adapter->stDebugState.subtype[DBG_TYPE_OTHERS] = 0xffffffff; 237 Adapter->stDebugState.subtype[DBG_TYPE_RX] = 0xffffffff; 238 Adapter->stDebugState.subtype[DBG_TYPE_TX] = 0xffffffff; 239 Adapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0xffffffff; 240 241 printk("-------ps_adapter->stDebugState.type=%x\n",Adapter->stDebugState.type); 242 printk("-------ps_adapter->stDebugState.subtype[DBG_TYPE_OTHERS]=%x\n",Adapter->stDebugState.subtype[DBG_TYPE_OTHERS]); 243 printk("-------ps_adapter->stDebugState.subtype[DBG_TYPE_RX]=%x\n",Adapter->stDebugState.subtype[DBG_TYPE_RX]); 244 printk("-------ps_adapter->stDebugState.subtype[DBG_TYPE_TX]=%x\n",Adapter->stDebugState.subtype[DBG_TYPE_TX]); 245#endif 246 247 return 0; 248} 249 250void bcm_unregister_networkdev(PMINI_ADAPTER Adapter) 251{ 252 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unregistering the Net Dev...\n"); 253 if(Adapter->dev && !IS_ERR(Adapter->dev) && Adapter->bNetworkInterfaceRegistered) 254 unregister_netdev(Adapter->dev); 255 /* Unregister the notifier block */ 256 if(Adapter->bNetdeviceNotifierRegistered == TRUE) 257 { 258 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unregistering netdevice notifier\n"); 259 unregister_netdevice_notifier(&bcm_notifier_block); 260 } 261} 262 263static int bcm_init(void) 264{ 265 int result; 266 result = InterfaceInitialize(); 267 if(result) 268 { 269 printk("Initialisation failed for usbbcm"); 270 } 271 else 272 { 273 printk("Initialised usbbcm"); 274 } 275 return result; 276} 277 278 279static void bcm_exit(void) 280{ 281 printk("%s %s Calling InterfaceExit\n",__FILE__, __FUNCTION__); 282 InterfaceExit(); 283 printk("%s %s InterfaceExit returned\n",__FILE__, __FUNCTION__); 284} 285 286module_init(bcm_init); 287module_exit(bcm_exit); 288MODULE_LICENSE ("GPL"); 289 290 291