📄 sdla_fr.c
字号:
u.cfg.kbps = conf->bps / 1000; u.cfg.cir_fwd = u.cfg.cir_bwd = 16; u.cfg.bc_fwd = u.cfg.bc_bwd = 16; u.cfg.options = 0x0000; printk(KERN_INFO "%s: Global CIR enabled by Default\n", card->devname); switch (conf->u.fr.signalling) { case WANOPT_FR_ANSI: u.cfg.options = 0x0000; break; case WANOPT_FR_Q933: u.cfg.options |= 0x0200; break; case WANOPT_FR_LMI: u.cfg.options |= 0x0400; break; case WANOPT_NO: u.cfg.options |= 0x0800; break; default: printk(KERN_INFO "%s: Illegal Signalling option\n", card->wandev.name); return -EINVAL; } card->wandev.signalling = conf->u.fr.signalling; if (conf->station == WANOPT_CPE) { if (conf->u.fr.signalling == WANOPT_NO){ printk(KERN_INFO "%s: ERROR - For NO signalling, station must be set to Node!", card->devname); return -EINVAL; } u.cfg.station = 0; u.cfg.options |= 0x8000; /* auto config DLCI */ card->u.f.dlci_num = 0; } else { u.cfg.station = 1; /* switch emulation mode */ /* For switch emulation we have to create a list of dlci(s) * that will be sent to be global SET_DLCI_CONFIGURATION * command in fr_configure() routine. */ card->u.f.dlci_num = min(max(conf->u.fr.dlci_num, 1), 100); for ( i = 0; i < card->u.f.dlci_num; i++) { card->u.f.node_dlci[i] = (unsigned short) conf->u.fr.dlci[i] ? conf->u.fr.dlci[i] : 16; } } if (conf->clocking == WANOPT_INTERNAL) u.cfg.port |= 0x0001; if (conf->interface == WANOPT_RS232) u.cfg.port |= 0x0002; if (conf->u.fr.t391) u.cfg.t391 = min(conf->u.fr.t391, 30); else u.cfg.t391 = 5; if (conf->u.fr.t392) u.cfg.t392 = min(conf->u.fr.t392, 30); else u.cfg.t392 = 15; if (conf->u.fr.n391) u.cfg.n391 = min(conf->u.fr.n391, 255); else u.cfg.n391 = 2; if (conf->u.fr.n392) u.cfg.n392 = min(conf->u.fr.n392, 10); else u.cfg.n392 = 3; if (conf->u.fr.n393) u.cfg.n393 = min(conf->u.fr.n393, 10); else u.cfg.n393 = 4; if (fr_configure(card, &u.cfg)) return -EIO; if (card->hw.type == SDLA_S514) { buf_info = (void*)(card->hw.dpmbase + FR_MB_VECTOR + FR508_RXBC_OFFS); card->rxmb = (void*)(buf_info->rse_next + card->hw.dpmbase); card->u.f.rxmb_base = (void*)(buf_info->rse_base + card->hw.dpmbase); card->u.f.rxmb_last = (void*)(buf_info->rse_base + (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) + card->hw.dpmbase); } else { buf_info = (void*)(card->hw.dpmbase + FR508_RXBC_OFFS); card->rxmb = (void*)(buf_info->rse_next - FR_MB_VECTOR + card->hw.dpmbase); card->u.f.rxmb_base = (void*)(buf_info->rse_base - FR_MB_VECTOR + card->hw.dpmbase); card->u.f.rxmb_last = (void*)(buf_info->rse_base + (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) - FR_MB_VECTOR + card->hw.dpmbase); } card->u.f.rx_base = buf_info->buf_base; card->u.f.rx_top = buf_info->buf_top; card->u.f.tx_interrupts_pending = 0; card->wandev.mtu = conf->mtu; card->wandev.bps = conf->bps; card->wandev.interface = conf->interface; card->wandev.clocking = conf->clocking; card->wandev.station = conf->station; card->poll = NULL; card->exec = &wpf_exec; card->wandev.update = &update; card->wandev.new_if = &new_if; card->wandev.del_if = &del_if; card->wandev.state = WAN_DISCONNECTED; card->wandev.ttl = conf->ttl; card->wandev.udp_port = conf->udp_port; /* Intialize global statistics for a card */ init_global_statistics( card ); card->TracingEnabled = 0; /* Interrupt Test */ Intr_test_counter = 0; card->intr_mode = INTR_TEST_MODE; err = intr_test( card ); if (err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { printk( "%s: Interrupt Test Failed, Counter: %i\n", card->devname, Intr_test_counter); printk( "Please choose another interrupt\n"); err = -EIO; return err; } printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n", card->devname, Intr_test_counter); return 0;}/******* WAN Device Driver Entry Points *************************************//*============================================================================ * Update device status & statistics. */static int update (wan_device_t* wandev){ volatile sdla_t* card; unsigned long timeout; fr508_flags_t* flags; /* sanity checks */ if ((wandev == NULL) || (wandev->private == NULL)) return -EFAULT; if (wandev->state == WAN_UNCONFIGURED) return -ENODEV; if (test_bit(1, (void*)&wandev->critical)) return -EAGAIN; card = wandev->private; flags = card->flags; card->u.f.update_comms_stats = 1; card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE; flags->imask |= FR_INTR_TIMER; timeout = jiffies; for(;;) { if(card->u.f.update_comms_stats == 0) break; if ((jiffies - timeout) > (1 * HZ)){ card->u.f.update_comms_stats = 0; 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 (wan_device_t* wandev, struct net_device* dev, wanif_conf_t* conf){ sdla_t* card = wandev->private; fr_channel_t* chan; int dlci = 0; 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; } /* allocate and initialize private data */ chan = kmalloc(sizeof(fr_channel_t), GFP_KERNEL); if (chan == NULL) return -ENOMEM; memset(chan, 0, sizeof(fr_channel_t)); strcpy(chan->name, conf->name); chan->card = card; /* verify media address */ if (is_digit(conf->addr[0])) { dlci = dec_to_uint(conf->addr, 0); if (dlci && (dlci <= HIGHEST_VALID_DLCI)) { chan->dlci = dlci; } else { printk(KERN_ERR "%s: invalid DLCI %u on interface %s!\n", wandev->name, dlci, chan->name); err = -EINVAL; } } else { printk(KERN_ERR "%s: invalid media address on interface %s!\n", wandev->name, chan->name); err = -EINVAL; } /* Setup wanpipe as a router (WANPIPE) or as an API */ if(strcmp(conf->usedby, "WANPIPE") == 0){ printk(KERN_INFO "%s: Running in WANPIPE mode %s\n", wandev->name, chan->name); chan->usedby = WANPIPE; } else if(strcmp(conf->usedby, "API") == 0){#ifdef FRAME_RELAY_API chan->usedby = API; printk(KERN_INFO "%s: Running in API mode %s\n", wandev->name, chan->name);#else printk(KERN_INFO "%s: API Mode is not supported !\n", wandev->name); printk(KERN_INFO "%s: API patch can be obtained from Sangoma Tech.\n", wandev->name); err = -EINVAL;#endif } if (err) { kfree(chan); return err; } card->u.f.dlci_to_dev_map[dlci] = dev; /* place cir,be,bc and other channel specific information into the * chan structure */ if (conf->cir) { chan->cir = max( 1, min( 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( 0, min( 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; /* FIXME: ARP is not supported by this frame relay verson */ if (conf->inarp == WANOPT_YES){ printk(KERN_INFO "%s: ERROR - This version of WANPIPE doesn't support ARPs\n", card->devname); //chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE; //chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10; kfree(chan); return -EINVAL; }else{ 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; /* Enable Interrupts and Communications */ if (!wandev->new_if_cnt){ fr508_flags_t* flags = card->flags; wandev->new_if_cnt++; /* If you enable comms and then set ints, you get a Tx int as you perform the SET_INT_TRIGGERS command. So, we only set int triggers and then adjust the interrupt mask (to disable Tx ints) before enabling comms. */ if (fr_set_intr_mode(card, (FR_INTR_RXRDY | FR_INTR_TXRDY | FR_INTR_DLC | FR_INTR_TIMER | FR_INTR_TX_MULT_DLCIs) , card->wandev.mtu, 0)) { kfree(chan); return -EIO; } flags->imask &= ~(FR_INTR_TXRDY | FR_INTR_TIMER); if (fr_comm_enable(card)) { kfree(chan); return -EIO; } wanpipe_set_state(card, WAN_CONNECTED); } return 0;}/*============================================================================ * Delete logical channel. */static int del_if (wan_device_t* wandev, struct net_device* dev){ sdla_t *card = wandev->private; /* Execute shutdown very first time we enter del_if */ if (!wandev->del_if_cnt) { wandev->del_if_cnt++; wanpipe_set_state(card, WAN_DISCONNECTED); fr_set_intr_mode(card, 0, 0, 0); fr_comm_disable(card);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -