📄 am930mac.c
字号:
/* am930_mac.c: Handles the 802.11 mac functions* --------------------------------------------------------------------** Linux WLAN ** The contents of this file are subject to the Mozilla Public* License Version 1.0 (the "License"); you may not use this file* except in compliance with the License. You may obtain a copy of* the License at http://www.mozilla.org/MPL/** 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.** The initial developer of the original code is Mark S. Mathews* <mark@absoval.com>. Portions created by Mark S. Mathews* are Copyright (C) 1998 AbsoluteValue Software, Inc. All Rights Reserved.* * --------------------------------------------------------------------** The author may be reached as mark@absoval.com, or C/O AbsoluteValue* Software Inc., P.O. Box 941149, Maitland, FL, 32794-1149** Thanks to David Hinds, Donald Becker, and the rest of the Linux* developers worldwide for making all of this possible.** --------------------------------------------------------------------**/#include <linux/config.h>#include <wlan/wlan_compat.h>#if (WLAN_OS == WLAN_LINUX_KERNEL)/* The following prevents "kernel_version" from being set in this file. */#define __NO_VERSION__/* PCMCIA headers generated during PCMCIA package installation */#ifdef WLAN_PCMCIA#include <pcmcia/config.h>#include <pcmcia/k_compat.h>#endif/* Module related headers, non-module drivers should not include */#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>/* Ethernet and network includes */#include <linux/if_ether.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/ioport.h>/* Standard driver includes */#include <linux/delay.h>#include <linux/types.h>#include <linux/fcntl.h>#include <asm/system.h>#include <asm/io.h>#include <linux/in.h>#include <linux/ptrace.h>#include <linux/interrupt.h>#include <linux/malloc.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/kernel_stat.h>#include <asm/bitops.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,11)#include <asm/spinlock.h>#else#include <linux/spinlock.h>#endif#include <linux/errno.h>/* Card and Driver services includes */#ifdef WLAN_PCMCIA#include <pcmcia/version.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/ds.h>#endif/* Local Includes */#include <wlan/version.h>#include <wlan/p80211hdr.h>#include <wlan/p80211mgmt.h>#include <wlan/am930mib.h>#include <wlan/wlan_stable.h>#include <wlan/wlan_ioctl.h>#ifdef WLAN_PCMCIA#include "am930di.h"#endif#include "am930llc.h"#include "am930mac.h"#include "am930hw.h"#include "am930mgr.h"#elif ( WLAN_OS == WLAN_LWOS )#include <wlan/wlan_compat.h>#include <stddef.h>#include <stdlibsys.h>#include <direct.h>#include <hal.h>#include <mem.h>#include <kernel.h>#include <clock.h>#include <wlan/version.h>#include <wlan/p80211hdr.h>#include <wlan/p80211mgmt.h>#include <wlan/am930mib.h>#include <wlan/wlan_stable.h>#include <lw-wlan.h>#include <wlan/am930mac.h>#include <wlan/am930hw.h>#include <wlan/am930mgr.h>#else #error "No WLAN_OS match!"#endif/*================================================================*//* Local Constants */#define LLCQ_LEN 20#define MACQ_LEN 20#define RXQ_LEN 40#define WLAN_CRC32_POLY_LE (0xedb88320UL)#define WLAN_CRC32_POLY_BE (0x04c11db7UL)/*================================================================*//* Local Functions */static void am930mac_rxmgmt( am930mac_t *mac, wlan_pb_t *pb, am930rxstats_t *stats);static void am930mac_rxdata( am930mac_t *mac, wlan_pb_t *pb, am930rxstats_t *stats);static wlan_pb_t *am930mac_defrag( am930mac_t *mac, wlan_pb_t *pb);static wlan_pb_t *am930mac_defragfinish( am930mac_t *mac, UINT8 hash );static void am930mac_timerfunc(am930mac_t *mac);static void am930mac_crc32_mktable(am930mac_t *mac);static UINT32 am930mac_crc32_block(am930mac_t *mac, UINT32 reg, UINT8 *p, UINT len);static UINT32 am930mac_crc32_blockfinish(am930mac_t *mac, UINT32 reg);/* static UINT32 am930mac_crc32_accum(am930mac_t *mac, UINT32 reg, UINT8 d); *//*================================================================*//* Externals */#if (WLAN_OS == WLAN_LWOS)am930mac_t gmac;#endif/*----------------------------------------------------------------* am930mac_construct** Allocates and initializes the mac object and it's subobjects.** returns: NULL on failure, the address of the new object* otherwise.----------------------------------------------------------------*/#if (WLAN_OS == WLAN_LINUX_KERNEL)am930mac_t* am930mac_construct(void *di, UINT32 iobase, UINT32 membase, UINT32 irq)#elif (WLAN_OS == WLAN_LWOS )am930mac_t* am930mac_construct(wlanInfo_t *lw, UINT32 iobase, UINT32 membase, UINT32 irq)#else #error "No WLAN_OS match!"#endif{ am930mac_t *mac; int i; DBFENTER;#if (WLAN_OS == WLAN_LINUX_KERNEL) /* Allocate the memory */ mac = kmalloc( sizeof(am930mac_t), GFP_KERNEL);#elif (WLAN_OS == WLAN_LWOS ) mac = &gmac;#else #error "No WLAN_OS match!"#endif if ( mac == NULL ) { WLAN_LOG_ERROR0("mac allocation failed!\n"); } else { /* zero the mac object */ memset( mac, 0, sizeof(am930mac_t)); /* init the crc table */ am930mac_crc32_mktable(mac); /* mark all the frag pools as avail */ for ( i = 0; i < AM930MAC_FRAGPOOLS_MAX; i++) { mac->defragpool[i].seq = AM930MAC_FRAGPOOL_FREE; } /* intialize the locks */ mac->fragpool_lock = SPIN_LOCK_UNLOCKED;#if (WLAN_OS == WLAN_LINUX_KERNEL)#ifdef WLAN_PCMCIA /* save a reference to the di */ mac->di = di; /* set the di priv ptr to mac */ ((dev_link_t*)di)->priv = mac;#endif /* Create the hw instance */ mac->hw = am930hw_construct( irq, iobase, membase, mac) ;#elif (WLAN_OS == WLAN_LWOS ) mac->lw = lw; mac->llc = lw; /* Create the hw instance */ mac->hw = am930hw_construct( irq, iobase, membase, mac) ;#else #error "No WLAN_OS match!"#endif if ( mac->hw == NULL) { WLAN_LOG_ERROR0("hw allocation failed!\n"); am930mac_destruct(mac); mac = NULL;#if (WLAN_OS == WLAN_LINUX_KERNEL)#ifdef WLAN_PCMCIA ((dev_link_t*)di)->priv = NULL;#endif#endif } else { /* Set up the transmit queues */ mac->llcq = am930q_init( LLCQ_LEN ); mac->macq = am930q_init( MACQ_LEN ); mac->rxq = am930q_init( RXQ_LEN ); /* Set the default MIB values (where zero is unacceptable) */ mac->maxrxlifetime = 1024; /* Now, call the second part of the hw initialization */ if ( am930hw_init_rx_tx( mac->hw ) != 0 ) { WLAN_LOG_ERROR0("hw_init_rx_tx failed!\n"); am930mac_destruct(mac); mac = NULL; #if (WLAN_OS == WLAN_LINUX_KERNEL)#ifdef WLAN_PCMCIA ((dev_link_t*)di)->priv = NULL;#endif#endif } else { mac->mgr = am930mgr_construct( mac, mac->hw ); if ( mac->mgr == NULL ) { WLAN_LOG_ERROR0("mgr allocation failed!\n"); am930mac_destruct(mac); mac = NULL; #if (WLAN_OS == WLAN_LWOS) }#elif (WLAN_OS == WLAN_LINUX_KERNEL)#ifdef WLAN_PCMCIA ((dev_link_t*)di)->priv = NULL;#endif } else { mac->llc = am930llc_construct( mac, mac->mgr); if ( mac->llc == NULL ) { WLAN_LOG_ERROR0("llc allocation failed!\n"); am930mac_destruct(mac); mac = NULL; #ifdef WLAN_PCMCIA ((dev_link_t*)di)->priv = NULL;#endif } }#else #error "No WLAN_OS match!"#endif mac->timerfunc = am930mac_timerfunc; /* Hard coded to match the AM930 phy mib default. */ /* Lame, I know....the new UI will fix it. */ mac->oprates[0] = 1; mac->oprates[1] = 2; mac->oprates[2] = 0x82; mac->oprates[3] = 0x84; } } } DBFEXIT; return mac;}/*----------------------------------------------------------------* am930mac_destruct** Destroys the subobjects and the mac object. Caller needs to be* aware that the pointer passed in is invalid after this call.** returns: nothing----------------------------------------------------------------*/void am930mac_destruct( am930mac_t* mac){ wlan_pb_t* pb; DBFENTER; mac->timerfunc = NULL; if ( mac->hw != NULL ) { am930hw_destruct( mac->hw ); mac->hw = NULL; }#if (WLAN_OS == WLAN_LINUX_KERNEL) if ( mac->llc != NULL ) { am930llc_destruct( mac->llc); mac->llc = NULL; }#endif /* TODO: handle destruction cleanly, call subobject destructors after testing subobject pointers for NULL */ /* get rid of the queues */ while ( (mac->llcq != NULL) && (pb = (wlan_pb_t*)am930q_dequeue(mac->llcq)) ) { am930shim_pbfree(pb); } kfree_s( mac->llcq, sizeof(am930q_t)); while ( (mac->macq != NULL) && (pb = (wlan_pb_t*)am930q_dequeue(mac->macq)) ) { am930shim_pbfree(pb); } kfree_s( mac->macq, sizeof(am930q_t)); /* all subobjects handled, now free the mac object */ kfree_s( mac, sizeof(am930mac_t)); DBFEXIT; return;}/*----------------------------------------------------------------* am930mac_crc32_block** Calculate the crc over a block of bytes. To get the final crc value,* don't forget to call crc32_blockfinish.* Arguments: * reg initial accumulator value, passing it in allows us to * crc non-contiguous blocks. On the first call to this * function for a given crc calculation, reg should be* 0xffffffffUL.* p ptr to the block* len size of block* returns: * crc32 value----------------------------------------------------------------*/UINT32 am930mac_crc32_block(am930mac_t *mac, UINT32 reg, UINT8 *p, UINT len){ while(len) { reg = mac->crc32_table[(reg ^ *p) & 0x000000ffUL] ^ (reg >> 8); len--; p++; } return reg;}UINT32 am930mac_crc32_blockfinish(am930mac_t *mac, UINT32 reg){ return reg ^ 0xffffffffUL;}/*----------------------------------------------------------------* am930mac_crc32_accum** Accumulates, in a given register, the crc of a series of bytes* passed to this function.* Arguments: * reg current accumulated crc value* d next byte in series* returns: * new accumulated crc32 value----------------------------------------------------------------*/#ifdef NOTUSED /* we're not using it right now, ifdef'd to stop warning */UINT32 am930mac_crc32_accum(am930mac_t *mac, UINT32 reg, UINT8 d){ reg = mac->crc32_table[(reg ^ d) & 0x000000ffUL] ^ (reg >> 8); return reg;}#endif/*----------------------------------------------------------------* am930mac_crc32_mktable** Constructs the table used for the crc32 calculation.* Arguments: none* returns: nothing----------------------------------------------------------------*/void am930mac_crc32_mktable(am930mac_t *mac){ UINT i; UINT k; UINT32 c; mac->crc32_table[0] = 0; for ( i = 1; i < 256; i++) { c = 0; for ( k = i | 256; k != 1; k >>= 1) { c = (c & 1) ? ((c >> 1) ^ WLAN_CRC32_POLY_LE) : (c >> 1); if ( k & 1 ) { c ^= WLAN_CRC32_POLY_LE; } } mac->crc32_table[i] = c; }}/*----------------------------------------------------------------* am930mac_ISR** ISR called from the di ISR. I know this is kindof a waste, but* I didn't want the di to know anything about the hw interface.** returns: nothing----------------------------------------------------------------*/void am930mac_ISR( am930mac_t *mac ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -