📄 sdla_chdlc.c
字号:
max_permitted_baud = (card->hw.type == SDLA_S514) ? PRI_MAX_BAUD_RATE_S514 : PRI_MAX_BAUD_RATE_S508; }else if(port_num == WANOPT_SEC) { /* For Secondary Port 1 */ max_permitted_baud = (card->hw.type == SDLA_S514) ? SEC_MAX_BAUD_RATE_S514 : SEC_MAX_BAUD_RATE_S508; } if(conf->bps > max_permitted_baud) { conf->bps = max_permitted_baud; printk(KERN_INFO "%s: Baud too high!\n", card->wandev.name); printk(KERN_INFO "%s: Baud rate set to %lu bps\n", card->wandev.name, max_permitted_baud); } card->wandev.bps = conf->bps; }else{ card->wandev.bps = 0; } /* Setup the Port MTU */ if((port_num == WANOPT_PRI) || card->u.c.receive_only) { /* For Primary Port 0 */ card->wandev.mtu = (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) : CHDLC_DFLT_DATA_LEN; } else if(port_num == WANOPT_SEC) { /* For Secondary Port 1 */ card->wandev.mtu = (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) : CHDLC_DFLT_DATA_LEN; } /* Set up the interrupt status area */ /* Read the CHDLC Configuration and obtain: * Ptr to shared memory infor struct * Use this pointer to calculate the value of card->u.c.flags ! */ mb1->buffer_length = 0; mb1->command = READ_CHDLC_CONFIGURATION; err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT; if(err != COMMAND_OK) { if(card->hw.type != SDLA_S514) enable_irq(card->hw.irq); chdlc_error(card, err, mb1); return -EIO; } if(card->hw.type == SDLA_S514){ card->u.c.flags = (void *)(card->hw.dpmbase + (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)-> ptr_shared_mem_info_struct)); }else{ card->u.c.flags = (void *)(card->hw.dpmbase + (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)-> ptr_shared_mem_info_struct % SDLA_WINDOWSIZE)); } flags = card->u.c.flags; /* This is for the ports link state */ card->wandev.state = WAN_DUALPORT; card->u.c.state = WAN_DISCONNECTED; if (!card->wandev.piggyback){ int err; /* Perform interrupt testing */ err = intr_test(card); if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { printk(KERN_INFO "%s: Interrupt test failed (%i)\n", card->devname, Intr_test_counter); printk(KERN_INFO "%s: Please choose another interrupt\n", card->devname); return -EIO; } printk(KERN_INFO "%s: Interrupt test passed (%i)\n", card->devname, Intr_test_counter); card->configured = 1; } if ((card->tty_opt=conf->tty) == WANOPT_YES){ int err; card->tty_minor = conf->tty_minor; /* On ASYNC connections internal clocking * is mandatory */ if ((card->u.c.async_mode = conf->tty_mode)){ card->wandev.clocking = 1; } err=wanpipe_tty_init(card); if (err){ return err; } }else{ if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){ printk (KERN_INFO "%s: " "Failed to set interrupt triggers!\n", card->devname); return -EIO; } /* Mask the Timer interrupt */ flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_TIMER; } /* If we are using CHDLC in backup mode, this flag will * indicate not to look for IP addresses in config_chdlc()*/ card->u.c.backup = conf->backup; printk(KERN_INFO "\n"); return 0;}/******* WAN Device Driver Entry Points *************************************//*============================================================================ * Update device status & statistics * This procedure is called when updating the PROC file system and returns * various communications statistics. These statistics are accumulated from 3 * different locations: * 1) The 'if_stats' recorded for the device. * 2) Communication error statistics on the adapter. * 3) CHDLC operational statistics on the adapter. * The board level statistics are read during a timer interrupt. Note that we * read the error and operational statistics during consecitive timer ticks so * as to minimize the time that we are inside the interrupt handler. * */static int update(struct wan_device* wandev){ sdla_t* card = wandev->private; struct net_device* dev; volatile chdlc_private_area_t* chdlc_priv_area; SHARED_MEMORY_INFO_STRUCT *flags; unsigned long timeout; /* sanity checks */ if((wandev == NULL) || (wandev->private == NULL)) return -EFAULT; if(wandev->state == WAN_UNCONFIGURED) return -ENODEV; /* more sanity checks */ if(!card->u.c.flags) return -ENODEV; if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) return -EAGAIN; if((dev=card->wandev.dev) == NULL) return -ENODEV; if((chdlc_priv_area=dev->priv) == NULL) return -ENODEV; flags = card->u.c.flags; if(chdlc_priv_area->update_comms_stats){ return -EAGAIN; } /* we will need 2 timer interrupts to complete the */ /* reading of the statistics */ chdlc_priv_area->update_comms_stats = 2; flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER; chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE; /* wait a maximum of 1 second for the statistics to be updated */ timeout = jiffies; for(;;) { if(chdlc_priv_area->update_comms_stats == 0) break; if ((jiffies - timeout) > (1 * HZ)){ chdlc_priv_area->update_comms_stats = 0; chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; return -EAGAIN; } } return 0;}/*============================================================================ * Create new logical channel. * This routine is called by the router when ROUTER_IFNEW IOCTL is being * handled. * o parse media- and hardware-specific configuration * o make sure that a new channel can be created * o allocate resources, if necessary * o prepare network device structure for registaration. * * Return: 0 o.k. * < 0 failure (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; chdlc_private_area_t* chdlc_priv_area; printk(KERN_INFO "%s: Configuring Interface: %s\n", card->devname, conf->name); if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) { printk(KERN_INFO "%s: Invalid interface name!\n", card->devname); return -EINVAL; } /* allocate and initialize private data */ chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL); if(chdlc_priv_area == NULL) return -ENOMEM; memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t)); chdlc_priv_area->card = card; chdlc_priv_area->common.sk = NULL; chdlc_priv_area->common.func = NULL; /* initialize data */ strcpy(card->u.c.if_name, conf->name); if(card->wandev.new_if_cnt > 0) { kfree(chdlc_priv_area); return -EEXIST; } card->wandev.new_if_cnt++; chdlc_priv_area->TracingEnabled = 0; chdlc_priv_area->route_status = NO_ROUTE; chdlc_priv_area->route_removed = 0; card->u.c.async_mode = conf->async_mode; /* setup for asynchronous mode */ if(conf->async_mode) { printk(KERN_INFO "%s: Configuring for asynchronous mode\n", wandev->name); if(card->u.c.comm_port == WANOPT_PRI) { printk(KERN_INFO "%s:Asynchronous mode on secondary port only\n", wandev->name); kfree(chdlc_priv_area); return -EINVAL; } if(strcmp(conf->usedby, "WANPIPE") == 0) { printk(KERN_INFO "%s: Running in WANIPE Async Mode\n", wandev->name); card->u.c.usedby = WANPIPE; }else{ card->u.c.usedby = API; } if(!card->wandev.clocking) { printk(KERN_INFO "%s: Asynch. clocking must be 'Internal'\n", wandev->name); kfree(chdlc_priv_area); return -EINVAL; } if((card->wandev.bps < MIN_ASY_BAUD_RATE) || (card->wandev.bps > MAX_ASY_BAUD_RATE)) { printk(KERN_INFO "%s: Selected baud rate is invalid.\n", wandev->name); printk(KERN_INFO "Must be between %u and %u bps.\n", MIN_ASY_BAUD_RATE, MAX_ASY_BAUD_RATE); kfree(chdlc_priv_area); return -EINVAL; } card->u.c.api_options = 0; if (conf->asy_data_trans == WANOPT_YES) { card->u.c.api_options |= ASY_RX_DATA_TRANSPARENT; } card->u.c.protocol_options = 0; if (conf->rts_hs_for_receive == WANOPT_YES) { card->u.c.protocol_options |= ASY_RTS_HS_FOR_RX; } if (conf->xon_xoff_hs_for_receive == WANOPT_YES) { card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_RX; } if (conf->xon_xoff_hs_for_transmit == WANOPT_YES) { card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_TX; } if (conf->dcd_hs_for_transmit == WANOPT_YES) { card->u.c.protocol_options |= ASY_DCD_HS_FOR_TX; } if (conf->cts_hs_for_transmit == WANOPT_YES) { card->u.c.protocol_options |= ASY_CTS_HS_FOR_TX; } card->u.c.tx_bits_per_char = conf->tx_bits_per_char; card->u.c.rx_bits_per_char = conf->rx_bits_per_char; card->u.c.stop_bits = conf->stop_bits; card->u.c.parity = conf->parity; card->u.c.break_timer = conf->break_timer; card->u.c.inter_char_timer = conf->inter_char_timer; card->u.c.rx_complete_length = conf->rx_complete_length; card->u.c.xon_char = conf->xon_char; } else { /* setup for synchronous mode */ card->u.c.protocol_options = 0; if (conf->ignore_dcd == WANOPT_YES){ card->u.c.protocol_options |= IGNORE_DCD_FOR_LINK_STAT; } if (conf->ignore_cts == WANOPT_YES){ card->u.c.protocol_options |= IGNORE_CTS_FOR_LINK_STAT; } if (conf->ignore_keepalive == WANOPT_YES) { card->u.c.protocol_options |= IGNORE_KPALV_FOR_LINK_STAT; card->u.c.kpalv_tx = MIN_Tx_KPALV_TIMER; card->u.c.kpalv_rx = MIN_Rx_KPALV_TIMER; card->u.c.kpalv_err = MIN_KPALV_ERR_TOL; } else { /* Do not ignore keepalives */ card->u.c.kpalv_tx = ((conf->keepalive_tx_tmr - MIN_Tx_KPALV_TIMER) >= 0) ? min_t(unsigned int, conf->keepalive_tx_tmr,MAX_Tx_KPALV_TIMER) : DEFAULT_Tx_KPALV_TIMER; card->u.c.kpalv_rx = ((conf->keepalive_rx_tmr - MIN_Rx_KPALV_TIMER) >= 0) ? min_t(unsigned int, conf->keepalive_rx_tmr,MAX_Rx_KPALV_TIMER) : DEFAULT_Rx_KPALV_TIMER; card->u.c.kpalv_err = ((conf->keepalive_err_margin-MIN_KPALV_ERR_TOL) >= 0) ? min_t(unsigned int, conf->keepalive_err_margin, MAX_KPALV_ERR_TOL) : DEFAULT_KPALV_ERR_TOL; } /* Setup slarp timer to control delay between slarps */ card->u.c.slarp_timer = ((conf->slarp_timer - MIN_SLARP_REQ_TIMER) >= 0) ? min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) : DEFAULT_SLARP_REQ_TIMER; if (conf->hdlc_streaming == WANOPT_YES) { printk(KERN_INFO "%s: Enabling HDLC STREAMING Mode\n", wandev->name); card->u.c.protocol_options = HDLC_STREAMING_MODE; } if ((chdlc_priv_area->true_if_encoding = conf->true_if_encoding) == WANOPT_YES){ printk(KERN_INFO "%s: Enabling, true interface type encoding.\n", card->devname); } /* Setup wanpipe as a router (WANPIPE) or as an API */ if( strcmp(conf->usedby, "WANPIPE") == 0) { printk(KERN_INFO "%s: Running in WANPIPE mode!\n", wandev->name); card->u.c.usedby = WANPIPE; /* Option to bring down the interface when * the link goes down */ if (conf->if_down){ set_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down); printk(KERN_INFO "%s: Dynamic interface configuration enabled\n", card->devname); } } else if( strcmp(conf->usedby, "API") == 0) { card->u.c.usedby = API; printk(KERN_INFO "%s: Running in API mode !\n", wandev->name); } } /* Tells us that if this interface is a * gateway or not */ if ((chdlc_priv_area->gateway = conf->gateway) == WANOPT_YES){ printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", card->devname,card->u.c.if_name); } /* Get Multicast Information */ chdlc_priv_area->mc = conf->mc; /* prepare network device data space for registration */ strcpy(dev->name,card->u.c.if_name); dev->init = &if_init; dev->priv = chdlc_priv_area; /* Initialize the polling work routine */ INIT_WORK(&chdlc_priv_area->poll_work, (void*)(void*)chdlc_poll, dev); /* Initialize the polling delay timer */ init_timer(&chdlc_priv_area->poll_delay_timer); chdlc_priv_area->poll_delay_timer.data = (unsigned long)dev; chdlc_priv_area->poll_delay_timer.function = chdlc_poll_delay; printk(KERN_INFO "\n"); 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){ chdlc_private_area_t* chdlc_priv_area = dev->priv; sdla_t* card = chdlc_priv_area->card; struct wan_device* wandev = &card->wandev;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -