📄 sdla_fr.c
字号:
printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n", card->devname); }else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){ chan->common.usedby = BRIDGE_NODE; printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n", card->devname); } if (!err){ /* Dynamic interface configuration option. * On disconnect, if the options is selected, * the interface will be brought down */ if (conf->if_down == WANOPT_YES){ set_bit(DYN_OPT_ON,&chan->interface_down); printk(KERN_INFO "%s: Dynamic interface configuration enabled.\n", card->devname); } } } else if(strcmp(conf->usedby, "API") == 0){ chan->common.usedby = API; printk(KERN_INFO "%s: Running in API mode.\n", wandev->name); } if (err) { kfree(chan); return err; } /* place cir,be,bc and other channel specific information into the * chan structure */ if (conf->cir) { chan->cir = max_t(unsigned int, 1, min_t(unsigned int, conf->cir, 512)); chan->cir_status = CIR_ENABLED; /* If CIR is enabled, force BC to equal CIR * this solves number of potential problems if CIR is * set and BC is not */ chan->bc = chan->cir; if (conf->be){ chan->be = max_t(unsigned int, 0, min_t(unsigned int, conf->be, 511)); }else{ conf->be = 0; } printk (KERN_INFO "%s: CIR enabled for DLCI %i \n", wandev->name,chan->dlci); printk (KERN_INFO "%s: CIR = %i ; BC = %i ; BE = %i\n", wandev->name,chan->cir,chan->bc,chan->be); }else{ chan->cir_status = CIR_DISABLED; printk (KERN_INFO "%s: CIR disabled for DLCI %i\n", wandev->name,chan->dlci); } chan->mc = conf->mc; if (conf->inarp == WANOPT_YES){ printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname); chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE; chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10; }else{ printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname); chan->inarp = INARP_NONE; chan->inarp_interval = 10; } chan->dlci_configured = DLCI_NOT_CONFIGURED; /*FIXME: IPX disabled in this WANPIPE version */ if (conf->enable_IPX == WANOPT_YES){ printk(KERN_INFO "%s: ERROR - This version of WANPIPE doesn't support IPX\n", card->devname); kfree(chan); return -EINVAL; }else{ chan->enable_IPX = WANOPT_NO; } if (conf->network_number){ chan->network_number = conf->network_number; }else{ chan->network_number = 0xDEADBEEF; } chan->route_flag = NO_ROUTE; init_chan_statistics(chan); chan->transmit_length = 0; /* prepare network device data space for registration */ strcpy(dev->name,chan->name); dev->init = &if_init; dev->priv = chan; /* Initialize FR Polling Task Queue * We need a poll routine for each network * interface. */ INIT_WORK(&chan->fr_poll_work, (void *)fr_poll, dev); init_timer(&chan->fr_arp_timer); chan->fr_arp_timer.data=(unsigned long)dev; chan->fr_arp_timer.function = fr_arp; wandev->new_if_cnt++; /* Tells us that if this interface is a * gateway or not */ if ((chan->gateway = conf->gateway) == WANOPT_YES){ printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", card->devname,dev->name); } /* M. Grant Patch Apr 28 2000 * Disallow duplicate dlci configurations. */ if (card->u.f.dlci_to_dev_map[chan->dlci] != NULL) { kfree(chan); return -EBUSY; } /* Configure this dlci at a later date, when * the interface comes up. i.e. when if_open() * executes */ set_bit(0,&chan->config_dlci); printk(KERN_INFO "\n"); return 0;}/*============================================================================ * Delete logical channel. */static int del_if(struct wan_device* wandev, struct net_device* dev){ fr_channel_t* chan = dev->priv; unsigned long smp_flags=0; /* This interface is dead, make sure the * ARP timer is stopped */ del_timer(&chan->fr_arp_timer); /* If we are a NODE, we must unconfigure this DLCI * Trigger an unconfigure command that will * be executed in timer interrupt. We must wait * for the command to complete. */ trigger_unconfig_fr(dev); lock_adapter_irq(&wandev->lock, &smp_flags); wandev->new_if_cnt--; unlock_adapter_irq(&wandev->lock, &smp_flags); return 0;}/*===================================================================== * disable_comm * * Description: * Disable communications. * This code runs in shutdown (sdlamain.c) * under critical flag. Therefore it is not * necessary to set a critical flag here * * Usage: * Commnunications are disabled only on a card * shutdown. */static void disable_comm (sdla_t *card){ printk(KERN_INFO "%s: Disabling Communications!\n", card->devname); fr_comm_disable(card);}/****** WANPIPE-specific entry points ***************************************//*============================================================================ * Execute adapter interface command. */static int wpf_exec (struct sdla* card, void* u_cmd, void* u_data){ fr_mbox_t* mbox = card->mbox; int retry = MAX_CMD_RETRY; int err, len; fr_cmd_t cmd; if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd))) return -EFAULT; /* execute command */ do { memcpy(&mbox->cmd, &cmd, sizeof(cmd)); if (cmd.length){ if( copy_from_user((void*)&mbox->data, u_data, cmd.length)) return -EFAULT; } if (sdla_exec(mbox)) err = mbox->cmd.result; else return -EIO; } while (err && retry-- && fr_event(card, err, mbox)); /* return result */ if (copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t))) return -EFAULT; len = mbox->cmd.length; if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len)) return -EFAULT; return 0;}/****** Network Device Interface ********************************************//*============================================================================ * Initialize Linux network interface. * * This routine is called only once for each interface, during Linux network * interface registration. Returning anything but zero will fail interface * registration. */static int if_init(struct net_device* dev){ fr_channel_t* chan = dev->priv; sdla_t* card = chan->card; struct wan_device* wandev = &card->wandev; /* Initialize device driver entry points */ dev->open = &if_open; dev->stop = &if_close; dev->hard_header = NULL; dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; if (chan->common.usedby == WANPIPE || chan->common.usedby == API){ /* Initialize media-specific parameters */ if (chan->true_if_encoding){ dev->type = ARPHRD_DLCI; /* This breaks tcpdump */ }else{ dev->type = ARPHRD_PPP; /* ARP h/w type */ } dev->flags |= IFF_POINTOPOINT; dev->flags |= IFF_NOARP; /* Enable Multicast addressing */ if (chan->mc == WANOPT_YES){ dev->flags |= IFF_MULTICAST; } dev->mtu = wandev->mtu - FR_HEADER_LEN; /* For an API, the maximum number of bytes that the stack will pass to the driver is (dev->mtu + dev->hard_header_len). So, adjust the mtu so that a frame of maximum size can be transmitted by the API. */ if(chan->common.usedby == API) { dev->mtu += (sizeof(api_tx_hdr_t) - FR_HEADER_LEN); } dev->hard_header_len = FR_HEADER_LEN;/* media header length */ dev->addr_len = 2; /* hardware address length */ *(unsigned short*)dev->dev_addr = htons(chan->dlci); /* Set transmit buffer queue length */ dev->tx_queue_len = 100; }else{ /* Setup the interface for Bridging */ int hw_addr=0; ether_setup(dev); /* Use a random number to generate the MAC address */ memcpy(dev->dev_addr, "\xFE\xFC\x00\x00\x00\x00", 6); get_random_bytes(&hw_addr, sizeof(hw_addr)); *(int *)(dev->dev_addr + 2) += hw_addr; } /* Initialize hardware parameters (just for reference) */ dev->irq = wandev->irq; dev->dma = wandev->dma; dev->base_addr = wandev->ioport; dev->mem_start = wandev->maddr; dev->mem_end = wandev->maddr + wandev->msize - 1; SET_MODULE_OWNER(dev); return 0;}/*============================================================================ * Open network interface. * o if this is the first open, then enable communications and interrupts. * o prevent module from unloading by incrementing use count * * Return 0 if O.k. or errno. */static int if_open(struct net_device* dev){ fr_channel_t* chan = dev->priv; sdla_t* card = chan->card; int err = 0; struct timeval tv; if (netif_running(dev)) return -EBUSY; /* Initialize the task queue */ chan->tq_working=0; INIT_WORK(&chan->common.wanpipe_work, (void *)fr_bh, dev); /* Allocate and initialize BH circular buffer */ chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC); memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF)); atomic_set(&chan->bh_buff_used, 0); netif_start_queue(dev); wanpipe_open(card); do_gettimeofday( &tv ); chan->router_start_time = tv.tv_sec; if (test_bit(0,&chan->config_dlci)){ trigger_config_fr (card); }else if (chan->inarp == INARP_REQUEST){ trigger_fr_arp(dev); } return err;}/*============================================================================ * Close network interface. * o if this is the last open, then disable communications and interrupts. * o reset flags. */static int if_close(struct net_device* dev){ fr_channel_t* chan = dev->priv; sdla_t* card = chan->card; if (chan->inarp == INARP_CONFIGURED) { chan->inarp = INARP_REQUEST; } netif_stop_queue(dev); wanpipe_close(card); return 0;}/*============================================================================ * Re-build media header. * * Return: 1 physical address resolved. * 0 physical address not resolved */static int if_rebuild_hdr (struct sk_buff* skb){ struct net_device *dev = skb->dev; fr_channel_t* chan = dev->priv; sdla_t* card = chan->card; printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", card->devname, dev->name); return 1;}/*============================================================================ * Handle transmit timeout event from netif watchdog */static void if_tx_timeout(struct net_device *dev){ fr_channel_t* chan = dev->priv; sdla_t *card = chan->card; /* If our device stays busy for at least 5 seconds then we will * kick start the device by making dev->tbusy = 0. We expect * that our device never stays busy more than 5 seconds. So this * is only used as a last resort. */ chan->drvstats_if_send.if_send_tbusy++; ++chan->ifstats.collisions; printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname, dev->name); chan->drvstats_if_send.if_send_tbusy_timeout++; netif_wake_queue (dev);}/*============================================================================ * Send a packet on a network interface. * o set tbusy flag (marks start of the transmission) to block a timer-based * transmit from overlapping. * o set critical flag when accessing board. * o check link state. If link is not up, then drop the packet. * o check channel status. If it's down then initiate a call. * o pass a packet to corresponding WAN device. * o free socket buffer * * Return: 0 complete (socket buffer must be freed)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -