📄 sdla_x25.c
字号:
static unsigned int hex_to_uint (unsigned char*, int);static void parse_call_info (unsigned char*, x25_call_info_t*);static struct net_device *find_channel(sdla_t *card, unsigned lcn);static void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn);static void setup_for_delayed_transmit(struct net_device *dev, void *buf, unsigned len);/*================================================= * X25 API Functions */static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev, struct sk_buff **);static void timer_intr_exec(sdla_t *, unsigned char);static int execute_delayed_cmd(sdla_t *card, struct net_device *dev, mbox_cmd_t *usr_cmd, char bad_cmd);static int api_incoming_call (sdla_t*, TX25Mbox *, int);static int alloc_and_init_skb_buf (sdla_t *,struct sk_buff **, int);static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev, TX25Mbox* mbox);static int clear_confirm_event (sdla_t *, TX25Mbox*);static void send_oob_msg (sdla_t *card, struct net_device *dev, TX25Mbox *mbox);static int timer_intr_cmd_exec(sdla_t *card);static void api_oob_event (sdla_t *card,TX25Mbox *mbox);static int check_bad_command(sdla_t *card, struct net_device *dev);static int channel_disconnect(sdla_t* card, struct net_device *dev);static void hdlc_link_down (sdla_t*);/*================================================= * XPIPEMON Functions */static int process_udp_mgmt_pkt(sdla_t *);static int udp_pkt_type( struct sk_buff *, sdla_t*);static int reply_udp( unsigned char *, unsigned int); static void init_x25_channel_struct( x25_channel_t *);static void init_global_statistics( sdla_t *);static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t *card, struct net_device *dev, struct sk_buff *skb, int lcn);static unsigned short calc_checksum (char *, int);/*================================================= * IPX functions */static void switch_net_numbers(unsigned char *, unsigned long, unsigned char);static int handle_IPXWAN(unsigned char *, char *, unsigned char , unsigned long , unsigned short );extern void disable_irq(unsigned int);extern void enable_irq(unsigned int);static void S508_S514_lock(sdla_t *, unsigned long *);static void S508_S514_unlock(sdla_t *, unsigned long *);/*================================================= * Global Variables *=================================================*//*================================================= * Public Functions *=================================================*//*=================================================================== * wpx_init: X.25 Protocol Initialization routine. * * Purpose: To initialize the protocol/firmware. * * Rationale: This function is called by setup() function, in * sdlamain.c, to dynamically setup the x25 protocol. * This is the first protocol specific function, which * executes once on startup. * * Description: This procedure initializes the x25 firmware and * sets up the mailbox, transmit and receive buffer * pointers. It also initializes all debugging structures * and sets up the X25 environment. * * Sets up hardware options defined by user in [wanpipe#] * section of wanpipe#.conf configuration file. * * At this point adapter is completely initialized * and X.25 firmware is running. * o read firmware version (to make sure it's alive) * o configure adapter * o initialize protocol-specific fields of the * adapter data space. * * Called by: setup() function in sdlamain.c * * Assumptions: None * * Warnings: None * * Return: 0 o.k. * < 0 failure. */int wpx_init (sdla_t* card, wandev_conf_t* conf){ union{ char str[80]; TX25Config cfg; } u; /* Verify configuration ID */ if (conf->config_id != WANCONFIG_X25){ printk(KERN_INFO "%s: invalid configuration ID %u!\n", card->devname, conf->config_id) ; return -EINVAL; } /* Initialize protocol-specific fields */ card->mbox = (void*)(card->hw.dpmbase + X25_MBOX_OFFS); card->rxmb = (void*)(card->hw.dpmbase + X25_RXMBOX_OFFS); card->flags = (void*)(card->hw.dpmbase + X25_STATUS_OFFS); /* Initialize for S514 Card */ if(card->hw.type == SDLA_S514) { card->mbox += X25_MB_VECTOR; card->flags += X25_MB_VECTOR; card->rxmb += X25_MB_VECTOR; } /* Read firmware version. Note that when adapter initializes, it * clears the mailbox, so it may appear that the first command was * executed successfully when in fact it was merely erased. To work * around this, we execute the first command twice. */ if (x25_get_version(card, NULL) || x25_get_version(card, u.str)) return -EIO; /* X25 firmware can run ether in X25 or LAPB HDLC mode. * Check the user defined option and configure accordingly */ if (conf->u.x25.LAPB_hdlc_only == WANOPT_YES){ if (set_hdlc_level(card) != CMD_OK){ return -EIO; }else{ printk(KERN_INFO "%s: running LAP_B HDLC firmware v%s\n", card->devname, u.str); } card->u.x.LAPB_hdlc = 1; }else{ printk(KERN_INFO "%s: running X.25 firmware v%s\n", card->devname, u.str); card->u.x.LAPB_hdlc = 0; } /* Configure adapter. Here we set resonable defaults, then parse * device configuration structure and set configuration options. * Most configuration options are verified and corrected (if * necessary) since we can't rely on the adapter to do so. */ memset(&u.cfg, 0, sizeof(u.cfg)); u.cfg.t1 = 3; u.cfg.n2 = 10; u.cfg.autoHdlc = 1; /* automatic HDLC connection */ u.cfg.hdlcWindow = 7; u.cfg.pktWindow = 2; u.cfg.station = 1; /* DTE */ u.cfg.options = 0x0090; /* disable D-bit pragmatics */ u.cfg.ccittCompat = 1988; u.cfg.t10t20 = 30; u.cfg.t11t21 = 30; u.cfg.t12t22 = 30; u.cfg.t13t23 = 30; u.cfg.t16t26 = 30; u.cfg.t28 = 30; u.cfg.r10r20 = 5; u.cfg.r12r22 = 5; u.cfg.r13r23 = 5; u.cfg.responseOpt = 1; /* RR's after every packet */ if (card->u.x.LAPB_hdlc){ u.cfg.hdlcMTU = 1027; } if (conf->u.x25.x25_conf_opt){ u.cfg.options = conf->u.x25.x25_conf_opt; } if (conf->clocking != WANOPT_EXTERNAL) u.cfg.baudRate = bps_to_speed_code(conf->bps); if (conf->station != WANOPT_DTE){ u.cfg.station = 0; /* DCE mode */ } if (conf->interface != WANOPT_RS232 ){ u.cfg.hdlcOptions |= 0x80; /* V35 mode */ } /* adjust MTU */ if (!conf->mtu || (conf->mtu >= 1024)) card->wandev.mtu = 1024; else if (conf->mtu >= 512) card->wandev.mtu = 512; else if (conf->mtu >= 256) card->wandev.mtu = 256; else if (conf->mtu >= 128) card->wandev.mtu = 128; else card->wandev.mtu = 64; u.cfg.defPktSize = u.cfg.pktMTU = card->wandev.mtu; if (conf->u.x25.hi_pvc){ card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, MAX_LCN_NUM); card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc); } if (conf->u.x25.hi_svc){ card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, MAX_LCN_NUM); card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc); } /* Figure out the total number of channels to configure */ card->u.x.num_of_ch = 0; if (card->u.x.hi_svc != 0){ card->u.x.num_of_ch = (card->u.x.hi_svc - card->u.x.lo_svc) + 1; } if (card->u.x.hi_pvc != 0){ card->u.x.num_of_ch += (card->u.x.hi_pvc - card->u.x.lo_pvc) + 1; } if (card->u.x.num_of_ch == 0){ printk(KERN_INFO "%s: ERROR, Minimum number of PVC/SVC channels is 1 !\n" "%s: Please set the Lowest/Highest PVC/SVC values !\n", card->devname,card->devname); return -ECHRNG; } u.cfg.loPVC = card->u.x.lo_pvc; u.cfg.hiPVC = card->u.x.hi_pvc; u.cfg.loTwoWaySVC = card->u.x.lo_svc; u.cfg.hiTwoWaySVC = card->u.x.hi_svc; if (conf->u.x25.hdlc_window) u.cfg.hdlcWindow = min_t(unsigned int, conf->u.x25.hdlc_window, 7); if (conf->u.x25.pkt_window) u.cfg.pktWindow = min_t(unsigned int, conf->u.x25.pkt_window, 7); if (conf->u.x25.t1) u.cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30); if (conf->u.x25.t2) u.cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 29); if (conf->u.x25.t4) u.cfg.t4 = min_t(unsigned int, conf->u.x25.t4, 240); if (conf->u.x25.n2) u.cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30); if (conf->u.x25.t10_t20) u.cfg.t10t20 = min_t(unsigned int, conf->u.x25.t10_t20,255); if (conf->u.x25.t11_t21) u.cfg.t11t21 = min_t(unsigned int, conf->u.x25.t11_t21,255); if (conf->u.x25.t12_t22) u.cfg.t12t22 = min_t(unsigned int, conf->u.x25.t12_t22,255); if (conf->u.x25.t13_t23) u.cfg.t13t23 = min_t(unsigned int, conf->u.x25.t13_t23,255); if (conf->u.x25.t16_t26) u.cfg.t16t26 = min_t(unsigned int, conf->u.x25.t16_t26, 255); if (conf->u.x25.t28) u.cfg.t28 = min_t(unsigned int, conf->u.x25.t28, 255); if (conf->u.x25.r10_r20) u.cfg.r10r20 = min_t(unsigned int, conf->u.x25.r10_r20,250); if (conf->u.x25.r12_r22) u.cfg.r12r22 = min_t(unsigned int, conf->u.x25.r12_r22,250); if (conf->u.x25.r13_r23) u.cfg.r13r23 = min_t(unsigned int, conf->u.x25.r13_r23,250); if (conf->u.x25.ccitt_compat) u.cfg.ccittCompat = conf->u.x25.ccitt_compat; /* initialize adapter */ if (card->u.x.LAPB_hdlc){ if (hdlc_configure(card, &u.cfg) != CMD_OK) return -EIO; }else{ if (x25_configure(card, &u.cfg) != CMD_OK) return -EIO; } if ((x25_close_hdlc(card) != CMD_OK) || /* close HDLC link */ (x25_set_dtr(card, 0) != CMD_OK)) /* drop DTR */ return -EIO; /* Initialize protocol-specific fields of adapter data space */ card->wandev.bps = conf->bps; card->wandev.interface = conf->interface; card->wandev.clocking = conf->clocking; card->wandev.station = conf->station; card->isr = &wpx_isr; card->poll = NULL; //&wpx_poll; card->disable_comm = &disable_comm; card->exec = &wpx_exec; card->wandev.update = &update; card->wandev.new_if = &new_if; card->wandev.del_if = &del_if; /* WARNING: This function cannot exit with an error * after the change of state */ card->wandev.state = WAN_DISCONNECTED; card->wandev.enable_tx_int = 0; card->irq_dis_if_send_count = 0; card->irq_dis_poll_count = 0; card->u.x.tx_dev = NULL; card->u.x.no_dev = 0; /* Configure for S514 PCI Card */ if (card->hw.type == SDLA_S514) { card->u.x.hdlc_buf_status = (volatile unsigned char *) (card->hw.dpmbase + X25_MB_VECTOR+ X25_MISC_HDLC_BITS); }else{ card->u.x.hdlc_buf_status = (volatile unsigned char *)(card->hw.dpmbase + X25_MISC_HDLC_BITS); } card->u.x.poll_device=NULL; card->wandev.udp_port = conf->udp_port; /* Enable or disable call setup logging */ if (conf->u.x25.logging == WANOPT_YES){ printk(KERN_INFO "%s: Enabling Call Logging.\n", card->devname); card->u.x.logging = 1; }else{ card->u.x.logging = 0; } /* Enable or disable modem status reporting */ if (conf->u.x25.oob_on_modem == WANOPT_YES){ printk(KERN_INFO "%s: Enabling OOB on Modem change.\n", card->devname); card->u.x.oob_on_modem = 1; }else{ card->u.x.oob_on_modem = 0; } init_global_statistics(card); INIT_WORK(&card->u.x.x25_poll_work, (void *)wpx_poll, card); init_timer(&card->u.x.x25_timer); card->u.x.x25_timer.data = (unsigned long)card; card->u.x.x25_timer.function = x25_timer_routine; return 0;}/*========================================================= * WAN Device Driver Entry Points *========================================================*//*============================================================ * Name: update(), Update device status & statistics. * * Purpose: To provide debugging and statitical * information to the /proc file system. * /proc/net/wanrouter/wanpipe# * * Rationale: The /proc file system is used to collect * information about the kernel and drivers. * Using the /proc file system the user * can see exactly what the sangoma drivers are * doing. And in what state they are in. * * Description: Collect all driver statistical information * and pass it to the top laywer. * * Since we have to execute a debugging command, * to obtain firmware statitics, we trigger a * UPDATE function within the timer interrtup. * We wait until the timer update is complete. * Once complete return the appropriate return * code to indicate that the update was successful. * * Called by: device_stat() in wanmain.c * * Assumptions: * * Warnings: This function will degrade the performance * of the router, since it uses the mailbox. * * Return: 0 OK * <0 Failed (or busy). */static int update(struct wan_device* wandev){ volatile sdla_t* card; TX25Status* status; unsigned long timeout; /* sanity checks */ if ((wandev == NULL) || (wandev->private == NULL)) return -EFAULT; if (wandev->state == WAN_UNCONFIGURED) return -ENODEV; if (test_bit(SEND_CRIT, (void*)&wandev->critical)) return -EAGAIN; if (!wandev->dev) return -ENODEV; card = wandev->private; status = card->flags; card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UPDATE; status->imask |= INTR_ON_TIMER; timeout = jiffies; for (;;){ if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE)){ break; } if (time_after(jiffies, timeout + 1*HZ)){ card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; return -EAGAIN; } } return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -