📄 sdla_fr.c
字号:
/* Setup wanpipe as a router (WANPIPE) even if it is * a bridged DLCI, or as an API */ if (strcmp(conf->usedby, "WANPIPE") == 0 || strcmp(conf->usedby, "BRIDGE") == 0 || strcmp(conf->usedby, "BRIDGE_N") == 0){ if(strcmp(conf->usedby, "WANPIPE") == 0){ chan->common.usedby = WANPIPE; printk(KERN_INFO "%s: Running in WANPIPE mode.\n", card->devname); }else if(strcmp(conf->usedby, "BRIDGE") == 0){ chan->common.usedby = BRIDGE; #if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n", card->devname);#else printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n", card->devname); err = -EPROTONOSUPPORT;#endif }else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){ chan->common.usedby = BRIDGE_NODE; #if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n", card->devname);#else printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n", card->devname); err = -EPROTONOSUPPORT;#endif } 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){#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->common.usedby = API; printk(KERN_INFO "%s: Running in API mode.\n", wandev->name);#else printk(KERN_INFO "%s: The API Mode is not supported for" "kernels lower than 2.2.X !\n", wandev->name); printk(KERN_INFO "%s: Please upgrade to a 2.2.X kernel for the API support\n", wandev->name); err = -EINVAL;#endif } 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){#if defined(LINUX_2_1) || defined(LINUX_2_4) 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: Warning, Inverse ARP Support not available for 2.0.X kernels!\n", card->devname); chan->inarp = INARP_NONE; chan->inarp_interval = 10;#endif }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 */#ifdef LINUX_2_4 strcpy(dev->name,chan->name);#else dev->name = (char *)kmalloc(strlen(chan->name) + 2, GFP_KERNEL); if(dev->name == NULL) { kfree(chan); return -ENOMEM; } sprintf(dev->name, "%s", chan->name);#endif dev->init = &if_init; dev->priv = chan; /* Initialize FR Polling Task Queue * We need a poll routine for each network * interface. */#ifndef LINUX_2_4 chan->fr_poll_task.next = NULL;#endif chan->fr_poll_task.sync = 0; chan->fr_poll_task.routine = (void *)(void *)fr_poll; chan->fr_poll_task.data = 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 (wan_device_t* wandev, netdevice_t* 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 defined(LINUX_2_1) || defined(LINUX_2_4) 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;#else if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(fr_cmd_t))) return -EFAULT; memcpy_fromfs((void*)&cmd, u_cmd, sizeof(cmd)); if (cmd.length) { if (!u_data || verify_area(VERIFY_READ, u_data, cmd.length)) return -EFAULT; } /* execute command */ do { memcpy(&mbox->cmd, &cmd, sizeof(cmd)); if (cmd.length) memcpy_fromfs((void*)&mbox->data, u_data, cmd.length); if (sdla_exec(mbox)) err = mbox->cmd.result; else return -EIO; } while (err && retry-- && fr_event(card, err, mbox)); /* return result */ memcpy_tofs(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t)); len = mbox->cmd.length; if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len)) memcpy_tofs(u_data, (void*)&mbox->data, len); return 0;#endif}/****** 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 (netdevice_t* dev){ fr_channel_t* chan = dev->priv; sdla_t* card = chan->card; wan_device_t* wandev = &card->wandev;#ifdef LINUX_2_0 int i;#endif /* 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;#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT;#endif if (chan->common.usedby == WANPIPE || chan->common.usedby == API){#ifdef LINUX_2_0 dev->family = AF_INET;#endif /* 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; /* Initialize socket buffers */#if !defined(LINUX_2_1) && !defined(LINUX_2_4) for (i = 0; i < DEV_NUMBUFFS; ++i) skb_queue_head_init(&dev->buffs[i]);#endif }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; return 0;}/*============================================================================ * Open network interface.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -