📄 sdla_x25.c
字号:
}/*=================================================================== * Name: new_if * * Purpose: To allocate and initialize resources for a * new logical channel. * * Rationale: A new channel can be added dynamically via * ioctl call. * * Description: Allocate a private channel structure, x25_channel_t. * Parse the user interface options from wanpipe#.conf * configuration file. * Bind the private are into the network device private * area pointer (dev->priv). * Prepare the network device structure for registration. * * Called by: ROUTER_IFNEW Ioctl call, from wanrouter_ioctl() * (wanmain.c) * * Assumptions: None * * Warnings: None * * Return: 0 Ok * <0 Failed (channel will not be created) */static int new_if(struct wan_device* wandev, struct net_device* dev, wanif_conf_t* conf){ sdla_t* card = wandev->private; x25_channel_t* chan; int err = 0; if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)){ printk(KERN_INFO "%s: invalid interface name!\n", card->devname); return -EINVAL; } if(card->wandev.new_if_cnt++ > 0 && card->u.x.LAPB_hdlc) { printk(KERN_INFO "%s: Error: Running LAPB HDLC Mode !\n", card->devname); printk(KERN_INFO "%s: Maximum number of network interfaces must be one !\n", card->devname); return -EEXIST; } /* allocate and initialize private data */ chan = kmalloc(sizeof(x25_channel_t), GFP_ATOMIC); if (chan == NULL){ return -ENOMEM; } memset(chan, 0, sizeof(x25_channel_t)); /* Bug Fix: Seg Err on PVC startup * It must be here since bind_lcn_to_dev expects * it bellow */ dev->priv = chan; strcpy(chan->name, conf->name); chan->card = card; chan->dev = dev; chan->common.sk = NULL; chan->common.func = NULL; chan->common.rw_bind = 0; chan->tx_skb = chan->rx_skb = NULL; /* verify media address */ if (conf->addr[0] == '@'){ /* SVC */ chan->common.svc = 1; strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ); /* Set channel timeouts (default if not specified) */ chan->idle_timeout = (conf->idle_timeout) ? conf->idle_timeout : 90; chan->hold_timeout = (conf->hold_timeout) ? conf->hold_timeout : 10; }else if (isdigit(conf->addr[0])){ /* PVC */ int lcn = dec_to_uint(conf->addr, 0); if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){ bind_lcn_to_dev (card, dev, lcn); }else{ printk(KERN_ERR "%s: PVC %u is out of range on interface %s!\n", wandev->name, lcn, chan->name); err = -EINVAL; } }else{ printk(KERN_ERR "%s: invalid media address on interface %s!\n", wandev->name, chan->name); err = -EINVAL; } if(strcmp(conf->usedby, "WANPIPE") == 0){ printk(KERN_INFO "%s: Running in WANPIPE mode %s\n", wandev->name, chan->name); chan->common.usedby = WANPIPE; chan->protocol = htons(ETH_P_IP); }else if(strcmp(conf->usedby, "API") == 0){ chan->common.usedby = API; printk(KERN_INFO "%s: Running in API mode %s\n", wandev->name, chan->name); chan->protocol = htons(X25_PROT); } if (err){ kfree(chan); dev->priv = NULL; return err; } chan->enable_IPX = conf->enable_IPX; if (chan->enable_IPX) chan->protocol = htons(ETH_P_IPX); if (conf->network_number) chan->network_number = conf->network_number; else chan->network_number = 0xDEADBEEF; /* prepare network device data space for registration */ strcpy(dev->name,chan->name); dev->init = &if_init; init_x25_channel_struct(chan); return 0;}/*=================================================================== * Name: del_if(), Remove a logical channel. * * Purpose: To dynamically remove a logical channel. * * Rationale: Each logical channel should be dynamically * removable. This functin is called by an * IOCTL_IFDEL ioctl call or shutdown(). * * Description: Do nothing. * * Called by: IOCTL_IFDEL : wanrouter_ioctl() from wanmain.c * shutdown() from sdlamain.c * * Assumptions: * * Warnings: * * Return: 0 Ok. Void function. *///FIXME Del IF Should be taken out now.static int del_if(struct wan_device* wandev, struct net_device* dev){ return 0;}/*============================================================ * Name: wpx_exec * * Description: Execute adapter interface command. * This option is currently dissabled. *===========================================================*/static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data){ return 0;}/*============================================================ * Name: disable_comm * * Description: Disable communications during shutdown. * Dont check return code because there is * nothing we can do about it. * * Warning: Dev and private areas are gone at this point. *===========================================================*/static void disable_comm(sdla_t* card){ disable_comm_shutdown(card); del_timer(&card->u.x.x25_timer); return;}/*============================================================ * Network Device Interface *===========================================================*//*=================================================================== * Name: if_init(), Netowrk Interface Initialization * * Purpose: To initialize a network interface device structure. * * Rationale: During network interface startup, the if_init * is called by the kernel to initialize the * netowrk device structure. Thus a driver * can customze a network device. * * Description: Initialize the netowrk device call back * routines. This is where we tell the kernel * which function to use when it wants to send * via our interface. * Furthermore, we initialize the device flags, * MTU and physical address of the board. * * Called by: Kernel (/usr/src/linux/net/core/dev.c) * (dev->init()) * * Assumptions: None * * Warnings: None * * Return: 0 Ok : Void function. */static int if_init(struct net_device* dev){ x25_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 = &if_header; 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; /* Initialize media-specific parameters */ dev->type = ARPHRD_PPP; /* ARP h/w type */ dev->flags |= IFF_POINTOPOINT; dev->flags |= IFF_NOARP; if (chan->common.usedby == API){ dev->mtu = X25_CHAN_MTU+sizeof(x25api_hdr_t); }else{ dev->mtu = card->wandev.mtu; } dev->hard_header_len = X25_HRDHDR_SZ; /* media header length */ dev->addr_len = 2; /* hardware address length */ if (!chan->common.svc){ *(unsigned short*)dev->dev_addr = htons(chan->common.lcn); } /* Initialize hardware parameters (just for reference) */ dev->irq = wandev->irq; dev->dma = wandev->dma; dev->base_addr = wandev->ioport; dev->mem_start = (unsigned long)wandev->maddr; dev->mem_end = wandev->maddr + wandev->msize - 1; /* Set transmit buffer queue length */ dev->tx_queue_len = 100; SET_MODULE_OWNER(dev); /* FIXME Why are we doing this */ set_chan_state(dev, WAN_DISCONNECTED); return 0;}/*=================================================================== * Name: if_open(), Open/Bring up the Netowrk Interface * * Purpose: To bring up a network interface. * * Rationale: * * Description: Open network interface. * o prevent module from unloading by incrementing use count * o if link is disconnected then initiate connection * * Called by: Kernel (/usr/src/linux/net/core/dev.c) * (dev->open()) * * Assumptions: None * * Warnings: None * * Return: 0 Ok * <0 Failure: Interface will not come up. */static int if_open(struct net_device* dev){ x25_channel_t* chan = dev->priv; sdla_t* card = chan->card; struct timeval tv; unsigned long smp_flags; if (netif_running(dev)) return -EBUSY; chan->tq_working = 0; /* Initialize the workqueue */ INIT_WORK(&chan->common.wanpipe_work, (void *)x25api_bh, dev); /* Allocate and initialize BH circular buffer */ /* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */ chan->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC); if (chan->bh_head == NULL){ printk(KERN_INFO "%s: ERROR, failed to allocate memory ! BH_BUFFERS !\n", card->devname); return -ENOBUFS; } memset(chan->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1))); atomic_set(&chan->bh_buff_used, 0); /* Increment the number of interfaces */ ++card->u.x.no_dev; wanpipe_open(card); /* LAPB protocol only uses one interface, thus * start the protocol after it comes up. */ if (card->u.x.LAPB_hdlc){ if (card->open_cnt == 1){ TX25Status* status = card->flags; S508_S514_lock(card, &smp_flags); x25_set_intr_mode(card, INTR_ON_TIMER); status->imask &= ~INTR_ON_TIMER; S508_S514_unlock(card, &smp_flags); } }else{ /* X25 can have multiple interfaces thus, start the * protocol once all interfaces are up */ //FIXME: There is a bug here. If interface is //brought down and up, it will try to enable comm. if (card->open_cnt == card->u.x.num_of_ch){ S508_S514_lock(card, &smp_flags); connect(card); S508_S514_unlock(card, &smp_flags); mod_timer(&card->u.x.x25_timer, jiffies + HZ); } } /* Device is not up until the we are in connected state */ do_gettimeofday( &tv ); chan->router_start_time = tv.tv_sec; netif_start_queue(dev); return 0;}/*=================================================================== * Name: if_close(), Close/Bring down the Netowrk Interface * * Purpose: To bring down a network interface. * * Rationale: * * Description: Close network interface. * o decrement use module use count * * Called by: Kernel (/usr/src/linux/net/core/dev.c) * (dev->close()) * ifconfig <name> down: will trigger the kernel * which will call this function. * * Assumptions: None * * Warnings: None * * Return: 0 Ok * <0 Failure: Interface will not exit properly. */static int if_close(struct net_device* dev){ x25_channel_t* chan = dev->priv; sdla_t* card = chan->card; unsigned long smp_flags; netif_stop_queue(dev); if ((chan->common.state == WAN_CONNECTED) || (chan->common.state == WAN_CONNECTING)){ S508_S514_lock(card, &smp_flags); chan_disc(dev); S508_S514_unlock(card, &smp_flags); } wanpipe_close(card); S508_S514_lock(card, &smp_flags); if (chan->bh_head){ int i; struct sk_buff *skb; for (i=0; i<(MAX_BH_BUFF+1); i++){ skb = ((bh_data_t *)&chan->bh_head[i])->skb; if (skb != NULL){ dev_kfree_skb_any(skb); } } kfree(chan->bh_head); chan->bh_head=NULL; } S508_S514_unlock(card, &smp_flags); /* If this is the last close, disconnect physical link */ if (!card->open_cnt){ S508_S514_lock(card, &smp_flags); disconnect(card); x25_set_intr_mode(card, 0); S508_S514_unlock(card, &smp_flags); } /* Decrement the number of interfaces */ --card->u.x.no_dev; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -