?? arlan-main.c
字號(hào):
/* * Copyright (C) 1997 Cullen Jennings * Copyright (C) 1998 Elmer Joandiu, elmer@ylenurme.ee * GNU General Public License applies * This module provides support for the Arlan 655 card made by Aironet */#include <linux/config.h>#include "arlan.h"#if BITS_PER_LONG != 32# error FIXME: this driver requires a 32-bit platform#endifstatic const char *arlan_version = "C.Jennigs 97 & Elmer.Joandi@ut.ee Oct'98, http://www.ylenurme.ee/~elmer/655/";struct net_device *arlan_device[MAX_ARLANS];static int SID = SIDUNKNOWN;static int radioNodeId = radioNodeIdUNKNOWN;static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};int arlan_debug = debugUNKNOWN;static int spreadingCode = spreadingCodeUNKNOWN;static int channelNumber = channelNumberUNKNOWN;static int channelSet = channelSetUNKNOWN;static int systemId = systemIdUNKNOWN;static int registrationMode = registrationModeUNKNOWN;static int keyStart;static int tx_delay_ms;static int retries = 5;static int tx_queue_len = 1;static int arlan_EEPROM_bad;#ifdef ARLAN_DEBUGGINGstatic int arlan_entry_debug;static int arlan_exit_debug;static int testMemory = testMemoryUNKNOWN;static int irq = irqUNKNOWN;static int txScrambled = 1;static int mdebug;#endifMODULE_PARM(irq, "i");MODULE_PARM(mem, "i");MODULE_PARM(arlan_debug, "i");MODULE_PARM(testMemory, "i");MODULE_PARM(spreadingCode, "i");MODULE_PARM(channelNumber, "i");MODULE_PARM(channelSet, "i");MODULE_PARM(systemId, "i");MODULE_PARM(registrationMode, "i");MODULE_PARM(radioNodeId, "i");MODULE_PARM(SID, "i");MODULE_PARM(txScrambled, "i");MODULE_PARM(keyStart, "i");MODULE_PARM(mdebug, "i");MODULE_PARM(tx_delay_ms, "i");MODULE_PARM(retries, "i");MODULE_PARM(async, "i");MODULE_PARM(tx_queue_len, "i");MODULE_PARM(arlan_entry_debug, "i");MODULE_PARM(arlan_exit_debug, "i");MODULE_PARM(arlan_entry_and_exit_debug, "i");MODULE_PARM(arlan_EEPROM_bad, "i");MODULE_PARM_DESC(irq, "(unused)");MODULE_PARM_DESC(mem, "Arlan memory address for single device probing");MODULE_PARM_DESC(arlan_debug, "Arlan debug enable (0-1)");MODULE_PARM_DESC(testMemory, "(unused)");MODULE_PARM_DESC(mdebug, "Arlan multicast debugging (0-1)");MODULE_PARM_DESC(retries, "Arlan maximum packet retransmisions");#ifdef ARLAN_ENTRY_EXIT_DEBUGGINGMODULE_PARM_DESC(arlan_entry_debug, "Arlan driver function entry debugging");MODULE_PARM_DESC(arlan_exit_debug, "Arlan driver function exit debugging");MODULE_PARM_DESC(arlan_entry_and_exit_debug, "Arlan driver function entry and exit debugging");#elseMODULE_PARM_DESC(arlan_entry_debug, "(ignored)");MODULE_PARM_DESC(arlan_exit_debug, "(ignored)");MODULE_PARM_DESC(arlan_entry_and_exit_debug, "(ignored)");#endifstruct arlan_conf_stru arlan_conf[MAX_ARLANS];static int arlans_found;static int arlan_open(struct net_device *dev);static int arlan_tx(struct sk_buff *skb, struct net_device *dev);static irqreturn_t arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int arlan_close(struct net_device *dev);static struct net_device_stats * arlan_statistics (struct net_device *dev);static void arlan_set_multicast (struct net_device *dev);static int arlan_hw_tx (struct net_device* dev, char *buf, int length );static int arlan_hw_config (struct net_device * dev);static void arlan_tx_done_interrupt (struct net_device * dev, int status);static void arlan_rx_interrupt (struct net_device * dev, u_char rxStatus, u_short, u_short);static void arlan_process_interrupt (struct net_device * dev);static void arlan_tx_timeout (struct net_device *dev);static inline long us2ticks(int us){ return us * (1000000 / HZ);}#ifdef ARLAN_ENTRY_EXIT_DEBUGGING#define ARLAN_DEBUG_ENTRY(name) \ {\ struct timeval timev;\ do_gettimeofday(&timev);\ if (arlan_entry_debug || arlan_entry_and_exit_debug)\ printk("--->>>" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec));\ }#define ARLAN_DEBUG_EXIT(name) \ {\ struct timeval timev;\ do_gettimeofday(&timev);\ if (arlan_exit_debug || arlan_entry_and_exit_debug)\ printk("<<<---" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec) );\ }#else#define ARLAN_DEBUG_ENTRY(name)#define ARLAN_DEBUG_EXIT(name)#endif#define arlan_interrupt_ack(dev)\ clearClearInterrupt(dev);\ setClearInterrupt(dev);static inline int arlan_drop_tx(struct net_device *dev){ struct arlan_private *priv = dev->priv; priv->stats.tx_errors++; if (priv->Conf->tx_delay_ms) { priv->tx_done_delayed = jiffies + priv->Conf->tx_delay_ms * HZ / 1000 + 1; } else { priv->waiting_command_mask &= ~ARLAN_COMMAND_TX; TXHEAD(dev).offset = 0; TXTAIL(dev).offset = 0; priv->txLast = 0; priv->bad = 0; if (!priv->under_reset && !priv->under_config) netif_wake_queue (dev); } return 1;}int arlan_command(struct net_device *dev, int command_p){ struct arlan_private *priv = dev->priv; volatile struct arlan_shmem *arlan = priv->card; struct arlan_conf_stru *conf = priv->Conf; int udelayed = 0; int i = 0; unsigned long flags; ARLAN_DEBUG_ENTRY("arlan_command"); if (priv->card_polling_interval) priv->card_polling_interval = 1; if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) printk(KERN_DEBUG "arlan_command, %lx commandByte %x waiting %lx incoming %x \n", jiffies, READSHMB(arlan->commandByte), priv->waiting_command_mask, command_p); priv->waiting_command_mask |= command_p; if (priv->waiting_command_mask & ARLAN_COMMAND_RESET) if (time_after(jiffies, priv->lastReset + 5 * HZ)) priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET; if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ACK) { arlan_interrupt_ack(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ACK; } if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ENABLE) { setInterruptEnable(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ENABLE; } /* Card access serializing lock */ spin_lock_irqsave(&priv->lock, flags); /* Check cards status and waiting */ if (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW)) { while (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW)) { if (READSHMB(arlan->resetFlag) || READSHMB(arlan->commandByte)) /* || (readControlRegister(dev) & ARLAN_ACCESS)) */ udelay(40); else priv->waiting_command_mask &= ~(ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW); udelayed++; if (priv->waiting_command_mask & ARLAN_COMMAND_LONG_WAIT_NOW) { if (udelayed * 40 > 1000000) { printk(KERN_ERR "%s long wait too long \n", dev->name); priv->waiting_command_mask |= ARLAN_COMMAND_RESET; break; } } else if (priv->waiting_command_mask & ARLAN_COMMAND_WAIT_NOW) { if (udelayed * 40 > 1000) { printk(KERN_ERR "%s short wait too long \n", dev->name); goto bad_end; } } } } else { i = 0; while ((READSHMB(arlan->resetFlag) || READSHMB(arlan->commandByte)) && conf->pre_Command_Wait > (i++) * 10) udelay(10); if ((READSHMB(arlan->resetFlag) || READSHMB(arlan->commandByte)) && !(priv->waiting_command_mask & ARLAN_COMMAND_RESET)) { goto card_busy_end; } } if (priv->waiting_command_mask & ARLAN_COMMAND_RESET) priv->under_reset = 1; if (priv->waiting_command_mask & ARLAN_COMMAND_CONF) priv->under_config = 1; /* Issuing command */ arlan_lock_card_access(dev); if (priv->waiting_command_mask & ARLAN_COMMAND_POWERUP) { // if (readControlRegister(dev) & (ARLAN_ACCESS && ARLAN_POWER)) setPowerOn(dev); arlan_interrupt_lancpu(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERUP; priv->waiting_command_mask |= ARLAN_COMMAND_RESET; priv->card_polling_interval = HZ / 10; } else if (priv->waiting_command_mask & ARLAN_COMMAND_ACTIVATE) { WRITESHMB(arlan->commandByte, ARLAN_COM_ACTIVATE); arlan_interrupt_lancpu(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_ACTIVATE; priv->card_polling_interval = HZ / 10; } else if (priv->waiting_command_mask & ARLAN_COMMAND_RX_ABORT) { if (priv->rx_command_given) { WRITESHMB(arlan->commandByte, ARLAN_COM_RX_ABORT); arlan_interrupt_lancpu(dev); priv->rx_command_given = 0; } priv->waiting_command_mask &= ~ARLAN_COMMAND_RX_ABORT; priv->card_polling_interval = 1; } else if (priv->waiting_command_mask & ARLAN_COMMAND_TX_ABORT) { if (priv->tx_command_given) { WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ABORT); arlan_interrupt_lancpu(dev); priv->tx_command_given = 0; } priv->waiting_command_mask &= ~ARLAN_COMMAND_TX_ABORT; priv->card_polling_interval = 1; } else if (priv->waiting_command_mask & ARLAN_COMMAND_RESET) { priv->under_reset=1; netif_stop_queue (dev); arlan_drop_tx(dev); if (priv->tx_command_given || priv->rx_command_given) { printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name); } netif_stop_queue (dev); if (arlan_debug & ARLAN_DEBUG_RESET) printk(KERN_ERR "%s: Doing chip reset\n", dev->name); priv->lastReset = jiffies; WRITESHM(arlan->commandByte, 0, u_char); /* hold card in reset state */ setHardwareReset(dev); /* set reset flag and then release reset */ WRITESHM(arlan->resetFlag, 0xff, u_char); clearChannelAttention(dev); clearHardwareReset(dev); priv->card_polling_interval = HZ / 4; priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET; priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK;// priv->waiting_command_mask |= ARLAN_COMMAND_INT_RENABLE; // priv->waiting_command_mask |= ARLAN_COMMAND_RX; } else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RACK) { clearHardwareReset(dev); clearClearInterrupt(dev); setClearInterrupt(dev); setInterruptEnable(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RACK; priv->waiting_command_mask |= ARLAN_COMMAND_CONF; priv->under_config = 1; priv->under_reset = 0; } else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RENABLE) { setInterruptEnable(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RENABLE; } else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF) { if (priv->tx_command_given || priv->rx_command_given) { printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name); } arlan_drop_tx(dev); setInterruptEnable(dev); arlan_hw_config(dev); arlan_interrupt_lancpu(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF; priv->card_polling_interval = HZ / 10;// priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK; // priv->waiting_command_mask |= ARLAN_COMMAND_INT_ENABLE; priv->waiting_command_mask |= ARLAN_COMMAND_CONF_WAIT; } else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF_WAIT) { if (READSHMB(arlan->configuredStatusFlag) != 0 && READSHMB(arlan->diagnosticInfo) == 0xff) { priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF_WAIT; priv->waiting_command_mask |= ARLAN_COMMAND_RX; priv->waiting_command_mask |= ARLAN_COMMAND_TBUSY_CLEAR; priv->card_polling_interval = HZ / 10; priv->tx_command_given = 0; priv->under_config = 0; } else { priv->card_polling_interval = 1; if (arlan_debug & ARLAN_DEBUG_TIMING) printk(KERN_ERR "configure delayed \n"); } } else if (priv->waiting_command_mask & ARLAN_COMMAND_RX) { if (!registrationBad(dev)) { setInterruptEnable(dev); memset_io((void *) arlan->commandParameter, 0, 0xf); WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_RX_ENABLE); WRITESHMB(arlan->commandParameter[0], conf->rxParameter); arlan_interrupt_lancpu(dev); priv->rx_command_given = 0; // mnjah, bad priv->waiting_command_mask &= ~ARLAN_COMMAND_RX; priv->card_polling_interval = 1; } else priv->card_polling_interval = 2; } else if (priv->waiting_command_mask & ARLAN_COMMAND_TBUSY_CLEAR) { if ( !registrationBad(dev) && (netif_queue_stopped(dev) || !netif_running(dev)) ) { priv->waiting_command_mask &= ~ARLAN_COMMAND_TBUSY_CLEAR; netif_wake_queue (dev); } } else if (priv->waiting_command_mask & ARLAN_COMMAND_TX) { if (!test_and_set_bit(0, (void *) &priv->tx_command_given)) { if (time_after(jiffies, priv->tx_last_sent + us2ticks(conf->rx_tweak1)) || time_before(jiffies, priv->last_rx_int_ack_time + us2ticks(conf->rx_tweak2))) { setInterruptEnable(dev); memset_io((void *) arlan->commandParameter, 0, 0xf); WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ENABLE | ARLAN_COM_INT); memcpy_toio((void *) arlan->commandParameter, &TXLAST(dev), 14);// for ( i=1 ; i < 15 ; i++) printk("%02x:",READSHMB(arlan->commandParameter[i])); priv->tx_last_sent = jiffies; arlan_interrupt_lancpu(dev); priv->tx_command_given = 1; priv->waiting_command_mask &= ~ARLAN_COMMAND_TX; priv->card_polling_interval = 1; } else { priv->tx_command_given = 0; priv->card_polling_interval = 1; } } else if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) printk(KERN_ERR "tx command when tx chain locked \n"); } else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOPINT) { { WRITESHMB(arlan->commandByte, ARLAN_COM_NOP | ARLAN_COM_INT); } arlan_interrupt_lancpu(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOPINT; priv->card_polling_interval = HZ / 3; } else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOP) { WRITESHMB(arlan->commandByte, ARLAN_COM_NOP); arlan_interrupt_lancpu(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOP; priv->card_polling_interval = HZ / 3; } else if (priv->waiting_command_mask & ARLAN_COMMAND_SLOW_POLL) { WRITESHMB(arlan->commandByte, ARLAN_COM_GOTO_SLOW_POLL); arlan_interrupt_lancpu(dev); priv->waiting_command_mask &= ~ARLAN_COMMAND_SLOW_POLL; priv->card_polling_interval = HZ / 3; } else if (priv->waiting_command_mask & ARLAN_COMMAND_POWERDOWN) { setPowerOff(dev); if (arlan_debug & ARLAN_DEBUG_CARD_STATE) printk(KERN_WARNING "%s: Arlan Going Standby\n", dev->name); priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERDOWN; priv->card_polling_interval = 3 * HZ; } arlan_unlock_card_access(dev); for (i = 0; READSHMB(arlan->commandByte) && i < 20; i++) udelay(10); if (READSHMB(arlan->commandByte)) if (arlan_debug & ARLAN_DEBUG_CARD_STATE) printk(KERN_ERR "card busy leaving command %lx\n", priv->waiting_command_mask); spin_unlock_irqrestore(&priv->lock, flags); ARLAN_DEBUG_EXIT("arlan_command"); priv->last_command_buff_free_time = jiffies; return 0;card_busy_end: if (time_after(jiffies, priv->last_command_buff_free_time + HZ)) priv->waiting_command_mask |= ARLAN_COMMAND_CLEAN_AND_RESET; if (arlan_debug & ARLAN_DEBUG_CARD_STATE) printk(KERN_ERR "%s arlan_command card busy end \n", dev->name); spin_unlock_irqrestore(&priv->lock, flags); ARLAN_DEBUG_EXIT("arlan_command"); return 1;bad_end: printk(KERN_ERR "%s arlan_command bad end \n", dev->name);
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -