📄 sdla_fr.c
字号:
/****************************************************************************** sdla_fr.c WANPIPE(tm) Multiprotocol WAN Link Driver. Frame relay module.** Author(s): Gene Kozin * Jaspreet Singh <jaspreet@sangoma.com>** Copyright: (c) 1995-1997 Sangoma Technologies Inc.** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version* 2 of the License, or (at your option) any later version.* ============================================================================* Nov 26, 1997 Jaspreet Singh o Improved load sharing with multiple boards* o Added Cli() to protect enabling of interrupts* while polling is called.* Nov 24, 1997 Jaspreet Singh o Added counters to avoid enabling of interrupts* when they have been disabled by another* interface or routine (eg. wpf_poll).* Nov 06, 1997 Jaspreet Singh o Added INTR_TEST_MODE to avoid polling * routine disable interrupts during interrupt* testing.* Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time.* Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow* control by avoiding RACE conditions. The* cli() and restore_flags() are taken out.* The fr_channel structure is appended for * Driver Statistics.* Oct 15, 1997 Farhan Thawar o updated if_send() and receive for IPX* Aug 29, 1997 Farhan Thawar o Removed most of the cli() and sti()* o Abstracted the UDP management stuff* o Now use tbusy and critical more intelligently* Jul 21, 1997 Jaspreet Singh o Can configure T391, T392, N391, N392 & N393* through router.conf.* o Protected calls to sdla_peek() by adDing * save_flags(), cli() and restore_flags().* o Added error message for Inactive DLCIs in* fr_event() and update_chan_state().* o Fixed freeing up of buffers using kfree() * when packets are received.* Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets * o Added ability to discard multicast and * broadcast source addressed packets* Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities * New case (0x44) statement in if_send routine * Added a global variable rCount to keep track* of FT1 status enabled on the board.* May 29, 1997 Jaspreet Singh o Fixed major Flow Control Problem* With multiple boards a problem was seen where* the second board always stopped transmitting* packet after running for a while. The code* got into a stage where the interrupts were* disabled and dev->tbusy was set to 1.* This caused the If_send() routine to get into* the if clause for it(0,dev->tbusy) * forever.* The code got into this stage due to an * interrupt occurring within the if clause for * set_bit(0,dev->tbusy). Since an interrupt * disables furhter transmit interrupt and * makes dev->tbusy = 0, this effect was undone * by making dev->tbusy = 1 in the if clause.* The Fix checks to see if Transmit interrupts* are disabled then do not make dev->tbusy = 1* Introduced a global variable: int_occur and* added tx_int_enabled in the wan_device * structure. * May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple* boards.** Apr 25, 1997 Farhan Thawar o added UDP Management stuff* o fixed bug in if_send() and tx_intr() to* sleep and wakeup all devices* Mar 11, 1997 Farhan Thawar Version 3.1.1* o fixed (+1) bug in fr508_rx_intr()* o changed if_send() to return 0 if* wandev.critical() is true* o free socket buffer in if_send() if* returning 0 * o added tx_intr() routine* Jan 30, 1997 Gene Kozin Version 3.1.0* o implemented exec() entry point* o fixed a bug causing driver configured as* a FR switch to be stuck in WAN_* mode* Jan 02, 1997 Gene Kozin Initial version.*****************************************************************************/#include <linux/kernel.h> /* printk(), and other useful stuff */#include <linux/stddef.h> /* offsetof(), etc. */#include <linux/errno.h> /* return codes */#include <linux/string.h> /* inline memset(), etc. */#include <linux/malloc.h> /* kmalloc(), kfree() */#include <linux/wanrouter.h> /* WAN router definitions */#include <linux/wanpipe.h> /* WANPIPE common user API definitions */#include <linux/if_arp.h> /* ARPHRD_* defines */#include <asm/byteorder.h> /* htons(), etc. */#include <asm/io.h> /* for inb(), outb(), etc. */#include <linux/time.h> /* for do_gettimeofday */#define _GNUC_#include <linux/sdla_fr.h> /* frame relay firmware API definitions */#include <asm/uaccess.h>/****** Defines & Macros ****************************************************/#define MAX_CMD_RETRY 10 /* max number of firmware retries */#define FR_HEADER_LEN 8 /* max encapsulation header size */#define FR_CHANNEL_MTU 1500 /* unfragmented logical channel MTU *//* Q.922 frame types */#define Q922_UI 0x03 /* Unnumbered Info frame */#define Q922_XID 0xAF /* ??? *//* DLCI configured or not */#define DLCI_NOT_CONFIGURED 0x00#define DLCI_CONFIG_PENDING 0x01#define DLCI_CONFIGURED 0x02/* CIR enabled or not */#define CIR_ENABLED 0x00#define CIR_DISABLED 0x01/* Interrupt mode for DLCI = 0 */#define BUFFER_INTR_MODE 0x00#define DLCI_LIST_INTR_MODE 0x01/* Transmit Interrupt Status */#define DISABLED 0x00#define WAITING_TO_BE_ENABLED 0x01/* For handle_IPXWAN() */#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))/****** Data Structures *****************************************************//* This is an extention of the 'struct device' we create for each network * interface to keep the rest of channel-specific data. */typedef struct fr_channel { char name[WAN_IFNAME_SZ + 1]; /* interface name, ASCIIZ */ unsigned dlci_configured; /* check whether configured or not */ unsigned cir_status; /* check whether CIR enabled or not */ unsigned dlci; /* logical channel number */ unsigned cir; /* committed information rate */ unsigned bc; /* committed burst size */ unsigned be; /* excess burst size */ unsigned mc; /* multicast support on or off */ unsigned tx_int_status; /* Transmit Interrupt Status */ unsigned short pkt_length; /* Packet Length */ unsigned long router_start_time; /* Router start time in seconds */ unsigned long tick_counter; /* counter for transmit time out */ char dev_pending_devtint; /* interface pending dev_tint() */ char state; /* channel state */ void *dlci_int_interface; /* pointer to the DLCI Interface */ unsigned long IB_addr; /* physical address of Interface Byte */ unsigned long state_tick; /* time of the last state change */ sdla_t *card; /* -> owner */ struct net_device_stats ifstats; /* interface statistics */ unsigned long if_send_entry; unsigned long if_send_skb_null; unsigned long if_send_broadcast; unsigned long if_send_multicast; unsigned long if_send_critical_ISR; unsigned long if_send_critical_non_ISR; unsigned long if_send_busy; unsigned long if_send_busy_timeout; unsigned long if_send_FPIPE_request; unsigned long if_send_DRVSTATS_request; unsigned long if_send_wan_disconnected; unsigned long if_send_dlci_disconnected; unsigned long if_send_no_bfrs; unsigned long if_send_adptr_bfrs_full; unsigned long if_send_bfrs_passed_to_adptr; unsigned long rx_intr_no_socket; unsigned long rx_intr_dev_not_started; unsigned long rx_intr_FPIPE_request; unsigned long rx_intr_DRVSTATS_request; unsigned long rx_intr_bfr_not_passed_to_stack; unsigned long rx_intr_bfr_passed_to_stack; unsigned long UDP_FPIPE_mgmt_kmalloc_err; unsigned long UDP_FPIPE_mgmt_direction_err; unsigned long UDP_FPIPE_mgmt_adptr_type_err; unsigned long UDP_FPIPE_mgmt_adptr_cmnd_OK; unsigned long UDP_FPIPE_mgmt_adptr_cmnd_timeout; unsigned long UDP_FPIPE_mgmt_adptr_send_passed; unsigned long UDP_FPIPE_mgmt_adptr_send_failed; unsigned long UDP_FPIPE_mgmt_not_passed_to_stack; unsigned long UDP_FPIPE_mgmt_passed_to_stack; unsigned long UDP_FPIPE_mgmt_no_socket; unsigned long UDP_DRVSTATS_mgmt_kmalloc_err; unsigned long UDP_DRVSTATS_mgmt_adptr_cmnd_OK; unsigned long UDP_DRVSTATS_mgmt_adptr_cmnd_timeout; unsigned long UDP_DRVSTATS_mgmt_adptr_send_passed; unsigned long UDP_DRVSTATS_mgmt_adptr_send_failed; unsigned long UDP_DRVSTATS_mgmt_not_passed_to_stack; unsigned long UDP_DRVSTATS_mgmt_passed_to_stack; unsigned long UDP_DRVSTATS_mgmt_no_socket; unsigned long router_up_time;} fr_channel_t;typedef struct dlci_status { unsigned short dlci PACKED; unsigned char state PACKED;} dlci_status_t;typedef struct dlci_IB_mapping { unsigned short dlci PACKED; unsigned long addr_value PACKED;} dlci_IB_mapping_t;/* This structure is used for DLCI list Tx interrupt mode. It is used to enable interrupt bit and set the packet length for transmission */typedef struct fr_dlci_interface { unsigned char gen_interrupt PACKED; unsigned short packet_length PACKED; unsigned char reserved PACKED;} fr_dlci_interface_t;static unsigned short num_frames;static unsigned long curr_trace_addr;static unsigned long start_trace_addr;static unsigned short available_buffer_space;static char TracingEnabled; /* variable for keeping track of enabling/disabling FT1 monitor status */static int rCount = 0;extern void disable_irq(unsigned int);extern void enable_irq(unsigned int);/* variable for keeping track of number of interrupts generated during * interrupt test routine */static int Intr_test_counter;/****** Function Prototypes *************************************************//* WAN link driver entry points. These are called by the WAN router module. */static int update(wan_device_t * wandev);static int new_if(wan_device_t * wandev, struct device *dev, wanif_conf_t * conf);static int del_if(wan_device_t * wandev, struct device *dev);/* WANPIPE-specific entry points */static int wpf_exec(struct sdla *card, void *u_cmd, void *u_data);/* Network device interface */static int if_init(struct device *dev);static int if_open(struct device *dev);static int if_close(struct device *dev);static int if_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);static int if_rebuild_hdr(struct sk_buff *skb);static int if_send(struct sk_buff *skb, struct device *dev);static struct net_device_stats *if_stats(struct device *dev);/* Interrupt handlers */static void fr502_isr(sdla_t * card);static void fr508_isr(sdla_t * card);static void fr502_rx_intr(sdla_t * card);static void fr508_rx_intr(sdla_t * card);static void tx_intr(sdla_t * card);static void spur_intr(sdla_t * card);/* Background polling routines */static void wpf_poll(sdla_t * card);/* Frame relay firmware interface functions */static int fr_read_version(sdla_t * card, char *str);static int fr_configure(sdla_t * card, fr_conf_t * conf);static int fr_dlci_configure(sdla_t * card, fr_dlc_conf_t * conf, unsigned dlci);static int fr_set_intr_mode(sdla_t * card, unsigned mode, unsigned mtu);static int fr_comm_enable(sdla_t * card);static int fr_comm_disable(sdla_t * card);static int fr_get_err_stats(sdla_t * card);static int fr_get_stats(sdla_t * card);static int fr_add_dlci(sdla_t * card, int dlci, int num);static int fr_activate_dlci(sdla_t * card, int dlci, int num);static int fr_issue_isf(sdla_t * card, int isf);static int fr502_send(sdla_t * card, int dlci, int attr, int len, void *buf);static int fr508_send(sdla_t * card, int dlci, int attr, int len, void *buf);/* Firmware asynchronous event handlers */static int fr_event(sdla_t * card, int event, fr_mbox_t * mbox);static int fr_modem_failure(sdla_t * card, fr_mbox_t * mbox);static int fr_dlci_change(sdla_t * card, fr_mbox_t * mbox);/* Miscellaneous functions */static int update_chan_state(struct device *dev);static void set_chan_state(struct device *dev, int state);static struct device *find_channel(sdla_t * card, unsigned dlci);static int is_tx_ready(sdla_t * card, fr_channel_t * chan);static unsigned int dec_to_uint(unsigned char *str, int len);static int reply_udp(unsigned char *data, unsigned int mbox_len);static int intr_test(sdla_t * card);static void init_chan_statistics(fr_channel_t * chan);static void init_global_statistics(sdla_t * card);static void read_DLCI_IB_mapping(sdla_t * card, fr_channel_t * chan);/* Udp management functions */static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct device *dev, int dlci, fr_channel_t * chan);static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_buff *skb, struct device *dev, int dlci, fr_channel_t * chan);static int udp_pkt_type(struct sk_buff *skb, sdla_t * card);/* IPX functions */static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming);static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number);/****** Public Functions ****************************************************//*============================================================================ * Frame relay protocol initialization routine. * * This routine is called by the main WANPIPE module during setup. At this * point adapter is completely initialized and 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. * * Return: 0 o.k. * < 0 failure. */int wpf_init(sdla_t * card, wandev_conf_t * conf){ union { char str[80]; fr_conf_t cfg; } u; int i; /* Verify configuration ID */ if (conf->config_id != WANCONFIG_FR) { printk(KERN_INFO "%s: invalid configuration ID %u!\n", card->devname, conf->config_id); return -EINVAL; } /* Initialize protocol-specific fields of adapter data space */ switch (card->hw.fwid) { case SFID_FR502: card->mbox = (void *) (card->hw.dpmbase + FR502_MBOX_OFFS); card->rxmb = (void *) (card->hw.dpmbase + FR502_RXMB_OFFS); card->flags = (void *) (card->hw.dpmbase + FR502_FLAG_OFFS); card->isr = &fr502_isr; break; case SFID_FR508: card->mbox = (void *) (card->hw.dpmbase + FR508_MBOX_OFFS); card->flags = (void *) (card->hw.dpmbase + FR508_FLAG_OFFS); card->isr = &fr508_isr; break; default: return -EINVAL; } /* 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 (fr_read_version(card, NULL) || fr_read_version(card, u.str)) return -EIO; printk(KERN_INFO "%s: running frame relay firmware v%s\n", card->devname, u.str); /* Adjust configuration */ conf->mtu = max(min(conf->mtu, 4080), FR_CHANNEL_MTU + FR_HEADER_LEN); conf->bps = min(conf->bps, 2048000); /* Configure adapter firmware */ memset(&u.cfg, 0, sizeof(u.cfg)); u.cfg.mtu = conf->mtu; u.cfg.kbps = conf->bps / 1000; u.cfg.cir_fwd = u.cfg.cir_bwd = 16; u.cfg.bc_fwd = u.cfg.bc_bwd = 16; if (conf->station == WANOPT_CPE) { u.cfg.options = 0x0080; printk(KERN_INFO "%s: Global CIR enabled by Default\n", card->devname); } else { u.cfg.options = 0x0081; } switch (conf->u.fr.signalling) { case WANOPT_FR_Q933: u.cfg.options |= 0x0200; break; case WANOPT_FR_LMI: u.cfg.options |= 0x0400; break; } if (conf->station == WANOPT_CPE) { 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -