From 9d99aaa31f5994d1923c3713ce9144c4c42332e1 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 7 Apr 2006 19:49:15 +0200 Subject: [PATCH] x86_64: Support memory hotadd without sparsemem Memory hotadd doesn't need SPARSEMEM, but can be handled by just preallocating mem_maps. This only needs some untangling of ifdefs to enable the necessary code even without SPARSEMEM. Originally from Keith Mannthey, hacked by AK. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- include/linux/init.h | 3 ++- include/linux/memory_hotplug.h | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/include/linux/init.h b/include/linux/init.h index ed0ac7c39fdc..93dcbe1abb4c 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -245,7 +245,8 @@ void __init parse_early_param(void); #define __cpuexitdata __exitdata #endif -#ifdef CONFIG_MEMORY_HOTPLUG +#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \ + || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) #define __meminit #define __meminitdata #define __memexit diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 968b1aa3732c..4ca3e6ad03ec 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -58,8 +58,6 @@ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro); /* need some defines for these for archs that don't support it */ extern void online_page(struct page *page); /* VM interface that may be used by firmware interface */ -extern int add_memory(u64 start, u64 size); -extern int remove_memory(u64 start, u64 size); extern int online_pages(unsigned long, unsigned long); /* reasonably generic interface to expand the physical pages in a zone */ @@ -92,11 +90,6 @@ static inline int mhp_notimplemented(const char *func) return -ENOSYS; } -static inline int __add_pages(struct zone *zone, unsigned long start_pfn, - unsigned long nr_pages) -{ - return mhp_notimplemented(__FUNCTION__); -} #endif /* ! CONFIG_MEMORY_HOTPLUG */ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, unsigned long nr_pages) @@ -105,4 +98,11 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, dump_stack(); return -ENOSYS; } + +#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \ + || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) +extern int add_memory(u64 start, u64 size); +extern int remove_memory(u64 start, u64 size); +#endif + #endif /* __LINUX_MEMORY_HOTPLUG_H */ -- cgit v1.2.3 From a8062231d80239cf3405982858c02aea21a6066a Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 7 Apr 2006 19:49:21 +0200 Subject: [PATCH] x86_64: Handle empty PXMs that only contain hotplug memory The node setup code would try to allocate the node metadata in the node itself, but that fails if there is no memory in there. This can happen with memory hotplug when the hotplug area defines an so far empty node. Now use bootmem to try to allocate the mem_map in other nodes. And if it fails don't panic, but just ignore the node. To make this work I added a new __alloc_bootmem_nopanic function that does what its name implies. TBD should try to use nearby nodes here. Currently we just use any. It's hard to do it better because bootmem doesn't have proper fallback lists yet. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/mm/numa.c | 41 ++++++++++++++++++++++++++++++++--------- arch/x86_64/mm/srat.c | 6 ++++++ include/linux/bootmem.h | 1 + mm/bootmem.c | 9 ++++++++- 4 files changed, 47 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 779132af29a7..cc02573a3271 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -100,11 +100,30 @@ int early_pfn_to_nid(unsigned long pfn) } #endif +static void * __init +early_node_mem(int nodeid, unsigned long start, unsigned long end, + unsigned long size) +{ + unsigned long mem = find_e820_area(start, end, size); + void *ptr; + if (mem != -1L) + return __va(mem); + ptr = __alloc_bootmem_nopanic(size, + SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)); + if (ptr == 0) { + printk(KERN_ERR "Cannot find %lu bytes in node %d\n", + size, nodeid); + return NULL; + } + return ptr; +} + /* Initialize bootmem allocator for a node */ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end) { unsigned long start_pfn, end_pfn, bootmap_pages, bootmap_size, bootmap_start; unsigned long nodedata_phys; + void *bootmap; const int pgdat_size = round_up(sizeof(pg_data_t), PAGE_SIZE); start = round_up(start, ZONE_ALIGN); @@ -114,13 +133,11 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en start_pfn = start >> PAGE_SHIFT; end_pfn = end >> PAGE_SHIFT; - nodedata_phys = find_e820_area(start, end, pgdat_size); - if (nodedata_phys == -1L) - panic("Cannot find memory pgdat in node %d\n", nodeid); - - Dprintk("nodedata_phys %lx\n", nodedata_phys); + node_data[nodeid] = early_node_mem(nodeid, start, end, pgdat_size); + if (node_data[nodeid] == NULL) + return; + nodedata_phys = __pa(node_data[nodeid]); - node_data[nodeid] = phys_to_virt(nodedata_phys); memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t)); NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid]; NODE_DATA(nodeid)->node_start_pfn = start_pfn; @@ -129,9 +146,15 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en /* Find a place for the bootmem map */ bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); bootmap_start = round_up(nodedata_phys + pgdat_size, PAGE_SIZE); - bootmap_start = find_e820_area(bootmap_start, end, bootmap_pages<= end) + free_bootmem((unsigned long)node_data[nodeid],pgdat_size); + node_data[nodeid] = NULL; + return; + } + bootmap_start = __pa(bootmap); Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages); bootmap_size = init_bootmem_node(NODE_DATA(nodeid), diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 443875eb15a2..15ae9fcd65a7 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c @@ -415,6 +415,12 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) /* Finally register nodes */ for_each_node_mask(i, nodes_parsed) setup_node_bootmem(i, nodes[i].start, nodes[i].end); + /* Try again in case setup_node_bootmem missed one due + to missing bootmem */ + for_each_node_mask(i, nodes_parsed) + if (!node_online(i)) + setup_node_bootmem(i, nodes[i].start, nodes[i].end); + for (i = 0; i < NR_CPUS; i++) { if (cpu_to_node[i] == NUMA_NO_NODE) continue; diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index de3eb8d8ae26..da2d107fe2cf 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -45,6 +45,7 @@ extern unsigned long __init bootmem_bootmap_pages (unsigned long); extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend); extern void __init free_bootmem (unsigned long addr, unsigned long size); extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal); +extern void * __init __alloc_bootmem_nopanic (unsigned long size, unsigned long align, unsigned long goal); extern void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, unsigned long goal); diff --git a/mm/bootmem.c b/mm/bootmem.c index d3e3bd2ffcea..d213feded10d 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -401,7 +401,7 @@ unsigned long __init free_all_bootmem (void) return(free_all_bootmem_core(NODE_DATA(0))); } -void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal) +void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, unsigned long goal) { bootmem_data_t *bdata; void *ptr; @@ -409,7 +409,14 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned list_for_each_entry(bdata, &bdata_list, list) if ((ptr = __alloc_bootmem_core(bdata, size, align, goal, 0))) return(ptr); + return NULL; +} +void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal) +{ + void *mem = __alloc_bootmem_nopanic(size,align,goal); + if (mem) + return mem; /* * Whoops, we cannot satisfy the allocation request. */ -- cgit v1.2.3 From b20367a6c2a0cd937cb1f0a8cf848f1402fef99c Mon Sep 17 00:00:00 2001 From: Jordan Hargrave Date: Fri, 7 Apr 2006 19:50:18 +0200 Subject: [PATCH] x86_64: Fix drift with HPET timer enabled If the HPET timer is enabled, the clock can drift by ~3 seconds a day. This is due to the HPET timer not being initialized with the correct setting (still using PIT count). If HZ changes, this drift can become even more pronounced. HPET patch initializes tick_nsec with correct tick_nsec settings for HPET timer. Vojtech comments: "It's not entirely correct (it assumes the HPET ticks totally exactly), but it's significantly better than assuming the PIT error there." Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/time.c | 2 ++ include/asm-i386/hpet.h | 1 + include/asm-x86_64/hpet.h | 2 ++ include/linux/jiffies.h | 6 ++++++ kernel/timer.c | 2 +- 5 files changed, 12 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 2eeaa95edff0..7392570f975d 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -917,6 +917,8 @@ void __init time_init(void) vxtime.hpet_address = 0; if (hpet_use_timer) { + /* set tick_nsec to use the proper rate for HPET */ + tick_nsec = TICK_NSEC_HPET; cpu_khz = hpet_calibrate_tsc(); timename = "HPET"; #ifdef CONFIG_X86_PM_TIMER diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h index 16ef9f996e3f..7f1a8a6ee32f 100644 --- a/include/asm-i386/hpet.h +++ b/include/asm-i386/hpet.h @@ -89,6 +89,7 @@ * then 32 bit HPET counter wrapsaround in less than 0.5 sec. */ #define HPET_MIN_PERIOD (100000UL) +#define HPET_TICK_RATE (HZ * 100000UL) extern unsigned long hpet_tick; /* hpet clks count per tick */ extern unsigned long hpet_address; /* hpet memory map physical address */ diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h index 08b75c15269a..18ff7ee9e774 100644 --- a/include/asm-x86_64/hpet.h +++ b/include/asm-x86_64/hpet.h @@ -51,6 +51,8 @@ #define HPET_TN_ROUTE_SHIFT 9 +#define HPET_TICK_RATE (HZ * 100000UL) + extern int is_hpet_enabled(void); extern int hpet_rtc_timer_init(void); extern int oem_force_hpet_timer(void); diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 99905e180532..043376920f51 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -36,6 +36,8 @@ /* LATCH is used in the interval timer and ftape setup. */ #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ +#define LATCH_HPET ((HPET_TICK_RATE + HZ/2) / HZ) + /* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can * improve accuracy by shifting LSH bits, hence calculating: * (NOM << LSH) / DEN @@ -51,9 +53,13 @@ /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) +#define ACTHZ_HPET (SH_DIV (HPET_TICK_RATE, LATCH_HPET, 8)) + /* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ #define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) +#define TICK_NSEC_HPET (SH_DIV(1000000UL * 1000, ACTHZ_HPET, 8)) + /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) diff --git a/kernel/timer.c b/kernel/timer.c index c3a874f1393c..471ab8710b8f 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1455,7 +1455,7 @@ static void time_interpolator_update(long delta_nsec) */ if (jiffies % INTERPOLATOR_ADJUST == 0) { - if (time_interpolator->skips == 0 && time_interpolator->offset > TICK_NSEC) + if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec) time_interpolator->nsec_per_cyc--; if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0) time_interpolator->nsec_per_cyc++; -- cgit v1.2.3 From 972d1cb1427946f4980240363aac4e73fb375290 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 6 Apr 2006 14:09:12 -0700 Subject: [NETFILTER]: Add helper functions for mass hook registration/unregistration Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter.h | 2 ++ net/netfilter/core.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 412e52ca9720..5aa931607923 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -110,6 +110,8 @@ struct nf_info /* Function to register/unregister hook points. */ int nf_register_hook(struct nf_hook_ops *reg); void nf_unregister_hook(struct nf_hook_ops *reg); +int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n); +void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n); /* Functions to register get/setsockopt ranges (non-inclusive). You need to check permissions yourself! */ diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 1ceb1a6c254b..645d62105571 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -63,6 +63,34 @@ void nf_unregister_hook(struct nf_hook_ops *reg) } EXPORT_SYMBOL(nf_unregister_hook); +int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n) +{ + unsigned int i; + int err = 0; + + for (i = 0; i < n; i++) { + err = nf_register_hook(®[i]); + if (err) + goto err; + } + return err; + +err: + if (i > 0) + nf_unregister_hooks(reg, i); + return err; +} +EXPORT_SYMBOL(nf_register_hooks); + +void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n) +{ + unsigned int i; + + for (i = 0; i < n; i++) + nf_unregister_hook(®[i]); +} +EXPORT_SYMBOL(nf_unregister_hooks); + unsigned int nf_iterate(struct list_head *head, struct sk_buff **skb, int hook, -- cgit v1.2.3 From 48bfee5fad0e46f4f18d46285efceba39e897482 Mon Sep 17 00:00:00 2001 From: Jing Min Zhao Date: Thu, 6 Apr 2006 14:13:42 -0700 Subject: [NETFILTER]: H.323 helper: move some function prototypes to ip_conntrack_h323.h Move prototypes of NAT callbacks to ip_conntrack_h323.h. Because the use of typedefs as arguments, some header files need to be moved as well. Signed-off-by: Jing Min Zhao Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter_ipv4/ip_conntrack_h323.h | 52 ++ .../netfilter_ipv4/ip_conntrack_helper_h323_asn1.h | 98 +++ .../ip_conntrack_helper_h323_types.h | 938 +++++++++++++++++++++ net/ipv4/netfilter/ip_conntrack_helper_h323.c | 2 - net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c | 2 +- net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h | 98 --- .../netfilter/ip_conntrack_helper_h323_types.h | 938 --------------------- net/ipv4/netfilter/ip_nat_helper_h323.c | 53 -- 8 files changed, 1089 insertions(+), 1092 deletions(-) create mode 100644 include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h create mode 100644 include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h delete mode 100644 net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h delete mode 100644 net/ipv4/netfilter/ip_conntrack_helper_h323_types.h (limited to 'include/linux') diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h index 0987cea53840..eace86bd2adb 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h @@ -3,6 +3,8 @@ #ifdef __KERNEL__ +#include + #define RAS_PORT 1719 #define Q931_PORT 1720 #define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */ @@ -25,6 +27,56 @@ struct ip_ct_h323_master { }; }; +struct ip_conntrack_expect; + +extern int get_h225_addr(unsigned char *data, TransportAddress * addr, + u_int32_t * ip, u_int16_t * port); +extern void ip_conntrack_h245_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this); +extern void ip_conntrack_q931_expect(struct ip_conntrack *new, + struct ip_conntrack_expect *this); +extern int (*set_h245_addr_hook) (struct sk_buff ** pskb, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, + u_int32_t ip, u_int16_t port); +extern int (*set_h225_addr_hook) (struct sk_buff ** pskb, + unsigned char **data, int dataoff, + TransportAddress * addr, + u_int32_t ip, u_int16_t port); +extern int (*set_sig_addr_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress * addr, int count); +extern int (*set_ras_addr_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, + TransportAddress * addr, int count); +extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb, + struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, + u_int16_t port, u_int16_t rtp_port, + struct ip_conntrack_expect * rtp_exp, + struct ip_conntrack_expect * rtcp_exp); +extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + H245_TransportAddress * addr, u_int16_t port, + struct ip_conntrack_expect * exp); +extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, int dataoff, + TransportAddress * addr, u_int16_t port, + struct ip_conntrack_expect * exp); +extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, + enum ip_conntrack_info ctinfo, + unsigned char **data, TransportAddress * addr, + int idx, u_int16_t port, + struct ip_conntrack_expect * exp); + #endif #endif diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h new file mode 100644 index 000000000000..0bd828081c0c --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h @@ -0,0 +1,98 @@ +/**************************************************************************** + * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323 + * conntrack/NAT module. + * + * Copyright (c) 2006 by Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + * + * + * This library is based on H.225 version 4, H.235 version 2 and H.245 + * version 7. It is extremely optimized to decode only the absolutely + * necessary objects in a signal for Linux kernel NAT module use, so don't + * expect it to be a full ASN.1 library. + * + * Features: + * + * 1. Small. The total size of code plus data is less than 20 KB (IA32). + * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866 + * takes only 3.9 seconds. + * 3. No memory allocation. It uses a static object. No need to initialize or + * cleanup. + * 4. Thread safe. + * 5. Support embedded architectures that has no misaligned memory access + * support. + * + * Limitations: + * + * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU. + * If a Setup signal contains more than 30 faststart, the packet size will + * very likely exceed the MTU size, then the TPKT will be fragmented. I + * don't know how to handle this in a Netfilter module. Anybody can help? + * Although I think 30 is enough for most of the cases. + * 2. IPv4 addresses only. + * + ****************************************************************************/ + +#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_ +#define _IP_CONNTRACK_HELPER_H323_ASN1_H_ + +/***************************************************************************** + * H.323 Types + ****************************************************************************/ +#include "ip_conntrack_helper_h323_types.h" + +typedef struct { + enum { + Q931_NationalEscape = 0x00, + Q931_Alerting = 0x01, + Q931_CallProceeding = 0x02, + Q931_Connect = 0x07, + Q931_ConnectAck = 0x0F, + Q931_Progress = 0x03, + Q931_Setup = 0x05, + Q931_SetupAck = 0x0D, + Q931_Resume = 0x26, + Q931_ResumeAck = 0x2E, + Q931_ResumeReject = 0x22, + Q931_Suspend = 0x25, + Q931_SuspendAck = 0x2D, + Q931_SuspendReject = 0x21, + Q931_UserInformation = 0x20, + Q931_Disconnect = 0x45, + Q931_Release = 0x4D, + Q931_ReleaseComplete = 0x5A, + Q931_Restart = 0x46, + Q931_RestartAck = 0x4E, + Q931_Segment = 0x60, + Q931_CongestionCtrl = 0x79, + Q931_Information = 0x7B, + Q931_Notify = 0x6E, + Q931_Status = 0x7D, + Q931_StatusEnquiry = 0x75, + Q931_Facility = 0x62 + } MessageType; + H323_UserInformation UUIE; +} Q931; + +/***************************************************************************** + * Decode Functions Return Codes + ****************************************************************************/ + +#define H323_ERROR_NONE 0 /* Decoded successfully */ +#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */ +#define H323_ERROR_BOUND -1 +#define H323_ERROR_RANGE -2 + + +/***************************************************************************** + * Decode Functions + ****************************************************************************/ + +int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras); +int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931); +int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, + MultimediaSystemControlMessage * + mscm); + +#endif diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h new file mode 100644 index 000000000000..cc98f7aa5abe --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h @@ -0,0 +1,938 @@ +/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006 + * + * Copyright (c) 2006 Jing Min Zhao + * + * This source code is licensed under General Public License version 2. + */ + +typedef struct TransportAddress_ipAddress { /* SEQUENCE */ + int options; /* No use */ + unsigned ip; +} TransportAddress_ipAddress; + +typedef struct TransportAddress { /* CHOICE */ + enum { + eTransportAddress_ipAddress, + eTransportAddress_ipSourceRoute, + eTransportAddress_ipxAddress, + eTransportAddress_ip6Address, + eTransportAddress_netBios, + eTransportAddress_nsap, + eTransportAddress_nonStandardAddress, + } choice; + union { + TransportAddress_ipAddress ipAddress; + }; +} TransportAddress; + +typedef struct DataProtocolCapability { /* CHOICE */ + enum { + eDataProtocolCapability_nonStandard, + eDataProtocolCapability_v14buffered, + eDataProtocolCapability_v42lapm, + eDataProtocolCapability_hdlcFrameTunnelling, + eDataProtocolCapability_h310SeparateVCStack, + eDataProtocolCapability_h310SingleVCStack, + eDataProtocolCapability_transparent, + eDataProtocolCapability_segmentationAndReassembly, + eDataProtocolCapability_hdlcFrameTunnelingwSAR, + eDataProtocolCapability_v120, + eDataProtocolCapability_separateLANStack, + eDataProtocolCapability_v76wCompression, + eDataProtocolCapability_tcp, + eDataProtocolCapability_udp, + } choice; +} DataProtocolCapability; + +typedef struct DataApplicationCapability_application { /* CHOICE */ + enum { + eDataApplicationCapability_application_nonStandard, + eDataApplicationCapability_application_t120, + eDataApplicationCapability_application_dsm_cc, + eDataApplicationCapability_application_userData, + eDataApplicationCapability_application_t84, + eDataApplicationCapability_application_t434, + eDataApplicationCapability_application_h224, + eDataApplicationCapability_application_nlpid, + eDataApplicationCapability_application_dsvdControl, + eDataApplicationCapability_application_h222DataPartitioning, + eDataApplicationCapability_application_t30fax, + eDataApplicationCapability_application_t140, + eDataApplicationCapability_application_t38fax, + eDataApplicationCapability_application_genericDataCapability, + } choice; + union { + DataProtocolCapability t120; + }; +} DataApplicationCapability_application; + +typedef struct DataApplicationCapability { /* SEQUENCE */ + int options; /* No use */ + DataApplicationCapability_application application; +} DataApplicationCapability; + +typedef struct DataType { /* CHOICE */ + enum { + eDataType_nonStandard, + eDataType_nullData, + eDataType_videoData, + eDataType_audioData, + eDataType_data, + eDataType_encryptionData, + eDataType_h235Control, + eDataType_h235Media, + eDataType_multiplexedStream, + } choice; + union { + DataApplicationCapability data; + }; +} DataType; + +typedef struct UnicastAddress_iPAddress { /* SEQUENCE */ + int options; /* No use */ + unsigned network; +} UnicastAddress_iPAddress; + +typedef struct UnicastAddress { /* CHOICE */ + enum { + eUnicastAddress_iPAddress, + eUnicastAddress_iPXAddress, + eUnicastAddress_iP6Address, + eUnicastAddress_netBios, + eUnicastAddress_iPSourceRouteAddress, + eUnicastAddress_nsap, + eUnicastAddress_nonStandardAddress, + } choice; + union { + UnicastAddress_iPAddress iPAddress; + }; +} UnicastAddress; + +typedef struct H245_TransportAddress { /* CHOICE */ + enum { + eH245_TransportAddress_unicastAddress, + eH245_TransportAddress_multicastAddress, + } choice; + union { + UnicastAddress unicastAddress; + }; +} H245_TransportAddress; + +typedef struct H2250LogicalChannelParameters { /* SEQUENCE */ + enum { + eH2250LogicalChannelParameters_nonStandard = (1 << 31), + eH2250LogicalChannelParameters_associatedSessionID = + (1 << 30), + eH2250LogicalChannelParameters_mediaChannel = (1 << 29), + eH2250LogicalChannelParameters_mediaGuaranteedDelivery = + (1 << 28), + eH2250LogicalChannelParameters_mediaControlChannel = + (1 << 27), + eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery + = (1 << 26), + eH2250LogicalChannelParameters_silenceSuppression = (1 << 25), + eH2250LogicalChannelParameters_destination = (1 << 24), + eH2250LogicalChannelParameters_dynamicRTPPayloadType = + (1 << 23), + eH2250LogicalChannelParameters_mediaPacketization = (1 << 22), + eH2250LogicalChannelParameters_transportCapability = + (1 << 21), + eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20), + eH2250LogicalChannelParameters_source = (1 << 19), + } options; + H245_TransportAddress mediaChannel; + H245_TransportAddress mediaControlChannel; +} H2250LogicalChannelParameters; + +typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */ + enum { + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none, + } choice; + union { + H2250LogicalChannelParameters h2250LogicalChannelParameters; + }; +} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters; + +typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */ + enum { + eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber + = (1 << 31), + eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency + = (1 << 30), + eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor + = (1 << 29), + } options; + DataType dataType; + OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters + multiplexParameters; +} OpenLogicalChannel_forwardLogicalChannelParameters; + +typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ + enum { + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, + } choice; + union { + H2250LogicalChannelParameters h2250LogicalChannelParameters; + }; +} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters; + +typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */ + enum { + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters + = (1 << 31), + eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency + = (1 << 30), + eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor + = (1 << 29), + } options; + OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters + multiplexParameters; +} OpenLogicalChannel_reverseLogicalChannelParameters; + +typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */ + enum { + eNetworkAccessParameters_networkAddress_q2931Address, + eNetworkAccessParameters_networkAddress_e164Address, + eNetworkAccessParameters_networkAddress_localAreaAddress, + } choice; + union { + H245_TransportAddress localAreaAddress; + }; +} NetworkAccessParameters_networkAddress; + +typedef struct NetworkAccessParameters { /* SEQUENCE */ + enum { + eNetworkAccessParameters_distribution = (1 << 31), + eNetworkAccessParameters_externalReference = (1 << 30), + eNetworkAccessParameters_t120SetupProcedure = (1 << 29), + } options; + NetworkAccessParameters_networkAddress networkAddress; +} NetworkAccessParameters; + +typedef struct OpenLogicalChannel { /* SEQUENCE */ + enum { + eOpenLogicalChannel_reverseLogicalChannelParameters = + (1 << 31), + eOpenLogicalChannel_separateStack = (1 << 30), + eOpenLogicalChannel_encryptionSync = (1 << 29), + } options; + OpenLogicalChannel_forwardLogicalChannelParameters + forwardLogicalChannelParameters; + OpenLogicalChannel_reverseLogicalChannelParameters + reverseLogicalChannelParameters; + NetworkAccessParameters separateStack; +} OpenLogicalChannel; + +typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Setup_UUIE_fastStart; + +typedef struct Setup_UUIE { /* SEQUENCE */ + enum { + eSetup_UUIE_h245Address = (1 << 31), + eSetup_UUIE_sourceAddress = (1 << 30), + eSetup_UUIE_destinationAddress = (1 << 29), + eSetup_UUIE_destCallSignalAddress = (1 << 28), + eSetup_UUIE_destExtraCallInfo = (1 << 27), + eSetup_UUIE_destExtraCRV = (1 << 26), + eSetup_UUIE_callServices = (1 << 25), + eSetup_UUIE_sourceCallSignalAddress = (1 << 24), + eSetup_UUIE_remoteExtensionAddress = (1 << 23), + eSetup_UUIE_callIdentifier = (1 << 22), + eSetup_UUIE_h245SecurityCapability = (1 << 21), + eSetup_UUIE_tokens = (1 << 20), + eSetup_UUIE_cryptoTokens = (1 << 19), + eSetup_UUIE_fastStart = (1 << 18), + eSetup_UUIE_mediaWaitForConnect = (1 << 17), + eSetup_UUIE_canOverlapSend = (1 << 16), + eSetup_UUIE_endpointIdentifier = (1 << 15), + eSetup_UUIE_multipleCalls = (1 << 14), + eSetup_UUIE_maintainConnection = (1 << 13), + eSetup_UUIE_connectionParameters = (1 << 12), + eSetup_UUIE_language = (1 << 11), + eSetup_UUIE_presentationIndicator = (1 << 10), + eSetup_UUIE_screeningIndicator = (1 << 9), + eSetup_UUIE_serviceControl = (1 << 8), + eSetup_UUIE_symmetricOperationRequired = (1 << 7), + eSetup_UUIE_capacity = (1 << 6), + eSetup_UUIE_circuitInfo = (1 << 5), + eSetup_UUIE_desiredProtocols = (1 << 4), + eSetup_UUIE_neededFeatures = (1 << 3), + eSetup_UUIE_desiredFeatures = (1 << 2), + eSetup_UUIE_supportedFeatures = (1 << 1), + eSetup_UUIE_parallelH245Control = (1 << 0), + } options; + TransportAddress h245Address; + TransportAddress destCallSignalAddress; + TransportAddress sourceCallSignalAddress; + Setup_UUIE_fastStart fastStart; +} Setup_UUIE; + +typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} CallProceeding_UUIE_fastStart; + +typedef struct CallProceeding_UUIE { /* SEQUENCE */ + enum { + eCallProceeding_UUIE_h245Address = (1 << 31), + eCallProceeding_UUIE_callIdentifier = (1 << 30), + eCallProceeding_UUIE_h245SecurityMode = (1 << 29), + eCallProceeding_UUIE_tokens = (1 << 28), + eCallProceeding_UUIE_cryptoTokens = (1 << 27), + eCallProceeding_UUIE_fastStart = (1 << 26), + eCallProceeding_UUIE_multipleCalls = (1 << 25), + eCallProceeding_UUIE_maintainConnection = (1 << 24), + eCallProceeding_UUIE_fastConnectRefused = (1 << 23), + eCallProceeding_UUIE_featureSet = (1 << 22), + } options; + TransportAddress h245Address; + CallProceeding_UUIE_fastStart fastStart; +} CallProceeding_UUIE; + +typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Connect_UUIE_fastStart; + +typedef struct Connect_UUIE { /* SEQUENCE */ + enum { + eConnect_UUIE_h245Address = (1 << 31), + eConnect_UUIE_callIdentifier = (1 << 30), + eConnect_UUIE_h245SecurityMode = (1 << 29), + eConnect_UUIE_tokens = (1 << 28), + eConnect_UUIE_cryptoTokens = (1 << 27), + eConnect_UUIE_fastStart = (1 << 26), + eConnect_UUIE_multipleCalls = (1 << 25), + eConnect_UUIE_maintainConnection = (1 << 24), + eConnect_UUIE_language = (1 << 23), + eConnect_UUIE_connectedAddress = (1 << 22), + eConnect_UUIE_presentationIndicator = (1 << 21), + eConnect_UUIE_screeningIndicator = (1 << 20), + eConnect_UUIE_fastConnectRefused = (1 << 19), + eConnect_UUIE_serviceControl = (1 << 18), + eConnect_UUIE_capacity = (1 << 17), + eConnect_UUIE_featureSet = (1 << 16), + } options; + TransportAddress h245Address; + Connect_UUIE_fastStart fastStart; +} Connect_UUIE; + +typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Alerting_UUIE_fastStart; + +typedef struct Alerting_UUIE { /* SEQUENCE */ + enum { + eAlerting_UUIE_h245Address = (1 << 31), + eAlerting_UUIE_callIdentifier = (1 << 30), + eAlerting_UUIE_h245SecurityMode = (1 << 29), + eAlerting_UUIE_tokens = (1 << 28), + eAlerting_UUIE_cryptoTokens = (1 << 27), + eAlerting_UUIE_fastStart = (1 << 26), + eAlerting_UUIE_multipleCalls = (1 << 25), + eAlerting_UUIE_maintainConnection = (1 << 24), + eAlerting_UUIE_alertingAddress = (1 << 23), + eAlerting_UUIE_presentationIndicator = (1 << 22), + eAlerting_UUIE_screeningIndicator = (1 << 21), + eAlerting_UUIE_fastConnectRefused = (1 << 20), + eAlerting_UUIE_serviceControl = (1 << 19), + eAlerting_UUIE_capacity = (1 << 18), + eAlerting_UUIE_featureSet = (1 << 17), + } options; + TransportAddress h245Address; + Alerting_UUIE_fastStart fastStart; +} Alerting_UUIE; + +typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Information_UUIE_fastStart; + +typedef struct Information_UUIE { /* SEQUENCE */ + enum { + eInformation_UUIE_callIdentifier = (1 << 31), + eInformation_UUIE_tokens = (1 << 30), + eInformation_UUIE_cryptoTokens = (1 << 29), + eInformation_UUIE_fastStart = (1 << 28), + eInformation_UUIE_fastConnectRefused = (1 << 27), + eInformation_UUIE_circuitInfo = (1 << 26), + } options; + Information_UUIE_fastStart fastStart; +} Information_UUIE; + +typedef struct FacilityReason { /* CHOICE */ + enum { + eFacilityReason_routeCallToGatekeeper, + eFacilityReason_callForwarded, + eFacilityReason_routeCallToMC, + eFacilityReason_undefinedReason, + eFacilityReason_conferenceListChoice, + eFacilityReason_startH245, + eFacilityReason_noH245, + eFacilityReason_newTokens, + eFacilityReason_featureSetUpdate, + eFacilityReason_forwardedElements, + eFacilityReason_transportedInformation, + } choice; +} FacilityReason; + +typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Facility_UUIE_fastStart; + +typedef struct Facility_UUIE { /* SEQUENCE */ + enum { + eFacility_UUIE_alternativeAddress = (1 << 31), + eFacility_UUIE_alternativeAliasAddress = (1 << 30), + eFacility_UUIE_conferenceID = (1 << 29), + eFacility_UUIE_callIdentifier = (1 << 28), + eFacility_UUIE_destExtraCallInfo = (1 << 27), + eFacility_UUIE_remoteExtensionAddress = (1 << 26), + eFacility_UUIE_tokens = (1 << 25), + eFacility_UUIE_cryptoTokens = (1 << 24), + eFacility_UUIE_conferences = (1 << 23), + eFacility_UUIE_h245Address = (1 << 22), + eFacility_UUIE_fastStart = (1 << 21), + eFacility_UUIE_multipleCalls = (1 << 20), + eFacility_UUIE_maintainConnection = (1 << 19), + eFacility_UUIE_fastConnectRefused = (1 << 18), + eFacility_UUIE_serviceControl = (1 << 17), + eFacility_UUIE_circuitInfo = (1 << 16), + eFacility_UUIE_featureSet = (1 << 15), + eFacility_UUIE_destinationInfo = (1 << 14), + eFacility_UUIE_h245SecurityMode = (1 << 13), + } options; + FacilityReason reason; + TransportAddress h245Address; + Facility_UUIE_fastStart fastStart; +} Facility_UUIE; + +typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */ + int count; + OpenLogicalChannel item[30]; +} Progress_UUIE_fastStart; + +typedef struct Progress_UUIE { /* SEQUENCE */ + enum { + eProgress_UUIE_h245Address = (1 << 31), + eProgress_UUIE_h245SecurityMode = (1 << 30), + eProgress_UUIE_tokens = (1 << 29), + eProgress_UUIE_cryptoTokens = (1 << 28), + eProgress_UUIE_fastStart = (1 << 27), + eProgress_UUIE_multipleCalls = (1 << 26), + eProgress_UUIE_maintainConnection = (1 << 25), + eProgress_UUIE_fastConnectRefused = (1 << 24), + } options; + TransportAddress h245Address; + Progress_UUIE_fastStart fastStart; +} Progress_UUIE; + +typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */ + enum { + eH323_UU_PDU_h323_message_body_setup, + eH323_UU_PDU_h323_message_body_callProceeding, + eH323_UU_PDU_h323_message_body_connect, + eH323_UU_PDU_h323_message_body_alerting, + eH323_UU_PDU_h323_message_body_information, + eH323_UU_PDU_h323_message_body_releaseComplete, + eH323_UU_PDU_h323_message_body_facility, + eH323_UU_PDU_h323_message_body_progress, + eH323_UU_PDU_h323_message_body_empty, + eH323_UU_PDU_h323_message_body_status, + eH323_UU_PDU_h323_message_body_statusInquiry, + eH323_UU_PDU_h323_message_body_setupAcknowledge, + eH323_UU_PDU_h323_message_body_notify, + } choice; + union { + Setup_UUIE setup; + CallProceeding_UUIE callProceeding; + Connect_UUIE connect; + Alerting_UUIE alerting; + Information_UUIE information; + Facility_UUIE facility; + Progress_UUIE progress; + }; +} H323_UU_PDU_h323_message_body; + +typedef struct RequestMessage { /* CHOICE */ + enum { + eRequestMessage_nonStandard, + eRequestMessage_masterSlaveDetermination, + eRequestMessage_terminalCapabilitySet, + eRequestMessage_openLogicalChannel, + eRequestMessage_closeLogicalChannel, + eRequestMessage_requestChannelClose, + eRequestMessage_multiplexEntrySend, + eRequestMessage_requestMultiplexEntry, + eRequestMessage_requestMode, + eRequestMessage_roundTripDelayRequest, + eRequestMessage_maintenanceLoopRequest, + eRequestMessage_communicationModeRequest, + eRequestMessage_conferenceRequest, + eRequestMessage_multilinkRequest, + eRequestMessage_logicalChannelRateRequest, + } choice; + union { + OpenLogicalChannel openLogicalChannel; + }; +} RequestMessage; + +typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ + enum { + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, + } choice; + union { + H2250LogicalChannelParameters h2250LogicalChannelParameters; + }; +} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters; + +typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */ + enum { + eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber + = (1 << 31), + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters + = (1 << 30), + eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor + = (1 << 29), + } options; + OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters + multiplexParameters; +} OpenLogicalChannelAck_reverseLogicalChannelParameters; + +typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */ + enum { + eH2250LogicalChannelAckParameters_nonStandard = (1 << 31), + eH2250LogicalChannelAckParameters_sessionID = (1 << 30), + eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29), + eH2250LogicalChannelAckParameters_mediaControlChannel = + (1 << 28), + eH2250LogicalChannelAckParameters_dynamicRTPPayloadType = + (1 << 27), + eH2250LogicalChannelAckParameters_flowControlToZero = + (1 << 26), + eH2250LogicalChannelAckParameters_portNumber = (1 << 25), + } options; + H245_TransportAddress mediaChannel; + H245_TransportAddress mediaControlChannel; +} H2250LogicalChannelAckParameters; + +typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */ + enum { + eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters, + } choice; + union { + H2250LogicalChannelAckParameters + h2250LogicalChannelAckParameters; + }; +} OpenLogicalChannelAck_forwardMultiplexAckParameters; + +typedef struct OpenLogicalChannelAck { /* SEQUENCE */ + enum { + eOpenLogicalChannelAck_reverseLogicalChannelParameters = + (1 << 31), + eOpenLogicalChannelAck_separateStack = (1 << 30), + eOpenLogicalChannelAck_forwardMultiplexAckParameters = + (1 << 29), + eOpenLogicalChannelAck_encryptionSync = (1 << 28), + } options; + OpenLogicalChannelAck_reverseLogicalChannelParameters + reverseLogicalChannelParameters; + OpenLogicalChannelAck_forwardMultiplexAckParameters + forwardMultiplexAckParameters; +} OpenLogicalChannelAck; + +typedef struct ResponseMessage { /* CHOICE */ + enum { + eResponseMessage_nonStandard, + eResponseMessage_masterSlaveDeterminationAck, + eResponseMessage_masterSlaveDeterminationReject, + eResponseMessage_terminalCapabilitySetAck, + eResponseMessage_terminalCapabilitySetReject, + eResponseMessage_openLogicalChannelAck, + eResponseMessage_openLogicalChannelReject, + eResponseMessage_closeLogicalChannelAck, + eResponseMessage_requestChannelCloseAck, + eResponseMessage_requestChannelCloseReject, + eResponseMessage_multiplexEntrySendAck, + eResponseMessage_multiplexEntrySendReject, + eResponseMessage_requestMultiplexEntryAck, + eResponseMessage_requestMultiplexEntryReject, + eResponseMessage_requestModeAck, + eResponseMessage_requestModeReject, + eResponseMessage_roundTripDelayResponse, + eResponseMessage_maintenanceLoopAck, + eResponseMessage_maintenanceLoopReject, + eResponseMessage_communicationModeResponse, + eResponseMessage_conferenceResponse, + eResponseMessage_multilinkResponse, + eResponseMessage_logicalChannelRateAcknowledge, + eResponseMessage_logicalChannelRateReject, + } choice; + union { + OpenLogicalChannelAck openLogicalChannelAck; + }; +} ResponseMessage; + +typedef struct MultimediaSystemControlMessage { /* CHOICE */ + enum { + eMultimediaSystemControlMessage_request, + eMultimediaSystemControlMessage_response, + eMultimediaSystemControlMessage_command, + eMultimediaSystemControlMessage_indication, + } choice; + union { + RequestMessage request; + ResponseMessage response; + }; +} MultimediaSystemControlMessage; + +typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */ + int count; + MultimediaSystemControlMessage item[4]; +} H323_UU_PDU_h245Control; + +typedef struct H323_UU_PDU { /* SEQUENCE */ + enum { + eH323_UU_PDU_nonStandardData = (1 << 31), + eH323_UU_PDU_h4501SupplementaryService = (1 << 30), + eH323_UU_PDU_h245Tunneling = (1 << 29), + eH323_UU_PDU_h245Control = (1 << 28), + eH323_UU_PDU_nonStandardControl = (1 << 27), + eH323_UU_PDU_callLinkage = (1 << 26), + eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25), + eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24), + eH323_UU_PDU_stimulusControl = (1 << 23), + eH323_UU_PDU_genericData = (1 << 22), + } options; + H323_UU_PDU_h323_message_body h323_message_body; + H323_UU_PDU_h245Control h245Control; +} H323_UU_PDU; + +typedef struct H323_UserInformation { /* SEQUENCE */ + enum { + eH323_UserInformation_user_data = (1 << 31), + } options; + H323_UU_PDU h323_uu_pdu; +} H323_UserInformation; + +typedef struct GatekeeperRequest { /* SEQUENCE */ + enum { + eGatekeeperRequest_nonStandardData = (1 << 31), + eGatekeeperRequest_gatekeeperIdentifier = (1 << 30), + eGatekeeperRequest_callServices = (1 << 29), + eGatekeeperRequest_endpointAlias = (1 << 28), + eGatekeeperRequest_alternateEndpoints = (1 << 27), + eGatekeeperRequest_tokens = (1 << 26), + eGatekeeperRequest_cryptoTokens = (1 << 25), + eGatekeeperRequest_authenticationCapability = (1 << 24), + eGatekeeperRequest_algorithmOIDs = (1 << 23), + eGatekeeperRequest_integrity = (1 << 22), + eGatekeeperRequest_integrityCheckValue = (1 << 21), + eGatekeeperRequest_supportsAltGK = (1 << 20), + eGatekeeperRequest_featureSet = (1 << 19), + eGatekeeperRequest_genericData = (1 << 18), + } options; + TransportAddress rasAddress; +} GatekeeperRequest; + +typedef struct GatekeeperConfirm { /* SEQUENCE */ + enum { + eGatekeeperConfirm_nonStandardData = (1 << 31), + eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30), + eGatekeeperConfirm_alternateGatekeeper = (1 << 29), + eGatekeeperConfirm_authenticationMode = (1 << 28), + eGatekeeperConfirm_tokens = (1 << 27), + eGatekeeperConfirm_cryptoTokens = (1 << 26), + eGatekeeperConfirm_algorithmOID = (1 << 25), + eGatekeeperConfirm_integrity = (1 << 24), + eGatekeeperConfirm_integrityCheckValue = (1 << 23), + eGatekeeperConfirm_featureSet = (1 << 22), + eGatekeeperConfirm_genericData = (1 << 21), + } options; + TransportAddress rasAddress; +} GatekeeperConfirm; + +typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} RegistrationRequest_callSignalAddress; + +typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} RegistrationRequest_rasAddress; + +typedef struct RegistrationRequest { /* SEQUENCE */ + enum { + eRegistrationRequest_nonStandardData = (1 << 31), + eRegistrationRequest_terminalAlias = (1 << 30), + eRegistrationRequest_gatekeeperIdentifier = (1 << 29), + eRegistrationRequest_alternateEndpoints = (1 << 28), + eRegistrationRequest_timeToLive = (1 << 27), + eRegistrationRequest_tokens = (1 << 26), + eRegistrationRequest_cryptoTokens = (1 << 25), + eRegistrationRequest_integrityCheckValue = (1 << 24), + eRegistrationRequest_keepAlive = (1 << 23), + eRegistrationRequest_endpointIdentifier = (1 << 22), + eRegistrationRequest_willSupplyUUIEs = (1 << 21), + eRegistrationRequest_maintainConnection = (1 << 20), + eRegistrationRequest_alternateTransportAddresses = (1 << 19), + eRegistrationRequest_additiveRegistration = (1 << 18), + eRegistrationRequest_terminalAliasPattern = (1 << 17), + eRegistrationRequest_supportsAltGK = (1 << 16), + eRegistrationRequest_usageReportingCapability = (1 << 15), + eRegistrationRequest_multipleCalls = (1 << 14), + eRegistrationRequest_supportedH248Packages = (1 << 13), + eRegistrationRequest_callCreditCapability = (1 << 12), + eRegistrationRequest_capacityReportingCapability = (1 << 11), + eRegistrationRequest_capacity = (1 << 10), + eRegistrationRequest_featureSet = (1 << 9), + eRegistrationRequest_genericData = (1 << 8), + } options; + RegistrationRequest_callSignalAddress callSignalAddress; + RegistrationRequest_rasAddress rasAddress; + unsigned timeToLive; +} RegistrationRequest; + +typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} RegistrationConfirm_callSignalAddress; + +typedef struct RegistrationConfirm { /* SEQUENCE */ + enum { + eRegistrationConfirm_nonStandardData = (1 << 31), + eRegistrationConfirm_terminalAlias = (1 << 30), + eRegistrationConfirm_gatekeeperIdentifier = (1 << 29), + eRegistrationConfirm_alternateGatekeeper = (1 << 28), + eRegistrationConfirm_timeToLive = (1 << 27), + eRegistrationConfirm_tokens = (1 << 26), + eRegistrationConfirm_cryptoTokens = (1 << 25), + eRegistrationConfirm_integrityCheckValue = (1 << 24), + eRegistrationConfirm_willRespondToIRR = (1 << 23), + eRegistrationConfirm_preGrantedARQ = (1 << 22), + eRegistrationConfirm_maintainConnection = (1 << 21), + eRegistrationConfirm_serviceControl = (1 << 20), + eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19), + eRegistrationConfirm_terminalAliasPattern = (1 << 18), + eRegistrationConfirm_supportedPrefixes = (1 << 17), + eRegistrationConfirm_usageSpec = (1 << 16), + eRegistrationConfirm_featureServerAlias = (1 << 15), + eRegistrationConfirm_capacityReportingSpec = (1 << 14), + eRegistrationConfirm_featureSet = (1 << 13), + eRegistrationConfirm_genericData = (1 << 12), + } options; + RegistrationConfirm_callSignalAddress callSignalAddress; + unsigned timeToLive; +} RegistrationConfirm; + +typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} UnregistrationRequest_callSignalAddress; + +typedef struct UnregistrationRequest { /* SEQUENCE */ + enum { + eUnregistrationRequest_endpointAlias = (1 << 31), + eUnregistrationRequest_nonStandardData = (1 << 30), + eUnregistrationRequest_endpointIdentifier = (1 << 29), + eUnregistrationRequest_alternateEndpoints = (1 << 28), + eUnregistrationRequest_gatekeeperIdentifier = (1 << 27), + eUnregistrationRequest_tokens = (1 << 26), + eUnregistrationRequest_cryptoTokens = (1 << 25), + eUnregistrationRequest_integrityCheckValue = (1 << 24), + eUnregistrationRequest_reason = (1 << 23), + eUnregistrationRequest_endpointAliasPattern = (1 << 22), + eUnregistrationRequest_supportedPrefixes = (1 << 21), + eUnregistrationRequest_alternateGatekeeper = (1 << 20), + eUnregistrationRequest_genericData = (1 << 19), + } options; + UnregistrationRequest_callSignalAddress callSignalAddress; +} UnregistrationRequest; + +typedef struct AdmissionRequest { /* SEQUENCE */ + enum { + eAdmissionRequest_callModel = (1 << 31), + eAdmissionRequest_destinationInfo = (1 << 30), + eAdmissionRequest_destCallSignalAddress = (1 << 29), + eAdmissionRequest_destExtraCallInfo = (1 << 28), + eAdmissionRequest_srcCallSignalAddress = (1 << 27), + eAdmissionRequest_nonStandardData = (1 << 26), + eAdmissionRequest_callServices = (1 << 25), + eAdmissionRequest_canMapAlias = (1 << 24), + eAdmissionRequest_callIdentifier = (1 << 23), + eAdmissionRequest_srcAlternatives = (1 << 22), + eAdmissionRequest_destAlternatives = (1 << 21), + eAdmissionRequest_gatekeeperIdentifier = (1 << 20), + eAdmissionRequest_tokens = (1 << 19), + eAdmissionRequest_cryptoTokens = (1 << 18), + eAdmissionRequest_integrityCheckValue = (1 << 17), + eAdmissionRequest_transportQOS = (1 << 16), + eAdmissionRequest_willSupplyUUIEs = (1 << 15), + eAdmissionRequest_callLinkage = (1 << 14), + eAdmissionRequest_gatewayDataRate = (1 << 13), + eAdmissionRequest_capacity = (1 << 12), + eAdmissionRequest_circuitInfo = (1 << 11), + eAdmissionRequest_desiredProtocols = (1 << 10), + eAdmissionRequest_desiredTunnelledProtocol = (1 << 9), + eAdmissionRequest_featureSet = (1 << 8), + eAdmissionRequest_genericData = (1 << 7), + } options; + TransportAddress destCallSignalAddress; + TransportAddress srcCallSignalAddress; +} AdmissionRequest; + +typedef struct AdmissionConfirm { /* SEQUENCE */ + enum { + eAdmissionConfirm_irrFrequency = (1 << 31), + eAdmissionConfirm_nonStandardData = (1 << 30), + eAdmissionConfirm_destinationInfo = (1 << 29), + eAdmissionConfirm_destExtraCallInfo = (1 << 28), + eAdmissionConfirm_destinationType = (1 << 27), + eAdmissionConfirm_remoteExtensionAddress = (1 << 26), + eAdmissionConfirm_alternateEndpoints = (1 << 25), + eAdmissionConfirm_tokens = (1 << 24), + eAdmissionConfirm_cryptoTokens = (1 << 23), + eAdmissionConfirm_integrityCheckValue = (1 << 22), + eAdmissionConfirm_transportQOS = (1 << 21), + eAdmissionConfirm_willRespondToIRR = (1 << 20), + eAdmissionConfirm_uuiesRequested = (1 << 19), + eAdmissionConfirm_language = (1 << 18), + eAdmissionConfirm_alternateTransportAddresses = (1 << 17), + eAdmissionConfirm_useSpecifiedTransport = (1 << 16), + eAdmissionConfirm_circuitInfo = (1 << 15), + eAdmissionConfirm_usageSpec = (1 << 14), + eAdmissionConfirm_supportedProtocols = (1 << 13), + eAdmissionConfirm_serviceControl = (1 << 12), + eAdmissionConfirm_multipleCalls = (1 << 11), + eAdmissionConfirm_featureSet = (1 << 10), + eAdmissionConfirm_genericData = (1 << 9), + } options; + TransportAddress destCallSignalAddress; +} AdmissionConfirm; + +typedef struct LocationRequest { /* SEQUENCE */ + enum { + eLocationRequest_endpointIdentifier = (1 << 31), + eLocationRequest_nonStandardData = (1 << 30), + eLocationRequest_sourceInfo = (1 << 29), + eLocationRequest_canMapAlias = (1 << 28), + eLocationRequest_gatekeeperIdentifier = (1 << 27), + eLocationRequest_tokens = (1 << 26), + eLocationRequest_cryptoTokens = (1 << 25), + eLocationRequest_integrityCheckValue = (1 << 24), + eLocationRequest_desiredProtocols = (1 << 23), + eLocationRequest_desiredTunnelledProtocol = (1 << 22), + eLocationRequest_featureSet = (1 << 21), + eLocationRequest_genericData = (1 << 20), + eLocationRequest_hopCount = (1 << 19), + eLocationRequest_circuitInfo = (1 << 18), + } options; + TransportAddress replyAddress; +} LocationRequest; + +typedef struct LocationConfirm { /* SEQUENCE */ + enum { + eLocationConfirm_nonStandardData = (1 << 31), + eLocationConfirm_destinationInfo = (1 << 30), + eLocationConfirm_destExtraCallInfo = (1 << 29), + eLocationConfirm_destinationType = (1 << 28), + eLocationConfirm_remoteExtensionAddress = (1 << 27), + eLocationConfirm_alternateEndpoints = (1 << 26), + eLocationConfirm_tokens = (1 << 25), + eLocationConfirm_cryptoTokens = (1 << 24), + eLocationConfirm_integrityCheckValue = (1 << 23), + eLocationConfirm_alternateTransportAddresses = (1 << 22), + eLocationConfirm_supportedProtocols = (1 << 21), + eLocationConfirm_multipleCalls = (1 << 20), + eLocationConfirm_featureSet = (1 << 19), + eLocationConfirm_genericData = (1 << 18), + eLocationConfirm_circuitInfo = (1 << 17), + eLocationConfirm_serviceControl = (1 << 16), + } options; + TransportAddress callSignalAddress; + TransportAddress rasAddress; +} LocationConfirm; + +typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */ + int count; + TransportAddress item[10]; +} InfoRequestResponse_callSignalAddress; + +typedef struct InfoRequestResponse { /* SEQUENCE */ + enum { + eInfoRequestResponse_nonStandardData = (1 << 31), + eInfoRequestResponse_endpointAlias = (1 << 30), + eInfoRequestResponse_perCallInfo = (1 << 29), + eInfoRequestResponse_tokens = (1 << 28), + eInfoRequestResponse_cryptoTokens = (1 << 27), + eInfoRequestResponse_integrityCheckValue = (1 << 26), + eInfoRequestResponse_needResponse = (1 << 25), + eInfoRequestResponse_capacity = (1 << 24), + eInfoRequestResponse_irrStatus = (1 << 23), + eInfoRequestResponse_unsolicited = (1 << 22), + eInfoRequestResponse_genericData = (1 << 21), + } options; + TransportAddress rasAddress; + InfoRequestResponse_callSignalAddress callSignalAddress; +} InfoRequestResponse; + +typedef struct RasMessage { /* CHOICE */ + enum { + eRasMessage_gatekeeperRequest, + eRasMessage_gatekeeperConfirm, + eRasMessage_gatekeeperReject, + eRasMessage_registrationRequest, + eRasMessage_registrationConfirm, + eRasMessage_registrationReject, + eRasMessage_unregistrationRequest, + eRasMessage_unregistrationConfirm, + eRasMessage_unregistrationReject, + eRasMessage_admissionRequest, + eRasMessage_admissionConfirm, + eRasMessage_admissionReject, + eRasMessage_bandwidthRequest, + eRasMessage_bandwidthConfirm, + eRasMessage_bandwidthReject, + eRasMessage_disengageRequest, + eRasMessage_disengageConfirm, + eRasMessage_disengageReject, + eRasMessage_locationRequest, + eRasMessage_locationConfirm, + eRasMessage_locationReject, + eRasMessage_infoRequest, + eRasMessage_infoRequestResponse, + eRasMessage_nonStandardMessage, + eRasMessage_unknownMessageResponse, + eRasMessage_requestInProgress, + eRasMessage_resourcesAvailableIndicate, + eRasMessage_resourcesAvailableConfirm, + eRasMessage_infoRequestAck, + eRasMessage_infoRequestNak, + eRasMessage_serviceControlIndication, + eRasMessage_serviceControlResponse, + } choice; + union { + GatekeeperRequest gatekeeperRequest; + GatekeeperConfirm gatekeeperConfirm; + RegistrationRequest registrationRequest; + RegistrationConfirm registrationConfirm; + UnregistrationRequest unregistrationRequest; + AdmissionRequest admissionRequest; + AdmissionConfirm admissionConfirm; + LocationRequest locationRequest; + LocationConfirm locationConfirm; + InfoRequestResponse infoRequestResponse; + }; +} RasMessage; diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index daeb1395faa4..fc817fd46caa 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -54,8 +54,6 @@ #include #include -#include "ip_conntrack_helper_h323_asn1.h" - #if 0 #define DEBUGP printk #else diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c index afa525129b51..48078002e450 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c @@ -15,7 +15,7 @@ #else #include #endif -#include "ip_conntrack_helper_h323_asn1.h" +#include /* Trace Flag */ #ifndef H323_TRACE diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h deleted file mode 100644 index 0bd828081c0c..000000000000 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.h +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** - * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323 - * conntrack/NAT module. - * - * Copyright (c) 2006 by Jing Min Zhao - * - * This source code is licensed under General Public License version 2. - * - * - * This library is based on H.225 version 4, H.235 version 2 and H.245 - * version 7. It is extremely optimized to decode only the absolutely - * necessary objects in a signal for Linux kernel NAT module use, so don't - * expect it to be a full ASN.1 library. - * - * Features: - * - * 1. Small. The total size of code plus data is less than 20 KB (IA32). - * 2. Fast. Decoding Netmeeting's Setup signal 1 million times on a PIII 866 - * takes only 3.9 seconds. - * 3. No memory allocation. It uses a static object. No need to initialize or - * cleanup. - * 4. Thread safe. - * 5. Support embedded architectures that has no misaligned memory access - * support. - * - * Limitations: - * - * 1. At most 30 faststart entries. Actually this is limited by ethernet's MTU. - * If a Setup signal contains more than 30 faststart, the packet size will - * very likely exceed the MTU size, then the TPKT will be fragmented. I - * don't know how to handle this in a Netfilter module. Anybody can help? - * Although I think 30 is enough for most of the cases. - * 2. IPv4 addresses only. - * - ****************************************************************************/ - -#ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_ -#define _IP_CONNTRACK_HELPER_H323_ASN1_H_ - -/***************************************************************************** - * H.323 Types - ****************************************************************************/ -#include "ip_conntrack_helper_h323_types.h" - -typedef struct { - enum { - Q931_NationalEscape = 0x00, - Q931_Alerting = 0x01, - Q931_CallProceeding = 0x02, - Q931_Connect = 0x07, - Q931_ConnectAck = 0x0F, - Q931_Progress = 0x03, - Q931_Setup = 0x05, - Q931_SetupAck = 0x0D, - Q931_Resume = 0x26, - Q931_ResumeAck = 0x2E, - Q931_ResumeReject = 0x22, - Q931_Suspend = 0x25, - Q931_SuspendAck = 0x2D, - Q931_SuspendReject = 0x21, - Q931_UserInformation = 0x20, - Q931_Disconnect = 0x45, - Q931_Release = 0x4D, - Q931_ReleaseComplete = 0x5A, - Q931_Restart = 0x46, - Q931_RestartAck = 0x4E, - Q931_Segment = 0x60, - Q931_CongestionCtrl = 0x79, - Q931_Information = 0x7B, - Q931_Notify = 0x6E, - Q931_Status = 0x7D, - Q931_StatusEnquiry = 0x75, - Q931_Facility = 0x62 - } MessageType; - H323_UserInformation UUIE; -} Q931; - -/***************************************************************************** - * Decode Functions Return Codes - ****************************************************************************/ - -#define H323_ERROR_NONE 0 /* Decoded successfully */ -#define H323_ERROR_STOP 1 /* Decoding stopped, not really an error */ -#define H323_ERROR_BOUND -1 -#define H323_ERROR_RANGE -2 - - -/***************************************************************************** - * Decode Functions - ****************************************************************************/ - -int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras); -int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931); -int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz, - MultimediaSystemControlMessage * - mscm); - -#endif diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h deleted file mode 100644 index cc98f7aa5abe..000000000000 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.h +++ /dev/null @@ -1,938 +0,0 @@ -/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006 - * - * Copyright (c) 2006 Jing Min Zhao - * - * This source code is licensed under General Public License version 2. - */ - -typedef struct TransportAddress_ipAddress { /* SEQUENCE */ - int options; /* No use */ - unsigned ip; -} TransportAddress_ipAddress; - -typedef struct TransportAddress { /* CHOICE */ - enum { - eTransportAddress_ipAddress, - eTransportAddress_ipSourceRoute, - eTransportAddress_ipxAddress, - eTransportAddress_ip6Address, - eTransportAddress_netBios, - eTransportAddress_nsap, - eTransportAddress_nonStandardAddress, - } choice; - union { - TransportAddress_ipAddress ipAddress; - }; -} TransportAddress; - -typedef struct DataProtocolCapability { /* CHOICE */ - enum { - eDataProtocolCapability_nonStandard, - eDataProtocolCapability_v14buffered, - eDataProtocolCapability_v42lapm, - eDataProtocolCapability_hdlcFrameTunnelling, - eDataProtocolCapability_h310SeparateVCStack, - eDataProtocolCapability_h310SingleVCStack, - eDataProtocolCapability_transparent, - eDataProtocolCapability_segmentationAndReassembly, - eDataProtocolCapability_hdlcFrameTunnelingwSAR, - eDataProtocolCapability_v120, - eDataProtocolCapability_separateLANStack, - eDataProtocolCapability_v76wCompression, - eDataProtocolCapability_tcp, - eDataProtocolCapability_udp, - } choice; -} DataProtocolCapability; - -typedef struct DataApplicationCapability_application { /* CHOICE */ - enum { - eDataApplicationCapability_application_nonStandard, - eDataApplicationCapability_application_t120, - eDataApplicationCapability_application_dsm_cc, - eDataApplicationCapability_application_userData, - eDataApplicationCapability_application_t84, - eDataApplicationCapability_application_t434, - eDataApplicationCapability_application_h224, - eDataApplicationCapability_application_nlpid, - eDataApplicationCapability_application_dsvdControl, - eDataApplicationCapability_application_h222DataPartitioning, - eDataApplicationCapability_application_t30fax, - eDataApplicationCapability_application_t140, - eDataApplicationCapability_application_t38fax, - eDataApplicationCapability_application_genericDataCapability, - } choice; - union { - DataProtocolCapability t120; - }; -} DataApplicationCapability_application; - -typedef struct DataApplicationCapability { /* SEQUENCE */ - int options; /* No use */ - DataApplicationCapability_application application; -} DataApplicationCapability; - -typedef struct DataType { /* CHOICE */ - enum { - eDataType_nonStandard, - eDataType_nullData, - eDataType_videoData, - eDataType_audioData, - eDataType_data, - eDataType_encryptionData, - eDataType_h235Control, - eDataType_h235Media, - eDataType_multiplexedStream, - } choice; - union { - DataApplicationCapability data; - }; -} DataType; - -typedef struct UnicastAddress_iPAddress { /* SEQUENCE */ - int options; /* No use */ - unsigned network; -} UnicastAddress_iPAddress; - -typedef struct UnicastAddress { /* CHOICE */ - enum { - eUnicastAddress_iPAddress, - eUnicastAddress_iPXAddress, - eUnicastAddress_iP6Address, - eUnicastAddress_netBios, - eUnicastAddress_iPSourceRouteAddress, - eUnicastAddress_nsap, - eUnicastAddress_nonStandardAddress, - } choice; - union { - UnicastAddress_iPAddress iPAddress; - }; -} UnicastAddress; - -typedef struct H245_TransportAddress { /* CHOICE */ - enum { - eH245_TransportAddress_unicastAddress, - eH245_TransportAddress_multicastAddress, - } choice; - union { - UnicastAddress unicastAddress; - }; -} H245_TransportAddress; - -typedef struct H2250LogicalChannelParameters { /* SEQUENCE */ - enum { - eH2250LogicalChannelParameters_nonStandard = (1 << 31), - eH2250LogicalChannelParameters_associatedSessionID = - (1 << 30), - eH2250LogicalChannelParameters_mediaChannel = (1 << 29), - eH2250LogicalChannelParameters_mediaGuaranteedDelivery = - (1 << 28), - eH2250LogicalChannelParameters_mediaControlChannel = - (1 << 27), - eH2250LogicalChannelParameters_mediaControlGuaranteedDelivery - = (1 << 26), - eH2250LogicalChannelParameters_silenceSuppression = (1 << 25), - eH2250LogicalChannelParameters_destination = (1 << 24), - eH2250LogicalChannelParameters_dynamicRTPPayloadType = - (1 << 23), - eH2250LogicalChannelParameters_mediaPacketization = (1 << 22), - eH2250LogicalChannelParameters_transportCapability = - (1 << 21), - eH2250LogicalChannelParameters_redundancyEncoding = (1 << 20), - eH2250LogicalChannelParameters_source = (1 << 19), - } options; - H245_TransportAddress mediaChannel; - H245_TransportAddress mediaControlChannel; -} H2250LogicalChannelParameters; - -typedef struct OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters { /* CHOICE */ - enum { - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, - eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_none, - } choice; - union { - H2250LogicalChannelParameters h2250LogicalChannelParameters; - }; -} OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters; - -typedef struct OpenLogicalChannel_forwardLogicalChannelParameters { /* SEQUENCE */ - enum { - eOpenLogicalChannel_forwardLogicalChannelParameters_portNumber - = (1 << 31), - eOpenLogicalChannel_forwardLogicalChannelParameters_forwardLogicalChannelDependency - = (1 << 30), - eOpenLogicalChannel_forwardLogicalChannelParameters_replacementFor - = (1 << 29), - } options; - DataType dataType; - OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters - multiplexParameters; -} OpenLogicalChannel_forwardLogicalChannelParameters; - -typedef struct OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ - enum { - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h223LogicalChannelParameters, - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_v76LogicalChannelParameters, - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, - } choice; - union { - H2250LogicalChannelParameters h2250LogicalChannelParameters; - }; -} OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters; - -typedef struct OpenLogicalChannel_reverseLogicalChannelParameters { /* SEQUENCE */ - enum { - eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters - = (1 << 31), - eOpenLogicalChannel_reverseLogicalChannelParameters_reverseLogicalChannelDependency - = (1 << 30), - eOpenLogicalChannel_reverseLogicalChannelParameters_replacementFor - = (1 << 29), - } options; - OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters - multiplexParameters; -} OpenLogicalChannel_reverseLogicalChannelParameters; - -typedef struct NetworkAccessParameters_networkAddress { /* CHOICE */ - enum { - eNetworkAccessParameters_networkAddress_q2931Address, - eNetworkAccessParameters_networkAddress_e164Address, - eNetworkAccessParameters_networkAddress_localAreaAddress, - } choice; - union { - H245_TransportAddress localAreaAddress; - }; -} NetworkAccessParameters_networkAddress; - -typedef struct NetworkAccessParameters { /* SEQUENCE */ - enum { - eNetworkAccessParameters_distribution = (1 << 31), - eNetworkAccessParameters_externalReference = (1 << 30), - eNetworkAccessParameters_t120SetupProcedure = (1 << 29), - } options; - NetworkAccessParameters_networkAddress networkAddress; -} NetworkAccessParameters; - -typedef struct OpenLogicalChannel { /* SEQUENCE */ - enum { - eOpenLogicalChannel_reverseLogicalChannelParameters = - (1 << 31), - eOpenLogicalChannel_separateStack = (1 << 30), - eOpenLogicalChannel_encryptionSync = (1 << 29), - } options; - OpenLogicalChannel_forwardLogicalChannelParameters - forwardLogicalChannelParameters; - OpenLogicalChannel_reverseLogicalChannelParameters - reverseLogicalChannelParameters; - NetworkAccessParameters separateStack; -} OpenLogicalChannel; - -typedef struct Setup_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Setup_UUIE_fastStart; - -typedef struct Setup_UUIE { /* SEQUENCE */ - enum { - eSetup_UUIE_h245Address = (1 << 31), - eSetup_UUIE_sourceAddress = (1 << 30), - eSetup_UUIE_destinationAddress = (1 << 29), - eSetup_UUIE_destCallSignalAddress = (1 << 28), - eSetup_UUIE_destExtraCallInfo = (1 << 27), - eSetup_UUIE_destExtraCRV = (1 << 26), - eSetup_UUIE_callServices = (1 << 25), - eSetup_UUIE_sourceCallSignalAddress = (1 << 24), - eSetup_UUIE_remoteExtensionAddress = (1 << 23), - eSetup_UUIE_callIdentifier = (1 << 22), - eSetup_UUIE_h245SecurityCapability = (1 << 21), - eSetup_UUIE_tokens = (1 << 20), - eSetup_UUIE_cryptoTokens = (1 << 19), - eSetup_UUIE_fastStart = (1 << 18), - eSetup_UUIE_mediaWaitForConnect = (1 << 17), - eSetup_UUIE_canOverlapSend = (1 << 16), - eSetup_UUIE_endpointIdentifier = (1 << 15), - eSetup_UUIE_multipleCalls = (1 << 14), - eSetup_UUIE_maintainConnection = (1 << 13), - eSetup_UUIE_connectionParameters = (1 << 12), - eSetup_UUIE_language = (1 << 11), - eSetup_UUIE_presentationIndicator = (1 << 10), - eSetup_UUIE_screeningIndicator = (1 << 9), - eSetup_UUIE_serviceControl = (1 << 8), - eSetup_UUIE_symmetricOperationRequired = (1 << 7), - eSetup_UUIE_capacity = (1 << 6), - eSetup_UUIE_circuitInfo = (1 << 5), - eSetup_UUIE_desiredProtocols = (1 << 4), - eSetup_UUIE_neededFeatures = (1 << 3), - eSetup_UUIE_desiredFeatures = (1 << 2), - eSetup_UUIE_supportedFeatures = (1 << 1), - eSetup_UUIE_parallelH245Control = (1 << 0), - } options; - TransportAddress h245Address; - TransportAddress destCallSignalAddress; - TransportAddress sourceCallSignalAddress; - Setup_UUIE_fastStart fastStart; -} Setup_UUIE; - -typedef struct CallProceeding_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} CallProceeding_UUIE_fastStart; - -typedef struct CallProceeding_UUIE { /* SEQUENCE */ - enum { - eCallProceeding_UUIE_h245Address = (1 << 31), - eCallProceeding_UUIE_callIdentifier = (1 << 30), - eCallProceeding_UUIE_h245SecurityMode = (1 << 29), - eCallProceeding_UUIE_tokens = (1 << 28), - eCallProceeding_UUIE_cryptoTokens = (1 << 27), - eCallProceeding_UUIE_fastStart = (1 << 26), - eCallProceeding_UUIE_multipleCalls = (1 << 25), - eCallProceeding_UUIE_maintainConnection = (1 << 24), - eCallProceeding_UUIE_fastConnectRefused = (1 << 23), - eCallProceeding_UUIE_featureSet = (1 << 22), - } options; - TransportAddress h245Address; - CallProceeding_UUIE_fastStart fastStart; -} CallProceeding_UUIE; - -typedef struct Connect_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Connect_UUIE_fastStart; - -typedef struct Connect_UUIE { /* SEQUENCE */ - enum { - eConnect_UUIE_h245Address = (1 << 31), - eConnect_UUIE_callIdentifier = (1 << 30), - eConnect_UUIE_h245SecurityMode = (1 << 29), - eConnect_UUIE_tokens = (1 << 28), - eConnect_UUIE_cryptoTokens = (1 << 27), - eConnect_UUIE_fastStart = (1 << 26), - eConnect_UUIE_multipleCalls = (1 << 25), - eConnect_UUIE_maintainConnection = (1 << 24), - eConnect_UUIE_language = (1 << 23), - eConnect_UUIE_connectedAddress = (1 << 22), - eConnect_UUIE_presentationIndicator = (1 << 21), - eConnect_UUIE_screeningIndicator = (1 << 20), - eConnect_UUIE_fastConnectRefused = (1 << 19), - eConnect_UUIE_serviceControl = (1 << 18), - eConnect_UUIE_capacity = (1 << 17), - eConnect_UUIE_featureSet = (1 << 16), - } options; - TransportAddress h245Address; - Connect_UUIE_fastStart fastStart; -} Connect_UUIE; - -typedef struct Alerting_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Alerting_UUIE_fastStart; - -typedef struct Alerting_UUIE { /* SEQUENCE */ - enum { - eAlerting_UUIE_h245Address = (1 << 31), - eAlerting_UUIE_callIdentifier = (1 << 30), - eAlerting_UUIE_h245SecurityMode = (1 << 29), - eAlerting_UUIE_tokens = (1 << 28), - eAlerting_UUIE_cryptoTokens = (1 << 27), - eAlerting_UUIE_fastStart = (1 << 26), - eAlerting_UUIE_multipleCalls = (1 << 25), - eAlerting_UUIE_maintainConnection = (1 << 24), - eAlerting_UUIE_alertingAddress = (1 << 23), - eAlerting_UUIE_presentationIndicator = (1 << 22), - eAlerting_UUIE_screeningIndicator = (1 << 21), - eAlerting_UUIE_fastConnectRefused = (1 << 20), - eAlerting_UUIE_serviceControl = (1 << 19), - eAlerting_UUIE_capacity = (1 << 18), - eAlerting_UUIE_featureSet = (1 << 17), - } options; - TransportAddress h245Address; - Alerting_UUIE_fastStart fastStart; -} Alerting_UUIE; - -typedef struct Information_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Information_UUIE_fastStart; - -typedef struct Information_UUIE { /* SEQUENCE */ - enum { - eInformation_UUIE_callIdentifier = (1 << 31), - eInformation_UUIE_tokens = (1 << 30), - eInformation_UUIE_cryptoTokens = (1 << 29), - eInformation_UUIE_fastStart = (1 << 28), - eInformation_UUIE_fastConnectRefused = (1 << 27), - eInformation_UUIE_circuitInfo = (1 << 26), - } options; - Information_UUIE_fastStart fastStart; -} Information_UUIE; - -typedef struct FacilityReason { /* CHOICE */ - enum { - eFacilityReason_routeCallToGatekeeper, - eFacilityReason_callForwarded, - eFacilityReason_routeCallToMC, - eFacilityReason_undefinedReason, - eFacilityReason_conferenceListChoice, - eFacilityReason_startH245, - eFacilityReason_noH245, - eFacilityReason_newTokens, - eFacilityReason_featureSetUpdate, - eFacilityReason_forwardedElements, - eFacilityReason_transportedInformation, - } choice; -} FacilityReason; - -typedef struct Facility_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Facility_UUIE_fastStart; - -typedef struct Facility_UUIE { /* SEQUENCE */ - enum { - eFacility_UUIE_alternativeAddress = (1 << 31), - eFacility_UUIE_alternativeAliasAddress = (1 << 30), - eFacility_UUIE_conferenceID = (1 << 29), - eFacility_UUIE_callIdentifier = (1 << 28), - eFacility_UUIE_destExtraCallInfo = (1 << 27), - eFacility_UUIE_remoteExtensionAddress = (1 << 26), - eFacility_UUIE_tokens = (1 << 25), - eFacility_UUIE_cryptoTokens = (1 << 24), - eFacility_UUIE_conferences = (1 << 23), - eFacility_UUIE_h245Address = (1 << 22), - eFacility_UUIE_fastStart = (1 << 21), - eFacility_UUIE_multipleCalls = (1 << 20), - eFacility_UUIE_maintainConnection = (1 << 19), - eFacility_UUIE_fastConnectRefused = (1 << 18), - eFacility_UUIE_serviceControl = (1 << 17), - eFacility_UUIE_circuitInfo = (1 << 16), - eFacility_UUIE_featureSet = (1 << 15), - eFacility_UUIE_destinationInfo = (1 << 14), - eFacility_UUIE_h245SecurityMode = (1 << 13), - } options; - FacilityReason reason; - TransportAddress h245Address; - Facility_UUIE_fastStart fastStart; -} Facility_UUIE; - -typedef struct Progress_UUIE_fastStart { /* SEQUENCE OF */ - int count; - OpenLogicalChannel item[30]; -} Progress_UUIE_fastStart; - -typedef struct Progress_UUIE { /* SEQUENCE */ - enum { - eProgress_UUIE_h245Address = (1 << 31), - eProgress_UUIE_h245SecurityMode = (1 << 30), - eProgress_UUIE_tokens = (1 << 29), - eProgress_UUIE_cryptoTokens = (1 << 28), - eProgress_UUIE_fastStart = (1 << 27), - eProgress_UUIE_multipleCalls = (1 << 26), - eProgress_UUIE_maintainConnection = (1 << 25), - eProgress_UUIE_fastConnectRefused = (1 << 24), - } options; - TransportAddress h245Address; - Progress_UUIE_fastStart fastStart; -} Progress_UUIE; - -typedef struct H323_UU_PDU_h323_message_body { /* CHOICE */ - enum { - eH323_UU_PDU_h323_message_body_setup, - eH323_UU_PDU_h323_message_body_callProceeding, - eH323_UU_PDU_h323_message_body_connect, - eH323_UU_PDU_h323_message_body_alerting, - eH323_UU_PDU_h323_message_body_information, - eH323_UU_PDU_h323_message_body_releaseComplete, - eH323_UU_PDU_h323_message_body_facility, - eH323_UU_PDU_h323_message_body_progress, - eH323_UU_PDU_h323_message_body_empty, - eH323_UU_PDU_h323_message_body_status, - eH323_UU_PDU_h323_message_body_statusInquiry, - eH323_UU_PDU_h323_message_body_setupAcknowledge, - eH323_UU_PDU_h323_message_body_notify, - } choice; - union { - Setup_UUIE setup; - CallProceeding_UUIE callProceeding; - Connect_UUIE connect; - Alerting_UUIE alerting; - Information_UUIE information; - Facility_UUIE facility; - Progress_UUIE progress; - }; -} H323_UU_PDU_h323_message_body; - -typedef struct RequestMessage { /* CHOICE */ - enum { - eRequestMessage_nonStandard, - eRequestMessage_masterSlaveDetermination, - eRequestMessage_terminalCapabilitySet, - eRequestMessage_openLogicalChannel, - eRequestMessage_closeLogicalChannel, - eRequestMessage_requestChannelClose, - eRequestMessage_multiplexEntrySend, - eRequestMessage_requestMultiplexEntry, - eRequestMessage_requestMode, - eRequestMessage_roundTripDelayRequest, - eRequestMessage_maintenanceLoopRequest, - eRequestMessage_communicationModeRequest, - eRequestMessage_conferenceRequest, - eRequestMessage_multilinkRequest, - eRequestMessage_logicalChannelRateRequest, - } choice; - union { - OpenLogicalChannel openLogicalChannel; - }; -} RequestMessage; - -typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters { /* CHOICE */ - enum { - eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h222LogicalChannelParameters, - eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters, - } choice; - union { - H2250LogicalChannelParameters h2250LogicalChannelParameters; - }; -} OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters; - -typedef struct OpenLogicalChannelAck_reverseLogicalChannelParameters { /* SEQUENCE */ - enum { - eOpenLogicalChannelAck_reverseLogicalChannelParameters_portNumber - = (1 << 31), - eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters - = (1 << 30), - eOpenLogicalChannelAck_reverseLogicalChannelParameters_replacementFor - = (1 << 29), - } options; - OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters - multiplexParameters; -} OpenLogicalChannelAck_reverseLogicalChannelParameters; - -typedef struct H2250LogicalChannelAckParameters { /* SEQUENCE */ - enum { - eH2250LogicalChannelAckParameters_nonStandard = (1 << 31), - eH2250LogicalChannelAckParameters_sessionID = (1 << 30), - eH2250LogicalChannelAckParameters_mediaChannel = (1 << 29), - eH2250LogicalChannelAckParameters_mediaControlChannel = - (1 << 28), - eH2250LogicalChannelAckParameters_dynamicRTPPayloadType = - (1 << 27), - eH2250LogicalChannelAckParameters_flowControlToZero = - (1 << 26), - eH2250LogicalChannelAckParameters_portNumber = (1 << 25), - } options; - H245_TransportAddress mediaChannel; - H245_TransportAddress mediaControlChannel; -} H2250LogicalChannelAckParameters; - -typedef struct OpenLogicalChannelAck_forwardMultiplexAckParameters { /* CHOICE */ - enum { - eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters, - } choice; - union { - H2250LogicalChannelAckParameters - h2250LogicalChannelAckParameters; - }; -} OpenLogicalChannelAck_forwardMultiplexAckParameters; - -typedef struct OpenLogicalChannelAck { /* SEQUENCE */ - enum { - eOpenLogicalChannelAck_reverseLogicalChannelParameters = - (1 << 31), - eOpenLogicalChannelAck_separateStack = (1 << 30), - eOpenLogicalChannelAck_forwardMultiplexAckParameters = - (1 << 29), - eOpenLogicalChannelAck_encryptionSync = (1 << 28), - } options; - OpenLogicalChannelAck_reverseLogicalChannelParameters - reverseLogicalChannelParameters; - OpenLogicalChannelAck_forwardMultiplexAckParameters - forwardMultiplexAckParameters; -} OpenLogicalChannelAck; - -typedef struct ResponseMessage { /* CHOICE */ - enum { - eResponseMessage_nonStandard, - eResponseMessage_masterSlaveDeterminationAck, - eResponseMessage_masterSlaveDeterminationReject, - eResponseMessage_terminalCapabilitySetAck, - eResponseMessage_terminalCapabilitySetReject, - eResponseMessage_openLogicalChannelAck, - eResponseMessage_openLogicalChannelReject, - eResponseMessage_closeLogicalChannelAck, - eResponseMessage_requestChannelCloseAck, - eResponseMessage_requestChannelCloseReject, - eResponseMessage_multiplexEntrySendAck, - eResponseMessage_multiplexEntrySendReject, - eResponseMessage_requestMultiplexEntryAck, - eResponseMessage_requestMultiplexEntryReject, - eResponseMessage_requestModeAck, - eResponseMessage_requestModeReject, - eResponseMessage_roundTripDelayResponse, - eResponseMessage_maintenanceLoopAck, - eResponseMessage_maintenanceLoopReject, - eResponseMessage_communicationModeResponse, - eResponseMessage_conferenceResponse, - eResponseMessage_multilinkResponse, - eResponseMessage_logicalChannelRateAcknowledge, - eResponseMessage_logicalChannelRateReject, - } choice; - union { - OpenLogicalChannelAck openLogicalChannelAck; - }; -} ResponseMessage; - -typedef struct MultimediaSystemControlMessage { /* CHOICE */ - enum { - eMultimediaSystemControlMessage_request, - eMultimediaSystemControlMessage_response, - eMultimediaSystemControlMessage_command, - eMultimediaSystemControlMessage_indication, - } choice; - union { - RequestMessage request; - ResponseMessage response; - }; -} MultimediaSystemControlMessage; - -typedef struct H323_UU_PDU_h245Control { /* SEQUENCE OF */ - int count; - MultimediaSystemControlMessage item[4]; -} H323_UU_PDU_h245Control; - -typedef struct H323_UU_PDU { /* SEQUENCE */ - enum { - eH323_UU_PDU_nonStandardData = (1 << 31), - eH323_UU_PDU_h4501SupplementaryService = (1 << 30), - eH323_UU_PDU_h245Tunneling = (1 << 29), - eH323_UU_PDU_h245Control = (1 << 28), - eH323_UU_PDU_nonStandardControl = (1 << 27), - eH323_UU_PDU_callLinkage = (1 << 26), - eH323_UU_PDU_tunnelledSignallingMessage = (1 << 25), - eH323_UU_PDU_provisionalRespToH245Tunneling = (1 << 24), - eH323_UU_PDU_stimulusControl = (1 << 23), - eH323_UU_PDU_genericData = (1 << 22), - } options; - H323_UU_PDU_h323_message_body h323_message_body; - H323_UU_PDU_h245Control h245Control; -} H323_UU_PDU; - -typedef struct H323_UserInformation { /* SEQUENCE */ - enum { - eH323_UserInformation_user_data = (1 << 31), - } options; - H323_UU_PDU h323_uu_pdu; -} H323_UserInformation; - -typedef struct GatekeeperRequest { /* SEQUENCE */ - enum { - eGatekeeperRequest_nonStandardData = (1 << 31), - eGatekeeperRequest_gatekeeperIdentifier = (1 << 30), - eGatekeeperRequest_callServices = (1 << 29), - eGatekeeperRequest_endpointAlias = (1 << 28), - eGatekeeperRequest_alternateEndpoints = (1 << 27), - eGatekeeperRequest_tokens = (1 << 26), - eGatekeeperRequest_cryptoTokens = (1 << 25), - eGatekeeperRequest_authenticationCapability = (1 << 24), - eGatekeeperRequest_algorithmOIDs = (1 << 23), - eGatekeeperRequest_integrity = (1 << 22), - eGatekeeperRequest_integrityCheckValue = (1 << 21), - eGatekeeperRequest_supportsAltGK = (1 << 20), - eGatekeeperRequest_featureSet = (1 << 19), - eGatekeeperRequest_genericData = (1 << 18), - } options; - TransportAddress rasAddress; -} GatekeeperRequest; - -typedef struct GatekeeperConfirm { /* SEQUENCE */ - enum { - eGatekeeperConfirm_nonStandardData = (1 << 31), - eGatekeeperConfirm_gatekeeperIdentifier = (1 << 30), - eGatekeeperConfirm_alternateGatekeeper = (1 << 29), - eGatekeeperConfirm_authenticationMode = (1 << 28), - eGatekeeperConfirm_tokens = (1 << 27), - eGatekeeperConfirm_cryptoTokens = (1 << 26), - eGatekeeperConfirm_algorithmOID = (1 << 25), - eGatekeeperConfirm_integrity = (1 << 24), - eGatekeeperConfirm_integrityCheckValue = (1 << 23), - eGatekeeperConfirm_featureSet = (1 << 22), - eGatekeeperConfirm_genericData = (1 << 21), - } options; - TransportAddress rasAddress; -} GatekeeperConfirm; - -typedef struct RegistrationRequest_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} RegistrationRequest_callSignalAddress; - -typedef struct RegistrationRequest_rasAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} RegistrationRequest_rasAddress; - -typedef struct RegistrationRequest { /* SEQUENCE */ - enum { - eRegistrationRequest_nonStandardData = (1 << 31), - eRegistrationRequest_terminalAlias = (1 << 30), - eRegistrationRequest_gatekeeperIdentifier = (1 << 29), - eRegistrationRequest_alternateEndpoints = (1 << 28), - eRegistrationRequest_timeToLive = (1 << 27), - eRegistrationRequest_tokens = (1 << 26), - eRegistrationRequest_cryptoTokens = (1 << 25), - eRegistrationRequest_integrityCheckValue = (1 << 24), - eRegistrationRequest_keepAlive = (1 << 23), - eRegistrationRequest_endpointIdentifier = (1 << 22), - eRegistrationRequest_willSupplyUUIEs = (1 << 21), - eRegistrationRequest_maintainConnection = (1 << 20), - eRegistrationRequest_alternateTransportAddresses = (1 << 19), - eRegistrationRequest_additiveRegistration = (1 << 18), - eRegistrationRequest_terminalAliasPattern = (1 << 17), - eRegistrationRequest_supportsAltGK = (1 << 16), - eRegistrationRequest_usageReportingCapability = (1 << 15), - eRegistrationRequest_multipleCalls = (1 << 14), - eRegistrationRequest_supportedH248Packages = (1 << 13), - eRegistrationRequest_callCreditCapability = (1 << 12), - eRegistrationRequest_capacityReportingCapability = (1 << 11), - eRegistrationRequest_capacity = (1 << 10), - eRegistrationRequest_featureSet = (1 << 9), - eRegistrationRequest_genericData = (1 << 8), - } options; - RegistrationRequest_callSignalAddress callSignalAddress; - RegistrationRequest_rasAddress rasAddress; - unsigned timeToLive; -} RegistrationRequest; - -typedef struct RegistrationConfirm_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} RegistrationConfirm_callSignalAddress; - -typedef struct RegistrationConfirm { /* SEQUENCE */ - enum { - eRegistrationConfirm_nonStandardData = (1 << 31), - eRegistrationConfirm_terminalAlias = (1 << 30), - eRegistrationConfirm_gatekeeperIdentifier = (1 << 29), - eRegistrationConfirm_alternateGatekeeper = (1 << 28), - eRegistrationConfirm_timeToLive = (1 << 27), - eRegistrationConfirm_tokens = (1 << 26), - eRegistrationConfirm_cryptoTokens = (1 << 25), - eRegistrationConfirm_integrityCheckValue = (1 << 24), - eRegistrationConfirm_willRespondToIRR = (1 << 23), - eRegistrationConfirm_preGrantedARQ = (1 << 22), - eRegistrationConfirm_maintainConnection = (1 << 21), - eRegistrationConfirm_serviceControl = (1 << 20), - eRegistrationConfirm_supportsAdditiveRegistration = (1 << 19), - eRegistrationConfirm_terminalAliasPattern = (1 << 18), - eRegistrationConfirm_supportedPrefixes = (1 << 17), - eRegistrationConfirm_usageSpec = (1 << 16), - eRegistrationConfirm_featureServerAlias = (1 << 15), - eRegistrationConfirm_capacityReportingSpec = (1 << 14), - eRegistrationConfirm_featureSet = (1 << 13), - eRegistrationConfirm_genericData = (1 << 12), - } options; - RegistrationConfirm_callSignalAddress callSignalAddress; - unsigned timeToLive; -} RegistrationConfirm; - -typedef struct UnregistrationRequest_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} UnregistrationRequest_callSignalAddress; - -typedef struct UnregistrationRequest { /* SEQUENCE */ - enum { - eUnregistrationRequest_endpointAlias = (1 << 31), - eUnregistrationRequest_nonStandardData = (1 << 30), - eUnregistrationRequest_endpointIdentifier = (1 << 29), - eUnregistrationRequest_alternateEndpoints = (1 << 28), - eUnregistrationRequest_gatekeeperIdentifier = (1 << 27), - eUnregistrationRequest_tokens = (1 << 26), - eUnregistrationRequest_cryptoTokens = (1 << 25), - eUnregistrationRequest_integrityCheckValue = (1 << 24), - eUnregistrationRequest_reason = (1 << 23), - eUnregistrationRequest_endpointAliasPattern = (1 << 22), - eUnregistrationRequest_supportedPrefixes = (1 << 21), - eUnregistrationRequest_alternateGatekeeper = (1 << 20), - eUnregistrationRequest_genericData = (1 << 19), - } options; - UnregistrationRequest_callSignalAddress callSignalAddress; -} UnregistrationRequest; - -typedef struct AdmissionRequest { /* SEQUENCE */ - enum { - eAdmissionRequest_callModel = (1 << 31), - eAdmissionRequest_destinationInfo = (1 << 30), - eAdmissionRequest_destCallSignalAddress = (1 << 29), - eAdmissionRequest_destExtraCallInfo = (1 << 28), - eAdmissionRequest_srcCallSignalAddress = (1 << 27), - eAdmissionRequest_nonStandardData = (1 << 26), - eAdmissionRequest_callServices = (1 << 25), - eAdmissionRequest_canMapAlias = (1 << 24), - eAdmissionRequest_callIdentifier = (1 << 23), - eAdmissionRequest_srcAlternatives = (1 << 22), - eAdmissionRequest_destAlternatives = (1 << 21), - eAdmissionRequest_gatekeeperIdentifier = (1 << 20), - eAdmissionRequest_tokens = (1 << 19), - eAdmissionRequest_cryptoTokens = (1 << 18), - eAdmissionRequest_integrityCheckValue = (1 << 17), - eAdmissionRequest_transportQOS = (1 << 16), - eAdmissionRequest_willSupplyUUIEs = (1 << 15), - eAdmissionRequest_callLinkage = (1 << 14), - eAdmissionRequest_gatewayDataRate = (1 << 13), - eAdmissionRequest_capacity = (1 << 12), - eAdmissionRequest_circuitInfo = (1 << 11), - eAdmissionRequest_desiredProtocols = (1 << 10), - eAdmissionRequest_desiredTunnelledProtocol = (1 << 9), - eAdmissionRequest_featureSet = (1 << 8), - eAdmissionRequest_genericData = (1 << 7), - } options; - TransportAddress destCallSignalAddress; - TransportAddress srcCallSignalAddress; -} AdmissionRequest; - -typedef struct AdmissionConfirm { /* SEQUENCE */ - enum { - eAdmissionConfirm_irrFrequency = (1 << 31), - eAdmissionConfirm_nonStandardData = (1 << 30), - eAdmissionConfirm_destinationInfo = (1 << 29), - eAdmissionConfirm_destExtraCallInfo = (1 << 28), - eAdmissionConfirm_destinationType = (1 << 27), - eAdmissionConfirm_remoteExtensionAddress = (1 << 26), - eAdmissionConfirm_alternateEndpoints = (1 << 25), - eAdmissionConfirm_tokens = (1 << 24), - eAdmissionConfirm_cryptoTokens = (1 << 23), - eAdmissionConfirm_integrityCheckValue = (1 << 22), - eAdmissionConfirm_transportQOS = (1 << 21), - eAdmissionConfirm_willRespondToIRR = (1 << 20), - eAdmissionConfirm_uuiesRequested = (1 << 19), - eAdmissionConfirm_language = (1 << 18), - eAdmissionConfirm_alternateTransportAddresses = (1 << 17), - eAdmissionConfirm_useSpecifiedTransport = (1 << 16), - eAdmissionConfirm_circuitInfo = (1 << 15), - eAdmissionConfirm_usageSpec = (1 << 14), - eAdmissionConfirm_supportedProtocols = (1 << 13), - eAdmissionConfirm_serviceControl = (1 << 12), - eAdmissionConfirm_multipleCalls = (1 << 11), - eAdmissionConfirm_featureSet = (1 << 10), - eAdmissionConfirm_genericData = (1 << 9), - } options; - TransportAddress destCallSignalAddress; -} AdmissionConfirm; - -typedef struct LocationRequest { /* SEQUENCE */ - enum { - eLocationRequest_endpointIdentifier = (1 << 31), - eLocationRequest_nonStandardData = (1 << 30), - eLocationRequest_sourceInfo = (1 << 29), - eLocationRequest_canMapAlias = (1 << 28), - eLocationRequest_gatekeeperIdentifier = (1 << 27), - eLocationRequest_tokens = (1 << 26), - eLocationRequest_cryptoTokens = (1 << 25), - eLocationRequest_integrityCheckValue = (1 << 24), - eLocationRequest_desiredProtocols = (1 << 23), - eLocationRequest_desiredTunnelledProtocol = (1 << 22), - eLocationRequest_featureSet = (1 << 21), - eLocationRequest_genericData = (1 << 20), - eLocationRequest_hopCount = (1 << 19), - eLocationRequest_circuitInfo = (1 << 18), - } options; - TransportAddress replyAddress; -} LocationRequest; - -typedef struct LocationConfirm { /* SEQUENCE */ - enum { - eLocationConfirm_nonStandardData = (1 << 31), - eLocationConfirm_destinationInfo = (1 << 30), - eLocationConfirm_destExtraCallInfo = (1 << 29), - eLocationConfirm_destinationType = (1 << 28), - eLocationConfirm_remoteExtensionAddress = (1 << 27), - eLocationConfirm_alternateEndpoints = (1 << 26), - eLocationConfirm_tokens = (1 << 25), - eLocationConfirm_cryptoTokens = (1 << 24), - eLocationConfirm_integrityCheckValue = (1 << 23), - eLocationConfirm_alternateTransportAddresses = (1 << 22), - eLocationConfirm_supportedProtocols = (1 << 21), - eLocationConfirm_multipleCalls = (1 << 20), - eLocationConfirm_featureSet = (1 << 19), - eLocationConfirm_genericData = (1 << 18), - eLocationConfirm_circuitInfo = (1 << 17), - eLocationConfirm_serviceControl = (1 << 16), - } options; - TransportAddress callSignalAddress; - TransportAddress rasAddress; -} LocationConfirm; - -typedef struct InfoRequestResponse_callSignalAddress { /* SEQUENCE OF */ - int count; - TransportAddress item[10]; -} InfoRequestResponse_callSignalAddress; - -typedef struct InfoRequestResponse { /* SEQUENCE */ - enum { - eInfoRequestResponse_nonStandardData = (1 << 31), - eInfoRequestResponse_endpointAlias = (1 << 30), - eInfoRequestResponse_perCallInfo = (1 << 29), - eInfoRequestResponse_tokens = (1 << 28), - eInfoRequestResponse_cryptoTokens = (1 << 27), - eInfoRequestResponse_integrityCheckValue = (1 << 26), - eInfoRequestResponse_needResponse = (1 << 25), - eInfoRequestResponse_capacity = (1 << 24), - eInfoRequestResponse_irrStatus = (1 << 23), - eInfoRequestResponse_unsolicited = (1 << 22), - eInfoRequestResponse_genericData = (1 << 21), - } options; - TransportAddress rasAddress; - InfoRequestResponse_callSignalAddress callSignalAddress; -} InfoRequestResponse; - -typedef struct RasMessage { /* CHOICE */ - enum { - eRasMessage_gatekeeperRequest, - eRasMessage_gatekeeperConfirm, - eRasMessage_gatekeeperReject, - eRasMessage_registrationRequest, - eRasMessage_registrationConfirm, - eRasMessage_registrationReject, - eRasMessage_unregistrationRequest, - eRasMessage_unregistrationConfirm, - eRasMessage_unregistrationReject, - eRasMessage_admissionRequest, - eRasMessage_admissionConfirm, - eRasMessage_admissionReject, - eRasMessage_bandwidthRequest, - eRasMessage_bandwidthConfirm, - eRasMessage_bandwidthReject, - eRasMessage_disengageRequest, - eRasMessage_disengageConfirm, - eRasMessage_disengageReject, - eRasMessage_locationRequest, - eRasMessage_locationConfirm, - eRasMessage_locationReject, - eRasMessage_infoRequest, - eRasMessage_infoRequestResponse, - eRasMessage_nonStandardMessage, - eRasMessage_unknownMessageResponse, - eRasMessage_requestInProgress, - eRasMessage_resourcesAvailableIndicate, - eRasMessage_resourcesAvailableConfirm, - eRasMessage_infoRequestAck, - eRasMessage_infoRequestNak, - eRasMessage_serviceControlIndication, - eRasMessage_serviceControlResponse, - } choice; - union { - GatekeeperRequest gatekeeperRequest; - GatekeeperConfirm gatekeeperConfirm; - RegistrationRequest registrationRequest; - RegistrationConfirm registrationConfirm; - UnregistrationRequest unregistrationRequest; - AdmissionRequest admissionRequest; - AdmissionConfirm admissionConfirm; - LocationRequest locationRequest; - LocationConfirm locationConfirm; - InfoRequestResponse infoRequestResponse; - }; -} RasMessage; diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c index a0bc883928c0..6f19c20b34cf 100644 --- a/net/ipv4/netfilter/ip_nat_helper_h323.c +++ b/net/ipv4/netfilter/ip_nat_helper_h323.c @@ -41,65 +41,12 @@ #include #include -#include "ip_conntrack_helper_h323_asn1.h" - #if 0 #define DEBUGP printk #else #define DEBUGP(format, args...) #endif -extern int get_h245_addr(unsigned char *data, H245_TransportAddress * addr, - u_int32_t * ip, u_int16_t * port); -extern int get_h225_addr(unsigned char *data, TransportAddress * addr, - u_int32_t * ip, u_int16_t * port); -extern void ip_conntrack_h245_expect(struct ip_conntrack *new, - struct ip_conntrack_expect *this); -extern void ip_conntrack_q931_expect(struct ip_conntrack *new, - struct ip_conntrack_expect *this); -extern int (*set_h245_addr_hook) (struct sk_buff ** pskb, - unsigned char **data, int dataoff, - H245_TransportAddress * addr, - u_int32_t ip, u_int16_t port); -extern int (*set_h225_addr_hook) (struct sk_buff ** pskb, - unsigned char **data, int dataoff, - TransportAddress * addr, - u_int32_t ip, u_int16_t port); -extern int (*set_sig_addr_hook) (struct sk_buff ** pskb, - struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, - TransportAddress * addr, int count); -extern int (*set_ras_addr_hook) (struct sk_buff ** pskb, - struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, - TransportAddress * addr, int count); -extern int (*nat_rtp_rtcp_hook) (struct sk_buff ** pskb, - struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, int dataoff, - H245_TransportAddress * addr, - u_int16_t port, u_int16_t rtp_port, - struct ip_conntrack_expect * rtp_exp, - struct ip_conntrack_expect * rtcp_exp); -extern int (*nat_t120_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, int dataoff, - H245_TransportAddress * addr, u_int16_t port, - struct ip_conntrack_expect * exp); -extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, int dataoff, - TransportAddress * addr, u_int16_t port, - struct ip_conntrack_expect * exp); -extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct, - enum ip_conntrack_info ctinfo, - unsigned char **data, TransportAddress * addr, - int idx, u_int16_t port, - struct ip_conntrack_expect * exp); - - /****************************************************************************/ static int set_addr(struct sk_buff **pskb, unsigned char **data, int dataoff, -- cgit v1.2.3 From bce8032ef3cc58170ab3550e9e271dba7b4c4764 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 6 Apr 2006 14:18:09 -0700 Subject: [NETFILTER]: Introduce infrastructure for address family specific operations Change the queue rerouter intrastructure to a generic usable infrastructure for address family specific operations as a base for some cleanups. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter.h | 23 +++++++++++++++------- net/ipv4/netfilter.c | 17 ++++++++-------- net/ipv6/netfilter.c | 17 ++++++++-------- net/netfilter/core.c | 23 ++++++++++++++++++++++ net/netfilter/nf_queue.c | 49 +++++++++++++---------------------------------- 5 files changed, 70 insertions(+), 59 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 5aa931607923..6ee168c4978a 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -283,16 +283,25 @@ extern void nf_invalidate_cache(int pf); Returns true or false. */ extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); -struct nf_queue_rerouter { - void (*save)(const struct sk_buff *skb, struct nf_info *info); - int (*reroute)(struct sk_buff **skb, const struct nf_info *info); - int rer_size; +struct nf_afinfo { + unsigned short family; + void (*saveroute)(const struct sk_buff *skb, + struct nf_info *info); + int (*reroute)(struct sk_buff **skb, + const struct nf_info *info); + int route_key_size; }; -#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info)) +extern struct nf_afinfo *nf_afinfo[]; +static inline struct nf_afinfo *nf_get_afinfo(unsigned short family) +{ + return rcu_dereference(nf_afinfo[family]); +} -extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer); -extern int nf_unregister_queue_rerouter(int pf); +extern int nf_register_afinfo(struct nf_afinfo *afinfo); +extern void nf_unregister_afinfo(struct nf_afinfo *afinfo); + +#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info)) #include extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index b5ad9ac2fbcc..b25339c11ea0 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -133,7 +133,7 @@ struct ip_rt_info { u_int8_t tos; }; -static void queue_save(const struct sk_buff *skb, struct nf_info *info) +static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info) { struct ip_rt_info *rt_info = nf_info_reroute(info); @@ -146,7 +146,7 @@ static void queue_save(const struct sk_buff *skb, struct nf_info *info) } } -static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) +static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) { const struct ip_rt_info *rt_info = nf_info_reroute(info); @@ -161,20 +161,21 @@ static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } -static struct nf_queue_rerouter ip_reroute = { - .rer_size = sizeof(struct ip_rt_info), - .save = queue_save, - .reroute = queue_reroute, +static struct nf_afinfo nf_ip_afinfo = { + .family = AF_INET, + .saveroute = nf_ip_saveroute, + .reroute = nf_ip_reroute, + .route_key_size = sizeof(struct ip_rt_info), }; static int ipv4_netfilter_init(void) { - return nf_register_queue_rerouter(PF_INET, &ip_reroute); + return nf_register_afinfo(&nf_ip_afinfo); } static void ipv4_netfilter_fini(void) { - nf_unregister_queue_rerouter(PF_INET); + nf_unregister_afinfo(&nf_ip_afinfo); } module_init(ipv4_netfilter_init); diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index d750cfc019dc..f514a0113b9f 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -54,7 +54,7 @@ struct ip6_rt_info { struct in6_addr saddr; }; -static void save(const struct sk_buff *skb, struct nf_info *info) +static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info) { struct ip6_rt_info *rt_info = nf_info_reroute(info); @@ -66,7 +66,7 @@ static void save(const struct sk_buff *skb, struct nf_info *info) } } -static int reroute(struct sk_buff **pskb, const struct nf_info *info) +static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) { struct ip6_rt_info *rt_info = nf_info_reroute(info); @@ -79,15 +79,16 @@ static int reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } -static struct nf_queue_rerouter ip6_reroute = { - .rer_size = sizeof(struct ip6_rt_info), - .save = &save, - .reroute = &reroute, +static struct nf_afinfo nf_ip6_afinfo = { + .family = AF_INET6, + .saveroute = nf_ip6_saveroute, + .reroute = nf_ip6_reroute, + .route_key_size = sizeof(struct ip6_rt_info), }; int __init ipv6_netfilter_init(void) { - return nf_register_queue_rerouter(PF_INET6, &ip6_reroute); + return nf_register_afinfo(&nf_ip6_afinfo); } /* This can be called from inet6_init() on errors, so it cannot @@ -95,5 +96,5 @@ int __init ipv6_netfilter_init(void) */ void ipv6_netfilter_fini(void) { - nf_unregister_queue_rerouter(PF_INET6); + nf_unregister_afinfo(&nf_ip6_afinfo); } diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 645d62105571..8455a32ea5c4 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -27,6 +27,29 @@ #include "nf_internals.h" +static DEFINE_SPINLOCK(afinfo_lock); + +struct nf_afinfo *nf_afinfo[NPROTO]; +EXPORT_SYMBOL(nf_afinfo); + +int nf_register_afinfo(struct nf_afinfo *afinfo) +{ + spin_lock(&afinfo_lock); + rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo); + spin_unlock(&afinfo_lock); + return 0; +} +EXPORT_SYMBOL_GPL(nf_register_afinfo); + +void nf_unregister_afinfo(struct nf_afinfo *afinfo) +{ + spin_lock(&afinfo_lock); + rcu_assign_pointer(nf_afinfo[afinfo->family], NULL); + spin_unlock(&afinfo_lock); + synchronize_rcu(); +} +EXPORT_SYMBOL_GPL(nf_unregister_afinfo); + /* In this code, we can be waiting indefinitely for userspace to * service a packet if a hook returns NF_QUEUE. We could keep a count * of skbuffs queued for userspace, and not deregister a hook unless diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index d9f0d7ef103b..ee8f70889f47 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -17,7 +17,6 @@ * for queueing and must reinject all packets it receives, no matter what. */ static struct nf_queue_handler *queue_handler[NPROTO]; -static struct nf_queue_rerouter *queue_rerouter[NPROTO]; static DEFINE_RWLOCK(queue_handler_lock); @@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf) } EXPORT_SYMBOL(nf_unregister_queue_handler); -int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer) -{ - if (pf >= NPROTO) - return -EINVAL; - - write_lock_bh(&queue_handler_lock); - rcu_assign_pointer(queue_rerouter[pf], rer); - write_unlock_bh(&queue_handler_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(nf_register_queue_rerouter); - -int nf_unregister_queue_rerouter(int pf) -{ - if (pf >= NPROTO) - return -EINVAL; - - write_lock_bh(&queue_handler_lock); - rcu_assign_pointer(queue_rerouter[pf], NULL); - write_unlock_bh(&queue_handler_lock); - synchronize_rcu(); - return 0; -} -EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); - void nf_unregister_queue_handlers(struct nf_queue_handler *qh) { int pf; @@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb, struct net_device *physindev = NULL; struct net_device *physoutdev = NULL; #endif - struct nf_queue_rerouter *rerouter; + struct nf_afinfo *afinfo; /* QUEUE == DROP if noone is waiting, to be safe. */ read_lock(&queue_handler_lock); @@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb, return 1; } - info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC); + afinfo = nf_get_afinfo(pf); + if (!afinfo) { + read_unlock(&queue_handler_lock); + kfree_skb(*skb); + return 1; + } + + info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC); if (!info) { if (net_ratelimit()) printk(KERN_ERR "OOM queueing packet %p\n", @@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb, if (physoutdev) dev_hold(physoutdev); } #endif - rerouter = rcu_dereference(queue_rerouter[pf]); - if (rerouter) - rerouter->save(*skb, info); - + afinfo->saveroute(*skb, info); status = queue_handler[pf]->outfn(*skb, info, queuenum, queue_handler[pf]->data); @@ -190,7 +167,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, { struct list_head *elem = &info->elem->list; struct list_head *i; - struct nf_queue_rerouter *rerouter; + struct nf_afinfo *afinfo; rcu_read_lock(); @@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, } if (verdict == NF_ACCEPT) { - rerouter = rcu_dereference(queue_rerouter[info->pf]); - if (rerouter && rerouter->reroute(&skb, info) < 0) + afinfo = nf_get_afinfo(info->pf); + if (!afinfo || afinfo->reroute(&skb, info) < 0) verdict = NF_DROP; } -- cgit v1.2.3 From 422c346fad806e2abaeffac686860ebc98dfe33e Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 6 Apr 2006 14:18:43 -0700 Subject: [NETFILTER]: Add address family specific checksum helpers Add checksum operation which takes care of verifying the checksum and dealing with HW checksum errors and avoids multiple checksum operations by setting ip_summed to CHECKSUM_UNNECESSARY after successful verification. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netfilter.h | 17 +++++++++++++++++ include/linux/netfilter_ipv4.h | 2 ++ include/linux/netfilter_ipv6.h | 3 +++ net/ipv4/netfilter.c | 33 +++++++++++++++++++++++++++++++++ net/ipv6/netfilter.c | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 89 insertions(+) (limited to 'include/linux') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 6ee168c4978a..b31a9bca9361 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -285,6 +285,8 @@ extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); struct nf_afinfo { unsigned short family; + unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol); void (*saveroute)(const struct sk_buff *skb, struct nf_info *info); int (*reroute)(struct sk_buff **skb, @@ -298,6 +300,21 @@ static inline struct nf_afinfo *nf_get_afinfo(unsigned short family) return rcu_dereference(nf_afinfo[family]); } +static inline unsigned int +nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, + u_int8_t protocol, unsigned short family) +{ + struct nf_afinfo *afinfo; + unsigned int csum = 0; + + rcu_read_lock(); + afinfo = nf_get_afinfo(family); + if (afinfo) + csum = afinfo->checksum(skb, hook, dataoff, protocol); + rcu_read_unlock(); + return csum; +} + extern int nf_register_afinfo(struct nf_afinfo *afinfo); extern void nf_unregister_afinfo(struct nf_afinfo *afinfo); diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index 43c09d790b83..85301c5e8d24 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h @@ -80,6 +80,8 @@ enum nf_ip_hook_priorities { #ifdef __KERNEL__ extern int ip_route_me_harder(struct sk_buff **pskb); extern int ip_xfrm_me_harder(struct sk_buff **pskb); +extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol); #endif /*__KERNEL__*/ #endif /*__LINUX_IP_NETFILTER_H*/ diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h index 14f2bd010884..52a7b9e76428 100644 --- a/include/linux/netfilter_ipv6.h +++ b/include/linux/netfilter_ipv6.h @@ -73,6 +73,9 @@ enum nf_ip6_hook_priorities { }; #ifdef CONFIG_NETFILTER +extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol); + extern int ipv6_netfilter_init(void); extern void ipv6_netfilter_fini(void); #else /* CONFIG_NETFILTER */ diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index b25339c11ea0..6a9e34b794bc 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -161,8 +161,41 @@ static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } +unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) +{ + struct iphdr *iph = skb->nh.iph; + unsigned int csum = 0; + + switch (skb->ip_summed) { + case CHECKSUM_HW: + if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN) + break; + if ((protocol == 0 && !(u16)csum_fold(skb->csum)) || + !csum_tcpudp_magic(iph->saddr, iph->daddr, + skb->len - dataoff, protocol, + skb->csum)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } + /* fall through */ + case CHECKSUM_NONE: + if (protocol == 0) + skb->csum = 0; + else + skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, + skb->len - dataoff, + protocol, 0); + csum = __skb_checksum_complete(skb); + } + return csum; +} + +EXPORT_SYMBOL(nf_ip_checksum); + static struct nf_afinfo nf_ip_afinfo = { .family = AF_INET, + .checksum = nf_ip_checksum, .saveroute = nf_ip_saveroute, .reroute = nf_ip_reroute, .route_key_size = sizeof(struct ip_rt_info), diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index f514a0113b9f..3e9ecfaf67e2 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -79,8 +79,42 @@ static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } +unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, + unsigned int dataoff, u_int8_t protocol) +{ + struct ipv6hdr *ip6h = skb->nh.ipv6h; + unsigned int csum = 0; + + switch (skb->ip_summed) { + case CHECKSUM_HW: + if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN) + break; + if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->len - dataoff, protocol, + csum_sub(skb->csum, + skb_checksum(skb, 0, + dataoff, 0)))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } + /* fall through */ + case CHECKSUM_NONE: + skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->len - dataoff, + protocol, + csum_sub(0, + skb_checksum(skb, 0, + dataoff, 0))); + csum = __skb_checksum_complete(skb); + } + return csum; +} + +EXPORT_SYMBOL(nf_ip6_checksum); + static struct nf_afinfo nf_ip6_afinfo = { .family = AF_INET6, + .checksum = nf_ip6_checksum, .saveroute = nf_ip6_saveroute, .reroute = nf_ip6_reroute, .route_key_size = sizeof(struct ip6_rt_info), -- cgit v1.2.3 From 3a326a2ce88e71d00ac0d133e314a3342a7709f8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 10 Apr 2006 15:18:35 +0200 Subject: [PATCH] introduce a "kernel-internal pipe object" abstraction separate out the 'internal pipe object' abstraction, and make it usable to splice. This cleans up and fixes several aspects of the internal splice APIs and the pipe code: - pipes: the allocation and freeing of pipe_inode_info is now more symmetric and more streamlined with existing kernel practices. - splice: small micro-optimization: less pointer dereferencing in splice methods Signed-off-by: Ingo Molnar Update XFS for the ->splice_read/->splice_write changes. Signed-off-by: Jens Axboe --- fs/fifo.c | 12 +++-- fs/pipe.c | 51 +++++++++--------- fs/splice.c | 122 ++++++++++++++++++++++--------------------- fs/xfs/linux-2.6/xfs_file.c | 8 +-- fs/xfs/linux-2.6/xfs_lrw.c | 4 +- fs/xfs/linux-2.6/xfs_lrw.h | 4 +- fs/xfs/linux-2.6/xfs_vnode.h | 4 +- include/linux/fs.h | 8 +-- include/linux/pipe_fs_i.h | 7 +-- 9 files changed, 114 insertions(+), 106 deletions(-) (limited to 'include/linux') diff --git a/fs/fifo.c b/fs/fifo.c index 889f722ee36d..b16e2f597d61 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -15,12 +15,13 @@ #include #include -static void wait_for_partner(struct inode* inode, unsigned int* cnt) +static void wait_for_partner(struct inode* inode, unsigned int *cnt) { int cur = *cnt; - while(cur == *cnt) { - pipe_wait(inode); - if(signal_pending(current)) + + while (cur == *cnt) { + pipe_wait(inode->i_pipe); + if (signal_pending(current)) break; } } @@ -37,7 +38,8 @@ static int fifo_open(struct inode *inode, struct file *filp) mutex_lock(PIPE_MUTEX(*inode)); if (!inode->i_pipe) { ret = -ENOMEM; - if(!pipe_new(inode)) + inode->i_pipe = alloc_pipe_info(inode); + if (!inode->i_pipe) goto err_nocleanup; } filp->f_version = 0; diff --git a/fs/pipe.c b/fs/pipe.c index 795df987cd38..705b48692627 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -36,7 +36,7 @@ */ /* Drop the inode semaphore and wait for a pipe event, atomically */ -void pipe_wait(struct inode * inode) +void pipe_wait(struct pipe_inode_info *pipe) { DEFINE_WAIT(wait); @@ -44,11 +44,13 @@ void pipe_wait(struct inode * inode) * Pipes are system-local resources, so sleeping on them * is considered a noninteractive wait: */ - prepare_to_wait(PIPE_WAIT(*inode), &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE); - mutex_unlock(PIPE_MUTEX(*inode)); + prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE); + if (pipe->inode) + mutex_unlock(&pipe->inode->i_mutex); schedule(); - finish_wait(PIPE_WAIT(*inode), &wait); - mutex_lock(PIPE_MUTEX(*inode)); + finish_wait(&pipe->wait, &wait); + if (pipe->inode) + mutex_lock(&pipe->inode->i_mutex); } static int @@ -223,7 +225,7 @@ pipe_readv(struct file *filp, const struct iovec *_iov, wake_up_interruptible_sync(PIPE_WAIT(*inode)); kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); } - pipe_wait(inode); + pipe_wait(inode->i_pipe); } mutex_unlock(PIPE_MUTEX(*inode)); /* Signal writers asynchronously that there is more room. */ @@ -370,7 +372,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov, do_wakeup = 0; } PIPE_WAITING_WRITERS(*inode)++; - pipe_wait(inode); + pipe_wait(inode->i_pipe); PIPE_WAITING_WRITERS(*inode)--; } out: @@ -675,6 +677,20 @@ static struct file_operations rdwr_pipe_fops = { .fasync = pipe_rdwr_fasync, }; +struct pipe_inode_info * alloc_pipe_info(struct inode *inode) +{ + struct pipe_inode_info *info; + + info = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); + if (info) { + init_waitqueue_head(&info->wait); + info->r_counter = info->w_counter = 1; + info->inode = inode; + } + + return info; +} + void free_pipe_info(struct inode *inode) { int i; @@ -691,23 +707,6 @@ void free_pipe_info(struct inode *inode) kfree(info); } -struct inode* pipe_new(struct inode* inode) -{ - struct pipe_inode_info *info; - - info = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); - if (!info) - goto fail_page; - inode->i_pipe = info; - - init_waitqueue_head(PIPE_WAIT(*inode)); - PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1; - - return inode; -fail_page: - return NULL; -} - static struct vfsmount *pipe_mnt __read_mostly; static int pipefs_delete_dentry(struct dentry *dentry) { @@ -724,8 +723,10 @@ static struct inode * get_pipe_inode(void) if (!inode) goto fail_inode; - if(!pipe_new(inode)) + inode->i_pipe = alloc_pipe_info(inode); + if (!inode->i_pipe) goto fail_iput; + PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; inode->i_fop = &rdwr_pipe_fops; diff --git a/fs/splice.c b/fs/splice.c index 9bfd6af0cf45..ed91a62402e0 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -136,34 +136,33 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = { * Pipe output worker. This sets up our pipe format with the page cache * pipe buffer operations. Otherwise very similar to the regular pipe_writev(). */ -static ssize_t move_to_pipe(struct inode *inode, struct page **pages, +static ssize_t move_to_pipe(struct pipe_inode_info *pipe, struct page **pages, int nr_pages, unsigned long offset, unsigned long len, unsigned int flags) { - struct pipe_inode_info *info; int ret, do_wakeup, i; ret = 0; do_wakeup = 0; i = 0; - mutex_lock(PIPE_MUTEX(*inode)); + if (pipe->inode) + mutex_lock(&pipe->inode->i_mutex); - info = inode->i_pipe; for (;;) { int bufs; - if (!PIPE_READERS(*inode)) { + if (!pipe->readers) { send_sig(SIGPIPE, current, 0); if (!ret) ret = -EPIPE; break; } - bufs = info->nrbufs; + bufs = pipe->nrbufs; if (bufs < PIPE_BUFFERS) { - int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS - 1); - struct pipe_buffer *buf = info->bufs + newbuf; + int newbuf = (pipe->curbuf + bufs) & (PIPE_BUFFERS - 1); + struct pipe_buffer *buf = pipe->bufs + newbuf; struct page *page = pages[i++]; unsigned long this_len; @@ -175,7 +174,7 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages, buf->offset = offset; buf->len = this_len; buf->ops = &page_cache_pipe_buf_ops; - info->nrbufs = ++bufs; + pipe->nrbufs = ++bufs; do_wakeup = 1; ret += this_len; @@ -205,25 +204,25 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages, if (do_wakeup) { smp_mb(); - if (waitqueue_active(PIPE_WAIT(*inode))) - wake_up_interruptible_sync(PIPE_WAIT(*inode)); - kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, - POLL_IN); + if (waitqueue_active(&pipe->wait)) + wake_up_interruptible_sync(&pipe->wait); + kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); do_wakeup = 0; } - PIPE_WAITING_WRITERS(*inode)++; - pipe_wait(inode); - PIPE_WAITING_WRITERS(*inode)--; + pipe->waiting_writers++; + pipe_wait(pipe); + pipe->waiting_writers--; } - mutex_unlock(PIPE_MUTEX(*inode)); + if (pipe->inode) + mutex_unlock(&pipe->inode->i_mutex); if (do_wakeup) { smp_mb(); - if (waitqueue_active(PIPE_WAIT(*inode))) - wake_up_interruptible(PIPE_WAIT(*inode)); - kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); + if (waitqueue_active(&pipe->wait)) + wake_up_interruptible(&pipe->wait); + kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); } while (i < nr_pages) @@ -232,8 +231,9 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages, return ret; } -static int __generic_file_splice_read(struct file *in, struct inode *pipe, - size_t len, unsigned int flags) +static int +__generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, + size_t len, unsigned int flags) { struct address_space *mapping = in->f_mapping; unsigned int offset, nr_pages; @@ -298,7 +298,7 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe, * Will read pages from given file and fill them into a pipe. * */ -ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, +ssize_t generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { ssize_t spliced; @@ -306,6 +306,7 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, ret = 0; spliced = 0; + while (len) { ret = __generic_file_splice_read(in, pipe, len, flags); @@ -509,11 +510,10 @@ typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, * key here is the 'actor' worker passed in that actually moves the data * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. */ -static ssize_t move_from_pipe(struct inode *inode, struct file *out, +static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, size_t len, unsigned int flags, splice_actor *actor) { - struct pipe_inode_info *info; int ret, do_wakeup, err; struct splice_desc sd; @@ -525,22 +525,22 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, sd.file = out; sd.pos = out->f_pos; - mutex_lock(PIPE_MUTEX(*inode)); + if (pipe->inode) + mutex_lock(&pipe->inode->i_mutex); - info = inode->i_pipe; for (;;) { - int bufs = info->nrbufs; + int bufs = pipe->nrbufs; if (bufs) { - int curbuf = info->curbuf; - struct pipe_buffer *buf = info->bufs + curbuf; + int curbuf = pipe->curbuf; + struct pipe_buffer *buf = pipe->bufs + curbuf; struct pipe_buf_operations *ops = buf->ops; sd.len = buf->len; if (sd.len > sd.total_len) sd.len = sd.total_len; - err = actor(info, buf, &sd); + err = actor(pipe, buf, &sd); if (err) { if (!ret && err != -ENODATA) ret = err; @@ -553,10 +553,10 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, buf->len -= sd.len; if (!buf->len) { buf->ops = NULL; - ops->release(info, buf); + ops->release(pipe, buf); curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1); - info->curbuf = curbuf; - info->nrbufs = --bufs; + pipe->curbuf = curbuf; + pipe->nrbufs = --bufs; do_wakeup = 1; } @@ -568,9 +568,9 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, if (bufs) continue; - if (!PIPE_WRITERS(*inode)) + if (!pipe->writers) break; - if (!PIPE_WAITING_WRITERS(*inode)) { + if (!pipe->waiting_writers) { if (ret) break; } @@ -589,22 +589,23 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, if (do_wakeup) { smp_mb(); - if (waitqueue_active(PIPE_WAIT(*inode))) - wake_up_interruptible_sync(PIPE_WAIT(*inode)); - kill_fasync(PIPE_FASYNC_WRITERS(*inode),SIGIO,POLL_OUT); + if (waitqueue_active(&pipe->wait)) + wake_up_interruptible_sync(&pipe->wait); + kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); do_wakeup = 0; } - pipe_wait(inode); + pipe_wait(pipe); } - mutex_unlock(PIPE_MUTEX(*inode)); + if (pipe->inode) + mutex_unlock(&pipe->inode->i_mutex); if (do_wakeup) { smp_mb(); - if (waitqueue_active(PIPE_WAIT(*inode))) - wake_up_interruptible(PIPE_WAIT(*inode)); - kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); + if (waitqueue_active(&pipe->wait)) + wake_up_interruptible(&pipe->wait); + kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); } mutex_lock(&out->f_mapping->host->i_mutex); @@ -616,7 +617,7 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, /** * generic_file_splice_write - splice data from a pipe to a file - * @inode: pipe inode + * @pipe: pipe info * @out: file to write to * @len: number of bytes to splice * @flags: splice modifier flags @@ -625,11 +626,14 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, * the given pipe inode to the given file. * */ -ssize_t generic_file_splice_write(struct inode *inode, struct file *out, - size_t len, unsigned int flags) +ssize_t +generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, + size_t len, unsigned int flags) { struct address_space *mapping = out->f_mapping; - ssize_t ret = move_from_pipe(inode, out, len, flags, pipe_to_file); + ssize_t ret; + + ret = move_from_pipe(pipe, out, len, flags, pipe_to_file); /* * if file or inode is SYNC and we actually wrote some data, sync it @@ -664,10 +668,10 @@ EXPORT_SYMBOL(generic_file_splice_write); * is involved. * */ -ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, +ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, size_t len, unsigned int flags) { - return move_from_pipe(inode, out, len, flags, pipe_to_sendpage); + return move_from_pipe(pipe, out, len, flags, pipe_to_sendpage); } EXPORT_SYMBOL(generic_splice_sendpage); @@ -675,8 +679,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); /* * Attempt to initiate a splice from pipe to file. */ -static long do_splice_from(struct inode *pipe, struct file *out, size_t len, - unsigned int flags) +static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + size_t len, unsigned int flags) { loff_t pos; int ret; @@ -698,8 +702,8 @@ static long do_splice_from(struct inode *pipe, struct file *out, size_t len, /* * Attempt to initiate a splice from a file to a pipe. */ -static long do_splice_to(struct file *in, struct inode *pipe, size_t len, - unsigned int flags) +static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, + size_t len, unsigned int flags) { loff_t pos, isize, left; int ret; @@ -732,14 +736,14 @@ static long do_splice_to(struct file *in, struct inode *pipe, size_t len, static long do_splice(struct file *in, struct file *out, size_t len, unsigned int flags) { - struct inode *pipe; + struct pipe_inode_info *pipe; - pipe = in->f_dentry->d_inode; - if (pipe->i_pipe) + pipe = in->f_dentry->d_inode->i_pipe; + if (pipe) return do_splice_from(pipe, out, len, flags); - pipe = out->f_dentry->d_inode; - if (pipe->i_pipe) + pipe = out->f_dentry->d_inode->i_pipe; + if (pipe) return do_splice_to(in, pipe, len, flags); return -EINVAL; diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index ae4c4754ed31..269721af02f3 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -252,7 +252,7 @@ xfs_file_sendfile_invis( STATIC ssize_t xfs_file_splice_read( struct file *infilp, - struct inode *pipe, + struct pipe_inode_info *pipe, size_t len, unsigned int flags) { @@ -266,7 +266,7 @@ xfs_file_splice_read( STATIC ssize_t xfs_file_splice_read_invis( struct file *infilp, - struct inode *pipe, + struct pipe_inode_info *pipe, size_t len, unsigned int flags) { @@ -279,7 +279,7 @@ xfs_file_splice_read_invis( STATIC ssize_t xfs_file_splice_write( - struct inode *pipe, + struct pipe_inode_info *pipe, struct file *outfilp, size_t len, unsigned int flags) @@ -293,7 +293,7 @@ xfs_file_splice_write( STATIC ssize_t xfs_file_splice_write_invis( - struct inode *pipe, + struct pipe_inode_info *pipe, struct file *outfilp, size_t len, unsigned int flags) diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 90cd314acbaa..74a52937f208 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -338,7 +338,7 @@ ssize_t xfs_splice_read( bhv_desc_t *bdp, struct file *infilp, - struct inode *pipe, + struct pipe_inode_info *pipe, size_t count, int flags, int ioflags, @@ -380,7 +380,7 @@ xfs_splice_read( ssize_t xfs_splice_write( bhv_desc_t *bdp, - struct inode *pipe, + struct pipe_inode_info *pipe, struct file *outfilp, size_t count, int flags, diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index eaa5659713fb..55c689a86ad2 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h @@ -94,9 +94,9 @@ extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, loff_t *, int, size_t, read_actor_t, void *, struct cred *); extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, - struct inode *, size_t, int, int, + struct pipe_inode_info *, size_t, int, int, struct cred *); -extern ssize_t xfs_splice_write(struct bhv_desc *, struct inode *, +extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *, struct file *, size_t, int, int, struct cred *); diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 6f1c79a28f8b..88b09f186289 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -174,9 +174,9 @@ typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, loff_t *, int, size_t, read_actor_t, void *, struct cred *); typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, - struct inode *, size_t, int, int, + struct pipe_inode_info *, size_t, int, int, struct cred *); -typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct inode *, +typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *, struct file *, size_t, int, int, struct cred *); typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, diff --git a/include/linux/fs.h b/include/linux/fs.h index 1e9ebaba07b7..7e6454454fbd 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1039,8 +1039,8 @@ struct file_operations { int (*check_flags)(int); int (*dir_notify)(struct file *filp, unsigned long arg); int (*flock) (struct file *, int, struct file_lock *); - ssize_t (*splice_write)(struct inode *, struct file *, size_t, unsigned int); - ssize_t (*splice_read)(struct file *, struct inode *, size_t, unsigned int); + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int); + ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); }; struct inode_operations { @@ -1611,8 +1611,8 @@ extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor extern void do_generic_mapping_read(struct address_space *mapping, struct file_ra_state *, struct file *, loff_t *, read_descriptor_t *, read_actor_t); -extern ssize_t generic_file_splice_read(struct file *, struct inode *, size_t, unsigned int); -extern ssize_t generic_file_splice_write(struct inode *, struct file *, size_t, unsigned int); +extern ssize_t generic_file_splice_read(struct file *, struct pipe_inode_info *, size_t, unsigned int); +extern ssize_t generic_file_splice_write(struct pipe_inode_info *, struct file *, size_t, unsigned int); extern void file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index ec384958d509..9cf99cb34c15 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -36,6 +36,7 @@ struct pipe_inode_info { unsigned int w_counter; struct fasync_struct *fasync_readers; struct fasync_struct *fasync_writers; + struct inode *inode; }; /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual @@ -53,10 +54,10 @@ struct pipe_inode_info { #define PIPE_FASYNC_WRITERS(inode) (&((inode).i_pipe->fasync_writers)) /* Drop the inode semaphore and wait for a pipe event, atomically */ -void pipe_wait(struct inode * inode); +void pipe_wait(struct pipe_inode_info *pipe); -struct inode* pipe_new(struct inode* inode); -void free_pipe_info(struct inode* inode); +struct pipe_inode_info * alloc_pipe_info(struct inode * inode); +void free_pipe_info(struct inode * inode); /* * splice is tied to pipes as a transport (at least for now), so we'll just -- cgit v1.2.3 From 529565dcb1581c9a1e3f6df1c1763ca3e0f0d512 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 10 Apr 2006 15:18:58 +0200 Subject: [PATCH] splice: add optional input and output offsets add optional input and output offsets to sys_splice(), for seekable file descriptors: asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, int fd_out, loff_t __user *off_out, size_t len, unsigned int flags); semantics are straightforward: f_pos will be updated with the offset provided by user-space, before the splice transfer is about to begin. Providing a NULL offset pointer means the existing f_pos will be used (and updated in situ). Providing an offset for a pipe results in -ESPIPE. Providing an invalid offset pointer results in -EFAULT. Signed-off-by: Ingo Molnar Signed-off-by: Jens Axboe --- fs/splice.c | 54 ++++++++++++++++++++++++++++++++++++------------ include/linux/syscalls.h | 7 +++++-- 2 files changed, 46 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/fs/splice.c b/fs/splice.c index ed91a62402e0..a5326127aad5 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -680,7 +680,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); * Attempt to initiate a splice from pipe to file. */ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, - size_t len, unsigned int flags) + loff_t __user *off_out, size_t len, + unsigned int flags) { loff_t pos; int ret; @@ -691,7 +692,11 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, if (!(out->f_mode & FMODE_WRITE)) return -EBADF; + if (off_out && copy_from_user(&out->f_pos, off_out, sizeof(loff_t))) + return -EFAULT; + pos = out->f_pos; + ret = rw_verify_area(WRITE, out, &pos, len); if (unlikely(ret < 0)) return ret; @@ -702,8 +707,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, /* * Attempt to initiate a splice from a file to a pipe. */ -static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, - size_t len, unsigned int flags) +static long do_splice_to(struct file *in, loff_t __user *off_in, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { loff_t pos, isize, left; int ret; @@ -714,7 +720,11 @@ static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, if (!(in->f_mode & FMODE_READ)) return -EBADF; + if (off_in && copy_from_user(&in->f_pos, off_in, sizeof(loff_t))) + return -EFAULT; + pos = in->f_pos; + ret = rw_verify_area(READ, in, &pos, len); if (unlikely(ret < 0)) return ret; @@ -733,23 +743,39 @@ static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, /* * Determine where to splice to/from. */ -static long do_splice(struct file *in, struct file *out, size_t len, - unsigned int flags) +static long do_splice(struct file *in, loff_t __user *off_in, + struct file *out, loff_t __user *off_out, + size_t len, unsigned int flags) { struct pipe_inode_info *pipe; + if (off_out && out->f_op->llseek == no_llseek) + return -EINVAL; + if (off_in && in->f_op->llseek == no_llseek) + return -EINVAL; + pipe = in->f_dentry->d_inode->i_pipe; - if (pipe) - return do_splice_from(pipe, out, len, flags); + if (pipe) { + if (off_in) + return -ESPIPE; + + return do_splice_from(pipe, out, off_out, len, flags); + } pipe = out->f_dentry->d_inode->i_pipe; - if (pipe) - return do_splice_to(in, pipe, len, flags); + if (pipe) { + if (off_out) + return -ESPIPE; + + return do_splice_to(in, off_in, pipe, len, flags); + } return -EINVAL; } -asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags) +asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, + int fd_out, loff_t __user *off_out, + size_t len, unsigned int flags) { long error; struct file *in, *out; @@ -759,13 +785,15 @@ asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags) return 0; error = -EBADF; - in = fget_light(fdin, &fput_in); + in = fget_light(fd_in, &fput_in); if (in) { if (in->f_mode & FMODE_READ) { - out = fget_light(fdout, &fput_out); + out = fget_light(fd_out, &fput_out); if (out) { if (out->f_mode & FMODE_WRITE) - error = do_splice(in, out, len, flags); + error = do_splice(in, off_in, + out, off_out, + len, flags); fput_light(out, fput_out); } } diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 5717147596b6..4c292faa70c9 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -569,8 +569,11 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user * filename, asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode); asmlinkage long sys_unshare(unsigned long unshare_flags); -asmlinkage long sys_splice(int fdin, int fdout, size_t len, - unsigned int flags); + +asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, + int fd_out, loff_t __user *off_out, + size_t len, unsigned int flags); + asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, int flags); -- cgit v1.2.3 From 676165a8af7167f488abdcce6851a9bc36e83254 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 10 Apr 2006 11:21:48 +1000 Subject: [PATCH] Fix buddy list race that could lead to page lru list corruptions Rohit found an obscure bug causing buddy list corruption. page_is_buddy is using a non-atomic test (PagePrivate && page_count == 0) to determine whether or not a free page's buddy is itself free and in the buddy lists. Each of the conjuncts may be true at different times due to unrelated conditions, so the non-atomic page_is_buddy test may find each conjunct to be true even if they were not both true at the same time (ie. the page was not on the buddy lists). Signed-off-by: Martin Bligh Signed-off-by: Rohit Seth Signed-off-by: Nick Piggin Signed-off-by: KAMEZAWA Hiroyuki Signed-off-by: Linus Torvalds --- include/linux/mm.h | 5 ++--- include/linux/page-flags.h | 8 +++++++- mm/page_alloc.c | 31 ++++++++++++++++++------------- 3 files changed, 27 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mm.h b/include/linux/mm.h index 6aa016f1d3ae..1154684209a4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -229,10 +229,9 @@ struct page { unsigned long private; /* Mapping-private opaque data: * usually used for buffer_heads * if PagePrivate set; used for - * swp_entry_t if PageSwapCache. - * When page is free, this + * swp_entry_t if PageSwapCache; * indicates order in the buddy - * system. + * system if PG_buddy is set. */ struct address_space *mapping; /* If low bit clear, points to * inode address_space, or NULL. diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 9ea629c02a4b..547aac7696cd 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -74,7 +74,9 @@ #define PG_mappedtodisk 16 /* Has blocks allocated on-disk */ #define PG_reclaim 17 /* To be reclaimed asap */ #define PG_nosave_free 18 /* Free, should not be written */ -#define PG_uncached 19 /* Page has been mapped as uncached */ +#define PG_buddy 19 /* Page is free, on buddy lists */ + +#define PG_uncached 20 /* Page has been mapped as uncached */ /* * Global page accounting. One instance per CPU. Only unsigned longs are @@ -317,6 +319,10 @@ extern void __mod_page_state_offset(unsigned long offset, unsigned long delta); #define SetPageNosaveFree(page) set_bit(PG_nosave_free, &(page)->flags) #define ClearPageNosaveFree(page) clear_bit(PG_nosave_free, &(page)->flags) +#define PageBuddy(page) test_bit(PG_buddy, &(page)->flags) +#define __SetPageBuddy(page) __set_bit(PG_buddy, &(page)->flags) +#define __ClearPageBuddy(page) __clear_bit(PG_buddy, &(page)->flags) + #define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags) #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags) #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index dc523a1f270d..b8165e037dee 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -151,7 +151,8 @@ static void bad_page(struct page *page) 1 << PG_reclaim | 1 << PG_slab | 1 << PG_swapcache | - 1 << PG_writeback ); + 1 << PG_writeback | + 1 << PG_buddy ); set_page_count(page, 0); reset_page_mapcount(page); page->mapping = NULL; @@ -236,12 +237,12 @@ static inline unsigned long page_order(struct page *page) { static inline void set_page_order(struct page *page, int order) { set_page_private(page, order); - __SetPagePrivate(page); + __SetPageBuddy(page); } static inline void rmv_page_order(struct page *page) { - __ClearPagePrivate(page); + __ClearPageBuddy(page); set_page_private(page, 0); } @@ -280,11 +281,13 @@ __find_combined_index(unsigned long page_idx, unsigned int order) * This function checks whether a page is free && is the buddy * we can do coalesce a page and its buddy if * (a) the buddy is not in a hole && - * (b) the buddy is free && - * (c) the buddy is on the buddy system && - * (d) a page and its buddy have the same order. - * for recording page's order, we use page_private(page) and PG_private. + * (b) the buddy is in the buddy system && + * (c) a page and its buddy have the same order. + * + * For recording whether a page is in the buddy system, we use PG_buddy. + * Setting, clearing, and testing PG_buddy is serialized by zone->lock. * + * For recording page's order, we use page_private(page). */ static inline int page_is_buddy(struct page *page, int order) { @@ -293,10 +296,10 @@ static inline int page_is_buddy(struct page *page, int order) return 0; #endif - if (PagePrivate(page) && - (page_order(page) == order) && - page_count(page) == 0) + if (PageBuddy(page) && page_order(page) == order) { + BUG_ON(page_count(page) != 0); return 1; + } return 0; } @@ -313,7 +316,7 @@ static inline int page_is_buddy(struct page *page, int order) * as necessary, plus some accounting needed to play nicely with other * parts of the VM system. * At each level, we keep a list of pages, which are heads of continuous - * free pages of length of (1 << order) and marked with PG_Private.Page's + * free pages of length of (1 << order) and marked with PG_buddy. Page's * order is recorded in page_private(page) field. * So when we are allocating or freeing one, we can derive the state of the * other. That is, if we allocate a small block, and both were @@ -376,7 +379,8 @@ static inline int free_pages_check(struct page *page) 1 << PG_slab | 1 << PG_swapcache | 1 << PG_writeback | - 1 << PG_reserved )))) + 1 << PG_reserved | + 1 << PG_buddy )))) bad_page(page); if (PageDirty(page)) __ClearPageDirty(page); @@ -524,7 +528,8 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags) 1 << PG_slab | 1 << PG_swapcache | 1 << PG_writeback | - 1 << PG_reserved )))) + 1 << PG_reserved | + 1 << PG_buddy )))) bad_page(page); /* -- cgit v1.2.3 From 9227c33de80ac01f269ed33624990ce84358e419 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 1 Apr 2006 19:21:04 +0200 Subject: [PATCH] move ->eh_strategy_handler to the transport class Overriding the whole EH code is a per-transport, not per-host thing. Move ->eh_strategy_handler to the transport class, same as ->eh_timed_out. Downside is that scsi_host_alloc can't check for the total lack of EH anymore, but the transition period from old EH where we needed it is long gone already. Signed-off-by: Christoph Hellwig Signed-off-by: Jeff Garzik --- Documentation/DocBook/libata.tmpl | 2 +- Documentation/scsi/scsi_eh.txt | 14 +++++++------- Documentation/scsi/scsi_mid_low_api.txt | 19 ------------------- drivers/scsi/ahci.c | 1 - drivers/scsi/ata_piix.c | 1 - drivers/scsi/hosts.c | 12 ------------ drivers/scsi/libata-core.c | 1 - drivers/scsi/libata-scsi.c | 8 +++----- drivers/scsi/libata.h | 1 - drivers/scsi/pdc_adma.c | 1 - drivers/scsi/sata_mv.c | 2 -- drivers/scsi/sata_nv.c | 1 - drivers/scsi/sata_promise.c | 1 - drivers/scsi/sata_qstor.c | 1 - drivers/scsi/sata_sil.c | 1 - drivers/scsi/sata_sil24.c | 1 - drivers/scsi/sata_sis.c | 1 - drivers/scsi/sata_svw.c | 1 - drivers/scsi/sata_sx4.c | 1 - drivers/scsi/sata_uli.c | 1 - drivers/scsi/sata_via.c | 1 - drivers/scsi/sata_vsc.c | 1 - drivers/scsi/scsi_error.c | 4 ++-- include/linux/libata.h | 1 - include/scsi/scsi_host.h | 1 - include/scsi/scsi_transport.h | 5 +++++ 26 files changed, 18 insertions(+), 66 deletions(-) (limited to 'include/linux') diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl index 5bcbb6ee3bc0..f869b03929db 100644 --- a/Documentation/DocBook/libata.tmpl +++ b/Documentation/DocBook/libata.tmpl @@ -705,7 +705,7 @@ and other resources, etc. ata_scsi_error() - ata_scsi_error() is the current hostt->eh_strategy_handler() + ata_scsi_error() is the current transportt->eh_strategy_handler() for libata. As discussed above, this will be entered in two cases - timeout and ATAPI error completion. This function calls low level libata driver's eng_timeout() callback, the diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt index 331afd791cbb..ce767b90bb0d 100644 --- a/Documentation/scsi/scsi_eh.txt +++ b/Documentation/scsi/scsi_eh.txt @@ -19,9 +19,9 @@ TABLE OF CONTENTS [2-1-1] Overview [2-1-2] Flow of scmds through EH [2-1-3] Flow of control - [2-2] EH through hostt->eh_strategy_handler() - [2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions - [2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions + [2-2] EH through transportt->eh_strategy_handler() + [2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions + [2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions [2-2-3] Things to consider @@ -413,9 +413,9 @@ scmd->allowed. layer of failure of the scmds. -[2-2] EH through hostt->eh_strategy_handler() +[2-2] EH through transportt->eh_strategy_handler() - hostt->eh_strategy_handler() is invoked in the place of + transportt->eh_strategy_handler() is invoked in the place of scsi_unjam_host() and it is responsible for whole recovery process. On completion, the handler should have made lower layers forget about all failed scmds and either ready for new commands or offline. Also, @@ -424,7 +424,7 @@ SCSI midlayer. IOW, of the steps described in [2-1-2], all steps except for #1 must be implemented by eh_strategy_handler(). -[2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions +[2-2-1] Pre transportt->eh_strategy_handler() SCSI midlayer conditions The following conditions are true on entry to the handler. @@ -437,7 +437,7 @@ except for #1 must be implemented by eh_strategy_handler(). - shost->host_failed == shost->host_busy -[2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions +[2-2-2] Post transportt->eh_strategy_handler() SCSI midlayer conditions The following conditions must be true on exit from the handler. diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index 8bbae3e1abdf..75a535a975c3 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -804,7 +804,6 @@ Summary: eh_bus_reset_handler - issue SCSI bus reset eh_device_reset_handler - issue SCSI device reset eh_host_reset_handler - reset host (host bus adapter) - eh_strategy_handler - driver supplied alternate to scsi_unjam_host() info - supply information about given host ioctl - driver can respond to ioctls proc_info - supports /proc/scsi/{driver_name}/{host_no} @@ -969,24 +968,6 @@ Details: int eh_host_reset_handler(struct scsi_cmnd * scp) -/** - * eh_strategy_handler - driver supplied alternate to scsi_unjam_host() - * @shp: host on which error has occurred - * - * Returns TRUE if host unjammed, else FALSE. - * - * Locks: none - * - * Calling context: kernel thread - * - * Notes: Invoked from scsi_eh thread. LLD supplied alternate to - * scsi_unjam_host() found in scsi_error.c - * - * Optionally defined in: LLD - **/ - int eh_strategy_handler(struct Scsi_Host * shp) - - /** * info - supply information about given host: driver name plus data * to distinguish given host diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 1bd82c4e52a0..b4f8fb1d628b 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -207,7 +207,6 @@ static struct scsi_host_template ahci_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = AHCI_MAX_SG, diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 24e71b555172..6dc88149f9f1 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -209,7 +209,6 @@ static struct scsi_host_template piix_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index ef57f253031c..dfcb96f3e60c 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -294,18 +294,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) if (sht->unchecked_isa_dma && privsize) gfp_mask |= __GFP_DMA; - /* Check to see if this host has any error handling facilities */ - if (!sht->eh_strategy_handler && !sht->eh_abort_handler && - !sht->eh_device_reset_handler && !sht->eh_bus_reset_handler && - !sht->eh_host_reset_handler) { - printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\n" - "ERROR: This is not a safe way to run your " - "SCSI host\n" - "ERROR: The error handling must be added to " - "this driver\n", sht->proc_name); - dump_stack(); - } - shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask); if (!shost) return NULL; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e63c1ff1e102..bd147207f25d 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4938,7 +4938,6 @@ EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); -EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 53f5b0d9161c..a0289ec3e283 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -53,6 +53,7 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); +static void ata_scsi_error(struct Scsi_Host *host); enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); #define RW_RECOVERY_MPAGE 0x1 @@ -99,6 +100,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { * It just needs the eh_timed_out hook. */ struct scsi_transport_template ata_scsi_transport_template = { + .eh_strategy_handler = ata_scsi_error, .eh_timed_out = ata_scsi_timed_out, }; @@ -772,12 +774,9 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) * * LOCKING: * Inherited from SCSI layer (none, can sleep) - * - * RETURNS: - * Zero. */ -int ata_scsi_error(struct Scsi_Host *host) +static void ata_scsi_error(struct Scsi_Host *host) { struct ata_port *ap; unsigned long flags; @@ -805,7 +804,6 @@ int ata_scsi_error(struct Scsi_Host *host) spin_unlock_irqrestore(&ap->host_set->lock, flags); DPRINTK("EXIT\n"); - return 0; } static void ata_eh_scsidone(struct scsi_cmnd *scmd) diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 1c755b14521a..bac8cbae06fe 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -60,7 +60,6 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); extern struct scsi_transport_template ata_scsi_transport_template; extern void ata_scsi_scan_host(struct ata_port *ap); -extern int ata_scsi_error(struct Scsi_Host *host); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 3c85c4b66e19..5cda16cfacb0 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -143,7 +143,6 @@ static struct scsi_host_template adma_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index fa901fd65085..0ebf13668f51 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -378,8 +378,6 @@ static struct scsi_host_template mv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, - .can_queue = MV_USE_Q_DEPTH, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = MV_MAX_SG_CT / 2, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index f77bf183dfab..9f553081b5e8 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -201,7 +201,6 @@ static struct scsi_host_template nv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index cc928c68a479..7eb67a6bdc64 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -111,7 +111,6 @@ static struct scsi_host_template pdc_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 9ffe1ef0d205..886f3447dd48 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -132,7 +132,6 @@ static struct scsi_host_template qs_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = QS_MAX_PRD, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 18c296c56899..106627299d55 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -146,7 +146,6 @@ static struct scsi_host_template sil_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 068c98a4111b..f7264fd611c2 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -281,7 +281,6 @@ static struct scsi_host_template sil24_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index acc8439dea23..728530df2e07 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -87,7 +87,6 @@ static struct scsi_host_template sis_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = ATA_MAX_PRD, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 724f0ed6a52d..53b0d5c0a61f 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -290,7 +290,6 @@ static struct scsi_host_template k2_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index ae70f60c7c0d..4139ad4b1df0 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -182,7 +182,6 @@ static struct scsi_host_template pdc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 7ac5a5f5a905..38b52bd3fa3f 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -81,7 +81,6 @@ static struct scsi_host_template uli_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index 791bf652ba63..9e7ae4e0db32 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -94,7 +94,6 @@ static struct scsi_host_template svia_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 836bbbb26ff2..8a29ce340b47 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -263,7 +263,6 @@ static struct scsi_host_template vsc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 5f0fdfb2618c..1c75646f9689 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1537,8 +1537,8 @@ int scsi_error_handler(void *data) * what we need to do to get it up and online again (if we can). * If we fail, we end up taking the thing offline. */ - if (shost->hostt->eh_strategy_handler) - shost->hostt->eh_strategy_handler(shost); + if (shost->transportt->eh_strategy_handler) + shost->transportt->eh_strategy_handler(shost); else scsi_unjam_host(shost); diff --git a/include/linux/libata.h b/include/linux/libata.h index 0d61357604d5..b80d2e7fa6d2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -523,7 +523,6 @@ extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); -extern int ata_scsi_error(struct Scsi_Host *host); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); extern int ata_scsi_release(struct Scsi_Host *host); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index dc6862d09e53..de6ce541a046 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -140,7 +140,6 @@ struct scsi_host_template { * * Status: REQUIRED (at least one of them) */ - int (* eh_strategy_handler)(struct Scsi_Host *); int (* eh_abort_handler)(struct scsi_cmnd *); int (* eh_device_reset_handler)(struct scsi_cmnd *); int (* eh_bus_reset_handler)(struct scsi_cmnd *); diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index b3657f111937..cca1d4926d2a 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -49,6 +49,11 @@ struct scsi_transport_template { */ unsigned int create_work_queue : 1; + /* + * Allows a transport to override the default error handler. + */ + void (* eh_strategy_handler)(struct Scsi_Host *); + /* * This is an optional routine that allows the transport to become * involved when a scsi io timer fires. The return value tells the -- cgit v1.2.3 From de12a7878c11f3b282d640888aa635e0711d0b5e Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 10 Apr 2006 17:16:49 -0600 Subject: [PATCH] de_thread: Don't confuse users do_each_thread. Oleg Nesterov spotted two interesting bugs with the current de_thread code. The simplest is a long standing double decrement of __get_cpu_var(process_counts) in __unhash_process. Caused by two processes exiting when only one was created. The other is that since we no longer detach from the thread_group list it is possible for do_each_thread when run under the tasklist_lock to see the same task_struct twice. Once on the task list as a thread_group_leader, and once on the thread list of another thread. The double appearance in do_each_thread can cause a double increment of mm_core_waiters in zap_threads resulting in problems later on in coredump_wait. To remedy those two problems this patch takes the simple approach of changing the old thread group leader into a child thread. The only routine in release_task that cares is __unhash_process, and it can be trivially seen that we handle cleaning up a thread group leader properly. Since de_thread doesn't change the pid of the exiting leader process and instead shares it with the new leader process. I change thread_group_leader to recognize group leadership based on the group_leader field and not based on pids. This should also be slightly cheaper then the existing thread_group_leader macro. I performed a quick audit and I couldn't see any user of thread_group_leader that cared about the difference. Signed-off-by: Eric W. Biederman Signed-off-by: Linus Torvalds --- fs/exec.c | 7 ++++++- include/linux/sched.h | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/fs/exec.c b/fs/exec.c index 0291a68a3626..4d38ad0b70d6 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -723,7 +723,12 @@ static int de_thread(struct task_struct *tsk) current->parent = current->real_parent = leader->real_parent; leader->parent = leader->real_parent = child_reaper; current->group_leader = current; - leader->group_leader = leader; + leader->group_leader = current; + + /* Reduce leader to a thread */ + detach_pid(leader, PIDTYPE_PGID); + detach_pid(leader, PIDTYPE_SID); + list_del_init(&leader->tasks); add_parent(current); add_parent(leader); diff --git a/include/linux/sched.h b/include/linux/sched.h index 541f4828f5e7..a3e4f6b503a3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1203,7 +1203,8 @@ extern void wait_task_inactive(task_t * p); #define while_each_thread(g, t) \ while ((t = next_thread(t)) != g) -#define thread_group_leader(p) (p->pid == p->tgid) +/* de_thread depends on thread_group_leader not being a pid based check */ +#define thread_group_leader(p) (p == p->group_leader) static inline task_t *next_thread(task_t *p) { -- cgit v1.2.3 From b92ce55893745e011edae70830b8bc863be881f9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 11 Apr 2006 13:52:07 +0200 Subject: [PATCH] splice: add direct fd <-> fd splicing support It's more efficient for sendfile() emulation. Basically we cache an internal private pipe and just use that as the intermediate area for pages. Direct splicing is not available from sys_splice(), it is only meant to be used for sendfile() emulation. Additional patch from Ingo Molnar to avoid the PIPE_BUFFERS loop at exit for the normal fast path. Signed-off-by: Jens Axboe --- fs/pipe.c | 10 +++- fs/splice.c | 148 ++++++++++++++++++++++++++++++++++++++++------ include/linux/fs.h | 2 + include/linux/pipe_fs_i.h | 1 + include/linux/sched.h | 6 ++ kernel/exit.c | 4 ++ 6 files changed, 150 insertions(+), 21 deletions(-) (limited to 'include/linux') diff --git a/fs/pipe.c b/fs/pipe.c index 705b48692627..036536f072c9 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -691,12 +691,10 @@ struct pipe_inode_info * alloc_pipe_info(struct inode *inode) return info; } -void free_pipe_info(struct inode *inode) +void __free_pipe_info(struct pipe_inode_info *info) { int i; - struct pipe_inode_info *info = inode->i_pipe; - inode->i_pipe = NULL; for (i = 0; i < PIPE_BUFFERS; i++) { struct pipe_buffer *buf = info->bufs + i; if (buf->ops) @@ -707,6 +705,12 @@ void free_pipe_info(struct inode *inode) kfree(info); } +void free_pipe_info(struct inode *inode) +{ + __free_pipe_info(inode->i_pipe); + inode->i_pipe = NULL; +} + static struct vfsmount *pipe_mnt __read_mostly; static int pipefs_delete_dentry(struct dentry *dentry) { diff --git a/fs/splice.c b/fs/splice.c index a5326127aad5..c47b561edac0 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -680,8 +680,7 @@ EXPORT_SYMBOL(generic_splice_sendpage); * Attempt to initiate a splice from pipe to file. */ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, - loff_t __user *off_out, size_t len, - unsigned int flags) + size_t len, unsigned int flags) { loff_t pos; int ret; @@ -692,9 +691,6 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, if (!(out->f_mode & FMODE_WRITE)) return -EBADF; - if (off_out && copy_from_user(&out->f_pos, off_out, sizeof(loff_t))) - return -EFAULT; - pos = out->f_pos; ret = rw_verify_area(WRITE, out, &pos, len); @@ -707,9 +703,8 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, /* * Attempt to initiate a splice from a file to a pipe. */ -static long do_splice_to(struct file *in, loff_t __user *off_in, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags) +static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, + size_t len, unsigned int flags) { loff_t pos, isize, left; int ret; @@ -720,9 +715,6 @@ static long do_splice_to(struct file *in, loff_t __user *off_in, if (!(in->f_mode & FMODE_READ)) return -EBADF; - if (off_in && copy_from_user(&in->f_pos, off_in, sizeof(loff_t))) - return -EFAULT; - pos = in->f_pos; ret = rw_verify_area(READ, in, &pos, len); @@ -740,6 +732,118 @@ static long do_splice_to(struct file *in, loff_t __user *off_in, return in->f_op->splice_read(in, pipe, len, flags); } +long do_splice_direct(struct file *in, struct file *out, size_t len, + unsigned int flags) +{ + struct pipe_inode_info *pipe; + long ret, bytes; + umode_t i_mode; + int i; + + /* + * We require the input being a regular file, as we don't want to + * randomly drop data for eg socket -> socket splicing. Use the + * piped splicing for that! + */ + i_mode = in->f_dentry->d_inode->i_mode; + if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode))) + return -EINVAL; + + /* + * neither in nor out is a pipe, setup an internal pipe attached to + * 'out' and transfer the wanted data from 'in' to 'out' through that + */ + pipe = current->splice_pipe; + if (!pipe) { + pipe = alloc_pipe_info(NULL); + if (!pipe) + return -ENOMEM; + + /* + * We don't have an immediate reader, but we'll read the stuff + * out of the pipe right after the move_to_pipe(). So set + * PIPE_READERS appropriately. + */ + pipe->readers = 1; + + current->splice_pipe = pipe; + } + + /* + * do the splice + */ + ret = 0; + bytes = 0; + + while (len) { + size_t read_len, max_read_len; + + /* + * Do at most PIPE_BUFFERS pages worth of transfer: + */ + max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); + + ret = do_splice_to(in, pipe, max_read_len, flags); + if (unlikely(ret < 0)) + goto out_release; + + read_len = ret; + + /* + * NOTE: nonblocking mode only applies to the input. We + * must not do the output in nonblocking mode as then we + * could get stuck data in the internal pipe: + */ + ret = do_splice_from(pipe, out, read_len, + flags & ~SPLICE_F_NONBLOCK); + if (unlikely(ret < 0)) + goto out_release; + + bytes += ret; + len -= ret; + + /* + * In nonblocking mode, if we got back a short read then + * that was due to either an IO error or due to the + * pagecache entry not being there. In the IO error case + * the _next_ splice attempt will produce a clean IO error + * return value (not a short read), so in both cases it's + * correct to break out of the loop here: + */ + if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len)) + break; + } + + pipe->nrbufs = pipe->curbuf = 0; + + return bytes; + +out_release: + /* + * If we did an incomplete transfer we must release + * the pipe buffers in question: + */ + for (i = 0; i < PIPE_BUFFERS; i++) { + struct pipe_buffer *buf = pipe->bufs + i; + + if (buf->ops) { + buf->ops->release(pipe, buf); + buf->ops = NULL; + } + } + pipe->nrbufs = pipe->curbuf = 0; + + /* + * If we transferred some data, return the number of bytes: + */ + if (bytes > 0) + return bytes; + + return ret; +} + +EXPORT_SYMBOL(do_splice_direct); + /* * Determine where to splice to/from. */ @@ -749,25 +853,33 @@ static long do_splice(struct file *in, loff_t __user *off_in, { struct pipe_inode_info *pipe; - if (off_out && out->f_op->llseek == no_llseek) - return -EINVAL; - if (off_in && in->f_op->llseek == no_llseek) - return -EINVAL; - pipe = in->f_dentry->d_inode->i_pipe; if (pipe) { if (off_in) return -ESPIPE; + if (off_out) { + if (out->f_op->llseek == no_llseek) + return -EINVAL; + if (copy_from_user(&out->f_pos, off_out, + sizeof(loff_t))) + return -EFAULT; + } - return do_splice_from(pipe, out, off_out, len, flags); + return do_splice_from(pipe, out, len, flags); } pipe = out->f_dentry->d_inode->i_pipe; if (pipe) { if (off_out) return -ESPIPE; + if (off_in) { + if (in->f_op->llseek == no_llseek) + return -EINVAL; + if (copy_from_user(&in->f_pos, off_in, sizeof(loff_t))) + return -EFAULT; + } - return do_splice_to(in, off_in, pipe, len, flags); + return do_splice_to(in, pipe, len, flags); } return -EINVAL; diff --git a/include/linux/fs.h b/include/linux/fs.h index 7e6454454fbd..9e8e2ee353b4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1613,6 +1613,8 @@ extern void do_generic_mapping_read(struct address_space *mapping, loff_t *, read_descriptor_t *, read_actor_t); extern ssize_t generic_file_splice_read(struct file *, struct pipe_inode_info *, size_t, unsigned int); extern ssize_t generic_file_splice_write(struct pipe_inode_info *, struct file *, size_t, unsigned int); +extern long do_splice_direct(struct file *in, struct file *out, + size_t len, unsigned int flags); extern void file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 9cf99cb34c15..660e9d866e5d 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -58,6 +58,7 @@ void pipe_wait(struct pipe_inode_info *pipe); struct pipe_inode_info * alloc_pipe_info(struct inode * inode); void free_pipe_info(struct inode * inode); +void __free_pipe_info(struct pipe_inode_info *); /* * splice is tied to pipes as a transport (at least for now), so we'll just diff --git a/include/linux/sched.h b/include/linux/sched.h index 541f4828f5e7..e194ec75833d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -684,6 +684,7 @@ static inline void prefetch_stack(struct task_struct *t) { } struct audit_context; /* See audit.c */ struct mempolicy; +struct pipe_inode_info; enum sleep_type { SLEEP_NORMAL, @@ -882,6 +883,11 @@ struct task_struct { atomic_t fs_excl; /* holding fs exclusive resources */ struct rcu_head rcu; + + /* + * cache last used pipe for splice + */ + struct pipe_inode_info *splice_pipe; }; static inline pid_t process_group(struct task_struct *tsk) diff --git a/kernel/exit.c b/kernel/exit.c index 6c2eeb8f6390..1a9787ac6173 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -941,6 +942,9 @@ fastcall NORET_TYPE void do_exit(long code) if (tsk->io_context) exit_io_context(); + if (tsk->splice_pipe) + __free_pipe_info(tsk->splice_pipe); + /* PF_DEAD causes final put_task_struct after we schedule. */ preempt_disable(); BUG_ON(tsk->flags & PF_DEAD); -- cgit v1.2.3 From 9aeedfc4712ed58d9f7ae41596185c72b8dc97e8 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 11 Apr 2006 13:53:10 +0200 Subject: [PATCH] get rid of the PIPE_*() macros get rid of the PIPE_*() macros. Scripted transformation. Signed-off-by: Ingo Molnar Signed-off-by: Jens Axboe --- fs/fifo.c | 48 ++++++++++----------- fs/pipe.c | 104 +++++++++++++++++++++++----------------------- include/linux/pipe_fs_i.h | 10 ----- 3 files changed, 76 insertions(+), 86 deletions(-) (limited to 'include/linux') diff --git a/fs/fifo.c b/fs/fifo.c index b16e2f597d61..2c27f56d7304 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -28,14 +28,14 @@ static void wait_for_partner(struct inode* inode, unsigned int *cnt) static void wake_up_partner(struct inode* inode) { - wake_up_interruptible(PIPE_WAIT(*inode)); + wake_up_interruptible(&inode->i_pipe->wait); } static int fifo_open(struct inode *inode, struct file *filp) { int ret; - mutex_lock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); if (!inode->i_pipe) { ret = -ENOMEM; inode->i_pipe = alloc_pipe_info(inode); @@ -55,18 +55,18 @@ static int fifo_open(struct inode *inode, struct file *filp) * opened, even when there is no process writing the FIFO. */ filp->f_op = &read_fifo_fops; - PIPE_RCOUNTER(*inode)++; - if (PIPE_READERS(*inode)++ == 0) + inode->i_pipe->r_counter++; + if (inode->i_pipe->readers++ == 0) wake_up_partner(inode); - if (!PIPE_WRITERS(*inode)) { + if (!inode->i_pipe->writers) { if ((filp->f_flags & O_NONBLOCK)) { /* suppress POLLHUP until we have * seen a writer */ - filp->f_version = PIPE_WCOUNTER(*inode); + filp->f_version = inode->i_pipe->w_counter; } else { - wait_for_partner(inode, &PIPE_WCOUNTER(*inode)); + wait_for_partner(inode, &inode->i_pipe->w_counter); if(signal_pending(current)) goto err_rd; } @@ -80,16 +80,16 @@ static int fifo_open(struct inode *inode, struct file *filp) * errno=ENXIO when there is no process reading the FIFO. */ ret = -ENXIO; - if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode)) + if ((filp->f_flags & O_NONBLOCK) && !inode->i_pipe->readers) goto err; filp->f_op = &write_fifo_fops; - PIPE_WCOUNTER(*inode)++; - if (!PIPE_WRITERS(*inode)++) + inode->i_pipe->w_counter++; + if (!inode->i_pipe->writers++) wake_up_partner(inode); - if (!PIPE_READERS(*inode)) { - wait_for_partner(inode, &PIPE_RCOUNTER(*inode)); + if (!inode->i_pipe->readers) { + wait_for_partner(inode, &inode->i_pipe->r_counter); if (signal_pending(current)) goto err_wr; } @@ -104,11 +104,11 @@ static int fifo_open(struct inode *inode, struct file *filp) */ filp->f_op = &rdwr_fifo_fops; - PIPE_READERS(*inode)++; - PIPE_WRITERS(*inode)++; - PIPE_RCOUNTER(*inode)++; - PIPE_WCOUNTER(*inode)++; - if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1) + inode->i_pipe->readers++; + inode->i_pipe->writers++; + inode->i_pipe->r_counter++; + inode->i_pipe->w_counter++; + if (inode->i_pipe->readers == 1 || inode->i_pipe->writers == 1) wake_up_partner(inode); break; @@ -118,27 +118,27 @@ static int fifo_open(struct inode *inode, struct file *filp) } /* Ok! */ - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_unlock(&inode->i_mutex); return 0; err_rd: - if (!--PIPE_READERS(*inode)) - wake_up_interruptible(PIPE_WAIT(*inode)); + if (!--inode->i_pipe->readers) + wake_up_interruptible(&inode->i_pipe->wait); ret = -ERESTARTSYS; goto err; err_wr: - if (!--PIPE_WRITERS(*inode)) - wake_up_interruptible(PIPE_WAIT(*inode)); + if (!--inode->i_pipe->writers) + wake_up_interruptible(&inode->i_pipe->wait); ret = -ERESTARTSYS; goto err; err: - if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) + if (!inode->i_pipe->readers && !inode->i_pipe->writers) free_pipe_info(inode); err_nocleanup: - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_unlock(&inode->i_mutex); return ret; } diff --git a/fs/pipe.c b/fs/pipe.c index 036536f072c9..0602fc9f7eba 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -158,7 +158,7 @@ pipe_readv(struct file *filp, const struct iovec *_iov, do_wakeup = 0; ret = 0; - mutex_lock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); info = inode->i_pipe; for (;;) { int bufs = info->nrbufs; @@ -202,9 +202,9 @@ pipe_readv(struct file *filp, const struct iovec *_iov, } if (bufs) /* More to do? */ continue; - if (!PIPE_WRITERS(*inode)) + if (!inode->i_pipe->writers) break; - if (!PIPE_WAITING_WRITERS(*inode)) { + if (!inode->i_pipe->waiting_writers) { /* syscall merging: Usually we must not sleep * if O_NONBLOCK is set, or if we got some data. * But if a writer sleeps in kernel space, then @@ -222,16 +222,16 @@ pipe_readv(struct file *filp, const struct iovec *_iov, break; } if (do_wakeup) { - wake_up_interruptible_sync(PIPE_WAIT(*inode)); - kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); + wake_up_interruptible_sync(&inode->i_pipe->wait); + kill_fasync(&inode->i_pipe->fasync_writers, SIGIO, POLL_OUT); } pipe_wait(inode->i_pipe); } - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_unlock(&inode->i_mutex); /* Signal writers asynchronously that there is more room. */ if (do_wakeup) { - wake_up_interruptible(PIPE_WAIT(*inode)); - kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); + wake_up_interruptible(&inode->i_pipe->wait); + kill_fasync(&inode->i_pipe->fasync_writers, SIGIO, POLL_OUT); } if (ret > 0) file_accessed(filp); @@ -264,10 +264,10 @@ pipe_writev(struct file *filp, const struct iovec *_iov, do_wakeup = 0; ret = 0; - mutex_lock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); info = inode->i_pipe; - if (!PIPE_READERS(*inode)) { + if (!inode->i_pipe->readers) { send_sig(SIGPIPE, current, 0); ret = -EPIPE; goto out; @@ -306,7 +306,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov, for (;;) { int bufs; - if (!PIPE_READERS(*inode)) { + if (!inode->i_pipe->readers) { send_sig(SIGPIPE, current, 0); if (!ret) ret = -EPIPE; break; @@ -367,19 +367,19 @@ pipe_writev(struct file *filp, const struct iovec *_iov, break; } if (do_wakeup) { - wake_up_interruptible_sync(PIPE_WAIT(*inode)); - kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); + wake_up_interruptible_sync(&inode->i_pipe->wait); + kill_fasync(&inode->i_pipe->fasync_readers, SIGIO, POLL_IN); do_wakeup = 0; } - PIPE_WAITING_WRITERS(*inode)++; + inode->i_pipe->waiting_writers++; pipe_wait(inode->i_pipe); - PIPE_WAITING_WRITERS(*inode)--; + inode->i_pipe->waiting_writers--; } out: - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_unlock(&inode->i_mutex); if (do_wakeup) { - wake_up_interruptible(PIPE_WAIT(*inode)); - kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); + wake_up_interruptible(&inode->i_pipe->wait); + kill_fasync(&inode->i_pipe->fasync_readers, SIGIO, POLL_IN); } if (ret > 0) file_update_time(filp); @@ -416,7 +416,7 @@ pipe_ioctl(struct inode *pino, struct file *filp, switch (cmd) { case FIONREAD: - mutex_lock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); info = inode->i_pipe; count = 0; buf = info->curbuf; @@ -425,7 +425,7 @@ pipe_ioctl(struct inode *pino, struct file *filp, count += info->bufs[buf].len; buf = (buf+1) & (PIPE_BUFFERS-1); } - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_unlock(&inode->i_mutex); return put_user(count, (int __user *)arg); default: return -EINVAL; @@ -441,14 +441,14 @@ pipe_poll(struct file *filp, poll_table *wait) struct pipe_inode_info *info = inode->i_pipe; int nrbufs; - poll_wait(filp, PIPE_WAIT(*inode), wait); + poll_wait(filp, &inode->i_pipe->wait, wait); /* Reading only -- no need for acquiring the semaphore. */ nrbufs = info->nrbufs; mask = 0; if (filp->f_mode & FMODE_READ) { mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0; - if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode)) + if (!inode->i_pipe->writers && filp->f_version != inode->i_pipe->w_counter) mask |= POLLHUP; } @@ -458,7 +458,7 @@ pipe_poll(struct file *filp, poll_table *wait) * Most Unices do not set POLLERR for FIFOs but on Linux they * behave exactly like pipes for poll(). */ - if (!PIPE_READERS(*inode)) + if (!inode->i_pipe->readers) mask |= POLLERR; } @@ -468,17 +468,17 @@ pipe_poll(struct file *filp, poll_table *wait) static int pipe_release(struct inode *inode, int decr, int decw) { - mutex_lock(PIPE_MUTEX(*inode)); - PIPE_READERS(*inode) -= decr; - PIPE_WRITERS(*inode) -= decw; - if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) { + mutex_lock(&inode->i_mutex); + inode->i_pipe->readers -= decr; + inode->i_pipe->writers -= decw; + if (!inode->i_pipe->readers && !inode->i_pipe->writers) { free_pipe_info(inode); } else { - wake_up_interruptible(PIPE_WAIT(*inode)); - kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); - kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); + wake_up_interruptible(&inode->i_pipe->wait); + kill_fasync(&inode->i_pipe->fasync_readers, SIGIO, POLL_IN); + kill_fasync(&inode->i_pipe->fasync_writers, SIGIO, POLL_OUT); } - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_unlock(&inode->i_mutex); return 0; } @@ -489,9 +489,9 @@ pipe_read_fasync(int fd, struct file *filp, int on) struct inode *inode = filp->f_dentry->d_inode; int retval; - mutex_lock(PIPE_MUTEX(*inode)); - retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode)); - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); + retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers); + mutex_unlock(&inode->i_mutex); if (retval < 0) return retval; @@ -506,9 +506,9 @@ pipe_write_fasync(int fd, struct file *filp, int on) struct inode *inode = filp->f_dentry->d_inode; int retval; - mutex_lock(PIPE_MUTEX(*inode)); - retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode)); - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); + retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers); + mutex_unlock(&inode->i_mutex); if (retval < 0) return retval; @@ -523,14 +523,14 @@ pipe_rdwr_fasync(int fd, struct file *filp, int on) struct inode *inode = filp->f_dentry->d_inode; int retval; - mutex_lock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); - retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode)); + retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_readers); if (retval >= 0) - retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode)); + retval = fasync_helper(fd, filp, on, &inode->i_pipe->fasync_writers); - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_unlock(&inode->i_mutex); if (retval < 0) return retval; @@ -569,9 +569,9 @@ pipe_read_open(struct inode *inode, struct file *filp) { /* We could have perhaps used atomic_t, but this and friends below are the only places. So it doesn't seem worthwhile. */ - mutex_lock(PIPE_MUTEX(*inode)); - PIPE_READERS(*inode)++; - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); + inode->i_pipe->readers++; + mutex_unlock(&inode->i_mutex); return 0; } @@ -579,9 +579,9 @@ pipe_read_open(struct inode *inode, struct file *filp) static int pipe_write_open(struct inode *inode, struct file *filp) { - mutex_lock(PIPE_MUTEX(*inode)); - PIPE_WRITERS(*inode)++; - mutex_unlock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); + inode->i_pipe->writers++; + mutex_unlock(&inode->i_mutex); return 0; } @@ -589,12 +589,12 @@ pipe_write_open(struct inode *inode, struct file *filp) static int pipe_rdwr_open(struct inode *inode, struct file *filp) { - mutex_lock(PIPE_MUTEX(*inode)); + mutex_lock(&inode->i_mutex); if (filp->f_mode & FMODE_READ) - PIPE_READERS(*inode)++; + inode->i_pipe->readers++; if (filp->f_mode & FMODE_WRITE) - PIPE_WRITERS(*inode)++; - mutex_unlock(PIPE_MUTEX(*inode)); + inode->i_pipe->writers++; + mutex_unlock(&inode->i_mutex); return 0; } @@ -731,7 +731,7 @@ static struct inode * get_pipe_inode(void) if (!inode->i_pipe) goto fail_iput; - PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; + inode->i_pipe->readers = inode->i_pipe->writers = 1; inode->i_fop = &rdwr_pipe_fops; /* diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 660e9d866e5d..123a7c24bc72 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -43,16 +43,6 @@ struct pipe_inode_info { memory allocation, whereas PIPE_BUF makes atomicity guarantees. */ #define PIPE_SIZE PAGE_SIZE -#define PIPE_MUTEX(inode) (&(inode).i_mutex) -#define PIPE_WAIT(inode) (&(inode).i_pipe->wait) -#define PIPE_READERS(inode) ((inode).i_pipe->readers) -#define PIPE_WRITERS(inode) ((inode).i_pipe->writers) -#define PIPE_WAITING_WRITERS(inode) ((inode).i_pipe->waiting_writers) -#define PIPE_RCOUNTER(inode) ((inode).i_pipe->r_counter) -#define PIPE_WCOUNTER(inode) ((inode).i_pipe->w_counter) -#define PIPE_FASYNC_READERS(inode) (&((inode).i_pipe->fasync_readers)) -#define PIPE_FASYNC_WRITERS(inode) (&((inode).i_pipe->fasync_writers)) - /* Drop the inode semaphore and wait for a pipe event, atomically */ void pipe_wait(struct pipe_inode_info *pipe); -- cgit v1.2.3 From 88e6faefaeed40a162041d85689e94595756d4c3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 11 Apr 2006 13:59:36 +0200 Subject: [PATCH] splice: warning fix From: Andrew Morton net/socket.c:148: warning: initialization from incompatible pointer type extern declarations in .c files! Bad boy. Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- include/linux/fs.h | 13 ++++++++++--- net/socket.c | 4 ---- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/include/linux/fs.h b/include/linux/fs.h index 9e8e2ee353b4..2a629fd88ef0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1611,10 +1611,17 @@ extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor extern void do_generic_mapping_read(struct address_space *mapping, struct file_ra_state *, struct file *, loff_t *, read_descriptor_t *, read_actor_t); -extern ssize_t generic_file_splice_read(struct file *, struct pipe_inode_info *, size_t, unsigned int); -extern ssize_t generic_file_splice_write(struct pipe_inode_info *, struct file *, size_t, unsigned int); + +/* fs/splice.c */ +extern ssize_t generic_file_splice_read(struct file *, + struct pipe_inode_info *, size_t, unsigned int); +extern ssize_t generic_file_splice_write(struct pipe_inode_info *, + struct file *, size_t, unsigned int); +extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, + struct file *out, size_t len, unsigned int flags); extern long do_splice_direct(struct file *in, struct file *out, - size_t len, unsigned int flags); + size_t len, unsigned int flags); + extern void file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, diff --git a/net/socket.c b/net/socket.c index b807f360e02c..9ed9f6521155 100644 --- a/net/socket.c +++ b/net/socket.c @@ -119,10 +119,6 @@ static ssize_t sock_writev(struct file *file, const struct iovec *vector, static ssize_t sock_sendpage(struct file *file, struct page *page, int offset, size_t size, loff_t *ppos, int more); -extern ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, - size_t len, unsigned int flags); - - /* * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear * in the operation structures but are done directly via the socketcall() multiplexor. -- cgit v1.2.3 From 6f91fe88e4e28b40b4f08d99e0ea6d17b70e9567 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 10 Apr 2006 22:52:48 -0700 Subject: [PATCH] md: make sure 64bit fields in version-1 metadata are 64-bit aligned reshape_position is a 64bit field that was not 64bit aligned. So swap with new_level. NOTE: this is a user-visible change. However: - The bad code has not appeared in a released kernel - This code is still marked 'experimental' - This only affects version-1 superblock, which are not in wide use - These field are only used (rather than simply reported) by user-space tools in extemely rare circumstances : after a reshape crashes in the first second of the reshape process. So I believe that, at this stage, the change is safe. Especially if people heed the 'help' message on use mdadm-2.4.1. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/Kconfig | 11 ++++++----- include/linux/raid/md_p.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index fd2aae150ccc..ac25a48362ac 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -139,11 +139,12 @@ config MD_RAID5_RESHAPE is online. However it is still EXPERIMENTAL code. It should work, but please be sure that you have backups. - You will need a version of mdadm newer than 2.3.1. During the - early stage of reshape there is a critical section where live data - is being over-written. A crash during this time needs extra care - for recovery. The newer mdadm takes a copy of the data in the - critical section and will restore it, if necessary, after a crash. + You will need mdadm verion 2.4.1 or later to use this + feature safely. During the early stage of reshape there is + a critical section where live data is being over-written. A + crash during this time needs extra care for recovery. The + newer mdadm takes a copy of the data in the critical section + and will restore it, if necessary, after a crash. The mdadm usage is e.g. mdadm --grow /dev/md1 --raid-disks=6 diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h index 774e1acfb8c4..f1fbae7e390e 100644 --- a/include/linux/raid/md_p.h +++ b/include/linux/raid/md_p.h @@ -227,8 +227,8 @@ struct mdp_superblock_1 { */ /* These are only valid with feature bit '4' */ - __u64 reshape_position; /* next address in array-space for reshape */ __u32 new_level; /* new level we are reshaping to */ + __u64 reshape_position; /* next address in array-space for reshape */ __u32 delta_disks; /* change in number of raid_disks */ __u32 new_layout; /* new layout */ __u32 new_chunk; /* new chunk size (bytes) */ -- cgit v1.2.3 From cb45b0e966cbe747b6189c15b108901cc7d6c97c Mon Sep 17 00:00:00 2001 From: Hideo AOKI Date: Mon, 10 Apr 2006 22:52:59 -0700 Subject: [PATCH] overcommit: add calculate_totalreserve_pages() These patches are an enhancement of OVERCOMMIT_GUESS algorithm in __vm_enough_memory(). - why the kernel needed patching When the kernel can't allocate anonymous pages in practice, currnet OVERCOMMIT_GUESS could return success. This implementation might be the cause of oom kill in memory pressure situation. If the Linux runs with page reservation features like /proc/sys/vm/lowmem_reserve_ratio and without swap region, I think the oom kill occurs easily. - the overall design approach in the patch When the OVERCOMMET_GUESS algorithm calculates number of free pages, the reserved free pages are regarded as non-free pages. This change helps to avoid the pitfall that the number of free pages become less than the number which the kernel tries to keep free. - testing results I tested the patches using my test kernel module. If the patches aren't applied to the kernel, __vm_enough_memory() returns success in the situation but autual page allocation is failed. On the other hand, if the patches are applied to the kernel, memory allocation failure is avoided since __vm_enough_memory() returns failure in the situation. I checked that on i386 SMP 16GB memory machine. I haven't tested on nommu environment currently. This patch adds totalreserve_pages for __vm_enough_memory(). Calculate_totalreserve_pages() checks maximum lowmem_reserve pages and pages_high in each zone. Finally, the function stores the sum of each zone to totalreserve_pages. The totalreserve_pages is calculated when the VM is initilized. And the variable is updated when /proc/sys/vm/lowmem_reserve_raito or /proc/sys/vm/min_free_kbytes are changed. Signed-off-by: Hideo Aoki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/swap.h | 1 + mm/page_alloc.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) (limited to 'include/linux') diff --git a/include/linux/swap.h b/include/linux/swap.h index 54eac8a39a4c..5b1fdf1cff4f 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -155,6 +155,7 @@ extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct * /* linux/mm/page_alloc.c */ extern unsigned long totalram_pages; extern unsigned long totalhigh_pages; +extern unsigned long totalreserve_pages; extern long nr_swap_pages; extern unsigned int nr_free_pages(void); extern unsigned int nr_free_pages_pgdat(pg_data_t *pgdat); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b8165e037dee..97d6827c7d66 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -51,6 +51,7 @@ nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL; EXPORT_SYMBOL(node_possible_map); unsigned long totalram_pages __read_mostly; unsigned long totalhigh_pages __read_mostly; +unsigned long totalreserve_pages __read_mostly; long nr_swap_pages; int percpu_pagelist_fraction; @@ -2476,6 +2477,38 @@ void __init page_alloc_init(void) hotcpu_notifier(page_alloc_cpu_notify, 0); } +/* + * calculate_totalreserve_pages - called when sysctl_lower_zone_reserve_ratio + * or min_free_kbytes changes. + */ +static void calculate_totalreserve_pages(void) +{ + struct pglist_data *pgdat; + unsigned long reserve_pages = 0; + int i, j; + + for_each_online_pgdat(pgdat) { + for (i = 0; i < MAX_NR_ZONES; i++) { + struct zone *zone = pgdat->node_zones + i; + unsigned long max = 0; + + /* Find valid and maximum lowmem_reserve in the zone */ + for (j = i; j < MAX_NR_ZONES; j++) { + if (zone->lowmem_reserve[j] > max) + max = zone->lowmem_reserve[j]; + } + + /* we treat pages_high as reserved pages. */ + max += zone->pages_high; + + if (max > zone->present_pages) + max = zone->present_pages; + reserve_pages += max; + } + } + totalreserve_pages = reserve_pages; +} + /* * setup_per_zone_lowmem_reserve - called whenever * sysctl_lower_zone_reserve_ratio changes. Ensures that each zone @@ -2507,6 +2540,9 @@ static void setup_per_zone_lowmem_reserve(void) } } } + + /* update totalreserve_pages */ + calculate_totalreserve_pages(); } /* @@ -2561,6 +2597,9 @@ void setup_per_zone_pages_min(void) zone->pages_high = zone->pages_min + tmp / 2; spin_unlock_irqrestore(&zone->lru_lock, flags); } + + /* update totalreserve_pages */ + calculate_totalreserve_pages(); } /* -- cgit v1.2.3 From 91fc8ab3c6312931d64c72845ee2f93a0f87f1a5 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Mon, 10 Apr 2006 22:53:01 -0700 Subject: [PATCH] page flags: add commentry regarding field reservation Add some documentation regarding the utilisation of the flags field in struct page. This field is overloaded for per page bits and to hold node, zone and SPARSEMEM information. Make it clear which areas are used for what and how many bits are in each area. Signed-off-by: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/page-flags.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 547aac7696cd..d276a4e2f825 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -48,8 +48,20 @@ /* * Don't use the *_dontuse flags. Use the macros. Otherwise you'll break - * locked- and dirty-page accounting. The top eight bits of page->flags are - * used for page->zone, so putting flag bits there doesn't work. + * locked- and dirty-page accounting. + * + * The page flags field is split into two parts, the main flags area + * which extends from the low bits upwards, and the fields area which + * extends from the high bits downwards. + * + * | FIELD | ... | FLAGS | + * N-1 ^ 0 + * (N-FLAGS_RESERVED) + * + * The fields area is reserved for fields mapping zone, node and SPARSEMEM + * section. The boundry between these two areas is defined by + * FLAGS_RESERVED which defines the width of the fields section + * (see linux/mmzone.h). New flags must _not_ overlap with this area. */ #define PG_locked 0 /* Page is locked. Don't touch. */ #define PG_error 1 -- cgit v1.2.3 From 7b04d7170e9af805cac19f97b28fff10db897893 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 10 Apr 2006 22:53:27 -0700 Subject: [PATCH] Add GFP_NOWAIT Introduce GFP_NOWAIT, as an alias for GFP_ATOMIC & ~__GFP_HIGH. This also changes XFS, which is the only in-tree user of this idiom that I could find. The XFS piece is compile-tested only. Signed-off-by: Jeff Dike Acked-by: Nathan Scott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/xfs/linux-2.6/xfs_buf.c | 2 +- include/linux/gfp.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 9fb0312665ca..26fed0756f01 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -182,7 +182,7 @@ free_address( { a_list_t *aentry; - aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC & ~__GFP_HIGH); + aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT); if (likely(aentry)) { spin_lock(&as_lock); aentry->next = as_free_head; diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 7851e6b520cf..3ac452945a7d 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -57,6 +57,8 @@ struct vm_area_struct; __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \ __GFP_NOMEMALLOC|__GFP_HARDWALL) +/* This equals 0, but use constants in case they ever change */ +#define GFP_NOWAIT (GFP_ATOMIC & ~__GFP_HIGH) /* GFP_ATOMIC means both !wait (__GFP_WAIT not set) and use emergency pool */ #define GFP_ATOMIC (__GFP_HIGH) #define GFP_NOIO (__GFP_WAIT) -- cgit v1.2.3 From c80d79d746cc48bd94b0ce4f6d4f3c90cd403aaf Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Mon, 10 Apr 2006 22:53:53 -0700 Subject: [PATCH] Configurable NODES_SHIFT Current implementations define NODES_SHIFT in include/asm-xxx/numnodes.h for each arch. Its definition is sometimes configurable. Indeed, ia64 defines 5 NODES_SHIFT values in the current git tree. But it looks a bit messy. SGI-SN2(ia64) system requires 1024 nodes, and the number of nodes already has been changeable by config. Suitable node's number may be changed in the future even if it is other architecture. So, I wrote configurable node's number. This patch set defines just default value for each arch which needs multi nodes except ia64. But, it is easy to change to configurable if necessary. On ia64 the number of nodes can be already configured in generic ia64 and SN2 config. But, NODES_SHIFT is defined for DIG64 and HP'S machine too. So, I changed it so that all platforms can be configured via CONFIG_NODES_SHIFT. It would be simpler. See also: http://marc.theaimsgroup.com/?l=linux-kernel&m=114358010523896&w=2 Signed-off-by: Yasunori Goto Cc: Hirokazu Takata Cc: "Luck, Tony" Cc: Andi Kleen Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Ivan Kokshaysky Cc: Richard Henderson Cc: Kyle McMartin Cc: Russell King Cc: Ralf Baechle Cc: Jack Steiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/Kconfig | 5 +++++ arch/arm/Kconfig | 6 ++++++ arch/i386/Kconfig | 6 ++++++ arch/ia64/Kconfig | 19 ++++++++++--------- arch/m32r/Kconfig | 5 +++++ arch/mips/Kconfig | 5 +++++ arch/parisc/Kconfig | 5 +++++ arch/powerpc/Kconfig | 5 +++++ arch/sh/Kconfig | 5 +++++ arch/x86_64/Kconfig | 5 +++++ include/asm-alpha/numnodes.h | 7 ------- include/asm-arm/arch-lh7a40x/memory.h | 2 -- include/asm-arm/numnodes.h | 26 -------------------------- include/asm-i386/numnodes.h | 18 ------------------ include/asm-ia64/numnodes.h | 20 -------------------- include/asm-m32r/numnodes.h | 15 --------------- include/asm-mips/numnodes.h | 7 ------- include/asm-parisc/numnodes.h | 7 ------- include/asm-powerpc/numnodes.h | 9 --------- include/asm-sh/numnodes.h | 7 ------- include/asm-x86_64/numa.h | 1 - include/asm-x86_64/numnodes.h | 10 ---------- include/linux/numa.h | 8 +++----- 23 files changed, 60 insertions(+), 143 deletions(-) delete mode 100644 include/asm-alpha/numnodes.h delete mode 100644 include/asm-arm/numnodes.h delete mode 100644 include/asm-i386/numnodes.h delete mode 100644 include/asm-ia64/numnodes.h delete mode 100644 include/asm-m32r/numnodes.h delete mode 100644 include/asm-mips/numnodes.h delete mode 100644 include/asm-parisc/numnodes.h delete mode 100644 include/asm-powerpc/numnodes.h delete mode 100644 include/asm-sh/numnodes.h delete mode 100644 include/asm-x86_64/numnodes.h (limited to 'include/linux') diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 9bef61b30367..8290b69da202 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -549,6 +549,11 @@ config NUMA Access). This option is for configuring high-end multiprocessor server machines. If in doubt, say N. +config NODES_SHIFT + int + default "7" + depends on NEED_MULTIPLE_NODES + # LARGE_VMALLOC is racy, if you *really* need it then fix it first config ALPHA_LARGE_VMALLOC bool diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index dc5a9332c915..1dbf6ddb300d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -512,6 +512,12 @@ config ARCH_DISCONTIGMEM_ENABLE or have huge holes in the physical address space for other reasons. See for more. +config NODES_SHIFT + int + default "4" if ARCH_LH7A40X + default "2" + depends on NEED_MULTIPLE_NODES + source "mm/Kconfig" config LEDS diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 57301db056f5..18ec9fe6deb6 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -522,6 +522,12 @@ config NUMA comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI" depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI) +config NODES_SHIFT + int + default "4" if X86_NUMAQ + default "3" + depends on NEED_MULTIPLE_NODES + config HAVE_ARCH_BOOTMEM_NODE bool depends on NUMA diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index edffe25a477a..9f40eeff0b5c 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -260,15 +260,6 @@ config NR_CPUS than 64 will cause the use of a CPU mask array, causing a small performance hit. -config IA64_NR_NODES - int "Maximum number of NODEs (256-1024)" if (IA64_SGI_SN2 || IA64_GENERIC) - range 256 1024 - depends on IA64_SGI_SN2 || IA64_GENERIC - default "256" - help - This option specifies the maximum number of nodes in your SSI system. - If in doubt, use the default. - config HOTPLUG_CPU bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" depends on SMP && EXPERIMENTAL @@ -352,6 +343,16 @@ config NUMA Access). This option is for configuring high-end multiprocessor server systems. If in doubt, say N. +config NODES_SHIFT + int "Max num nodes shift(3-10)" + range 3 10 + default "8" + depends on NEED_MULTIPLE_NODES + help + This option specifies the maximum number of nodes in your SSI system. + MAX_NUMNODES will be 2^(This value). + If in doubt, use the default. + # VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent. # VIRTUAL_MEM_MAP has been retained for historical reasons. config VIRTUAL_MEM_MAP diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index 05c864c6c2d9..41fd490af3b4 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -285,6 +285,11 @@ config NUMA depends on SMP && BROKEN default n +config NODES_SHIFT + int + default "1" + depends on NEED_MULTIPLE_NODES + # turning this on wastes a bunch of space. # Summit needs it only when NUMA is on config BOOT_IOREMAP diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e15709ce8866..7aec60d40420 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1590,6 +1590,11 @@ config ARCH_FLATMEM_ENABLE def_bool y depends on !NUMA +config NODES_SHIFT + int + default "6" + depends on NEED_MULTIPLE_NODES + source "mm/Kconfig" config SMP diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 2fdf21989dc2..19f911c5dd58 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -177,6 +177,11 @@ config ARCH_DISCONTIGMEM_DEFAULT def_bool y depends on ARCH_DISCONTIGMEM_ENABLE +config NODES_SHIFT + int + default "3" + depends on NEED_MULTIPLE_NODES + source "kernel/Kconfig.preempt" source "kernel/Kconfig.hz" source "mm/Kconfig" diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 2cdc35ce8045..167e70e95556 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -649,6 +649,11 @@ config NUMA depends on PPC64 default y if SMP && PPC_PSERIES +config NODES_SHIFT + int + default "4" + depends on NEED_MULTIPLE_NODES + config ARCH_SELECT_MEMORY_MODEL def_bool y depends on PPC64 diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 58583f459471..2bcecf422573 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -527,6 +527,11 @@ config CPU_HAS_SR_RB See for further information on SR.RB and register banking in the kernel in general. +config NODES_SHIFT + int + default "1" + depends on NEED_MULTIPLE_NODES + endmenu menu "Boot options" diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 7df2fe1844be..408d44a59756 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -288,6 +288,11 @@ config K8_NUMA Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA instead, which also takes priority if both are compiled in. +config NODES_SHIFT + int + default "6" + depends on NEED_MULTIPLE_NODES + # Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig. config X86_64_ACPI_NUMA diff --git a/include/asm-alpha/numnodes.h b/include/asm-alpha/numnodes.h deleted file mode 100644 index cd425827e4f3..000000000000 --- a/include/asm-alpha/numnodes.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_MAX_NUMNODES_H -#define _ASM_MAX_NUMNODES_H - -/* Max 128 Nodes - Marvel */ -#define NODES_SHIFT 7 - -#endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h index c92bcb837629..9f1a58cbf407 100644 --- a/include/asm-arm/arch-lh7a40x/memory.h +++ b/include/asm-arm/arch-lh7a40x/memory.h @@ -31,8 +31,6 @@ #ifdef CONFIG_DISCONTIGMEM -#define NODES_SHIFT 4 /* Up to 16 nodes */ - /* * Given a kernel address, find the home node of the underlying memory. */ diff --git a/include/asm-arm/numnodes.h b/include/asm-arm/numnodes.h deleted file mode 100644 index 8df36818ebc9..000000000000 --- a/include/asm-arm/numnodes.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * linux/include/asm-arm/numnodes.h - * - * Copyright (C) 2002 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* This declaration for the size of the NUMA (CONFIG_DISCONTIGMEM) - * memory node table is the default. - * - * A good place to override this value is include/asm/arch/memory.h. - */ - -#ifndef __ASM_ARM_NUMNODES_H -#define __ASM_ARM_NUMNODES_H - -#include - -#ifndef NODES_SHIFT -# define NODES_SHIFT 2 /* Normally, Max 4 Nodes */ -#endif - -#endif diff --git a/include/asm-i386/numnodes.h b/include/asm-i386/numnodes.h deleted file mode 100644 index a61f38c8176f..000000000000 --- a/include/asm-i386/numnodes.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _ASM_MAX_NUMNODES_H -#define _ASM_MAX_NUMNODES_H - -#include - -#ifdef CONFIG_X86_NUMAQ - -/* Max 16 Nodes */ -#define NODES_SHIFT 4 - -#elif defined(CONFIG_ACPI_SRAT) - -/* Max 8 Nodes */ -#define NODES_SHIFT 3 - -#endif /* CONFIG_X86_NUMAQ */ - -#endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-ia64/numnodes.h b/include/asm-ia64/numnodes.h deleted file mode 100644 index e9d356f549d9..000000000000 --- a/include/asm-ia64/numnodes.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _ASM_MAX_NUMNODES_H -#define _ASM_MAX_NUMNODES_H - -#ifdef CONFIG_IA64_DIG -/* Max 8 Nodes */ -# define NODES_SHIFT 3 -#elif defined(CONFIG_IA64_HP_ZX1) || defined(CONFIG_IA64_HP_ZX1_SWIOTLB) -/* Max 32 Nodes */ -# define NODES_SHIFT 5 -#elif defined(CONFIG_IA64_SGI_SN2) || defined(CONFIG_IA64_GENERIC) -# if CONFIG_IA64_NR_NODES == 256 -# define NODES_SHIFT 8 -# elif CONFIG_IA64_NR_NODES <= 512 -# define NODES_SHIFT 9 -# elif CONFIG_IA64_NR_NODES <= 1024 -# define NODES_SHIFT 10 -# endif -#endif - -#endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-m32r/numnodes.h b/include/asm-m32r/numnodes.h deleted file mode 100644 index 479a39d49f83..000000000000 --- a/include/asm-m32r/numnodes.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _ASM_NUMNODES_H_ -#define _ASM_NUMNODES_H_ - -#include - -#ifdef CONFIG_DISCONTIGMEM - -#if defined(CONFIG_CHIP_M32700) -#define NODES_SHIFT 1 /* Max 2 Nodes */ -#endif /* CONFIG_CHIP_M32700 */ - -#endif /* CONFIG_DISCONTIGMEM */ - -#endif /* _ASM_NUMNODES_H_ */ - diff --git a/include/asm-mips/numnodes.h b/include/asm-mips/numnodes.h deleted file mode 100644 index 4f00c16ceeb0..000000000000 --- a/include/asm-mips/numnodes.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_MAX_NUMNODES_H -#define _ASM_MAX_NUMNODES_H - -/* Max 128 Nodes */ -#define NODES_SHIFT 6 - -#endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-parisc/numnodes.h b/include/asm-parisc/numnodes.h deleted file mode 100644 index 6c67651efd1c..000000000000 --- a/include/asm-parisc/numnodes.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_MAX_NUMNODES_H -#define _ASM_MAX_NUMNODES_H - -/* Max 8 Nodes */ -#define NODES_SHIFT 3 - -#endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-powerpc/numnodes.h b/include/asm-powerpc/numnodes.h deleted file mode 100644 index e138edae09dd..000000000000 --- a/include/asm-powerpc/numnodes.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _ASM_POWERPC_MAX_NUMNODES_H -#define _ASM_POWERPC_MAX_NUMNODES_H -#ifdef __KERNEL__ - -/* Max 16 Nodes */ -#define NODES_SHIFT 4 - -#endif /* __KERNEL__ */ -#endif /* _ASM_POWERPC_MAX_NUMNODES_H */ diff --git a/include/asm-sh/numnodes.h b/include/asm-sh/numnodes.h deleted file mode 100644 index f73e85b72ecb..000000000000 --- a/include/asm-sh/numnodes.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_MAX_NUMNODES_H -#define _ASM_MAX_NUMNODES_H - -/* Max 2 Nodes */ -#define NODES_SHIFT 1 - -#endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h index f0ba4d984bdf..1cc92fe02503 100644 --- a/include/asm-x86_64/numa.h +++ b/include/asm-x86_64/numa.h @@ -2,7 +2,6 @@ #define _ASM_X8664_NUMA_H 1 #include -#include struct bootnode { u64 start,end; diff --git a/include/asm-x86_64/numnodes.h b/include/asm-x86_64/numnodes.h deleted file mode 100644 index 5a1d506b8299..000000000000 --- a/include/asm-x86_64/numnodes.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _ASM_X8664_NUMNODES_H -#define _ASM_X8664_NUMNODES_H 1 - -#include - -#ifdef CONFIG_NUMA -#define NODES_SHIFT 6 -#endif - -#endif diff --git a/include/linux/numa.h b/include/linux/numa.h index f0c539bd3cfc..e481feb1bfd8 100644 --- a/include/linux/numa.h +++ b/include/linux/numa.h @@ -3,11 +3,9 @@ #include -#ifndef CONFIG_FLATMEM -#include -#endif - -#ifndef NODES_SHIFT +#ifdef CONFIG_NODES_SHIFT +#define NODES_SHIFT CONFIG_NODES_SHIFT +#else #define NODES_SHIFT 0 #endif -- cgit v1.2.3 From 8833d328caf009f8da58337e17a2cf5d52993a7c Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 10 Apr 2006 22:53:57 -0700 Subject: [PATCH] Clean up arch-overrides in linux/string.h Some string functions were safely overrideable in lib/string.c, but their corresponding declarations in linux/string.h were not. Correct this, and make strcspn overrideable. Odds of someone wanting to do optimized assembly of these are small, but for the sake of cleanliness, might as well bring them into line with the rest of the file. Signed-off-by: Kyle McMartin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/string.h | 17 ++++++++++++----- lib/string.c | 2 ++ 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/string.h b/include/linux/string.h index dee221429ad0..c61306da8c52 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -13,11 +13,6 @@ extern "C" { #endif -extern char * strpbrk(const char *,const char *); -extern char * strsep(char **,const char *); -extern __kernel_size_t strspn(const char *,const char *); -extern __kernel_size_t strcspn(const char *,const char *); - extern char *strndup_user(const char __user *, long); /* @@ -70,6 +65,18 @@ extern __kernel_size_t strlen(const char *); #ifndef __HAVE_ARCH_STRNLEN extern __kernel_size_t strnlen(const char *,__kernel_size_t); #endif +#ifndef __HAVE_ARCH_STRPBRK +extern char * strpbrk(const char *,const char *); +#endif +#ifndef __HAVE_ARCH_STRSEP +extern char * strsep(char **,const char *); +#endif +#ifndef __HAVE_ARCH_STRSPN +extern __kernel_size_t strspn(const char *,const char *); +#endif +#ifndef __HAVE_ARCH_STRCSPN +extern __kernel_size_t strcspn(const char *,const char *); +#endif #ifndef __HAVE_ARCH_MEMSET extern void * memset(void *,int,__kernel_size_t); diff --git a/lib/string.c b/lib/string.c index 037a48acedbb..7be6f0a87e83 100644 --- a/lib/string.c +++ b/lib/string.c @@ -362,6 +362,7 @@ size_t strspn(const char *s, const char *accept) EXPORT_SYMBOL(strspn); #endif +#ifndef __HAVE_ARCH_STRCSPN /** * strcspn - Calculate the length of the initial substring of @s which does * not contain letters in @reject @@ -384,6 +385,7 @@ size_t strcspn(const char *s, const char *reject) return count; } EXPORT_SYMBOL(strcspn); +#endif #ifndef __HAVE_ARCH_STRPBRK /** -- cgit v1.2.3 From 5246d0503130fa58904c8beb987fcf93b96d8ab6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 10 Apr 2006 22:53:57 -0700 Subject: [PATCH] sync_file_range(): use unsigned for flags Ulrich suggested that the `flags' arg to sync_file_range() become unsigned. Cc: Ulrich Drepper Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/sync.c | 4 ++-- include/linux/fs.h | 2 +- include/linux/syscalls.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/fs/sync.c b/fs/sync.c index 8616006d2094..aab5ffe77e9f 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -61,7 +61,7 @@ * will be available after a crash. */ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, - int flags) + unsigned int flags) { int ret; struct file *file; @@ -126,7 +126,7 @@ out: * `endbyte' is inclusive */ int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte, - int flags) + unsigned int flags) { int ret; struct address_space *mapping; diff --git a/include/linux/fs.h b/include/linux/fs.h index 1e9ebaba07b7..504dcf5b297b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -762,7 +762,7 @@ extern int fcntl_getlease(struct file *filp); #define SYNC_FILE_RANGE_WRITE 2 #define SYNC_FILE_RANGE_WAIT_AFTER 4 extern int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte, - int flags); + unsigned int flags); /* fs/locks.c */ extern void locks_init_lock(struct file_lock *); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 5717147596b6..89c4180d42f5 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -572,6 +572,6 @@ asmlinkage long sys_unshare(unsigned long unshare_flags); asmlinkage long sys_splice(int fdin, int fdout, size_t len, unsigned int flags); asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, - int flags); + unsigned int flags); #endif -- cgit v1.2.3 From aa7271076ae6547d7f370ad7e91ef86fdb318f17 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 10 Apr 2006 22:53:59 -0700 Subject: [PATCH] the scheduled unexport of panic_timeout Implement the scheduled unexport of panic_timeout. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 8 -------- include/linux/kernel.h | 2 +- kernel/panic.c | 1 - 3 files changed, 1 insertion(+), 10 deletions(-) (limited to 'include/linux') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 59d0c74c79c9..293fed113dff 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -71,14 +71,6 @@ Who: Mauro Carvalho Chehab --------------------------- -What: remove EXPORT_SYMBOL(panic_timeout) -When: April 2006 -Files: kernel/panic.c -Why: No modular usage in the kernel. -Who: Adrian Bunk - ---------------------------- - What: remove EXPORT_SYMBOL(insert_resource) When: April 2006 Files: kernel/resource.c diff --git a/include/linux/kernel.h b/include/linux/kernel.h index a3720f973ea5..e1bd0842f6a1 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -176,7 +176,7 @@ static inline void console_verbose(void) extern void bust_spinlocks(int yes); extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */ -extern __deprecated_for_modules int panic_timeout; +extern int panic_timeout; extern int panic_on_oops; extern int tainted; extern const char *print_tainted(void); diff --git a/kernel/panic.c b/kernel/panic.c index f895c7c01d5b..cc2a4c9c36ac 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -27,7 +27,6 @@ static int pause_on_oops_flag; static DEFINE_SPINLOCK(pause_on_oops_lock); int panic_timeout; -EXPORT_SYMBOL(panic_timeout); ATOMIC_NOTIFIER_HEAD(panic_notifier_list); -- cgit v1.2.3 From fb5035dbbea8826cdbeb5c43d7605255eb6f0baa Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Apr 2006 22:54:02 -0700 Subject: [PATCH] leds: re-layout include/linux/leds.h Lay out the structure definitions in include/linux/leds.h to be aligned as much as possible. Also minor updates to the comments to make them more concise. Signed-off-by: Ben Dooks Acked-by: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/leds.h | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/include/linux/leds.h b/include/linux/leds.h index 4617e75903b0..dc23c7c639f3 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -19,39 +19,38 @@ struct class_device; */ enum led_brightness { - LED_OFF = 0, - LED_HALF = 127, - LED_FULL = 255, + LED_OFF = 0, + LED_HALF = 127, + LED_FULL = 255, }; struct led_classdev { - const char *name; - int brightness; - int flags; -#define LED_SUSPENDED (1 << 0) + const char *name; + int brightness; + int flags; - /* A function to set the brightness of the led */ - void (*brightness_set)(struct led_classdev *led_cdev, - enum led_brightness brightness); +#define LED_SUSPENDED (1 << 0) - struct class_device *class_dev; - /* LED Device linked list */ - struct list_head node; + /* Set LED brightness level */ + void (*brightness_set)(struct led_classdev *led_cdev, + enum led_brightness brightness); + + struct class_device *class_dev; + struct list_head node; /* LED Device list */ + char *default_trigger; /* Trigger to use */ - /* Trigger data */ - char *default_trigger; #ifdef CONFIG_LEDS_TRIGGERS - rwlock_t trigger_lock; /* Protects the trigger data below */ + rwlock_t trigger_lock; - struct led_trigger *trigger; - struct list_head trig_list; - void *trigger_data; + struct led_trigger *trigger; + struct list_head trig_list; + void *trigger_data; #endif }; extern int led_classdev_register(struct device *parent, - struct led_classdev *led_cdev); + struct led_classdev *led_cdev); extern void led_classdev_unregister(struct led_classdev *led_cdev); extern void led_classdev_suspend(struct led_classdev *led_cdev); extern void led_classdev_resume(struct led_classdev *led_cdev); @@ -65,16 +64,16 @@ extern void led_classdev_resume(struct led_classdev *led_cdev); struct led_trigger { /* Trigger Properties */ - const char *name; - void (*activate)(struct led_classdev *led_cdev); - void (*deactivate)(struct led_classdev *led_cdev); + const char *name; + void (*activate)(struct led_classdev *led_cdev); + void (*deactivate)(struct led_classdev *led_cdev); /* LEDs under control by this trigger (for simple triggers) */ - rwlock_t leddev_list_lock; - struct list_head led_cdevs; + rwlock_t leddev_list_lock; + struct list_head led_cdevs; /* Link to next registered trigger */ - struct list_head next_trig; + struct list_head next_trig; }; /* Registration functions for complex triggers */ -- cgit v1.2.3 From e1a2509023785bd3199ac068ab80155aeba01265 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 10 Apr 2006 22:54:05 -0700 Subject: [PATCH] make tty_insert_flip_string_flags() a non gpl export We changed the wrong symbol. It's tty_insert_flip_string_flags() which is called from the previously-non-GPL'ed now-inlined tty_insert_flip_char(). Fix that up, and uninline tty_schedule_flip() while we're there. Cc: Tobias Powalowski Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 22 ++++++++++++++++------ include/linux/tty_flip.h | 25 ++----------------------- 2 files changed, 18 insertions(+), 29 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 98b126c2ded8..6f58cacec341 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -351,10 +351,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) spin_unlock_irqrestore(&tty->buf.lock, flags); return size; } - EXPORT_SYMBOL_GPL(tty_buffer_request_room); -int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size) +int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, + size_t size) { int copied = 0; do { @@ -368,17 +368,16 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, s tb->used += space; copied += space; chars += space; -/* printk("Flip insert %d.\n", space); */ } /* There is a small chance that we need to split the data over several buffers. If this is the case we must loop */ while (unlikely(size > copied)); return copied; } - EXPORT_SYMBOL(tty_insert_flip_string); -int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) +int tty_insert_flip_string_flags(struct tty_struct *tty, + const unsigned char *chars, const char *flags, size_t size) { int copied = 0; do { @@ -399,9 +398,20 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *ch while (unlikely(size > copied)); return copied; } - EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags); +void tty_schedule_flip(struct tty_struct *tty) +{ + unsigned long flags; + spin_lock_irqsave(&tty->buf.lock, flags); + if (tty->buf.tail != NULL) { + tty->buf.tail->active = 0; + tty->buf.tail->commit = tty->buf.tail->used; + } + spin_unlock_irqrestore(&tty->buf.lock, flags); + schedule_delayed_work(&tty->buf.work, 1); +} +EXPORT_SYMBOL(tty_schedule_flip); /* * Prepare a block of space in the buffer for data. Returns the length diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 0976a163b459..31548303ee37 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -6,9 +6,10 @@ extern int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *c extern int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size); extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size); extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size); +void tty_schedule_flip(struct tty_struct *tty); static inline int tty_insert_flip_char(struct tty_struct *tty, - unsigned char ch, char flag) + unsigned char ch, char flag) { struct tty_buffer *tb = tty->buf.tail; if (tb && tb->active && tb->used < tb->size) { @@ -19,26 +20,4 @@ static inline int tty_insert_flip_char(struct tty_struct *tty, return tty_insert_flip_string_flags(tty, &ch, &flag, 1); } -static inline void tty_schedule_flip(struct tty_struct *tty) -{ - unsigned long flags; - spin_lock_irqsave(&tty->buf.lock, flags); - if (tty->buf.tail != NULL) { - tty->buf.tail->active = 0; - tty->buf.tail->commit = tty->buf.tail->used; - } - spin_unlock_irqrestore(&tty->buf.lock, flags); - schedule_delayed_work(&tty->buf.work, 1); -} - -#undef _INLINE_ - - #endif /* _LINUX_TTY_FLIP_H */ - - - - - - - -- cgit v1.2.3 From a9cdf410ca8f59b52bc7061a6751050010c7cc5b Mon Sep 17 00:00:00 2001 From: Keith Owens Date: Mon, 10 Apr 2006 22:54:07 -0700 Subject: [PATCH] Reinstate const in next_thread() Before commit 47e65328a7b1cdfc4e3102e50d60faf94ebba7d3, next_thread() took a const task_t. Reinstate the const qualifier, getting the next thread never changes the current thread. Signed-off-by: Keith Owens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/sched.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/sched.h b/include/linux/sched.h index a3e4f6b503a3..83d657811d01 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1206,7 +1206,7 @@ extern void wait_task_inactive(task_t * p); /* de_thread depends on thread_group_leader not being a pid based check */ #define thread_group_leader(p) (p == p->group_leader) -static inline task_t *next_thread(task_t *p) +static inline task_t *next_thread(const task_t *p) { return list_entry(rcu_dereference(p->thread_group.next), task_t, thread_group); -- cgit v1.2.3 From 80e8ff634169be3fc2ac48f258cc7638e898cd46 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Mon, 10 Apr 2006 22:54:10 -0700 Subject: [PATCH] kdump proc vmcore size oveflow fix A couple of /proc/vmcore data structures overflow with 32bit systems having memory more than 4G. This patch fixes those. Signed-off-by: Ken'ichi Ohmichi Signed-off-by: Vivek Goyal Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/vmcore.c | 4 ++-- include/linux/proc_fs.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 7efa73d44c9a..20d4b2237fce 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -103,8 +103,8 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos) { ssize_t acc = 0, tmp; - size_t tsz, nr_bytes; - u64 start; + size_t tsz; + u64 start, nr_bytes; struct vmcore *curr_m = NULL; if (buflen == 0 || *fpos >= vmcore_size) diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 135871df9911..4b47a0253425 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -79,7 +79,7 @@ struct kcore_list { struct vmcore { struct list_head list; unsigned long long paddr; - unsigned long size; + unsigned long long size; loff_t offset; }; -- cgit v1.2.3 From 56b146d36db933844011d5026c6f55593037c7b8 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 10 Apr 2006 22:54:21 -0700 Subject: [PATCH] Last DMA_xBIT_MASK cleanups These are the last conversions of pci_set_dma_mask(), pci_set_consistent_dma_mask() and pci_dma_supported() to use DMA_xBIT_MASK constants from linux/dma-mapping.h Signed-off-by: Tobias Klauser Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DMA-mapping.txt | 4 ++-- .../sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 16 ++++++++-------- drivers/media/video/saa7134/saa7134-core.c | 3 ++- drivers/sn/ioc3.c | 5 +++-- include/linux/dma-mapping.h | 2 +- sound/oss/emu10k1/main.c | 3 ++- sound/pci/als300.c | 5 +++-- 7 files changed, 21 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt index ee4bb73683cd..10bf4deb96aa 100644 --- a/Documentation/DMA-mapping.txt +++ b/Documentation/DMA-mapping.txt @@ -194,7 +194,7 @@ document for how to handle this case. Finally, if your device can only drive the low 24-bits of address during PCI bus mastering you might do something like: - if (pci_set_dma_mask(pdev, 0x00ffffff)) { + if (pci_set_dma_mask(pdev, DMA_24BIT_MASK)) { printk(KERN_WARNING "mydev: 24-bit DMA addressing not available.\n"); goto ignore_this_device; @@ -212,7 +212,7 @@ functions (for example a sound card provides playback and record functions) and the various different functions have _different_ DMA addressing limitations, you may wish to probe each mask and only provide the functionality which the machine can handle. It -is important that the last call to pci_set_dma_mask() be for the +is important that the last call to pci_set_dma_mask() be for the most specific mask. Here is pseudo-code showing how this might be done: diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 6feef9e82b63..68eeebc17ff4 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl @@ -1123,8 +1123,8 @@ if ((err = pci_enable_device(pci)) < 0) return err; /* check PCI availability (28bit DMA) */ - if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { printk(KERN_ERR "error to set 28bit mask DMA\n"); pci_disable_device(pci); return -ENXIO; @@ -1216,7 +1216,7 @@ The allocation of PCI resources is done in the probe() function, and usually an extra xxx_create() function is written for this - purpose. + purpose. @@ -1225,7 +1225,7 @@ allocating resources. Also, you need to set the proper PCI DMA mask to limit the accessed i/o range. In some cases, you might need to call pci_set_master() function, - too. + too. @@ -1236,8 +1236,8 @@ Now assume that this PCI device has an I/O port with 8 bytes and an interrupt. Then struct mychip will have the - following fields: + following fields: diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index c98571c9d5a6..13de05532e0a 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "saa7134-reg.h" #include "saa7134.h" @@ -870,7 +871,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,pci_resource_start(pci_dev,0)); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev,0xffffffff)) { + if (!pci_dma_supported(pci_dev, DMA_32BIT_MASK)) { printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name); err = -EIO; goto fail1; diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c index 93449a1a0065..0b49ff78efc1 100644 --- a/drivers/sn/ioc3.c +++ b/drivers/sn/ioc3.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -619,9 +620,9 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) pci_set_master(pdev); #ifdef USE_64BIT_DMA - ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); + ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK); if (!ret) { - ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); + ret = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); if (ret < 0) { printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA " "for consistent allocations\n", diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 9b4751aecc23..ff61817082fa 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -21,7 +21,7 @@ enum dma_data_direction { #define DMA_30BIT_MASK 0x000000003fffffffULL #define DMA_29BIT_MASK 0x000000001fffffffULL #define DMA_28BIT_MASK 0x000000000fffffffULL -#define DMA_24BIT_MASK 0x0000000000ffffffULL +#define DMA_24BIT_MASK 0x0000000000ffffffULL #include diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c index 0cd44a6f7ac0..3721c5857b90 100644 --- a/sound/oss/emu10k1/main.c +++ b/sound/oss/emu10k1/main.c @@ -94,6 +94,7 @@ #include #include #include +#include #include "hwaccess.h" #include "8010.h" @@ -119,7 +120,7 @@ /* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */ -#define EMU10K1_DMA_MASK 0x1fffffff /* DMA buffer mask for pci_alloc_consist */ +#define EMU10K1_DMA_MASK DMA_29BIT_MASK /* DMA buffer mask for pci_alloc_consist */ #ifndef PCI_VENDOR_ID_CREATIVE #define PCI_VENDOR_ID_CREATIVE 0x1102 diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 37b80570a5c6..91899f87f037 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -691,8 +692,8 @@ static int __devinit snd_als300_create(snd_card_t *card, if ((err = pci_enable_device(pci)) < 0) return err; - if (pci_set_dma_mask(pci, 0x0fffffff) < 0 || - pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) { + if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 || + pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) { printk(KERN_ERR "error setting 28bit DMA mask\n"); pci_disable_device(pci); return -ENXIO; -- cgit v1.2.3 From 5ac90c9f78953b1a2ac937cc5a2f90c3521a710e Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Mon, 10 Apr 2006 22:54:28 -0700 Subject: [PATCH] module support: record in vermagic ability to unload a module An UML user reported (against 2.6.13.3/UML) he got kernel Oopses when trying to rmmod (on a kernel with module unloading enabled) a module compiled with module unloading disabled. As crashing is a very correct thing to do in that case, a solution is altering the vermagic string to include this too. Possibly, however, the code should not crash in this case, even if the module didn't support unloading - it should simply abort the module removal. In this case, fixing that bug would be a better solution. I've not investigated though. (akpm: a bit marginal - root screwed up and shot himself in the foot). Cc: Hayim Shaul Cc: Rusty Russell Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/vermagic.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h index fadc535e2925..dc7c621e4647 100644 --- a/include/linux/vermagic.h +++ b/include/linux/vermagic.h @@ -12,6 +12,11 @@ #else #define MODULE_VERMAGIC_PREEMPT "" #endif +#ifdef CONFIG_MODULE_UNLOAD +#define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload " +#else +#define MODULE_VERMAGIC_MODULE_UNLOAD "" +#endif #ifndef MODULE_ARCH_VERMAGIC #define MODULE_ARCH_VERMAGIC "" #endif @@ -19,5 +24,5 @@ #define VERMAGIC_STRING \ UTS_RELEASE " " \ MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \ - MODULE_ARCH_VERMAGIC \ + MODULE_VERMAGIC_MODULE_UNLOAD MODULE_ARCH_VERMAGIC \ "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__) -- cgit v1.2.3 From 6f54e2d0d3a904e55c9c50b78542072f6c42080e Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 10 Apr 2006 22:55:36 -0700 Subject: [PATCH] knfsd: svcrpc: WARN() instead of returning an error from svc_take_page Every caller of svc_take_page ignores its return value and assumes it succeeded. So just WARN() instead of returning an ignored error. This would have saved some time debugging a recent nfsd4 problem. If there are still failure cases here, then the result is probably that we overwrite an earlier part of the reply while xdr-encoding. While the corrupted reply is a nasty bug, it would be worse to panic here and create the possibility of a remote DOS; hence WARN() instead of BUG(). Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Cc: Ingo Oeser Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/sunrpc/svc.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 50cab2a09f28..503564384545 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -197,15 +197,16 @@ svc_take_res_page(struct svc_rqst *rqstp) return rqstp->rq_respages[rqstp->rq_resused++]; } -static inline int svc_take_page(struct svc_rqst *rqstp) +static inline void svc_take_page(struct svc_rqst *rqstp) { - if (rqstp->rq_arghi <= rqstp->rq_argused) - return -ENOMEM; + if (rqstp->rq_arghi <= rqstp->rq_argused) { + WARN_ON(1); + return; + } rqstp->rq_arghi--; rqstp->rq_respages[rqstp->rq_resused] = rqstp->rq_argpages[rqstp->rq_arghi]; rqstp->rq_resused++; - return 0; } static inline void svc_pushback_allpages(struct svc_rqst *rqstp) -- cgit v1.2.3 From 89ec4c238e7a3d7e660291f3f1a8181381baad77 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 10 Apr 2006 22:55:48 -0700 Subject: [PATCH] vesafb: Fix incorrect logo colors in x86_64 Bugzilla Bug 6299: A pixel size of 8 bits produces wrong logo colors in x86_64. The driver has 2 methods for setting the color map, using the protected mode interface provided by the video BIOS and directly writing to the VGA registers. The former is not supported in x86_64 and the latter is enabled only in i386. Fix by enabling the latter method in x86_64 only if supported by the BIOS. If both methods are unsupported, change the visual of vesafb to STATIC_PSEUDOCOLOR. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/boot/video.S | 5 +++++ arch/x86_64/boot/video.S | 5 +++++ drivers/video/vesafb.c | 27 +++++++++++++++++++++------ include/linux/screen_info.h | 3 ++- 4 files changed, 33 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S index 0000a2674537..c9343c3a8082 100644 --- a/arch/i386/boot/video.S +++ b/arch/i386/boot/video.S @@ -97,6 +97,7 @@ #define PARAM_VESAPM_OFF 0x30 #define PARAM_LFB_PAGES 0x32 #define PARAM_VESA_ATTRIB 0x34 +#define PARAM_CAPABILITIES 0x36 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ #ifdef CONFIG_VIDEO_RETAIN @@ -233,6 +234,10 @@ mopar_gr: movw 18(%di), %ax movl %eax, %fs:(PARAM_LFB_SIZE) +# store mode capabilities + movl 10(%di), %eax + movl %eax, %fs:(PARAM_CAPABILITIES) + # switching the DAC to 8-bit is for <= 8 bpp only movw %fs:(PARAM_LFB_DEPTH), %ax cmpw $8, %ax diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S index 0587477c99f2..32327bb37aff 100644 --- a/arch/x86_64/boot/video.S +++ b/arch/x86_64/boot/video.S @@ -97,6 +97,7 @@ #define PARAM_VESAPM_OFF 0x30 #define PARAM_LFB_PAGES 0x32 #define PARAM_VESA_ATTRIB 0x34 +#define PARAM_CAPABILITIES 0x36 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ #ifdef CONFIG_VIDEO_RETAIN @@ -233,6 +234,10 @@ mopar_gr: movw 18(%di), %ax movl %eax, %fs:(PARAM_LFB_SIZE) +# store mode capabilities + movl 10(%di), %eax + movl %eax, %fs:(PARAM_CAPABILITIES) + # switching the DAC to 8-bit is for <= 8 bpp only movw %fs:(PARAM_LFB_DEPTH), %ax cmpw $8, %ax diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 8982e540214c..b0b9acfdd430 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -57,7 +57,7 @@ static unsigned short *pmi_base = NULL; static void (*pmi_start)(void); static void (*pmi_pal)(void); static int depth; - +static int vga_compat; /* --------------------------------------------------------------------- */ static int vesafb_pan_display(struct fb_var_screeninfo *var, @@ -83,9 +83,10 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue) { + int shift = 16 - depth; + #ifdef __i386__ struct { u_char blue, green, red, pad; } entry; - int shift = 16 - depth; if (pmi_setpal) { entry.red = red >> shift; @@ -101,14 +102,20 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green, "d" (regno), /* EDX */ "D" (&entry), /* EDI */ "S" (&pmi_pal)); /* ESI */ - } else { - /* without protected mode interface, try VGA registers... */ + return; + } +#endif + +/* + * without protected mode interface and if VGA compatible, + * try VGA registers... + */ + if (vga_compat) { outb_p(regno, dac_reg); outb_p(red >> shift, dac_val); outb_p(green >> shift, dac_val); outb_p(blue >> shift, dac_val); } -#endif } static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, @@ -214,6 +221,7 @@ static int __init vesafb_probe(struct platform_device *dev) if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return -ENODEV; + vga_compat = (screen_info.capabilities & 2) ? 0 : 1; vesafb_fix.smem_start = screen_info.lfb_base; vesafb_defined.bits_per_pixel = screen_info.lfb_depth; if (15 == vesafb_defined.bits_per_pixel) @@ -318,6 +326,12 @@ static int __init vesafb_probe(struct platform_device *dev) } } + if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) { + printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n" + " colors may be incorrect\n"); + vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; + } + vesafb_defined.xres_virtual = vesafb_defined.xres; vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length; if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) { @@ -354,7 +368,8 @@ static int __init vesafb_probe(struct platform_device *dev) printk(KERN_INFO "vesafb: %s: " "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", (vesafb_defined.bits_per_pixel > 8) ? - "Truecolor" : "Pseudocolor", + "Truecolor" : (vga_compat || pmi_setpal) ? + "Pseudocolor" : "Static Pseudocolor", screen_info.rsvd_size, screen_info.red_size, screen_info.green_size, diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h index 6336987dae62..2925e66a6732 100644 --- a/include/linux/screen_info.h +++ b/include/linux/screen_info.h @@ -41,7 +41,8 @@ struct screen_info { u16 vesapm_off; /* 0x30 */ u16 pages; /* 0x32 */ u16 vesa_attributes; /* 0x34 */ - /* 0x36 -- 0x3f reserved for future expansion */ + u32 capabilities; /* 0x36 */ + /* 0x3a -- 0x3f reserved for future expansion */ }; extern struct screen_info screen_info; -- cgit v1.2.3 From cde227afe6b997dce08bcfc2aa6e373fb56857b0 Mon Sep 17 00:00:00 2001 From: "mao, bibo" Date: Tue, 11 Apr 2006 12:54:54 +0200 Subject: [PATCH] x86_64: inline function prefix with __always_inline in vsyscall In vsyscall function do_vgettimeofday(), some functions are declared as inlined, which is a hint for gcc to compile the function inlined but it not forced. Sometimes compiler does not compile the function as inlined, so here inline is replaced by __always_inline prefix. It does not happen in gcc compiler actually, but it possibly happens. Signed-off-by: bibo mao Signed-off-by: Linus Torvalds --- include/asm-x86_64/io.h | 2 +- include/linux/seqlock.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h index cafdfb37f0d8..a05da8a50bfd 100644 --- a/include/asm-x86_64/io.h +++ b/include/asm-x86_64/io.h @@ -177,7 +177,7 @@ static inline __u16 __readw(const volatile void __iomem *addr) { return *(__force volatile __u16 *)addr; } -static inline __u32 __readl(const volatile void __iomem *addr) +static __always_inline __u32 __readl(const volatile void __iomem *addr) { return *(__force volatile __u32 *)addr; } diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h index fca9b0fb5b4e..5a095572881d 100644 --- a/include/linux/seqlock.h +++ b/include/linux/seqlock.h @@ -73,7 +73,7 @@ static inline int write_tryseqlock(seqlock_t *sl) } /* Start of read calculation -- fetch last complete writer token */ -static inline unsigned read_seqbegin(const seqlock_t *sl) +static __always_inline unsigned read_seqbegin(const seqlock_t *sl) { unsigned ret = sl->sequence; smp_rmb(); @@ -88,7 +88,7 @@ static inline unsigned read_seqbegin(const seqlock_t *sl) * * Using xor saves one conditional branch. */ -static inline int read_seqretry(const seqlock_t *sl, unsigned iv) +static __always_inline int read_seqretry(const seqlock_t *sl, unsigned iv) { smp_rmb(); return (iv & 1) | (sl->sequence ^ iv); -- cgit v1.2.3 From cbb7e577e732f576b9f399bc2600bdc0626c68dc Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 11 Apr 2006 14:57:50 +0200 Subject: [PATCH] splice: pass offset around for ->splice_read() and ->splice_write() We need not use ->f_pos as the offset for the file input/output. If the user passed an offset pointer in through sys_splice(), just use that and leave ->f_pos alone. Signed-off-by: Jens Axboe --- fs/splice.c | 86 ++++++++++++++++++++++---------------------- fs/xfs/linux-2.6/xfs_file.c | 12 ++++--- fs/xfs/linux-2.6/xfs_lrw.c | 14 ++++---- fs/xfs/linux-2.6/xfs_lrw.h | 4 +-- fs/xfs/linux-2.6/xfs_vnode.h | 12 +++---- include/linux/fs.h | 12 +++---- 6 files changed, 74 insertions(+), 66 deletions(-) (limited to 'include/linux') diff --git a/fs/splice.c b/fs/splice.c index e50a460239dd..5d3eda64703b 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -231,8 +231,9 @@ static ssize_t move_to_pipe(struct pipe_inode_info *pipe, struct page **pages, } static int -__generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, - size_t len, unsigned int flags) +__generic_file_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { struct address_space *mapping = in->f_mapping; unsigned int offset, nr_pages; @@ -241,8 +242,8 @@ __generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, pgoff_t index; int i, error; - index = in->f_pos >> PAGE_CACHE_SHIFT; - offset = in->f_pos & ~PAGE_CACHE_MASK; + index = *ppos >> PAGE_CACHE_SHIFT; + offset = *ppos & ~PAGE_CACHE_MASK; nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; if (nr_pages > PIPE_BUFFERS) @@ -348,8 +349,9 @@ fill_it: * * Will read pages from given file and fill them into a pipe. */ -ssize_t generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, - size_t len, unsigned int flags) +ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { ssize_t spliced; int ret; @@ -358,12 +360,12 @@ ssize_t generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, spliced = 0; while (len) { - ret = __generic_file_splice_read(in, pipe, len, flags); + ret = __generic_file_splice_read(in, ppos, pipe, len, flags); if (ret <= 0) break; - in->f_pos += ret; + *ppos += ret; len -= ret; spliced += ret; @@ -561,7 +563,7 @@ typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. */ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, - size_t len, unsigned int flags, + loff_t *ppos, size_t len, unsigned int flags, splice_actor *actor) { int ret, do_wakeup, err; @@ -573,7 +575,7 @@ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, sd.total_len = len; sd.flags = flags; sd.file = out; - sd.pos = out->f_pos; + sd.pos = *ppos; if (pipe->inode) mutex_lock(&pipe->inode->i_mutex); @@ -656,9 +658,7 @@ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); } - out->f_pos = sd.pos; return ret; - } /** @@ -674,12 +674,12 @@ static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, */ ssize_t generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, - size_t len, unsigned int flags) + loff_t *ppos, size_t len, unsigned int flags) { struct address_space *mapping = out->f_mapping; ssize_t ret; - ret = move_from_pipe(pipe, out, len, flags, pipe_to_file); + ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); /* * If file or inode is SYNC and we actually wrote some data, sync it. @@ -715,9 +715,9 @@ EXPORT_SYMBOL(generic_file_splice_write); * */ ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, - size_t len, unsigned int flags) + loff_t *ppos, size_t len, unsigned int flags) { - return move_from_pipe(pipe, out, len, flags, pipe_to_sendpage); + return move_from_pipe(pipe, out, ppos, len, flags, pipe_to_sendpage); } EXPORT_SYMBOL(generic_splice_sendpage); @@ -726,9 +726,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); * Attempt to initiate a splice from pipe to file. */ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, - size_t len, unsigned int flags) + loff_t *ppos, size_t len, unsigned int flags) { - loff_t pos; int ret; if (unlikely(!out->f_op || !out->f_op->splice_write)) @@ -737,22 +736,21 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, if (unlikely(!(out->f_mode & FMODE_WRITE))) return -EBADF; - pos = out->f_pos; - - ret = rw_verify_area(WRITE, out, &pos, len); + ret = rw_verify_area(WRITE, out, ppos, len); if (unlikely(ret < 0)) return ret; - return out->f_op->splice_write(pipe, out, len, flags); + return out->f_op->splice_write(pipe, out, ppos, len, flags); } /* * Attempt to initiate a splice from a file to a pipe. */ -static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, - size_t len, unsigned int flags) +static long do_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { - loff_t pos, isize, left; + loff_t isize, left; int ret; if (unlikely(!in->f_op || !in->f_op->splice_read)) @@ -761,28 +759,27 @@ static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, if (unlikely(!(in->f_mode & FMODE_READ))) return -EBADF; - pos = in->f_pos; - - ret = rw_verify_area(READ, in, &pos, len); + ret = rw_verify_area(READ, in, ppos, len); if (unlikely(ret < 0)) return ret; isize = i_size_read(in->f_mapping->host); - if (unlikely(in->f_pos >= isize)) + if (unlikely(*ppos >= isize)) return 0; - left = isize - in->f_pos; + left = isize - *ppos; if (unlikely(left < len)) len = left; - return in->f_op->splice_read(in, pipe, len, flags); + return in->f_op->splice_read(in, ppos, pipe, len, flags); } -long do_splice_direct(struct file *in, struct file *out, size_t len, - unsigned int flags) +long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, + size_t len, unsigned int flags) { struct pipe_inode_info *pipe; long ret, bytes; + loff_t out_off; umode_t i_mode; int i; @@ -820,6 +817,7 @@ long do_splice_direct(struct file *in, struct file *out, size_t len, */ ret = 0; bytes = 0; + out_off = 0; while (len) { size_t read_len, max_read_len; @@ -829,7 +827,7 @@ long do_splice_direct(struct file *in, struct file *out, size_t len, */ max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); - ret = do_splice_to(in, pipe, max_read_len, flags); + ret = do_splice_to(in, ppos, pipe, max_read_len, flags); if (unlikely(ret < 0)) goto out_release; @@ -840,7 +838,7 @@ long do_splice_direct(struct file *in, struct file *out, size_t len, * must not do the output in nonblocking mode as then we * could get stuck data in the internal pipe: */ - ret = do_splice_from(pipe, out, read_len, + ret = do_splice_from(pipe, out, &out_off, read_len, flags & ~SPLICE_F_NONBLOCK); if (unlikely(ret < 0)) goto out_release; @@ -898,6 +896,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, size_t len, unsigned int flags) { struct pipe_inode_info *pipe; + loff_t offset, *off; pipe = in->f_dentry->d_inode->i_pipe; if (pipe) { @@ -906,12 +905,13 @@ static long do_splice(struct file *in, loff_t __user *off_in, if (off_out) { if (out->f_op->llseek == no_llseek) return -EINVAL; - if (copy_from_user(&out->f_pos, off_out, - sizeof(loff_t))) + if (copy_from_user(&offset, off_out, sizeof(loff_t))) return -EFAULT; - } + off = &offset; + } else + off = &out->f_pos; - return do_splice_from(pipe, out, len, flags); + return do_splice_from(pipe, out, off, len, flags); } pipe = out->f_dentry->d_inode->i_pipe; @@ -921,11 +921,13 @@ static long do_splice(struct file *in, loff_t __user *off_in, if (off_in) { if (in->f_op->llseek == no_llseek) return -EINVAL; - if (copy_from_user(&in->f_pos, off_in, sizeof(loff_t))) + if (copy_from_user(&offset, off_in, sizeof(loff_t))) return -EFAULT; - } + off = &offset; + } else + off = &in->f_pos; - return do_splice_to(in, pipe, len, flags); + return do_splice_to(in, off, pipe, len, flags); } return -EINVAL; diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 269721af02f3..c847416f6d10 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -252,6 +252,7 @@ xfs_file_sendfile_invis( STATIC ssize_t xfs_file_splice_read( struct file *infilp, + loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) @@ -259,13 +260,14 @@ xfs_file_splice_read( vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); ssize_t rval; - VOP_SPLICE_READ(vp, infilp, pipe, len, flags, 0, NULL, rval); + VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, 0, NULL, rval); return rval; } STATIC ssize_t xfs_file_splice_read_invis( struct file *infilp, + loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) @@ -273,7 +275,7 @@ xfs_file_splice_read_invis( vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); ssize_t rval; - VOP_SPLICE_READ(vp, infilp, pipe, len, flags, IO_INVIS, NULL, rval); + VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, IO_INVIS, NULL, rval); return rval; } @@ -281,13 +283,14 @@ STATIC ssize_t xfs_file_splice_write( struct pipe_inode_info *pipe, struct file *outfilp, + loff_t *ppos, size_t len, unsigned int flags) { vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); ssize_t rval; - VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, 0, NULL, rval); + VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, 0, NULL, rval); return rval; } @@ -295,13 +298,14 @@ STATIC ssize_t xfs_file_splice_write_invis( struct pipe_inode_info *pipe, struct file *outfilp, + loff_t *ppos, size_t len, unsigned int flags) { vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); ssize_t rval; - VOP_SPLICE_WRITE(vp, pipe, outfilp, len, flags, IO_INVIS, NULL, rval); + VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, IO_INVIS, NULL, rval); return rval; } diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 74a52937f208..67efe3308980 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -338,6 +338,7 @@ ssize_t xfs_splice_read( bhv_desc_t *bdp, struct file *infilp, + loff_t *ppos, struct pipe_inode_info *pipe, size_t count, int flags, @@ -360,7 +361,7 @@ xfs_splice_read( int error; error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), - infilp->f_pos, count, + *ppos, count, FILP_DELAY_FLAG(infilp), &locktype); if (error) { xfs_iunlock(ip, XFS_IOLOCK_SHARED); @@ -368,8 +369,8 @@ xfs_splice_read( } } xfs_rw_enter_trace(XFS_SPLICE_READ_ENTER, &ip->i_iocore, - pipe, count, infilp->f_pos, ioflags); - ret = generic_file_splice_read(infilp, pipe, count, flags); + pipe, count, *ppos, ioflags); + ret = generic_file_splice_read(infilp, ppos, pipe, count, flags); if (ret > 0) XFS_STATS_ADD(xs_read_bytes, ret); @@ -382,6 +383,7 @@ xfs_splice_write( bhv_desc_t *bdp, struct pipe_inode_info *pipe, struct file *outfilp, + loff_t *ppos, size_t count, int flags, int ioflags, @@ -403,7 +405,7 @@ xfs_splice_write( int error; error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp), - outfilp->f_pos, count, + *ppos, count, FILP_DELAY_FLAG(outfilp), &locktype); if (error) { xfs_iunlock(ip, XFS_IOLOCK_EXCL); @@ -411,8 +413,8 @@ xfs_splice_write( } } xfs_rw_enter_trace(XFS_SPLICE_WRITE_ENTER, &ip->i_iocore, - pipe, count, outfilp->f_pos, ioflags); - ret = generic_file_splice_write(pipe, outfilp, count, flags); + pipe, count, *ppos, ioflags); + ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags); if (ret > 0) XFS_STATS_ADD(xs_write_bytes, ret); diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index 55c689a86ad2..8f4539952350 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h @@ -93,11 +93,11 @@ extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *, extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, loff_t *, int, size_t, read_actor_t, void *, struct cred *); -extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, +extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *, struct pipe_inode_info *, size_t, int, int, struct cred *); extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *, - struct file *, size_t, int, int, + struct file *, loff_t *, size_t, int, int, struct cred *); #endif /* __XFS_LRW_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 88b09f186289..2a8e16c22353 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -173,11 +173,11 @@ typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *, typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, loff_t *, int, size_t, read_actor_t, void *, struct cred *); -typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, +typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *, struct pipe_inode_info *, size_t, int, int, struct cred *); typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *, - struct file *, size_t, int, int, + struct file *, loff_t *, size_t, int, int, struct cred *); typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, int, unsigned int, void __user *); @@ -284,10 +284,10 @@ typedef struct vnodeops { rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) #define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \ rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr) -#define VOP_SPLICE_READ(vp,f,pipe,cnt,fl,iofl,cr,rv) \ - rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr) -#define VOP_SPLICE_WRITE(vp,f,pipe,cnt,fl,iofl,cr,rv) \ - rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,pipe,cnt,fl,iofl,cr) +#define VOP_SPLICE_READ(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \ + rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr) +#define VOP_SPLICE_WRITE(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \ + rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr) #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) #define VOP_OPEN(vp, cr, rv) \ diff --git a/include/linux/fs.h b/include/linux/fs.h index 162c6e57307a..3de2bfb2410f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1039,8 +1039,8 @@ struct file_operations { int (*check_flags)(int); int (*dir_notify)(struct file *filp, unsigned long arg); int (*flock) (struct file *, int, struct file_lock *); - ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int); - ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); + ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); }; struct inode_operations { @@ -1613,13 +1613,13 @@ extern void do_generic_mapping_read(struct address_space *mapping, loff_t *, read_descriptor_t *, read_actor_t); /* fs/splice.c */ -extern ssize_t generic_file_splice_read(struct file *, +extern ssize_t generic_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); extern ssize_t generic_file_splice_write(struct pipe_inode_info *, - struct file *, size_t, unsigned int); + struct file *, loff_t *, size_t, unsigned int); extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, - struct file *out, size_t len, unsigned int flags); -extern long do_splice_direct(struct file *in, struct file *out, + struct file *out, loff_t *, size_t len, unsigned int flags); +extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, size_t len, unsigned int flags); extern void -- cgit v1.2.3 From 70524490ee2ea1bbf6cee6c106597b3ac25a3fc2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 11 Apr 2006 15:51:17 +0200 Subject: [PATCH] splice: add support for sys_tee() Basically an in-kernel implementation of tee, which uses splice and the pipe buffers as an intelligent way to pass data around by reference. Where the user space tee consumes the input and produces a stdout and file output, this syscall merely duplicates the data inside a pipe to another pipe. No data is copied, the output just grabs a reference to the input pipe data. Signed-off-by: Jens Axboe --- arch/i386/kernel/syscall_table.S | 1 + arch/ia64/kernel/entry.S | 1 + arch/powerpc/kernel/systbl.S | 1 + fs/pipe.c | 7 ++ fs/splice.c | 186 +++++++++++++++++++++++++++++++++++++++ include/asm-i386/unistd.h | 3 +- include/asm-ia64/unistd.h | 3 +- include/asm-powerpc/unistd.h | 3 +- include/asm-x86_64/unistd.h | 4 +- include/linux/pipe_fs_i.h | 1 + include/linux/syscalls.h | 2 + 11 files changed, 208 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 4f58b9c0efe3..f48bef15b4f0 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -314,3 +314,4 @@ ENTRY(sys_call_table) .long sys_get_robust_list .long sys_splice .long sys_sync_file_range + .long sys_tee /* 315 */ diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 6e16f6b35bd3..e30798811216 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1609,5 +1609,6 @@ sys_call_table: data8 sys_set_robust_list data8 sys_get_robust_list data8 sys_sync_file_range // 1300 + data8 sys_tee .org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 1424eab450ee..a14c96403840 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -323,3 +323,4 @@ COMPAT_SYS(pselect6) COMPAT_SYS(ppoll) SYSCALL(unshare) SYSCALL(splice) +SYSCALL(tee) diff --git a/fs/pipe.c b/fs/pipe.c index e984beb93a0e..7fefb10db8d9 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -131,12 +131,19 @@ static int anon_pipe_buf_steal(struct pipe_inode_info *pipe, return 0; } +static void anon_pipe_buf_get(struct pipe_inode_info *info, + struct pipe_buffer *buf) +{ + page_cache_get(buf->page); +} + static struct pipe_buf_operations anon_pipe_buf_ops = { .can_merge = 1, .map = anon_pipe_buf_map, .unmap = anon_pipe_buf_unmap, .release = anon_pipe_buf_release, .steal = anon_pipe_buf_steal, + .get = anon_pipe_buf_get, }; static ssize_t diff --git a/fs/splice.c b/fs/splice.c index 5d3eda64703b..8d57e89924a6 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -125,12 +125,19 @@ static void page_cache_pipe_buf_unmap(struct pipe_inode_info *info, kunmap(buf->page); } +static void page_cache_pipe_buf_get(struct pipe_inode_info *info, + struct pipe_buffer *buf) +{ + page_cache_get(buf->page); +} + static struct pipe_buf_operations page_cache_pipe_buf_ops = { .can_merge = 0, .map = page_cache_pipe_buf_map, .unmap = page_cache_pipe_buf_unmap, .release = page_cache_pipe_buf_release, .steal = page_cache_pipe_buf_steal, + .get = page_cache_pipe_buf_get, }; /* @@ -963,3 +970,182 @@ asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, return error; } + +/* + * Link contents of ipipe to opipe. + */ +static int link_pipe(struct pipe_inode_info *ipipe, + struct pipe_inode_info *opipe, + size_t len, unsigned int flags) +{ + struct pipe_buffer *ibuf, *obuf; + int ret = 0, do_wakeup = 0, i; + + /* + * Potential ABBA deadlock, work around it by ordering lock + * grabbing by inode address. Otherwise two different processes + * could deadlock (one doing tee from A -> B, the other from B -> A). + */ + if (ipipe->inode < opipe->inode) { + mutex_lock(&ipipe->inode->i_mutex); + mutex_lock(&opipe->inode->i_mutex); + } else { + mutex_lock(&opipe->inode->i_mutex); + mutex_lock(&ipipe->inode->i_mutex); + } + + for (i = 0;; i++) { + if (!opipe->readers) { + send_sig(SIGPIPE, current, 0); + if (!ret) + ret = -EPIPE; + break; + } + if (ipipe->nrbufs - i) { + ibuf = ipipe->bufs + ((ipipe->curbuf + i) & (PIPE_BUFFERS - 1)); + + /* + * If we have room, fill this buffer + */ + if (opipe->nrbufs < PIPE_BUFFERS) { + int nbuf = (opipe->curbuf + opipe->nrbufs) & (PIPE_BUFFERS - 1); + + /* + * Get a reference to this pipe buffer, + * so we can copy the contents over. + */ + ibuf->ops->get(ipipe, ibuf); + + obuf = opipe->bufs + nbuf; + *obuf = *ibuf; + + if (obuf->len > len) + obuf->len = len; + + opipe->nrbufs++; + do_wakeup = 1; + ret += obuf->len; + len -= obuf->len; + + if (!len) + break; + if (opipe->nrbufs < PIPE_BUFFERS) + continue; + } + + /* + * We have input available, but no output room. + * If we already copied data, return that. + */ + if (flags & SPLICE_F_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + break; + } + if (signal_pending(current)) { + if (!ret) + ret = -ERESTARTSYS; + break; + } + if (do_wakeup) { + smp_mb(); + if (waitqueue_active(&opipe->wait)) + wake_up_interruptible(&opipe->wait); + kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN); + do_wakeup = 0; + } + + opipe->waiting_writers++; + pipe_wait(opipe); + opipe->waiting_writers--; + continue; + } + + /* + * No input buffers, do the usual checks for available + * writers and blocking and wait if necessary + */ + if (!ipipe->writers) + break; + if (!ipipe->waiting_writers) { + if (ret) + break; + } + if (flags & SPLICE_F_NONBLOCK) { + if (!ret) + ret = -EAGAIN; + break; + } + if (signal_pending(current)) { + if (!ret) + ret = -ERESTARTSYS; + break; + } + + if (waitqueue_active(&ipipe->wait)) + wake_up_interruptible_sync(&ipipe->wait); + kill_fasync(&ipipe->fasync_writers, SIGIO, POLL_OUT); + + pipe_wait(ipipe); + } + + mutex_unlock(&ipipe->inode->i_mutex); + mutex_unlock(&opipe->inode->i_mutex); + + if (do_wakeup) { + smp_mb(); + if (waitqueue_active(&opipe->wait)) + wake_up_interruptible(&opipe->wait); + kill_fasync(&opipe->fasync_readers, SIGIO, POLL_IN); + } + + return ret; +} + +/* + * This is a tee(1) implementation that works on pipes. It doesn't copy + * any data, it simply references the 'in' pages on the 'out' pipe. + * The 'flags' used are the SPLICE_F_* variants, currently the only + * applicable one is SPLICE_F_NONBLOCK. + */ +static long do_tee(struct file *in, struct file *out, size_t len, + unsigned int flags) +{ + struct pipe_inode_info *ipipe = in->f_dentry->d_inode->i_pipe; + struct pipe_inode_info *opipe = out->f_dentry->d_inode->i_pipe; + + /* + * Link ipipe to the two output pipes, consuming as we go along. + */ + if (ipipe && opipe) + return link_pipe(ipipe, opipe, len, flags); + + return -EINVAL; +} + +asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags) +{ + struct file *in; + int error, fput_in; + + if (unlikely(!len)) + return 0; + + error = -EBADF; + in = fget_light(fdin, &fput_in); + if (in) { + if (in->f_mode & FMODE_READ) { + int fput_out; + struct file *out = fget_light(fdout, &fput_out); + + if (out) { + if (out->f_mode & FMODE_WRITE) + error = do_tee(in, out, len, flags); + fput_light(out, fput_out); + } + } + fput_light(in, fput_in); + } + + return error; +} diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index 6a8dd83c350f..d81d6cfc1bb4 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -320,8 +320,9 @@ #define __NR_get_robust_list 312 #define __NR_splice 313 #define __NR_sync_file_range 314 +#define __NR_tee 315 -#define NR_syscalls 315 +#define NR_syscalls 316 /* * user-visible error numbers are in the range -1 - -128: see diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h index 1c749acca021..a40ebec6aeeb 100644 --- a/include/asm-ia64/unistd.h +++ b/include/asm-ia64/unistd.h @@ -289,12 +289,13 @@ #define __NR_set_robust_list 1298 #define __NR_get_robust_list 1299 #define __NR_sync_file_range 1300 +#define __NR_tee 1301 #ifdef __KERNEL__ #include -#define NR_syscalls 277 /* length of syscall table */ +#define NR_syscalls 278 /* length of syscall table */ #define __ARCH_WANT_SYS_RT_SIGACTION diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 536ba0873052..c612f1a62772 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -302,8 +302,9 @@ #define __NR_ppoll 281 #define __NR_unshare 282 #define __NR_splice 283 +#define __NR_tee 284 -#define __NR_syscalls 284 +#define __NR_syscalls 285 #ifdef __KERNEL__ #define __NR__exit __NR_exit diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index f21ff2c1e960..d86494e23b63 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h @@ -611,8 +611,10 @@ __SYSCALL(__NR_set_robust_list, sys_set_robust_list) __SYSCALL(__NR_get_robust_list, sys_get_robust_list) #define __NR_splice 275 __SYSCALL(__NR_splice, sys_splice) +#define __NR_tee 276 +__SYSCALL(__NR_tee, sys_tee) -#define __NR_syscall_max __NR_splice +#define __NR_syscall_max __NR_tee #ifndef __NO_STUBS diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 123a7c24bc72..ef7f33c0be19 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -21,6 +21,7 @@ struct pipe_buf_operations { void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *); void (*release)(struct pipe_inode_info *, struct pipe_buffer *); int (*steal)(struct pipe_inode_info *, struct pipe_buffer *); + void (*get)(struct pipe_inode_info *, struct pipe_buffer *); }; struct pipe_inode_info { diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index f001bad28d9a..d3ebc0e68b2b 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -574,6 +574,8 @@ asmlinkage long sys_splice(int fd_in, loff_t __user *off_in, int fd_out, loff_t __user *off_out, size_t len, unsigned int flags); +asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags); + asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags); -- cgit v1.2.3 From 8db60bcf3021921e2d10d158641792d640e52fe8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 11 Apr 2006 17:28:33 -0700 Subject: [WAN]: Remove broken and unmaintained Sangoma drivers. The in-kernel Sangoma drivers are both not compiling and marked as BROKEN since at least kernel 2.6.0. Sangoma offers out-of-tree drivers, and David Mandelstam told me Sangoma does no longer maintain the in-kernel drivers and prefers to provide them as a separate installation package. This patch therefore removes these drivers. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- MAINTAINERS | 7 - drivers/net/wan/Kconfig | 97 - drivers/net/wan/Makefile | 13 - drivers/net/wan/sdla_chdlc.c | 4428 ----------------------------- drivers/net/wan/sdla_fr.c | 5061 ---------------------------------- drivers/net/wan/sdla_ft1.c | 345 --- drivers/net/wan/sdla_ppp.c | 3430 ----------------------- drivers/net/wan/sdla_x25.c | 5497 ------------------------------------- drivers/net/wan/sdladrv.c | 2314 ---------------- drivers/net/wan/sdlamain.c | 1346 --------- drivers/net/wan/wanpipe_multppp.c | 2358 ---------------- include/linux/sdla_asy.h | 226 -- include/linux/sdla_chdlc.h | 813 ------ include/linux/sdla_ppp.h | 575 ---- include/linux/sdla_x25.h | 772 ------ include/linux/sdladrv.h | 66 - include/linux/sdlapci.h | 72 - include/linux/sdlasfm.h | 104 - include/linux/wanpipe.h | 483 ---- net/wanrouter/af_wanpipe.c | 2 - 20 files changed, 28009 deletions(-) delete mode 100644 drivers/net/wan/sdla_chdlc.c delete mode 100644 drivers/net/wan/sdla_fr.c delete mode 100644 drivers/net/wan/sdla_ft1.c delete mode 100644 drivers/net/wan/sdla_ppp.c delete mode 100644 drivers/net/wan/sdla_x25.c delete mode 100644 drivers/net/wan/sdladrv.c delete mode 100644 drivers/net/wan/sdlamain.c delete mode 100644 drivers/net/wan/wanpipe_multppp.c delete mode 100644 include/linux/sdla_asy.h delete mode 100644 include/linux/sdla_chdlc.h delete mode 100644 include/linux/sdla_ppp.h delete mode 100644 include/linux/sdla_x25.h delete mode 100644 include/linux/sdladrv.h delete mode 100644 include/linux/sdlapci.h delete mode 100644 include/linux/sdlasfm.h delete mode 100644 include/linux/wanpipe.h (limited to 'include/linux') diff --git a/MAINTAINERS b/MAINTAINERS index d00dea52123f..6d3c401ccdb6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3058,13 +3058,6 @@ M: khali@linux-fr.org L: lm-sensors@lm-sensors.org S: Odd Fixes -WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC) -P: Nenad Corbic -M: ncorbic@sangoma.com -M: dm@sangoma.com -W: http://www.sangoma.com -S: Supported - WATCHDOG DEVICE DRIVERS P: Wim Van Sebroeck M: wim@iguana.be diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 883cf7da10fc..b5328b0ff927 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -410,103 +410,6 @@ config WAN_ROUTER_DRIVERS If unsure, say N. -config VENDOR_SANGOMA - tristate "Sangoma WANPIPE(tm) multiprotocol cards" - depends on WAN_ROUTER_DRIVERS && WAN_ROUTER && (PCI || ISA) && BROKEN - ---help--- - Driver for S514-PCI/ISA Synchronous Data Link Adapters (SDLA). - - WANPIPE from Sangoma Technologies Inc. - is a family of intelligent multiprotocol WAN adapters with data - transfer rates up to 4Mbps. Cards support: - - - X.25, Frame Relay, PPP, Cisco HDLC protocols. - - - API for protocols like HDLC (LAPB), HDLC Streaming, X.25, - Frame Relay and BiSync. - - - Ethernet Bridging over Frame Relay protocol. - - - MULTILINK PPP - - - Async PPP (Modem Dialup) - - The next questions will ask you about the protocols you want - the driver to support. - - If you have one or more of these cards, say M to this option; - and read . - - To compile this driver as a module, choose M here: the - module will be called wanpipe. - -config WANPIPE_CHDLC - bool "WANPIPE Cisco HDLC support" - depends on VENDOR_SANGOMA - ---help--- - Connect a WANPIPE card to a leased line using the Cisco HDLC. - - - Supports Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards - which allows user to build applications using the HDLC streaming API. - - - CHDLC Streaming MULTILINK PPP that can bind multiple WANPIPE T1 - cards into a single logical channel. - - Say Y and the Cisco HDLC support, HDLC streaming API and - MULTILINK PPP will be included in the driver. - -config WANPIPE_FR - bool "WANPIPE Frame Relay support" - depends on VENDOR_SANGOMA - help - Connect a WANPIPE card to a Frame Relay network, or use Frame Relay - API to develop custom applications. - - Contains the Ethernet Bridging over Frame Relay feature, where - a WANPIPE frame relay link can be directly connected to the Linux - kernel bridge. The Frame Relay option is supported on S514-PCI - and S508-ISA cards. - - Say Y and the Frame Relay support will be included in the driver. - -config WANPIPE_X25 - bool "WANPIPE X.25 support" - depends on VENDOR_SANGOMA - help - Connect a WANPIPE card to an X.25 network. - - Includes the X.25 API support for custom applications over the - X.25 protocol. The X.25 option is supported on S514-PCI and - S508-ISA cards. - - Say Y and the X.25 support will be included in the driver. - -config WANPIPE_PPP - bool "WANPIPE PPP support" - depends on VENDOR_SANGOMA - help - Connect a WANPIPE card to a leased line using Point-to-Point - Protocol (PPP). - - The PPP option is supported on S514-PCI/S508-ISA cards. - - Say Y and the PPP support will be included in the driver. - -config WANPIPE_MULTPPP - bool "WANPIPE Multi-Port PPP support" - depends on VENDOR_SANGOMA - help - Connect a WANPIPE card to a leased line using Point-to-Point - Protocol (PPP). - - Uses in-kernel SyncPPP protocol over the Sangoma HDLC Streaming - adapter. In this case each Sangoma adapter port can support an - independent PPP connection. For example, a single Quad-Port PCI - adapter can support up to four independent PPP links. The PPP - option is supported on S514-PCI/S508-ISA cards. - - Say Y and the Multi-Port PPP support will be included in the driver. - config CYCLADES_SYNC tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)" depends on WAN_ROUTER_DRIVERS && (PCI || ISA) diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile index ce6c56b903e7..823c6d5ab90d 100644 --- a/drivers/net/wan/Makefile +++ b/drivers/net/wan/Makefile @@ -5,14 +5,6 @@ # Rewritten to use lists instead of if-statements. # -wanpipe-y := sdlamain.o sdla_ft1.o -wanpipe-$(CONFIG_WANPIPE_X25) += sdla_x25.o -wanpipe-$(CONFIG_WANPIPE_FR) += sdla_fr.o -wanpipe-$(CONFIG_WANPIPE_CHDLC) += sdla_chdlc.o -wanpipe-$(CONFIG_WANPIPE_PPP) += sdla_ppp.o -wanpipe-$(CONFIG_WANPIPE_MULTPPP) += wanpipe_multppp.o -wanpipe-objs := $(wanpipe-y) - cyclomx-y := cycx_main.o cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o cyclomx-objs := $(cyclomx-y) @@ -43,11 +35,6 @@ obj-$(CONFIG_LANMEDIA) += lmc/ obj-$(CONFIG_DLCI) += dlci.o obj-$(CONFIG_SDLA) += sdla.o -ifeq ($(CONFIG_WANPIPE_MULTPPP),y) - obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o syncppp.o -else - obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o -endif obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o obj-$(CONFIG_LAPBETHER) += lapbether.o obj-$(CONFIG_SBNI) += sbni.o diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c deleted file mode 100644 index 496d29237e92..000000000000 --- a/drivers/net/wan/sdla_chdlc.c +++ /dev/null @@ -1,4428 +0,0 @@ -/***************************************************************************** -* sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module. -* -* Authors: Nenad Corbic -* Gideon Hack -* -* Copyright: (c) 1995-2001 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. -* ============================================================================ -* Feb 28, 2001 Nenad Corbic Updated if_tx_timeout() routine for -* 2.4.X kernels. -* Jan 25, 2001 Nenad Corbic Added a TTY Sync serial driver over the -* HDLC streaming protocol -* Added a TTY Async serial driver over the -* Async protocol. -* Dec 15, 2000 Nenad Corbic Updated for 2.4.X Kernel support -* Nov 13, 2000 Nenad Corbic Added true interface type encoding option. -* Tcpdump doesn't support CHDLC inteface -* types, to fix this "true type" option will set -* the interface type to RAW IP mode. -* Nov 07, 2000 Nenad Corbic Added security features for UDP debugging: -* Deny all and specify allowed requests. -* Jun 20, 2000 Nenad Corbic Fixed the API IP ERROR bug. Caused by the -* latest update. -* May 09, 2000 Nenad Corbic Option to bring down an interface -* upon disconnect. -* Mar 23, 2000 Nenad Corbic Improved task queue, bh handling. -* Mar 16, 2000 Nenad Corbic Fixed the SLARP Dynamic IP addressing. -* Mar 06, 2000 Nenad Corbic Bug Fix: corrupted mbox recovery. -* Feb 10, 2000 Gideon Hack Added ASYNC support. -* Feb 09, 2000 Nenad Corbic Fixed two shutdown bugs in update() and -* if_stats() functions. -* Jan 24, 2000 Nenad Corbic Fixed a startup wanpipe state racing, -* condition between if_open and isr. -* Jan 10, 2000 Nenad Corbic Added new socket API support. -* Dev 15, 1999 Nenad Corbic Fixed up header files for 2.0.X kernels -* Nov 20, 1999 Nenad Corbic Fixed zero length API bug. -* Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup. -* Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing -* Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices. -* Jun 02, 1999 Gideon Hack Added support for the S514 adapter. -* Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING). -* Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC. -* Aug 07, 1998 David Fong Initial version. -*****************************************************************************/ - -#include -#include /* printk(), and other useful stuff */ -#include /* offsetof(), etc. */ -#include /* return codes */ -#include /* inline memset(), etc. */ -#include /* kmalloc(), kfree() */ -#include /* WAN router definitions */ -#include /* WANPIPE common user API definitions */ -#include /* ARPHRD_* defines */ - - -#include -#include -#include - -#include /* sockaddr_in */ -#include -#include -#include /* htons(), etc. */ -#include -#include - -#include /* CHDLC firmware API definitions */ -#include /* CHDLC (async) API definitions */ - -#include /* Socket Driver common area */ -#include - -/* TTY Includes */ -#include -#include -#include - - -/****** Defines & Macros ****************************************************/ - -/* reasons for enabling the timer interrupt on the adapter */ -#define TMR_INT_ENABLED_UDP 0x01 -#define TMR_INT_ENABLED_UPDATE 0x02 -#define TMR_INT_ENABLED_CONFIG 0x10 - -#define MAX_IP_ERRORS 10 - -#define TTY_CHDLC_MAX_MTU 2000 -#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */ -#define CHDLC_HDR_LEN 1 - -#define CHDLC_API 0x01 - -#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" ) -#define MAX_BH_BUFF 10 - -//#define PRINT_DEBUG -#ifdef PRINT_DEBUG -#define dbg_printk(format, a...) printk(format, ## a) -#else -#define dbg_printk(format, a...) -#endif - -/******Data Structures*****************************************************/ - -/* This structure is placed in the private data area of the device structure. - * The card structure used to occupy the private area but now the following - * structure will incorporate the card structure along with CHDLC specific data - */ - -typedef struct chdlc_private_area -{ - wanpipe_common_t common; - sdla_t *card; - int TracingEnabled; /* For enabling Tracing */ - unsigned long curr_trace_addr; /* Used for Tracing */ - unsigned long start_trace_addr; - unsigned long end_trace_addr; - unsigned long base_addr_trace_buffer; - unsigned long end_addr_trace_buffer; - unsigned short number_trace_elements; - unsigned available_buffer_space; - unsigned long router_start_time; - unsigned char route_status; - unsigned char route_removed; - unsigned long tick_counter; /* For 5s timeout counter */ - unsigned long router_up_time; - u32 IP_address; /* IP addressing */ - u32 IP_netmask; - u32 ip_local; - u32 ip_remote; - u32 ip_local_tmp; - u32 ip_remote_tmp; - u8 ip_error; - u8 config_chdlc; - u8 config_chdlc_timeout; - unsigned char mc; /* Mulitcast support on/off */ - unsigned short udp_pkt_lgth; /* udp packet processing */ - char udp_pkt_src; - char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; - unsigned short timer_int_enabled; - char update_comms_stats; /* updating comms stats */ - - bh_data_t *bh_head; /* Circular buffer for chdlc_bh */ - unsigned long tq_working; - volatile int bh_write; - volatile int bh_read; - atomic_t bh_buff_used; - - unsigned char interface_down; - - /* Polling work queue entry. Each interface - * has its own work queue entry, which is used - * to defer events from the interrupt */ - struct work_struct poll_work; - struct timer_list poll_delay_timer; - - u8 gateway; - u8 true_if_encoding; - //FIXME: add driver stats as per frame relay! - -} chdlc_private_area_t; - -/* Route Status options */ -#define NO_ROUTE 0x00 -#define ADD_ROUTE 0x01 -#define ROUTE_ADDED 0x02 -#define REMOVE_ROUTE 0x03 - - -/* variable for keeping track of enabling/disabling FT1 monitor status */ -static int rCount = 0; - -/* variable for tracking how many interfaces to open for WANPIPE on the - two ports */ - -extern void disable_irq(unsigned int); -extern void enable_irq(unsigned int); - -/****** Function Prototypes *************************************************/ -/* WAN link driver entry points. These are called by the WAN router module. */ -static int update(struct wan_device* wandev); -static int new_if(struct wan_device* wandev, struct net_device* dev, - wanif_conf_t* conf); - -/* Network device interface */ -static int if_init(struct net_device* dev); -static int if_open(struct net_device* dev); -static int if_close(struct net_device* dev); -static int if_header(struct sk_buff* skb, struct net_device* dev, - unsigned short type, void* daddr, void* saddr, - unsigned len); - -static int if_rebuild_hdr (struct sk_buff *skb); -static struct net_device_stats* if_stats(struct net_device* dev); - -static int if_send(struct sk_buff* skb, struct net_device* dev); - -/* CHDLC Firmware interface functions */ -static int chdlc_configure (sdla_t* card, void* data); -static int chdlc_comm_enable (sdla_t* card); -static int chdlc_read_version (sdla_t* card, char* str); -static int chdlc_set_intr_mode (sdla_t* card, unsigned mode); -static int chdlc_send (sdla_t* card, void* data, unsigned len); -static int chdlc_read_comm_err_stats (sdla_t* card); -static int chdlc_read_op_stats (sdla_t* card); -static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb); - - -static int chdlc_disable_comm_shutdown (sdla_t *card); -static void if_tx_timeout(struct net_device *dev); - -/* Miscellaneous CHDLC Functions */ -static int set_chdlc_config (sdla_t* card); -static void init_chdlc_tx_rx_buff( sdla_t* card); -static int process_chdlc_exception(sdla_t *card); -static int process_global_exception(sdla_t *card); -static int update_comms_stats(sdla_t* card, - chdlc_private_area_t* chdlc_priv_area); -static int configure_ip (sdla_t* card); -static int unconfigure_ip (sdla_t* card); -static void process_route(sdla_t *card); -static void port_set_state (sdla_t *card, int); -static int config_chdlc (sdla_t *card); -static void disable_comm (sdla_t *card); - -static void trigger_chdlc_poll(struct net_device *dev); -static void chdlc_poll(struct net_device *dev); -static void chdlc_poll_delay (unsigned long dev_ptr); - - -/* Miscellaneous asynchronous interface Functions */ -static int set_asy_config (sdla_t* card); -static int asy_comm_enable (sdla_t* card); - -/* Interrupt handlers */ -static void wpc_isr (sdla_t* card); -static void rx_intr (sdla_t* card); -static void timer_intr(sdla_t *); - -/* Bottom half handlers */ -static void chdlc_work(struct net_device *dev); -static int chdlc_work_cleanup(struct net_device *dev); -static int bh_enqueue(struct net_device *dev, struct sk_buff *skb); - -/* Miscellaneous functions */ -static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev, - struct sk_buff *skb); -static int reply_udp( unsigned char *data, unsigned int mbox_len ); -static int intr_test( sdla_t* card); -static int udp_pkt_type( struct sk_buff *skb , sdla_t* card); -static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, struct net_device* dev, - chdlc_private_area_t* chdlc_priv_area); -static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, - chdlc_private_area_t* chdlc_priv_area); -static unsigned short calc_checksum (char *, int); -static void s508_lock (sdla_t *card, unsigned long *smp_flags); -static void s508_unlock (sdla_t *card, unsigned long *smp_flags); - - -static int Intr_test_counter; - -/* TTY Global Definitions */ - -#define NR_PORTS 4 -#define WAN_TTY_MAJOR 226 -#define WAN_TTY_MINOR 0 - -#define WAN_CARD(port) (tty_card_map[port]) -#define MIN_PORT 0 -#define MAX_PORT NR_PORTS-1 - -#define CRC_LENGTH 2 - -static int wanpipe_tty_init(sdla_t *card); -static void wanpipe_tty_receive(sdla_t *, unsigned, unsigned int); -static void wanpipe_tty_trigger_poll(sdla_t *card); - -static struct tty_driver serial_driver; -static int tty_init_cnt=0; - -static struct serial_state rs_table[NR_PORTS]; - -static char tty_driver_mode=WANOPT_TTY_SYNC; - -static char *opt_decode[] = {"NONE","CRTSCTS","XONXOFF-RX", - "CRTSCTS XONXOFF-RX","XONXOFF-TX", - "CRTSCTS XONXOFF-TX","CRTSCTS XONXOFF"}; -static char *p_decode[] = {"NONE","ODD","EVEN"}; - -static void* tty_card_map[NR_PORTS] = {NULL,NULL,NULL,NULL}; - - -/****** Public Functions ****************************************************/ - -/*============================================================================ - * Cisco HDLC 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 wpc_init (sdla_t* card, wandev_conf_t* conf) -{ - unsigned char port_num; - int err; - unsigned long max_permitted_baud = 0; - SHARED_MEMORY_INFO_STRUCT *flags; - - union - { - char str[80]; - } u; - volatile CHDLC_MAILBOX_STRUCT* mb; - CHDLC_MAILBOX_STRUCT* mb1; - unsigned long timeout; - - /* Verify configuration ID */ - if (conf->config_id != WANCONFIG_CHDLC) { - printk(KERN_INFO "%s: invalid configuration ID %u!\n", - card->devname, conf->config_id); - return -EINVAL; - } - - /* Find out which Port to use */ - if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){ - if (card->next){ - - if (conf->comm_port != card->next->u.c.comm_port){ - card->u.c.comm_port = conf->comm_port; - }else{ - printk(KERN_INFO "%s: ERROR - %s port used!\n", - card->wandev.name, PORT(conf->comm_port)); - return -EINVAL; - } - }else{ - card->u.c.comm_port = conf->comm_port; - } - }else{ - printk(KERN_INFO "%s: ERROR - Invalid Port Selected!\n", - card->wandev.name); - return -EINVAL; - } - - - /* Initialize protocol-specific fields */ - if(card->hw.type != SDLA_S514){ - - if (card->u.c.comm_port == WANOPT_PRI){ - card->mbox = (void *) card->hw.dpmbase; - }else{ - card->mbox = (void *) card->hw.dpmbase + - SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT; - } - }else{ - /* for a S514 adapter, set a pointer to the actual mailbox in the */ - /* allocated virtual memory area */ - if (card->u.c.comm_port == WANOPT_PRI){ - card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT; - }else{ - card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT; - } - } - - mb = mb1 = card->mbox; - - if (!card->configured){ - - /* The board will place an 'I' in the return code to indicate that it is - ready to accept commands. We expect this to be completed in less - than 1 second. */ - - timeout = jiffies; - while (mb->return_code != 'I') /* Wait 1s for board to initialize */ - if ((jiffies - timeout) > 1*HZ) break; - - if (mb->return_code != 'I') { - printk(KERN_INFO - "%s: Initialization not completed by adapter\n", - card->devname); - printk(KERN_INFO "Please contact Sangoma representative.\n"); - return -EIO; - } - } - - /* 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 (chdlc_read_version(card, u.str)) - return -EIO; - - printk(KERN_INFO "%s: Running Cisco HDLC firmware v%s\n", - card->devname, u.str); - - card->isr = &wpc_isr; - card->poll = NULL; - card->exec = NULL; - card->wandev.update = &update; - card->wandev.new_if = &new_if; - card->wandev.del_if = NULL; - card->wandev.udp_port = conf->udp_port; - card->disable_comm = &disable_comm; - card->wandev.new_if_cnt = 0; - - /* reset the number of times the 'update()' proc has been called */ - card->u.c.update_call_count = 0; - - card->wandev.ttl = conf->ttl; - card->wandev.interface = conf->interface; - - if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&& - card->hw.type != SDLA_S514){ - printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n", - card->devname, PORT(card->u.c.comm_port)); - return -EIO; - } - - card->wandev.clocking = conf->clocking; - - port_num = card->u.c.comm_port; - - /* in API mode, we can configure for "receive only" buffering */ - if(card->hw.type == SDLA_S514) { - card->u.c.receive_only = conf->receive_only; - if(conf->receive_only) { - printk(KERN_INFO - "%s: Configured for 'receive only' mode\n", - card->devname); - } - } - - /* Setup Port Bps */ - - if(card->wandev.clocking) { - if((port_num == WANOPT_PRI) || card->u.c.receive_only) { - /* For Primary Port 0 */ - 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; - - /* 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->flags |= IFF_POINTOPOINT; - dev->flags |= IFF_NOARP; - - /* Enable Mulitcasting if user selected */ - if (chdlc_priv_area->mc == WANOPT_YES){ - dev->flags |= IFF_MULTICAST; - } - - if (chdlc_priv_area->true_if_encoding){ - dev->type = ARPHRD_HDLC; /* This breaks the tcpdump */ - }else{ - dev->type = ARPHRD_PPP; - } - - dev->mtu = card->wandev.mtu; - /* for API usage, add the API header size to the requested MTU size */ - if(card->u.c.usedby == API) { - dev->mtu += sizeof(api_tx_hdr_t); - } - - dev->hard_header_len = CHDLC_HDR_LEN; - - /* Initialize hardware parameters */ - dev->irq = wandev->irq; - dev->dma = wandev->dma; - dev->base_addr = wandev->ioport; - dev->mem_start = wandev->maddr; - dev->mem_end = wandev->maddr + wandev->msize - 1; - - /* Set transmit buffer queue length - * If too low packets will not be retransmitted - * by stack. - */ - dev->tx_queue_len = 100; - SET_MODULE_OWNER(dev); - - return 0; -} - -/*============================================================================ - * Open network interface. - * o enable communications and interrupts. - * o prevent module from unloading by incrementing use count - * - * Return 0 if O.k. or errno. - */ -static int if_open(struct net_device* dev) -{ - chdlc_private_area_t* chdlc_priv_area = dev->priv; - sdla_t* card = chdlc_priv_area->card; - struct timeval tv; - int err = 0; - - /* Only one open per interface is allowed */ - - if (netif_running(dev)) - return -EBUSY; - - /* Initialize the work queue entry */ - chdlc_priv_area->tq_working=0; - - INIT_WORK(&chdlc_priv_area->common.wanpipe_work, - (void *)(void *)chdlc_work, dev); - - /* Allocate and initialize BH circular buffer */ - /* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */ - chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC); - memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1))); - atomic_set(&chdlc_priv_area->bh_buff_used, 0); - - do_gettimeofday(&tv); - chdlc_priv_area->router_start_time = tv.tv_sec; - - netif_start_queue(dev); - - wanpipe_open(card); - - /* TTY is configured during wanpipe_set_termios - * call, not here */ - if (card->tty_opt) - return err; - - set_bit(0,&chdlc_priv_area->config_chdlc); - chdlc_priv_area->config_chdlc_timeout=jiffies; - - /* Start the CHDLC configuration after 1sec delay. - * This will give the interface initilization time - * to finish its configuration */ - mod_timer(&chdlc_priv_area->poll_delay_timer, jiffies + HZ); - return err; -} - -/*============================================================================ - * Close network interface. - * o if this is the last close, then disable communications and interrupts. - * o reset flags. - */ -static int if_close(struct net_device* dev) -{ - chdlc_private_area_t* chdlc_priv_area = dev->priv; - sdla_t* card = chdlc_priv_area->card; - - if (chdlc_priv_area->bh_head){ - int i; - struct sk_buff *skb; - - for (i=0; i<(MAX_BH_BUFF+1); i++){ - skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb; - if (skb != NULL){ - dev_kfree_skb_any(skb); - } - } - kfree(chdlc_priv_area->bh_head); - chdlc_priv_area->bh_head=NULL; - } - - netif_stop_queue(dev); - wanpipe_close(card); - del_timer(&chdlc_priv_area->poll_delay_timer); - return 0; -} - -static void disable_comm (sdla_t *card) -{ - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - - if (card->u.c.comm_enabled){ - chdlc_disable_comm_shutdown (card); - }else{ - flags->interrupt_info_struct.interrupt_permission = 0; - } - - if (!tty_init_cnt) - return; - - if (card->tty_opt){ - struct serial_state * state; - if (!(--tty_init_cnt)){ - int e1; - serial_driver.refcount=0; - - if ((e1 = tty_unregister_driver(&serial_driver))) - printk("SERIAL: failed to unregister serial driver (%d)\n", - e1); - printk(KERN_INFO "%s: Unregistering TTY Driver, Major %i\n", - card->devname,WAN_TTY_MAJOR); - } - card->tty=NULL; - tty_card_map[card->tty_minor]=NULL; - state = &rs_table[card->tty_minor]; - memset(state, 0, sizeof(*state)); - } - return; -} - - -/*============================================================================ - * Build media header. - * - * The trick here is to put packet type (Ethertype) into 'protocol' field of - * the socket buffer, so that we don't forget it. If packet type is not - * supported, set skb->protocol to 0 and discard packet later. - * - * Return: media header length. - */ -static int if_header(struct sk_buff* skb, struct net_device* dev, - unsigned short type, void* daddr, void* saddr, - unsigned len) -{ - skb->protocol = htons(type); - - return CHDLC_HDR_LEN; -} - - -/*============================================================================ - * Handle transmit timeout event from netif watchdog - */ -static void if_tx_timeout(struct net_device *dev) -{ - chdlc_private_area_t* chan = dev->priv; - sdla_t *card = chan->card; - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - - ++card->wandev.stats.collisions; - - printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); - netif_wake_queue (dev); -} - - - -/*============================================================================ - * Re-build media header. - * - * Return: 1 physical address resolved. - * 0 physical address not resolved - */ -static int if_rebuild_hdr (struct sk_buff *skb) -{ - return 1; -} - - -/*============================================================================ - * Send a packet on a network interface. - * o set tbusy flag (marks start of the transmission) to block a timer-based - * transmit from overlapping. - * o check link state. If link is not up, then drop the packet. - * o execute adapter send command. - * o free socket buffer - * - * Return: 0 complete (socket buffer must be freed) - * non-0 packet may be re-transmitted (tbusy must be set) - * - * Notes: - * 1. This routine is called either by the protocol stack or by the "net - * bottom half" (with interrupts enabled). - * 2. Setting tbusy flag will inhibit further transmit requests from the - * protocol stack and can be used for flow control with protocol layer. - */ -static int if_send(struct sk_buff* skb, struct net_device* dev) -{ - chdlc_private_area_t *chdlc_priv_area = dev->priv; - sdla_t *card = chdlc_priv_area->card; - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct; - int udp_type = 0; - unsigned long smp_flags; - int err=0; - - netif_stop_queue(dev); - - if (skb == NULL){ - /* If we get here, some higher layer thinks we've missed an - * tx-done interrupt. - */ - printk(KERN_INFO "%s: interface %s got kicked!\n", - card->devname, dev->name); - - netif_wake_queue(dev); - return 0; - } - - if (ntohs(skb->protocol) != htons(PVC_PROT)){ - - /* check the udp packet type */ - - udp_type = udp_pkt_type(skb, card); - - if (udp_type == UDP_CPIPE_TYPE){ - if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, - chdlc_priv_area)){ - chdlc_int->interrupt_permission |= - APP_INT_ON_TIMER; - } - netif_start_queue(dev); - return 0; - } - - /* check to see if the source IP address is a broadcast or */ - /* multicast IP address */ - if(chk_bcast_mcast_addr(card, dev, skb)){ - ++card->wandev.stats.tx_dropped; - dev_kfree_skb_any(skb); - netif_start_queue(dev); - return 0; - } - } - - /* Lock the 508 Card: SMP is supported */ - if(card->hw.type != SDLA_S514){ - s508_lock(card,&smp_flags); - } - - if(test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) { - - printk(KERN_INFO "%s: Critical in if_send: %lx\n", - card->wandev.name,card->wandev.critical); - ++card->wandev.stats.tx_dropped; - netif_start_queue(dev); - goto if_send_exit_crit; - } - - if(card->u.c.state != WAN_CONNECTED){ - ++card->wandev.stats.tx_dropped; - netif_start_queue(dev); - - }else if(!skb->protocol){ - ++card->wandev.stats.tx_errors; - netif_start_queue(dev); - - }else { - void* data = skb->data; - unsigned len = skb->len; - unsigned char attr; - - /* If it's an API packet pull off the API - * header. Also check that the packet size - * is larger than the API header - */ - if (card->u.c.usedby == API){ - api_tx_hdr_t* api_tx_hdr; - - /* discard the frame if we are configured for */ - /* 'receive only' mode or if there is no data */ - if (card->u.c.receive_only || - (len <= sizeof(api_tx_hdr_t))) { - - ++card->wandev.stats.tx_dropped; - netif_start_queue(dev); - goto if_send_exit_crit; - } - - api_tx_hdr = (api_tx_hdr_t *)data; - attr = api_tx_hdr->attr; - data += sizeof(api_tx_hdr_t); - len -= sizeof(api_tx_hdr_t); - } - - if(chdlc_send(card, data, len)) { - netif_stop_queue(dev); - }else{ - ++card->wandev.stats.tx_packets; - card->wandev.stats.tx_bytes += len; - - netif_start_queue(dev); - - dev->trans_start = jiffies; - } - } - -if_send_exit_crit: - - if (!(err=netif_queue_stopped(dev))) { - dev_kfree_skb_any(skb); - }else{ - chdlc_priv_area->tick_counter = jiffies; - chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; - } - - clear_bit(SEND_CRIT, (void*)&card->wandev.critical); - if(card->hw.type != SDLA_S514){ - s508_unlock(card,&smp_flags); - } - - return err; -} - - -/*============================================================================ - * Check to see if the packet to be transmitted contains a broadcast or - * multicast source IP address. - */ - -static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev, - struct sk_buff *skb) -{ - u32 src_ip_addr; - u32 broadcast_ip_addr = 0; - struct in_device *in_dev; - - /* read the IP source address from the outgoing packet */ - src_ip_addr = *(u32 *)(skb->data + 12); - - /* read the IP broadcast address for the device */ - in_dev = dev->ip_ptr; - if(in_dev != NULL) { - struct in_ifaddr *ifa= in_dev->ifa_list; - if(ifa != NULL) - broadcast_ip_addr = ifa->ifa_broadcast; - else - return 0; - } - - /* check if the IP Source Address is a Broadcast address */ - if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { - printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n", - card->devname); - return 1; - } - - /* check if the IP Source Address is a Multicast address */ - if((ntohl(src_ip_addr) >= 0xE0000001) && - (ntohl(src_ip_addr) <= 0xFFFFFFFE)) { - printk(KERN_INFO "%s: Multicast Source Address silently discarded\n", - card->devname); - return 1; - } - - return 0; -} - - -/*============================================================================ - * Reply to UDP Management system. - * Return length of reply. - */ -static int reply_udp( unsigned char *data, unsigned int mbox_len ) -{ - - unsigned short len, udp_length, temp, ip_length; - unsigned long ip_temp; - int even_bound = 0; - chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data; - - /* Set length of packet */ - len = sizeof(ip_pkt_t)+ - sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - sizeof(trace_info_t)+ - mbox_len; - - /* fill in UDP reply */ - c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; - - /* fill in UDP length */ - udp_length = sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - sizeof(trace_info_t)+ - mbox_len; - - /* put it on an even boundary */ - if ( udp_length & 0x0001 ) { - udp_length += 1; - len += 1; - even_bound = 1; - } - - temp = (udp_length<<8)|(udp_length>>8); - c_udp_pkt->udp_pkt.udp_length = temp; - - /* swap UDP ports */ - temp = c_udp_pkt->udp_pkt.udp_src_port; - c_udp_pkt->udp_pkt.udp_src_port = - c_udp_pkt->udp_pkt.udp_dst_port; - c_udp_pkt->udp_pkt.udp_dst_port = temp; - - /* add UDP pseudo header */ - temp = 0x1100; - *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp; - temp = (udp_length<<8)|(udp_length>>8); - *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp; - - - /* calculate UDP checksum */ - c_udp_pkt->udp_pkt.udp_checksum = 0; - c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET); - - /* fill in IP length */ - ip_length = len; - temp = (ip_length<<8)|(ip_length>>8); - c_udp_pkt->ip_pkt.total_length = temp; - - /* swap IP addresses */ - ip_temp = c_udp_pkt->ip_pkt.ip_src_address; - c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address; - c_udp_pkt->ip_pkt.ip_dst_address = ip_temp; - - /* fill in IP checksum */ - c_udp_pkt->ip_pkt.hdr_checksum = 0; - c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t)); - - return len; - -} /* reply_udp */ - -unsigned short calc_checksum (char *data, int len) -{ - unsigned short temp; - unsigned long sum=0; - int i; - - for( i = 0; i > 16 ) { - sum = (sum & 0xffffUL) + (sum >> 16); - } - - temp = (unsigned short)sum; - temp = ~temp; - - if( temp == 0 ) - temp = 0xffff; - - return temp; -} - - -/*============================================================================ - * Get ethernet-style interface statistics. - * Return a pointer to struct enet_statistics. - */ -static struct net_device_stats* if_stats(struct net_device* dev) -{ - sdla_t *my_card; - chdlc_private_area_t* chdlc_priv_area; - - if ((chdlc_priv_area=dev->priv) == NULL) - return NULL; - - my_card = chdlc_priv_area->card; - return &my_card->wandev.stats; -} - - -/****** Cisco HDLC Firmware Interface Functions *******************************/ - -/*============================================================================ - * Read firmware code version. - * Put code version as ASCII string in str. - */ -static int chdlc_read_version (sdla_t* card, char* str) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - int len; - char err; - mb->buffer_length = 0; - mb->command = READ_CHDLC_CODE_VERSION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - if(err != COMMAND_OK) { - chdlc_error(card,err,mb); - } - else if (str) { /* is not null */ - len = mb->buffer_length; - memcpy(str, mb->data, len); - str[len] = '\0'; - } - return (err); -} - -/*----------------------------------------------------------------------------- - * Configure CHDLC firmware. - */ -static int chdlc_configure (sdla_t* card, void* data) -{ - int err; - CHDLC_MAILBOX_STRUCT *mailbox = card->mbox; - int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT); - - mailbox->buffer_length = data_length; - memcpy(mailbox->data, data, data_length); - mailbox->command = SET_CHDLC_CONFIGURATION; - err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT; - - if (err != COMMAND_OK) chdlc_error (card, err, mailbox); - - return err; -} - - -/*============================================================================ - * Set interrupt mode -- HDLC Version. - */ - -static int chdlc_set_intr_mode (sdla_t* card, unsigned mode) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - CHDLC_INT_TRIGGERS_STRUCT* int_data = - (CHDLC_INT_TRIGGERS_STRUCT *)mb->data; - int err; - - int_data->CHDLC_interrupt_triggers = mode; - int_data->IRQ = card->hw.irq; - int_data->interrupt_timer = 1; - - mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT); - mb->command = SET_CHDLC_INTERRUPT_TRIGGERS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error (card, err, mb); - return err; -} - - -/*=========================================================== - * chdlc_disable_comm_shutdown - * - * Shutdown() disables the communications. We must - * have a sparate functions, because we must not - * call chdlc_error() hander since the private - * area has already been replaced */ - -static int chdlc_disable_comm_shutdown (sdla_t *card) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - CHDLC_INT_TRIGGERS_STRUCT* int_data = - (CHDLC_INT_TRIGGERS_STRUCT *)mb->data; - int err; - - /* Disable Interrutps */ - int_data->CHDLC_interrupt_triggers = 0; - int_data->IRQ = card->hw.irq; - int_data->interrupt_timer = 1; - - mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT); - mb->command = SET_CHDLC_INTERRUPT_TRIGGERS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - /* Disable Communications */ - - if (card->u.c.async_mode) { - mb->command = DISABLE_ASY_COMMUNICATIONS; - }else{ - mb->command = DISABLE_CHDLC_COMMUNICATIONS; - } - - mb->buffer_length = 0; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - card->u.c.comm_enabled = 0; - - return 0; -} - -/*============================================================================ - * Enable communications. - */ - -static int chdlc_comm_enable (sdla_t* card) -{ - int err; - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - - mb->buffer_length = 0; - mb->command = ENABLE_CHDLC_COMMUNICATIONS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error(card, err, mb); - else - card->u.c.comm_enabled = 1; - - return err; -} - -/*============================================================================ - * Read communication error statistics. - */ -static int chdlc_read_comm_err_stats (sdla_t* card) -{ - int err; - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - - mb->buffer_length = 0; - mb->command = READ_COMMS_ERROR_STATS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error(card,err,mb); - return err; -} - - -/*============================================================================ - * Read CHDLC operational statistics. - */ -static int chdlc_read_op_stats (sdla_t* card) -{ - int err; - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - - mb->buffer_length = 0; - mb->command = READ_CHDLC_OPERATIONAL_STATS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error(card,err,mb); - return err; -} - - -/*============================================================================ - * Update communications error and general packet statistics. - */ -static int update_comms_stats(sdla_t* card, - chdlc_private_area_t* chdlc_priv_area) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - COMMS_ERROR_STATS_STRUCT* err_stats; - CHDLC_OPERATIONAL_STATS_STRUCT *op_stats; - - /* on the first timer interrupt, read the comms error statistics */ - if(chdlc_priv_area->update_comms_stats == 2) { - if(chdlc_read_comm_err_stats(card)) - return 1; - err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data; - card->wandev.stats.rx_over_errors = - err_stats->Rx_overrun_err_count; - card->wandev.stats.rx_crc_errors = - err_stats->CRC_err_count; - card->wandev.stats.rx_frame_errors = - err_stats->Rx_abort_count; - card->wandev.stats.rx_fifo_errors = - err_stats->Rx_dis_pri_bfrs_full_count; - card->wandev.stats.rx_missed_errors = - card->wandev.stats.rx_fifo_errors; - card->wandev.stats.tx_aborted_errors = - err_stats->sec_Tx_abort_count; - } - - /* on the second timer interrupt, read the operational statistics */ - else { - if(chdlc_read_op_stats(card)) - return 1; - op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data; - card->wandev.stats.rx_length_errors = - (op_stats->Rx_Data_discard_short_count + - op_stats->Rx_Data_discard_long_count); - } - - return 0; -} - -/*============================================================================ - * Send packet. - * Return: 0 - o.k. - * 1 - no transmit buffers available - */ -static int chdlc_send (sdla_t* card, void* data, unsigned len) -{ - CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf; - - if (txbuf->opp_flag) - return 1; - - sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len); - - txbuf->frame_length = len; - txbuf->opp_flag = 1; /* start transmission */ - - /* Update transmit buffer control fields */ - card->u.c.txbuf = ++txbuf; - - if ((void*)txbuf > card->u.c.txbuf_last) - card->u.c.txbuf = card->u.c.txbuf_base; - - return 0; -} - -/****** Firmware Error Handler **********************************************/ - -/*============================================================================ - * Firmware error handler. - * This routine is called whenever firmware command returns non-zero - * return code. - * - * Return zero if previous command has to be cancelled. - */ -static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb) -{ - unsigned cmd = mb->command; - - switch (err) { - - case CMD_TIMEOUT: - printk(KERN_INFO "%s: command 0x%02X timed out!\n", - card->devname, cmd); - break; - - case S514_BOTH_PORTS_SAME_CLK_MODE: - if(cmd == SET_CHDLC_CONFIGURATION) { - printk(KERN_INFO - "%s: Configure both ports for the same clock source\n", - card->devname); - break; - } - - default: - printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n", - card->devname, cmd, err); - } - - return 0; -} - - -/********** Bottom Half Handlers ********************************************/ - -/* NOTE: There is no API, BH support for Kernels lower than 2.2.X. - * DO NOT INSERT ANY CODE HERE, NOTICE THE - * PREPROCESSOR STATEMENT ABOVE, UNLESS YOU KNOW WHAT YOU ARE - * DOING */ - -static void chdlc_work(struct net_device * dev) -{ - chdlc_private_area_t* chan = dev->priv; - sdla_t *card = chan->card; - struct sk_buff *skb; - - if (atomic_read(&chan->bh_buff_used) == 0){ - clear_bit(0, &chan->tq_working); - return; - } - - while (atomic_read(&chan->bh_buff_used)){ - - skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb; - - if (skb != NULL){ - - if (chan->common.sk == NULL || chan->common.func == NULL){ - ++card->wandev.stats.rx_dropped; - dev_kfree_skb_any(skb); - chdlc_work_cleanup(dev); - continue; - } - - if (chan->common.func(skb,dev,chan->common.sk) != 0){ - /* Sock full cannot send, queue us for another - * try */ - atomic_set(&chan->common.receive_block,1); - return; - }else{ - chdlc_work_cleanup(dev); - } - }else{ - chdlc_work_cleanup(dev); - } - } - clear_bit(0, &chan->tq_working); - - return; -} - -static int chdlc_work_cleanup(struct net_device *dev) -{ - chdlc_private_area_t* chan = dev->priv; - - ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL; - - if (chan->bh_read == MAX_BH_BUFF){ - chan->bh_read=0; - }else{ - ++chan->bh_read; - } - - atomic_dec(&chan->bh_buff_used); - return 0; -} - - - -static int bh_enqueue(struct net_device *dev, struct sk_buff *skb) -{ - /* Check for full */ - chdlc_private_area_t* chan = dev->priv; - sdla_t *card = chan->card; - - if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){ - ++card->wandev.stats.rx_dropped; - dev_kfree_skb_any(skb); - return 1; - } - - ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb; - - if (chan->bh_write == MAX_BH_BUFF){ - chan->bh_write=0; - }else{ - ++chan->bh_write; - } - - atomic_inc(&chan->bh_buff_used); - - return 0; -} - -/* END OF API BH Support */ - - -/****** Interrupt Handlers **************************************************/ - -/*============================================================================ - * Cisco HDLC interrupt service routine. - */ -static void wpc_isr (sdla_t* card) -{ - struct net_device* dev; - SHARED_MEMORY_INFO_STRUCT* flags = NULL; - int i; - sdla_t *my_card; - - - /* Check for which port the interrupt has been generated - * Since Secondary Port is piggybacking on the Primary - * the check must be done here. - */ - - flags = card->u.c.flags; - if (!flags->interrupt_info_struct.interrupt_type){ - /* Check for a second port (piggybacking) */ - if ((my_card = card->next)){ - flags = my_card->u.c.flags; - if (flags->interrupt_info_struct.interrupt_type){ - card = my_card; - card->isr(card); - return; - } - } - } - - flags = card->u.c.flags; - card->in_isr = 1; - dev = card->wandev.dev; - - /* If we get an interrupt with no network device, stop the interrupts - * and issue an error */ - if (!card->tty_opt && !dev && - flags->interrupt_info_struct.interrupt_type != - COMMAND_COMPLETE_APP_INT_PEND){ - - goto isr_done; - } - - /* if critical due to peripheral operations - * ie. update() or getstats() then reset the interrupt and - * wait for the board to retrigger. - */ - if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { - printk(KERN_INFO "ISR CRIT TO PERI\n"); - goto isr_done; - } - - /* On a 508 Card, if critical due to if_send - * Major Error !!! */ - if(card->hw.type != SDLA_S514) { - if(test_bit(SEND_CRIT, (void*)&card->wandev.critical)) { - printk(KERN_INFO "%s: Critical while in ISR: %lx\n", - card->devname, card->wandev.critical); - card->in_isr = 0; - flags->interrupt_info_struct.interrupt_type = 0; - return; - } - } - - switch(flags->interrupt_info_struct.interrupt_type) { - - case RX_APP_INT_PEND: /* 0x01: receive interrupt */ - rx_intr(card); - break; - - case TX_APP_INT_PEND: /* 0x02: transmit interrupt */ - flags->interrupt_info_struct.interrupt_permission &= - ~APP_INT_ON_TX_FRAME; - - if (card->tty_opt){ - wanpipe_tty_trigger_poll(card); - break; - } - - if (dev && netif_queue_stopped(dev)){ - if (card->u.c.usedby == API){ - netif_start_queue(dev); - wakeup_sk_bh(dev); - }else{ - netif_wake_queue(dev); - } - } - break; - - case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */ - ++ Intr_test_counter; - break; - - case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */ - process_chdlc_exception(card); - break; - - case GLOBAL_EXCEP_COND_APP_INT_PEND: - process_global_exception(card); - break; - - case TIMER_APP_INT_PEND: - timer_intr(card); - break; - - default: - printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", - card->devname, - flags->interrupt_info_struct.interrupt_type); - printk(KERN_INFO "Code name: "); - for(i = 0; i < 4; i ++) - printk(KERN_INFO "%c", - flags->global_info_struct.codename[i]); - printk(KERN_INFO "\nCode version: "); - for(i = 0; i < 4; i ++) - printk(KERN_INFO "%c", - flags->global_info_struct.codeversion[i]); - printk(KERN_INFO "\n"); - break; - } - -isr_done: - - card->in_isr = 0; - flags->interrupt_info_struct.interrupt_type = 0; - return; -} - -/*============================================================================ - * Receive interrupt handler. - */ -static void rx_intr (sdla_t* card) -{ - struct net_device *dev; - chdlc_private_area_t *chdlc_priv_area; - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb; - struct sk_buff *skb; - unsigned len; - unsigned addr = rxbuf->ptr_data_bfr; - void *buf; - int i,udp_type; - - if (rxbuf->opp_flag != 0x01) { - printk(KERN_INFO - "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", - card->devname, (unsigned)rxbuf, rxbuf->opp_flag); - printk(KERN_INFO "Code name: "); - for(i = 0; i < 4; i ++) - printk(KERN_INFO "%c", - flags->global_info_struct.codename[i]); - printk(KERN_INFO "\nCode version: "); - for(i = 0; i < 4; i ++) - printk(KERN_INFO "%c", - flags->global_info_struct.codeversion[i]); - printk(KERN_INFO "\n"); - - - /* Bug Fix: Mar 6 2000 - * If we get a corrupted mailbox, it measn that driver - * is out of sync with the firmware. There is no recovery. - * If we don't turn off all interrupts for this card - * the machine will crash. - */ - printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); - printk(KERN_INFO "Please contact Sangoma Technologies !\n"); - chdlc_set_intr_mode(card,0); - return; - } - - len = rxbuf->frame_length; - - if (card->tty_opt){ - - if (rxbuf->error_flag){ - goto rx_exit; - } - - if (len <= CRC_LENGTH){ - goto rx_exit; - } - - if (!card->u.c.async_mode){ - len -= CRC_LENGTH; - } - - wanpipe_tty_receive(card,addr,len); - goto rx_exit; - } - - dev = card->wandev.dev; - - if (!dev){ - goto rx_exit; - } - - if (!netif_running(dev)) - goto rx_exit; - - chdlc_priv_area = dev->priv; - - - /* Allocate socket buffer */ - skb = dev_alloc_skb(len); - - if (skb == NULL) { - printk(KERN_INFO "%s: no socket buffers available!\n", - card->devname); - ++card->wandev.stats.rx_dropped; - goto rx_exit; - } - - /* Copy data to the socket buffer */ - if((addr + len) > card->u.c.rx_top + 1) { - unsigned tmp = card->u.c.rx_top - addr + 1; - buf = skb_put(skb, tmp); - sdla_peek(&card->hw, addr, buf, tmp); - addr = card->u.c.rx_base; - len -= tmp; - } - - buf = skb_put(skb, len); - sdla_peek(&card->hw, addr, buf, len); - - skb->protocol = htons(ETH_P_IP); - - card->wandev.stats.rx_packets ++; - card->wandev.stats.rx_bytes += skb->len; - udp_type = udp_pkt_type( skb, card ); - - if(udp_type == UDP_CPIPE_TYPE) { - if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, - card, skb, dev, chdlc_priv_area)) { - flags->interrupt_info_struct. - interrupt_permission |= - APP_INT_ON_TIMER; - } - } else if(card->u.c.usedby == API) { - - api_rx_hdr_t* api_rx_hdr; - skb_push(skb, sizeof(api_rx_hdr_t)); - api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00]; - api_rx_hdr->error_flag = rxbuf->error_flag; - api_rx_hdr->time_stamp = rxbuf->time_stamp; - - skb->protocol = htons(PVC_PROT); - skb->mac.raw = skb->data; - skb->dev = dev; - skb->pkt_type = WAN_PACKET_DATA; - - bh_enqueue(dev, skb); - - if (!test_and_set_bit(0,&chdlc_priv_area->tq_working)) - wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work); - }else{ - /* FIXME: we should check to see if the received packet is a - multicast packet so that we can increment the multicast - statistic - ++ chdlc_priv_area->if_stats.multicast; - */ - /* Pass it up the protocol stack */ - - skb->dev = dev; - skb->mac.raw = skb->data; - netif_rx(skb); - dev->last_rx = jiffies; - } - -rx_exit: - /* Release buffer element and calculate a pointer to the next one */ - rxbuf->opp_flag = 0x00; - card->u.c.rxmb = ++ rxbuf; - if((void*)rxbuf > card->u.c.rxbuf_last){ - card->u.c.rxmb = card->u.c.rxbuf_base; - } -} - -/*============================================================================ - * Timer interrupt handler. - * The timer interrupt is used for two purposes: - * 1) Processing udp calls from 'cpipemon'. - * 2) Reading board-level statistics for updating the proc file system. - */ -void timer_intr(sdla_t *card) -{ - struct net_device* dev; - chdlc_private_area_t* chdlc_priv_area = NULL; - SHARED_MEMORY_INFO_STRUCT* flags = NULL; - - if ((dev = card->wandev.dev)==NULL){ - flags = card->u.c.flags; - flags->interrupt_info_struct.interrupt_permission &= - ~APP_INT_ON_TIMER; - return; - } - - chdlc_priv_area = dev->priv; - - if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) { - if (!config_chdlc(card)){ - chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG; - } - } - - /* process a udp call if pending */ - if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) { - process_udp_mgmt_pkt(card, dev, - chdlc_priv_area); - chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP; - } - - /* read the communications statistics if required */ - if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) { - update_comms_stats(card, chdlc_priv_area); - if(!(-- chdlc_priv_area->update_comms_stats)) { - chdlc_priv_area->timer_int_enabled &= - ~TMR_INT_ENABLED_UPDATE; - } - } - - /* only disable the timer interrupt if there are no udp or statistic */ - /* updates pending */ - if(!chdlc_priv_area->timer_int_enabled) { - flags = card->u.c.flags; - flags->interrupt_info_struct.interrupt_permission &= - ~APP_INT_ON_TIMER; - } -} - -/*------------------------------------------------------------------------------ - Miscellaneous Functions - - set_chdlc_config() used to set configuration options on the board -------------------------------------------------------------------------------*/ - -static int set_chdlc_config(sdla_t* card) -{ - CHDLC_CONFIGURATION_STRUCT cfg; - - memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT)); - - if(card->wandev.clocking){ - cfg.baud_rate = card->wandev.bps; - } - - cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ? - INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35; - - cfg.modem_config_options = 0; - cfg.modem_status_timer = 100; - - cfg.CHDLC_protocol_options = card->u.c.protocol_options; - - if (card->tty_opt){ - cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES; - } - - cfg.percent_data_buffer_for_Tx = (card->u.c.receive_only) ? 0 : 50; - cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT | - CHDLC_RX_DATA_BYTE_COUNT_STAT); - - if (card->tty_opt){ - card->wandev.mtu = TTY_CHDLC_MAX_MTU; - } - cfg.max_CHDLC_data_field_length = card->wandev.mtu; - cfg.transmit_keepalive_timer = card->u.c.kpalv_tx; - cfg.receive_keepalive_timer = card->u.c.kpalv_rx; - cfg.keepalive_error_tolerance = card->u.c.kpalv_err; - cfg.SLARP_request_timer = card->u.c.slarp_timer; - - if (cfg.SLARP_request_timer) { - cfg.IP_address = 0; - cfg.IP_netmask = 0; - - }else if (card->wandev.dev){ - struct net_device *dev = card->wandev.dev; - chdlc_private_area_t *chdlc_priv_area = dev->priv; - - struct in_device *in_dev = dev->ip_ptr; - - if(in_dev != NULL) { - struct in_ifaddr *ifa = in_dev->ifa_list; - - if (ifa != NULL ) { - cfg.IP_address = ntohl(ifa->ifa_local); - cfg.IP_netmask = ntohl(ifa->ifa_mask); - chdlc_priv_area->IP_address = ntohl(ifa->ifa_local); - chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask); - } - } - - /* FIXME: We must re-think this message in next release - if((cfg.IP_address & 0x000000FF) > 2) { - printk(KERN_WARNING "\n"); - printk(KERN_WARNING " WARNING:%s configured with an\n", - card->devname); - printk(KERN_WARNING " invalid local IP address.\n"); - printk(KERN_WARNING " Slarp pragmatics will fail.\n"); - printk(KERN_WARNING " IP address should be of the\n"); - printk(KERN_WARNING " format A.B.C.1 or A.B.C.2.\n"); - } - */ - } - - return chdlc_configure(card, &cfg); -} - - -/*----------------------------------------------------------------------------- - set_asy_config() used to set asynchronous configuration options on the board -------------------------------------------------------------------------------*/ - -static int set_asy_config(sdla_t* card) -{ - - ASY_CONFIGURATION_STRUCT cfg; - CHDLC_MAILBOX_STRUCT *mailbox = card->mbox; - int err; - - memset(&cfg, 0, sizeof(ASY_CONFIGURATION_STRUCT)); - - if(card->wandev.clocking) - cfg.baud_rate = card->wandev.bps; - - cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ? - INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35; - - cfg.modem_config_options = 0; - cfg.asy_API_options = card->u.c.api_options; - cfg.asy_protocol_options = card->u.c.protocol_options; - cfg.Tx_bits_per_char = card->u.c.tx_bits_per_char; - cfg.Rx_bits_per_char = card->u.c.rx_bits_per_char; - cfg.stop_bits = card->u.c.stop_bits; - cfg.parity = card->u.c.parity; - cfg.break_timer = card->u.c.break_timer; - cfg.asy_Rx_inter_char_timer = card->u.c.inter_char_timer; - cfg.asy_Rx_complete_length = card->u.c.rx_complete_length; - cfg.XON_char = card->u.c.xon_char; - cfg.XOFF_char = card->u.c.xoff_char; - cfg.asy_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT | - CHDLC_RX_DATA_BYTE_COUNT_STAT); - - mailbox->buffer_length = sizeof(ASY_CONFIGURATION_STRUCT); - memcpy(mailbox->data, &cfg, mailbox->buffer_length); - mailbox->command = SET_ASY_CONFIGURATION; - err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error (card, err, mailbox); - return err; -} - -/*============================================================================ - * Enable asynchronous communications. - */ - -static int asy_comm_enable (sdla_t* card) -{ - - int err; - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - - mb->buffer_length = 0; - mb->command = ENABLE_ASY_COMMUNICATIONS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK && card->wandev.dev) - chdlc_error(card, err, mb); - - if (!err) - card->u.c.comm_enabled = 1; - - return err; -} - -/*============================================================================ - * Process global exception condition - */ -static int process_global_exception(sdla_t *card) -{ - CHDLC_MAILBOX_STRUCT* mbox = card->mbox; - int err; - - mbox->buffer_length = 0; - mbox->command = READ_GLOBAL_EXCEPTION_CONDITION; - err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT; - - if(err != CMD_TIMEOUT ){ - - switch(mbox->return_code) { - - case EXCEP_MODEM_STATUS_CHANGE: - - printk(KERN_INFO "%s: Modem status change\n", - card->devname); - - switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) { - case (DCD_HIGH): - printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname); - break; - case (CTS_HIGH): - printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname); - break; - case ((DCD_HIGH | CTS_HIGH)): - printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname); - break; - default: - printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname); - break; - } - break; - - case EXCEP_TRC_DISABLED: - printk(KERN_INFO "%s: Line trace disabled\n", - card->devname); - break; - - case EXCEP_IRQ_TIMEOUT: - printk(KERN_INFO "%s: IRQ timeout occurred\n", - card->devname); - break; - - case 0x17: - if (card->tty_opt){ - if (card->tty && card->tty_open){ - printk(KERN_INFO - "%s: Modem Hangup Exception: Hanging Up!\n", - card->devname); - tty_hangup(card->tty); - } - break; - } - - /* If TTY is not used just drop throught */ - - default: - printk(KERN_INFO "%s: Global exception %x\n", - card->devname, mbox->return_code); - break; - } - } - return 0; -} - - -/*============================================================================ - * Process chdlc exception condition - */ -static int process_chdlc_exception(sdla_t *card) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - int err; - - mb->buffer_length = 0; - mb->command = READ_CHDLC_EXCEPTION_CONDITION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if(err != CMD_TIMEOUT) { - - switch (err) { - - case EXCEP_LINK_ACTIVE: - port_set_state(card, WAN_CONNECTED); - trigger_chdlc_poll(card->wandev.dev); - break; - - case EXCEP_LINK_INACTIVE_MODEM: - port_set_state(card, WAN_DISCONNECTED); - unconfigure_ip(card); - trigger_chdlc_poll(card->wandev.dev); - break; - - case EXCEP_LINK_INACTIVE_KPALV: - port_set_state(card, WAN_DISCONNECTED); - printk(KERN_INFO "%s: Keepalive timer expired.\n", - card->devname); - unconfigure_ip(card); - trigger_chdlc_poll(card->wandev.dev); - break; - - case EXCEP_IP_ADDRESS_DISCOVERED: - if (configure_ip(card)) - return -1; - break; - - case EXCEP_LOOPBACK_CONDITION: - printk(KERN_INFO "%s: Loopback Condition Detected.\n", - card->devname); - break; - - case NO_CHDLC_EXCEP_COND_TO_REPORT: - printk(KERN_INFO "%s: No exceptions reported.\n", - card->devname); - break; - } - - } - return 0; -} - - -/*============================================================================ - * Configure IP from SLARP negotiation - * This adds dynamic routes when SLARP has provided valid addresses - */ - -static int configure_ip (sdla_t* card) -{ - struct net_device *dev = card->wandev.dev; - chdlc_private_area_t *chdlc_priv_area; - char err; - - if (!dev) - return 0; - - chdlc_priv_area = dev->priv; - - - /* set to discover */ - if(card->u.c.slarp_timer != 0x00) { - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - CHDLC_CONFIGURATION_STRUCT *cfg; - - mb->buffer_length = 0; - mb->command = READ_CHDLC_CONFIGURATION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - if(err != COMMAND_OK) { - chdlc_error(card,err,mb); - return -1; - } - - cfg = (CHDLC_CONFIGURATION_STRUCT *)mb->data; - chdlc_priv_area->IP_address = cfg->IP_address; - chdlc_priv_area->IP_netmask = cfg->IP_netmask; - - /* Set flag to add route */ - chdlc_priv_area->route_status = ADD_ROUTE; - - /* The idea here is to add the route in the poll routine. - This way, we aren't in interrupt context when adding routes */ - trigger_chdlc_poll(dev); - } - - return 0; -} - - -/*============================================================================ - * Un-Configure IP negotiated by SLARP - * This removes dynamic routes when the link becomes inactive. - */ - -static int unconfigure_ip (sdla_t* card) -{ - struct net_device *dev = card->wandev.dev; - chdlc_private_area_t *chdlc_priv_area; - - if (!dev) - return 0; - - chdlc_priv_area= dev->priv; - - if (chdlc_priv_area->route_status == ROUTE_ADDED) { - - /* Note: If this function is called, the - * port state has been DISCONNECTED. This state - * change will trigger a poll_disconnected - * function, that will check for this condition. - */ - chdlc_priv_area->route_status = REMOVE_ROUTE; - - } - return 0; -} - -/*============================================================================ - * Routine to add/remove routes - * Called like a polling routine when Routes are flagged to be added/removed. - */ - -static void process_route (sdla_t *card) -{ - struct net_device *dev = card->wandev.dev; - unsigned char port_num; - chdlc_private_area_t *chdlc_priv_area = NULL; - u32 local_IP_addr = 0; - u32 remote_IP_addr = 0; - u32 IP_netmask, IP_addr; - int err = 0; - struct in_device *in_dev; - mm_segment_t fs; - struct ifreq if_info; - struct sockaddr_in *if_data1, *if_data2; - - chdlc_priv_area = dev->priv; - port_num = card->u.c.comm_port; - - /* Bug Fix Mar 16 2000 - * AND the IP address to the Mask before checking - * the last two bits. */ - - if((chdlc_priv_area->route_status == ADD_ROUTE) && - ((chdlc_priv_area->IP_address & ~chdlc_priv_area->IP_netmask) > 2)) { - - printk(KERN_INFO "%s: Dynamic route failure.\n",card->devname); - - if(card->u.c.slarp_timer) { - u32 addr_net = htonl(chdlc_priv_area->IP_address); - - printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u received\n", - card->devname, - NIPQUAD(addr_net)); - printk(KERN_INFO "%s: from remote station.\n", - card->devname); - - }else{ - u32 addr_net = htonl(chdlc_priv_area->IP_address); - - printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u issued\n", - card->devname, - NIPQUAD(addr_net)); - printk(KERN_INFO "%s: to remote station. Local\n", - card->devname); - printk(KERN_INFO "%s: IP address must be A.B.C.1\n", - card->devname); - printk(KERN_INFO "%s: or A.B.C.2.\n",card->devname); - } - - /* remove the route due to the IP address error condition */ - chdlc_priv_area->route_status = REMOVE_ROUTE; - err = 1; - } - - /* If we are removing a route with bad IP addressing, then use the */ - /* locally configured IP addresses */ - if((chdlc_priv_area->route_status == REMOVE_ROUTE) && err) { - - /* do not remove a bad route that has already been removed */ - if(chdlc_priv_area->route_removed) { - return; - } - - in_dev = dev->ip_ptr; - - if(in_dev != NULL) { - struct in_ifaddr *ifa = in_dev->ifa_list; - if (ifa != NULL ) { - local_IP_addr = ifa->ifa_local; - IP_netmask = ifa->ifa_mask; - } - } - }else{ - /* According to Cisco HDLC, if the point-to-point address is - A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa. - */ - IP_netmask = ntohl(chdlc_priv_area->IP_netmask); - remote_IP_addr = ntohl(chdlc_priv_area->IP_address); - - - /* If Netmask is 255.255.255.255 the local address - * calculation will fail. Default it back to 255.255.255.0 */ - if (IP_netmask == 0xffffffff) - IP_netmask &= 0x00ffffff; - - /* Bug Fix Mar 16 2000 - * AND the Remote IP address with IP netmask, instead - * of static netmask of 255.255.255.0 */ - local_IP_addr = (remote_IP_addr & IP_netmask) + - (~remote_IP_addr & ntohl(0x0003)); - - if(!card->u.c.slarp_timer) { - IP_addr = local_IP_addr; - local_IP_addr = remote_IP_addr; - remote_IP_addr = IP_addr; - } - } - - fs = get_fs(); /* Save file system */ - set_fs(get_ds()); /* Get user space block */ - - /* Setup a structure for adding/removing routes */ - memset(&if_info, 0, sizeof(if_info)); - strcpy(if_info.ifr_name, dev->name); - - switch (chdlc_priv_area->route_status) { - - case ADD_ROUTE: - - if(!card->u.c.slarp_timer) { - if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; - if_data2->sin_addr.s_addr = remote_IP_addr; - if_data2->sin_family = AF_INET; - err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); - } else { - if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; - if_data1->sin_addr.s_addr = local_IP_addr; - if_data1->sin_family = AF_INET; - if(!(err = devinet_ioctl(SIOCSIFADDR, &if_info))){ - if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; - if_data2->sin_addr.s_addr = remote_IP_addr; - if_data2->sin_family = AF_INET; - err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); - } - } - - if(err) { - printk(KERN_INFO "%s: Add route %u.%u.%u.%u failed (%d)\n", - card->devname, NIPQUAD(remote_IP_addr), err); - } else { - ((chdlc_private_area_t *)dev->priv)->route_status = ROUTE_ADDED; - printk(KERN_INFO "%s: Dynamic route added.\n", - card->devname); - printk(KERN_INFO "%s: Local IP addr : %u.%u.%u.%u\n", - card->devname, NIPQUAD(local_IP_addr)); - printk(KERN_INFO "%s: Remote IP addr: %u.%u.%u.%u\n", - card->devname, NIPQUAD(remote_IP_addr)); - chdlc_priv_area->route_removed = 0; - } - break; - - - case REMOVE_ROUTE: - - /* Change the local ip address of the interface to 0. - * This will also delete the destination route. - */ - if(!card->u.c.slarp_timer) { - if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; - if_data2->sin_addr.s_addr = 0; - if_data2->sin_family = AF_INET; - err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); - } else { - if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; - if_data1->sin_addr.s_addr = 0; - if_data1->sin_family = AF_INET; - err = devinet_ioctl(SIOCSIFADDR,&if_info); - - } - if(err) { - printk(KERN_INFO - "%s: Remove route %u.%u.%u.%u failed, (err %d)\n", - card->devname, NIPQUAD(remote_IP_addr), - err); - } else { - ((chdlc_private_area_t *)dev->priv)->route_status = - NO_ROUTE; - printk(KERN_INFO "%s: Dynamic route removed: %u.%u.%u.%u\n", - card->devname, NIPQUAD(local_IP_addr)); - chdlc_priv_area->route_removed = 1; - } - break; - } - - set_fs(fs); /* Restore file system */ - -} - - -/*============================================================================= - * Store a UDP management packet for later processing. - */ - -static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, struct net_device* dev, - chdlc_private_area_t* chdlc_priv_area) -{ - int udp_pkt_stored = 0; - - if(!chdlc_priv_area->udp_pkt_lgth && - (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) { - chdlc_priv_area->udp_pkt_lgth = skb->len; - chdlc_priv_area->udp_pkt_src = udp_pkt_src; - memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len); - chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP; - udp_pkt_stored = 1; - } - - if(udp_pkt_src == UDP_PKT_FRM_STACK){ - dev_kfree_skb_any(skb); - }else{ - dev_kfree_skb_any(skb); - } - - return(udp_pkt_stored); -} - - -/*============================================================================= - * Process UDP management packet. - */ - -static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, - chdlc_private_area_t* chdlc_priv_area ) -{ - unsigned char *buf; - unsigned int frames, len; - struct sk_buff *new_skb; - unsigned short buffer_length, real_len; - unsigned long data_ptr; - unsigned data_length; - int udp_mgmt_req_valid = 1; - CHDLC_MAILBOX_STRUCT *mb = card->mbox; - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - chdlc_udp_pkt_t *chdlc_udp_pkt; - struct timeval tv; - int err; - char ut_char; - - chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data; - - if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){ - - /* Only these commands are support for remote debugging. - * All others are not */ - switch(chdlc_udp_pkt->cblock.command) { - - case READ_GLOBAL_STATISTICS: - case READ_MODEM_STATUS: - case READ_CHDLC_LINK_STATUS: - case CPIPE_ROUTER_UP_TIME: - case READ_COMMS_ERROR_STATS: - case READ_CHDLC_OPERATIONAL_STATS: - - /* These two commands are executed for - * each request */ - case READ_CHDLC_CONFIGURATION: - case READ_CHDLC_CODE_VERSION: - udp_mgmt_req_valid = 1; - break; - default: - udp_mgmt_req_valid = 0; - break; - } - } - - if(!udp_mgmt_req_valid) { - - /* set length to 0 */ - chdlc_udp_pkt->cblock.buffer_length = 0; - - /* set return code */ - chdlc_udp_pkt->cblock.return_code = 0xCD; - - if (net_ratelimit()){ - printk(KERN_INFO - "%s: Warning, Illegal UDP command attempted from network: %x\n", - card->devname,chdlc_udp_pkt->cblock.command); - } - - } else { - unsigned long trace_status_cfg_addr = 0; - TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct; - TRACE_STATUS_ELEMENT_STRUCT trace_element_struct; - - switch(chdlc_udp_pkt->cblock.command) { - - case CPIPE_ENABLE_TRACING: - if (!chdlc_priv_area->TracingEnabled) { - - /* OPERATE_DATALINE_MONITOR */ - - mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT); - mb->command = SET_TRACE_CONFIGURATION; - - ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> - trace_config = TRACE_ACTIVE; - /* Trace delay mode is not used because it slows - down transfer and results in a standoff situation - when there is a lot of data */ - - /* Configure the Trace based on user inputs */ - ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |= - chdlc_udp_pkt->data[0]; - - ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> - trace_deactivation_timer = 4000; - - - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) { - chdlc_error(card,err,mb); - card->TracingEnabled = 0; - chdlc_udp_pkt->cblock.return_code = err; - mb->buffer_length = 0; - break; - } - - /* Get the base address of the trace element list */ - mb->buffer_length = 0; - mb->command = READ_TRACE_CONFIGURATION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - if (err != COMMAND_OK) { - chdlc_error(card,err,mb); - chdlc_priv_area->TracingEnabled = 0; - chdlc_udp_pkt->cblock.return_code = err; - mb->buffer_length = 0; - break; - } - - trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *) - mb->data) -> ptr_trace_stat_el_cfg_struct; - - sdla_peek(&card->hw, trace_status_cfg_addr, - &trace_cfg_struct, sizeof(trace_cfg_struct)); - - chdlc_priv_area->start_trace_addr = trace_cfg_struct. - base_addr_trace_status_elements; - - chdlc_priv_area->number_trace_elements = - trace_cfg_struct.number_trace_status_elements; - - chdlc_priv_area->end_trace_addr = (unsigned long) - ((TRACE_STATUS_ELEMENT_STRUCT *) - chdlc_priv_area->start_trace_addr + - (chdlc_priv_area->number_trace_elements - 1)); - - chdlc_priv_area->base_addr_trace_buffer = - trace_cfg_struct.base_addr_trace_buffer; - - chdlc_priv_area->end_addr_trace_buffer = - trace_cfg_struct.end_addr_trace_buffer; - - chdlc_priv_area->curr_trace_addr = - trace_cfg_struct.next_trace_element_to_use; - - chdlc_priv_area->available_buffer_space = 2000 - - sizeof(ip_pkt_t) - - sizeof(udp_pkt_t) - - sizeof(wp_mgmt_t) - - sizeof(cblock_t) - - sizeof(trace_info_t); - } - chdlc_udp_pkt->cblock.return_code = COMMAND_OK; - mb->buffer_length = 0; - chdlc_priv_area->TracingEnabled = 1; - break; - - - case CPIPE_DISABLE_TRACING: - if (chdlc_priv_area->TracingEnabled) { - - /* OPERATE_DATALINE_MONITOR */ - mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT); - mb->command = SET_TRACE_CONFIGURATION; - ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> - trace_config = TRACE_INACTIVE; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - } - - chdlc_priv_area->TracingEnabled = 0; - chdlc_udp_pkt->cblock.return_code = COMMAND_OK; - mb->buffer_length = 0; - break; - - - case CPIPE_GET_TRACE_INFO: - - if (!chdlc_priv_area->TracingEnabled) { - chdlc_udp_pkt->cblock.return_code = 1; - mb->buffer_length = 0; - break; - } - - chdlc_udp_pkt->trace_info.ismoredata = 0x00; - buffer_length = 0; /* offset of packet already occupied */ - - for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){ - - trace_pkt_t *trace_pkt = (trace_pkt_t *) - &chdlc_udp_pkt->data[buffer_length]; - - sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr, - (unsigned char *)&trace_element_struct, - sizeof(TRACE_STATUS_ELEMENT_STRUCT)); - - if (trace_element_struct.opp_flag == 0x00) { - break; - } - - /* get pointer to real data */ - data_ptr = trace_element_struct.ptr_data_bfr; - - /* See if there is actual data on the trace buffer */ - if (data_ptr){ - data_length = trace_element_struct.trace_length; - }else{ - data_length = 0; - chdlc_udp_pkt->trace_info.ismoredata = 0x01; - } - - if( (chdlc_priv_area->available_buffer_space - buffer_length) - < ( sizeof(trace_pkt_t) + data_length) ) { - - /* indicate there are more frames on board & exit */ - chdlc_udp_pkt->trace_info.ismoredata = 0x01; - break; - } - - trace_pkt->status = trace_element_struct.trace_type; - - trace_pkt->time_stamp = - trace_element_struct.trace_time_stamp; - - trace_pkt->real_length = - trace_element_struct.trace_length; - - /* see if we can fit the frame into the user buffer */ - real_len = trace_pkt->real_length; - - if (data_ptr == 0) { - trace_pkt->data_avail = 0x00; - } else { - unsigned tmp = 0; - - /* get the data from circular buffer - must check for end of buffer */ - trace_pkt->data_avail = 0x01; - - if ((data_ptr + real_len) > - chdlc_priv_area->end_addr_trace_buffer + 1){ - - tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1; - sdla_peek(&card->hw, data_ptr, - trace_pkt->data,tmp); - data_ptr = chdlc_priv_area->base_addr_trace_buffer; - } - - sdla_peek(&card->hw, data_ptr, - &trace_pkt->data[tmp], real_len - tmp); - } - - /* zero the opp flag to show we got the frame */ - ut_char = 0x00; - sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1); - - /* now move onto the next frame */ - chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT); - - /* check if we went over the last address */ - if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) { - chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr; - } - - if(trace_pkt->data_avail == 0x01) { - buffer_length += real_len - 1; - } - - /* for the header */ - buffer_length += sizeof(trace_pkt_t); - - } /* For Loop */ - - if (frames == chdlc_priv_area->number_trace_elements){ - chdlc_udp_pkt->trace_info.ismoredata = 0x01; - } - chdlc_udp_pkt->trace_info.num_frames = frames; - - mb->buffer_length = buffer_length; - chdlc_udp_pkt->cblock.buffer_length = buffer_length; - - chdlc_udp_pkt->cblock.return_code = COMMAND_OK; - - break; - - - case CPIPE_FT1_READ_STATUS: - ((unsigned char *)chdlc_udp_pkt->data )[0] = - flags->FT1_info_struct.parallel_port_A_input; - - ((unsigned char *)chdlc_udp_pkt->data )[1] = - flags->FT1_info_struct.parallel_port_B_input; - - chdlc_udp_pkt->cblock.return_code = COMMAND_OK; - chdlc_udp_pkt->cblock.buffer_length = 2; - mb->buffer_length = 2; - break; - - case CPIPE_ROUTER_UP_TIME: - do_gettimeofday( &tv ); - chdlc_priv_area->router_up_time = tv.tv_sec - - chdlc_priv_area->router_start_time; - *(unsigned long *)&chdlc_udp_pkt->data = - chdlc_priv_area->router_up_time; - mb->buffer_length = sizeof(unsigned long); - chdlc_udp_pkt->cblock.buffer_length = sizeof(unsigned long); - chdlc_udp_pkt->cblock.return_code = COMMAND_OK; - break; - - case FT1_MONITOR_STATUS_CTRL: - /* Enable FT1 MONITOR STATUS */ - if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) || - (chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) { - - if( rCount++ != 0 ) { - chdlc_udp_pkt->cblock. - return_code = COMMAND_OK; - mb->buffer_length = 1; - break; - } - } - - /* Disable FT1 MONITOR STATUS */ - if( chdlc_udp_pkt->data[0] == 0) { - - if( --rCount != 0) { - chdlc_udp_pkt->cblock. - return_code = COMMAND_OK; - mb->buffer_length = 1; - break; - } - } - goto dflt_1; - - default: -dflt_1: - /* it's a board command */ - mb->command = chdlc_udp_pkt->cblock.command; - mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length; - if (mb->buffer_length) { - memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt-> - data, mb->buffer_length); - } - /* run the command on the board */ - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) { - break; - } - - /* copy the result back to our buffer */ - memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t)); - - if (mb->buffer_length) { - memcpy(&chdlc_udp_pkt->data, &mb->data, - mb->buffer_length); - } - - } /* end of switch */ - } /* end of else */ - - /* Fill UDP TTL */ - chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl; - - len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length); - - - if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){ - - /* Must check if we interrupted if_send() routine. The - * tx buffers might be used. If so drop the packet */ - if (!test_bit(SEND_CRIT,&card->wandev.critical)) { - - if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) { - ++ card->wandev.stats.tx_packets; - card->wandev.stats.tx_bytes += len; - } - } - } else { - - /* Pass it up the stack - Allocate socket buffer */ - if ((new_skb = dev_alloc_skb(len)) != NULL) { - /* copy data into new_skb */ - - buf = skb_put(new_skb, len); - memcpy(buf, chdlc_priv_area->udp_pkt_data, len); - - /* Decapsulate pkt and pass it up the protocol stack */ - new_skb->protocol = htons(ETH_P_IP); - new_skb->dev = dev; - new_skb->mac.raw = new_skb->data; - - netif_rx(new_skb); - dev->last_rx = jiffies; - } else { - - printk(KERN_INFO "%s: no socket buffers available!\n", - card->devname); - } - } - - chdlc_priv_area->udp_pkt_lgth = 0; - - return 0; -} - -/*============================================================================ - * Initialize Receive and Transmit Buffers. - */ - -static void init_chdlc_tx_rx_buff( sdla_t* card) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config; - CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config; - char err; - - mb->buffer_length = 0; - mb->command = READ_CHDLC_CONFIGURATION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - if(err != COMMAND_OK) { - if (card->wandev.dev){ - chdlc_error(card,err,mb); - } - return; - } - - if(card->hw.type == SDLA_S514) { - tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + - (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> - ptr_CHDLC_Tx_stat_el_cfg_struct)); - rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + - (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> - ptr_CHDLC_Rx_stat_el_cfg_struct)); - - /* Setup Head and Tails for buffers */ - card->u.c.txbuf_base = (void *)(card->hw.dpmbase + - tx_config->base_addr_Tx_status_elements); - card->u.c.txbuf_last = - (CHDLC_DATA_TX_STATUS_EL_STRUCT *) - card->u.c.txbuf_base + - (tx_config->number_Tx_status_elements - 1); - - card->u.c.rxbuf_base = (void *)(card->hw.dpmbase + - rx_config->base_addr_Rx_status_elements); - card->u.c.rxbuf_last = - (CHDLC_DATA_RX_STATUS_EL_STRUCT *) - card->u.c.rxbuf_base + - (rx_config->number_Rx_status_elements - 1); - - /* Set up next pointer to be used */ - card->u.c.txbuf = (void *)(card->hw.dpmbase + - tx_config->next_Tx_status_element_to_use); - card->u.c.rxmb = (void *)(card->hw.dpmbase + - rx_config->next_Rx_status_element_to_use); - } - else { - tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + - (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> - ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE)); - - rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + - (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> - ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE)); - - /* Setup Head and Tails for buffers */ - card->u.c.txbuf_base = (void *)(card->hw.dpmbase + - (tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE)); - card->u.c.txbuf_last = - (CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base - + (tx_config->number_Tx_status_elements - 1); - card->u.c.rxbuf_base = (void *)(card->hw.dpmbase + - (rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE)); - card->u.c.rxbuf_last = - (CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base - + (rx_config->number_Rx_status_elements - 1); - - /* Set up next pointer to be used */ - card->u.c.txbuf = (void *)(card->hw.dpmbase + - (tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE)); - card->u.c.rxmb = (void *)(card->hw.dpmbase + - (rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE)); - } - - /* Setup Actual Buffer Start and end addresses */ - card->u.c.rx_base = rx_config->base_addr_Rx_buffer; - card->u.c.rx_top = rx_config->end_addr_Rx_buffer; - -} - -/*============================================================================= - * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR - * _TEST_COUNTER times. - */ -static int intr_test( sdla_t* card) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - int err,i; - - Intr_test_counter = 0; - - err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE); - - if (err == CMD_OK) { - for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) { - mb->buffer_length = 0; - mb->command = READ_CHDLC_CODE_VERSION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != CMD_OK) - chdlc_error(card, err, mb); - } - } - else { - return err; - } - - err = chdlc_set_intr_mode(card, 0); - - if (err != CMD_OK) - return err; - - return 0; -} - -/*============================================================================== - * Determine what type of UDP call it is. CPIPEAB ? - */ -static int udp_pkt_type(struct sk_buff *skb, sdla_t* card) -{ - chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data; - -#ifdef _WAN_UDP_DEBUG - printk(KERN_INFO "SIG %s = %s\n\ - UPP %x = %x\n\ - PRT %x = %x\n\ - REQ %i = %i\n\ - 36 th = %x 37th = %x\n", - chdlc_udp_pkt->wp_mgmt.signature, - UDPMGMT_SIGNATURE, - chdlc_udp_pkt->udp_pkt.udp_dst_port, - ntohs(card->wandev.udp_port), - chdlc_udp_pkt->ip_pkt.protocol, - UDPMGMT_UDP_PROTOCOL, - chdlc_udp_pkt->wp_mgmt.request_reply, - UDPMGMT_REQUEST, - skb->data[36], skb->data[37]); -#endif - - if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) && - (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) && - (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) && - (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) { - - return UDP_CPIPE_TYPE; - - }else{ - return UDP_INVALID_TYPE; - } -} - -/*============================================================================ - * Set PORT state. - */ -static void port_set_state (sdla_t *card, int state) -{ - if (card->u.c.state != state) - { - switch (state) - { - case WAN_CONNECTED: - printk (KERN_INFO "%s: Link connected!\n", - card->devname); - break; - - case WAN_CONNECTING: - printk (KERN_INFO "%s: Link connecting...\n", - card->devname); - break; - - case WAN_DISCONNECTED: - printk (KERN_INFO "%s: Link disconnected!\n", - card->devname); - break; - } - - card->wandev.state = card->u.c.state = state; - if (card->wandev.dev){ - struct net_device *dev = card->wandev.dev; - chdlc_private_area_t *chdlc_priv_area = dev->priv; - chdlc_priv_area->common.state = state; - } - } -} - -/*=========================================================================== - * config_chdlc - * - * Configure the chdlc protocol and enable communications. - * - * The if_open() function binds this function to the poll routine. - * Therefore, this function will run every time the chdlc interface - * is brought up. We cannot run this function from the if_open - * because if_open does not have access to the remote IP address. - * - * If the communications are not enabled, proceed to configure - * the card and enable communications. - * - * If the communications are enabled, it means that the interface - * was shutdown by ether the user or driver. In this case, we - * have to check that the IP addresses have not changed. If - * the IP addresses have changed, we have to reconfigure the firmware - * and update the changed IP addresses. Otherwise, just exit. - * - */ - -static int config_chdlc (sdla_t *card) -{ - struct net_device *dev = card->wandev.dev; - chdlc_private_area_t *chdlc_priv_area = dev->priv; - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - - if (card->u.c.comm_enabled){ - - /* Jun 20. 2000: NC - * IP addresses are not used in the API mode */ - - if ((chdlc_priv_area->ip_local_tmp != chdlc_priv_area->ip_local || - chdlc_priv_area->ip_remote_tmp != chdlc_priv_area->ip_remote) && - card->u.c.usedby == WANPIPE) { - - /* The IP addersses have changed, we must - * stop the communications and reconfigure - * the card. Reason: the firmware must know - * the local and remote IP addresses. */ - disable_comm(card); - port_set_state(card, WAN_DISCONNECTED); - printk(KERN_INFO - "%s: IP addresses changed!\n", - card->devname); - printk(KERN_INFO - "%s: Restarting communications ...\n", - card->devname); - }else{ - /* IP addresses are the same and the link is up, - * we don't have to do anything here. Therefore, exit */ - return 0; - } - } - - chdlc_priv_area->ip_local = chdlc_priv_area->ip_local_tmp; - chdlc_priv_area->ip_remote = chdlc_priv_area->ip_remote_tmp; - - - /* Setup the Board for asynchronous mode */ - if (card->u.c.async_mode){ - - if (set_asy_config(card)) { - printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n", - card->devname); - return 0; - } - }else{ - /* Setup the Board for CHDLC */ - if (set_chdlc_config(card)) { - printk (KERN_INFO "%s: Failed CHDLC configuration!\n", - card->devname); - return 0; - } - } - - /* Set interrupt mode and mask */ - if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME | - APP_INT_ON_GLOBAL_EXCEP_COND | - APP_INT_ON_TX_FRAME | - APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){ - printk (KERN_INFO "%s: Failed to set interrupt triggers!\n", - card->devname); - return 0; - } - - - /* Mask the Transmit and Timer interrupt */ - flags->interrupt_info_struct.interrupt_permission &= - ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER); - - /* In TTY mode, receive interrupt will be enabled during - * wanpipe_tty_open() operation */ - if (card->tty_opt){ - flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_RX_FRAME; - } - - /* Enable communications */ - if (card->u.c.async_mode){ - if (asy_comm_enable(card) != 0) { - printk(KERN_INFO "%s: Failed to enable async commnunication!\n", - card->devname); - flags->interrupt_info_struct.interrupt_permission = 0; - card->u.c.comm_enabled=0; - chdlc_set_intr_mode(card,0); - return 0; - } - }else{ - if (chdlc_comm_enable(card) != 0) { - printk(KERN_INFO "%s: Failed to enable chdlc communications!\n", - card->devname); - flags->interrupt_info_struct.interrupt_permission = 0; - card->u.c.comm_enabled=0; - chdlc_set_intr_mode(card,0); - return 0; - } - } - - /* Initialize Rx/Tx buffer control fields */ - init_chdlc_tx_rx_buff(card); - port_set_state(card, WAN_CONNECTING); - return 0; -} - - -/*============================================================ - * chdlc_poll - * - * Rationale: - * We cannot manipulate the routing tables, or - * ip addresses withing the interrupt. Therefore - * we must perform such actons outside an interrupt - * at a later time. - * - * Description: - * CHDLC polling routine, responsible for - * shutting down interfaces upon disconnect - * and adding/removing routes. - * - * Usage: - * This function is executed for each CHDLC - * interface through a tq_schedule bottom half. - * - * trigger_chdlc_poll() function is used to kick - * the chldc_poll routine. - */ - -static void chdlc_poll(struct net_device *dev) -{ - chdlc_private_area_t *chdlc_priv_area; - sdla_t *card; - u8 check_gateway=0; - SHARED_MEMORY_INFO_STRUCT* flags; - - - if (!dev || (chdlc_priv_area=dev->priv) == NULL) - return; - - card = chdlc_priv_area->card; - flags = card->u.c.flags; - - /* (Re)Configuraiton is in progress, stop what you are - * doing and get out */ - if (test_bit(PERI_CRIT,&card->wandev.critical)){ - clear_bit(POLL_CRIT,&card->wandev.critical); - return; - } - - /* if_open() function has triggered the polling routine - * to determine the configured IP addresses. Once the - * addresses are found, trigger the chdlc configuration */ - if (test_bit(0,&chdlc_priv_area->config_chdlc)){ - - chdlc_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP); - chdlc_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP); - - /* Jun 20. 2000 Bug Fix - * Only perform this check in WANPIPE mode, since - * IP addresses are not used in the API mode. */ - - if (chdlc_priv_area->ip_local_tmp == chdlc_priv_area->ip_remote_tmp && - card->u.c.slarp_timer == 0x00 && - !card->u.c.backup && - card->u.c.usedby == WANPIPE){ - - if (++chdlc_priv_area->ip_error > MAX_IP_ERRORS){ - printk(KERN_INFO "\n%s: --- WARNING ---\n", - card->devname); - printk(KERN_INFO - "%s: The local IP address is the same as the\n", - card->devname); - printk(KERN_INFO - "%s: Point-to-Point IP address.\n", - card->devname); - printk(KERN_INFO "%s: --- WARNING ---\n\n", - card->devname); - }else{ - clear_bit(POLL_CRIT,&card->wandev.critical); - chdlc_priv_area->poll_delay_timer.expires = jiffies+HZ; - add_timer(&chdlc_priv_area->poll_delay_timer); - return; - } - } - - clear_bit(0,&chdlc_priv_area->config_chdlc); - clear_bit(POLL_CRIT,&card->wandev.critical); - - chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG; - flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER; - return; - } - /* Dynamic interface implementation, as well as dynamic - * routing. */ - - switch (card->u.c.state){ - - case WAN_DISCONNECTED: - - /* If the dynamic interface configuration is on, and interface - * is up, then bring down the netowrk interface */ - - if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) && - !test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) && - card->wandev.dev->flags & IFF_UP){ - - printk(KERN_INFO "%s: Interface %s down.\n", - card->devname,card->wandev.dev->name); - change_dev_flags(card->wandev.dev,(card->wandev.dev->flags&~IFF_UP)); - set_bit(DEV_DOWN,&chdlc_priv_area->interface_down); - chdlc_priv_area->route_status = NO_ROUTE; - - }else{ - /* We need to check if the local IP address is - * zero. If it is, we shouldn't try to remove it. - */ - - if (card->wandev.dev->flags & IFF_UP && - get_ip_address(card->wandev.dev,WAN_LOCAL_IP) && - chdlc_priv_area->route_status != NO_ROUTE && - card->u.c.slarp_timer){ - - process_route(card); - } - } - break; - - case WAN_CONNECTED: - - /* In SMP machine this code can execute before the interface - * comes up. In this case, we must make sure that we do not - * try to bring up the interface before dev_open() is finished */ - - - /* DEV_DOWN will be set only when we bring down the interface - * for the very first time. This way we know that it was us - * that brought the interface down */ - - if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) && - test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) && - !(card->wandev.dev->flags & IFF_UP)){ - - printk(KERN_INFO "%s: Interface %s up.\n", - card->devname,card->wandev.dev->name); - change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP)); - clear_bit(DEV_DOWN,&chdlc_priv_area->interface_down); - check_gateway=1; - } - - if (chdlc_priv_area->route_status == ADD_ROUTE && - card->u.c.slarp_timer){ - - process_route(card); - check_gateway=1; - } - - if (chdlc_priv_area->gateway && check_gateway) - add_gateway(card,dev); - - break; - } - - clear_bit(POLL_CRIT,&card->wandev.critical); -} - -/*============================================================ - * trigger_chdlc_poll - * - * Description: - * Add a chdlc_poll() work entry into the keventd work queue - * for a specific dlci/interface. This will kick - * the fr_poll() routine at a later time. - * - * Usage: - * Interrupts use this to defer a taks to - * a polling routine. - * - */ -static void trigger_chdlc_poll(struct net_device *dev) -{ - chdlc_private_area_t *chdlc_priv_area; - sdla_t *card; - - if (!dev) - return; - - if ((chdlc_priv_area = dev->priv)==NULL) - return; - - card = chdlc_priv_area->card; - - if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){ - return; - } - if (test_bit(PERI_CRIT,&card->wandev.critical)){ - return; - } - schedule_work(&chdlc_priv_area->poll_work); -} - - -static void chdlc_poll_delay (unsigned long dev_ptr) -{ - struct net_device *dev = (struct net_device *)dev_ptr; - trigger_chdlc_poll(dev); -} - - -void s508_lock (sdla_t *card, unsigned long *smp_flags) -{ - spin_lock_irqsave(&card->wandev.lock, *smp_flags); - if (card->next){ - spin_lock(&card->next->wandev.lock); - } -} - -void s508_unlock (sdla_t *card, unsigned long *smp_flags) -{ - if (card->next){ - spin_unlock(&card->next->wandev.lock); - } - spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -} - -//*********** TTY SECTION **************** - -static void wanpipe_tty_trigger_tx_irq(sdla_t *card) -{ - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct; - chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; -} - -static void wanpipe_tty_trigger_poll(sdla_t *card) -{ - schedule_work(&card->tty_work); -} - -static void tty_poll_work (void* data) -{ - sdla_t *card = (sdla_t*)data; - struct tty_struct *tty; - - if ((tty=card->tty)==NULL) - return; - - tty_wakeup(tty); -#if defined(SERIAL_HAVE_POLL_WAIT) - wake_up_interruptible(&tty->poll_wait); -#endif - return; -} - -static void wanpipe_tty_close(struct tty_struct *tty, struct file * filp) -{ - sdla_t *card; - unsigned long smp_flags; - - if (!tty || !tty->driver_data){ - return; - } - - card = (sdla_t*)tty->driver_data; - - if (!card) - return; - - printk(KERN_INFO "%s: Closing TTY Driver!\n", - card->devname); - - /* Sanity Check */ - if (!card->tty_open) - return; - - wanpipe_close(card); - if (--card->tty_open == 0){ - - lock_adapter_irq(&card->wandev.lock,&smp_flags); - card->tty=NULL; - chdlc_disable_comm_shutdown(card); - unlock_adapter_irq(&card->wandev.lock,&smp_flags); - - kfree(card->tty_buf); - card->tty_buf = NULL; - kfree(card->tty_rx); - card->tty_rx = NULL; - } - return; -} -static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp) -{ - unsigned long smp_flags; - sdla_t *card; - - if (!tty){ - return -ENODEV; - } - - if (!tty->driver_data){ - int port; - port = tty->index; - if ((port < 0) || (port >= NR_PORTS)) - return -ENODEV; - - tty->driver_data = WAN_CARD(port); - if (!tty->driver_data) - return -ENODEV; - } - - card = (sdla_t*)tty->driver_data; - - if (!card){ - lock_adapter_irq(&card->wandev.lock,&smp_flags); - card->tty=NULL; - unlock_adapter_irq(&card->wandev.lock,&smp_flags); - return -ENODEV; - } - - printk(KERN_INFO "%s: Opening TTY Driver!\n", - card->devname); - - if (card->tty_open == 0){ - lock_adapter_irq(&card->wandev.lock,&smp_flags); - card->tty=tty; - unlock_adapter_irq(&card->wandev.lock,&smp_flags); - - if (!card->tty_buf){ - card->tty_buf = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL); - if (!card->tty_buf){ - card->tty_buf=NULL; - card->tty=NULL; - return -ENOMEM; - } - } - - if (!card->tty_rx){ - card->tty_rx = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL); - if (!card->tty_rx){ - /* Free the buffer above */ - kfree(card->tty_buf); - card->tty_buf=NULL; - card->tty=NULL; - return -ENOMEM; - } - } - } - - ++card->tty_open; - wanpipe_open(card); - return 0; -} - -static int wanpipe_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) -{ - unsigned long smp_flags=0; - sdla_t *card=NULL; - - if (!tty){ - dbg_printk(KERN_INFO "NO TTY in Write\n"); - return -ENODEV; - } - - card = (sdla_t *)tty->driver_data; - - if (!card){ - dbg_printk(KERN_INFO "No Card in TTY Write\n"); - return -ENODEV; - } - - if (count > card->wandev.mtu){ - dbg_printk(KERN_INFO "Frame too big in Write %i Max: %i\n", - count,card->wandev.mtu); - return -EINVAL; - } - - if (card->wandev.state != WAN_CONNECTED){ - dbg_printk(KERN_INFO "Card not connected in TTY Write\n"); - return -EINVAL; - } - - /* Lock the 508 Card: SMP is supported */ - if(card->hw.type != SDLA_S514){ - s508_lock(card,&smp_flags); - } - - if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){ - printk(KERN_INFO "%s: Critical in TTY Write\n", - card->devname); - - /* Lock the 508 Card: SMP is supported */ - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - - return -EINVAL; - } - - if (chdlc_send(card,(void*)buf,count)){ - dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!\n", - card->devname); - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - wanpipe_tty_trigger_tx_irq(card); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - return 0; - } - dbg_printk(KERN_INFO "%s: Packet sent OK: %i\n",card->devname,count); - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - - return count; -} - -static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len) -{ - unsigned offset=0; - unsigned olen=len; - char fp=0; - struct tty_struct *tty; - int i; - struct tty_ldisc *ld; - - if (!card->tty_open){ - dbg_printk(KERN_INFO "%s: TTY not open during receive\n", - card->devname); - return; - } - - if ((tty=card->tty) == NULL){ - dbg_printk(KERN_INFO "%s: No TTY on receive\n", - card->devname); - return; - } - - if (!tty->driver_data){ - dbg_printk(KERN_INFO "%s: No Driver Data, or Flip on receive\n", - card->devname); - return; - } - - - if (card->u.c.async_mode){ - if ((tty->flip.count+len) >= TTY_FLIPBUF_SIZE){ - if (net_ratelimit()){ - printk(KERN_INFO - "%s: Received packet size too big: %i bytes, Max: %i!\n", - card->devname,len,TTY_FLIPBUF_SIZE); - } - return; - } - - - if((addr + len) > card->u.c.rx_top + 1) { - offset = card->u.c.rx_top - addr + 1; - - sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, offset); - - addr = card->u.c.rx_base; - len -= offset; - - tty->flip.char_buf_ptr+=offset; - tty->flip.count+=offset; - for (i=0;iflip.flag_buf_ptr = 0; - tty->flip.flag_buf_ptr++; - } - } - - sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, len); - - tty->flip.char_buf_ptr+=len; - card->tty->flip.count+=len; - for (i=0;iflip.flag_buf_ptr = 0; - tty->flip.flag_buf_ptr++; - } - - tty->low_latency=1; - tty_flip_buffer_push(tty); - }else{ - if (!card->tty_rx){ - if (net_ratelimit()){ - printk(KERN_INFO - "%s: Receive sync buffer not available!\n", - card->devname); - } - return; - } - - if (len > TTY_CHDLC_MAX_MTU){ - if (net_ratelimit()){ - printk(KERN_INFO - "%s: Received packet size too big: %i bytes, Max: %i!\n", - card->devname,len,TTY_FLIPBUF_SIZE); - } - return; - } - - - if((addr + len) > card->u.c.rx_top + 1) { - offset = card->u.c.rx_top - addr + 1; - - sdla_peek(&card->hw, addr, card->tty_rx, offset); - - addr = card->u.c.rx_base; - len -= offset; - } - sdla_peek(&card->hw, addr, card->tty_rx+offset, len); - ld = tty_ldisc_ref(tty); - if (ld) { - if (ld->receive_buf) - ld->receive_buf(tty,card->tty_rx,&fp,olen); - tty_ldisc_deref(ld); - }else{ - if (net_ratelimit()){ - printk(KERN_INFO - "%s: NO TTY Sync line discipline!\n", - card->devname); - } - } - } - - dbg_printk(KERN_INFO "%s: Received Data %i\n",card->devname,olen); - return; -} - -#if 0 -static int wanpipe_tty_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - return -ENOIOCTLCMD; -} -#endif - -static void wanpipe_tty_stop(struct tty_struct *tty) -{ - return; -} - -static void wanpipe_tty_start(struct tty_struct *tty) -{ - return; -} - -static int config_tty (sdla_t *card) -{ - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - - /* Setup the Board for asynchronous mode */ - if (card->u.c.async_mode){ - - if (set_asy_config(card)) { - printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n", - card->devname); - return -EINVAL; - } - }else{ - /* Setup the Board for CHDLC */ - if (set_chdlc_config(card)) { - printk (KERN_INFO "%s: Failed CHDLC configuration!\n", - card->devname); - return -EINVAL; - } - } - - /* Set interrupt mode and mask */ - if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME | - APP_INT_ON_GLOBAL_EXCEP_COND | - APP_INT_ON_TX_FRAME | - APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){ - printk (KERN_INFO "%s: Failed to set interrupt triggers!\n", - card->devname); - return -EINVAL; - } - - - /* Mask the Transmit and Timer interrupt */ - flags->interrupt_info_struct.interrupt_permission &= - ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER); - - - /* Enable communications */ - if (card->u.c.async_mode){ - if (asy_comm_enable(card) != 0) { - printk(KERN_INFO "%s: Failed to enable async commnunication!\n", - card->devname); - flags->interrupt_info_struct.interrupt_permission = 0; - card->u.c.comm_enabled=0; - chdlc_set_intr_mode(card,0); - return -EINVAL; - } - }else{ - if (chdlc_comm_enable(card) != 0) { - printk(KERN_INFO "%s: Failed to enable chdlc communications!\n", - card->devname); - flags->interrupt_info_struct.interrupt_permission = 0; - card->u.c.comm_enabled=0; - chdlc_set_intr_mode(card,0); - return -EINVAL; - } - } - - /* Initialize Rx/Tx buffer control fields */ - init_chdlc_tx_rx_buff(card); - port_set_state(card, WAN_CONNECTING); - return 0; -} - - -static int change_speed(sdla_t *card, struct tty_struct *tty, - struct termios *old_termios) -{ - int baud, ret=0; - unsigned cflag; - int dbits,sbits,parity,handshaking; - - cflag = tty->termios->c_cflag; - - /* There is always one stop bit */ - sbits=WANOPT_ONE; - - /* Parity is defaulted to NONE */ - parity = WANOPT_NONE; - - handshaking=0; - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: dbits = 5; break; - case CS6: dbits = 6; break; - case CS7: dbits = 7; break; - case CS8: dbits = 8; break; - /* Never happens, but GCC is too dumb to figure it out */ - default: dbits = 8; break; - } - - /* One more stop bit should be supported, thus increment - * the number of stop bits Max=2 */ - if (cflag & CSTOPB) { - sbits = WANOPT_TWO; - } - if (cflag & PARENB) { - parity = WANOPT_EVEN; - } - if (cflag & PARODD){ - parity = WANOPT_ODD; - } - - /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(tty); - - if (!baud) - baud = 9600; /* B0 transition handled in rs_set_termios */ - - if (cflag & CRTSCTS) { - handshaking|=ASY_RTS_HS_FOR_RX; - } - - if (I_IGNPAR(tty)) - parity = WANOPT_NONE; - - if (I_IXOFF(tty)){ - handshaking|=ASY_XON_XOFF_HS_FOR_RX; - handshaking|=ASY_XON_XOFF_HS_FOR_TX; - } - - if (I_IXON(tty)){ - handshaking|=ASY_XON_XOFF_HS_FOR_RX; - handshaking|=ASY_XON_XOFF_HS_FOR_TX; - } - - if (card->u.c.async_mode){ - if (card->wandev.bps != baud) - ret=1; - card->wandev.bps = baud; - } - - if (card->u.c.async_mode){ - if (card->u.c.protocol_options != handshaking) - ret=1; - card->u.c.protocol_options = handshaking; - - if (card->u.c.tx_bits_per_char != dbits) - ret=1; - card->u.c.tx_bits_per_char = dbits; - - if (card->u.c.rx_bits_per_char != dbits) - ret=1; - card->u.c.rx_bits_per_char = dbits; - - if (card->u.c.stop_bits != sbits) - ret=1; - card->u.c.stop_bits = sbits; - - if (card->u.c.parity != parity) - ret=1; - card->u.c.parity = parity; - - card->u.c.break_timer = 50; - card->u.c.inter_char_timer = 10; - card->u.c.rx_complete_length = 100; - card->u.c.xon_char = 0xFE; - }else{ - card->u.c.protocol_options = HDLC_STREAMING_MODE; - } - - return ret; -} - - -static void wanpipe_tty_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - sdla_t *card; - int err=1; - - if (!tty){ - return; - } - - card = (sdla_t *)tty->driver_data; - - if (!card) - return; - - if (change_speed(card, tty, old_termios) || !card->u.c.comm_enabled){ - unsigned long smp_flags; - - if (card->u.c.comm_enabled){ - lock_adapter_irq(&card->wandev.lock,&smp_flags); - chdlc_disable_comm_shutdown(card); - unlock_adapter_irq(&card->wandev.lock,&smp_flags); - } - lock_adapter_irq(&card->wandev.lock,&smp_flags); - err = config_tty(card); - unlock_adapter_irq(&card->wandev.lock,&smp_flags); - if (card->u.c.async_mode){ - printk(KERN_INFO "%s: TTY Async Configuration:\n" - " Baud =%i\n" - " Handshaking =%s\n" - " Tx Dbits =%i\n" - " Rx Dbits =%i\n" - " Parity =%s\n" - " Stop Bits =%i\n", - card->devname, - card->wandev.bps, - opt_decode[card->u.c.protocol_options], - card->u.c.tx_bits_per_char, - card->u.c.rx_bits_per_char, - p_decode[card->u.c.parity] , - card->u.c.stop_bits); - }else{ - printk(KERN_INFO "%s: TTY Sync Configuration:\n" - " Baud =%i\n" - " Protocol =HDLC_STREAMING\n", - card->devname,card->wandev.bps); - } - if (!err){ - port_set_state(card,WAN_CONNECTED); - }else{ - port_set_state(card,WAN_DISCONNECTED); - } - } - return; -} - -static void wanpipe_tty_put_char(struct tty_struct *tty, unsigned char ch) -{ - sdla_t *card; - unsigned long smp_flags=0; - - if (!tty){ - return; - } - - card = (sdla_t *)tty->driver_data; - - if (!card) - return; - - if (card->wandev.state != WAN_CONNECTED) - return; - - if(card->hw.type != SDLA_S514) - s508_lock(card,&smp_flags); - - if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){ - - wanpipe_tty_trigger_tx_irq(card); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - return; - } - - if (chdlc_send(card,(void*)&ch,1)){ - wanpipe_tty_trigger_tx_irq(card); - dbg_printk("%s: Failed to TX char!\n",card->devname); - } - - dbg_printk("%s: Char TX OK\n",card->devname); - - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - - if(card->hw.type != SDLA_S514) - s508_unlock(card,&smp_flags); - - return; -} - -static void wanpipe_tty_flush_chars(struct tty_struct *tty) -{ - return; -} - -static void wanpipe_tty_flush_buffer(struct tty_struct *tty) -{ - if (!tty) - return; - -#if defined(SERIAL_HAVE_POLL_WAIT) - wake_up_interruptible(&tty->poll_wait); -#endif - tty_wakeup(tty); - return; -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void wanpipe_tty_send_xchar(struct tty_struct *tty, char ch) -{ - return; -} - - -static int wanpipe_tty_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - - -static int wanpipe_tty_write_room(struct tty_struct *tty) -{ - sdla_t *card; - - printk(KERN_INFO "TTY Write Room\n"); - - if (!tty){ - return 0; - } - - card = (sdla_t *)tty->driver_data; - if (!card) - return 0; - - if (card->wandev.state != WAN_CONNECTED) - return 0; - - return SEC_MAX_NO_DATA_BYTES_IN_FRAME; -} - - -static int set_modem_status(sdla_t *card, unsigned char data) -{ - CHDLC_MAILBOX_STRUCT *mb = card->mbox; - int err; - - mb->buffer_length=1; - mb->command=SET_MODEM_STATUS; - mb->data[0]=data; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error (card, err, mb); - - return err; -} - -static void wanpipe_tty_hangup(struct tty_struct *tty) -{ - sdla_t *card; - unsigned long smp_flags; - - printk(KERN_INFO "TTY Hangup!\n"); - - if (!tty){ - return; - } - - card = (sdla_t *)tty->driver_data; - if (!card) - return; - - lock_adapter_irq(&card->wandev.lock,&smp_flags); - set_modem_status(card,0); - unlock_adapter_irq(&card->wandev.lock,&smp_flags); - return; -} - -static void wanpipe_tty_break(struct tty_struct *tty, int break_state) -{ - return; -} - -static void wanpipe_tty_wait_until_sent(struct tty_struct *tty, int timeout) -{ - return; -} - -static void wanpipe_tty_throttle(struct tty_struct * tty) -{ - return; -} - -static void wanpipe_tty_unthrottle(struct tty_struct * tty) -{ - return; -} - -int wanpipe_tty_read_proc(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - return 0; -} - -/* - * The serial driver boot-time initialization code! - */ -int wanpipe_tty_init(sdla_t *card) -{ - struct serial_state * state; - - /* Initialize the tty_driver structure */ - - if (card->tty_minor < 0 || card->tty_minor > NR_PORTS){ - printk(KERN_INFO "%s: Illegal Minor TTY number (0-4): %i\n", - card->devname,card->tty_minor); - return -EINVAL; - } - - if (WAN_CARD(card->tty_minor)){ - printk(KERN_INFO "%s: TTY Minor %i, already in use\n", - card->devname,card->tty_minor); - return -EBUSY; - } - - if (tty_init_cnt==0){ - - printk(KERN_INFO "%s: TTY %s Driver Init: Major %i, Minor Range %i-%i\n", - card->devname, - card->u.c.async_mode ? "ASYNC" : "SYNC", - WAN_TTY_MAJOR,MIN_PORT,MAX_PORT); - - tty_driver_mode = card->u.c.async_mode; - - memset(&serial_driver, 0, sizeof(struct tty_driver)); - serial_driver.magic = TTY_DRIVER_MAGIC; - serial_driver.owner = THIS_MODULE; - serial_driver.driver_name = "wanpipe_tty"; - serial_driver.name = "ttyW"; - serial_driver.major = WAN_TTY_MAJOR; - serial_driver.minor_start = WAN_TTY_MINOR; - serial_driver.num = NR_PORTS; - serial_driver.type = TTY_DRIVER_TYPE_SERIAL; - serial_driver.subtype = SERIAL_TYPE_NORMAL; - - serial_driver.init_termios = tty_std_termios; - serial_driver.init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver.flags = TTY_DRIVER_REAL_RAW; - - serial_driver.refcount = 1; /* !@!@^#^&!! */ - - serial_driver.open = wanpipe_tty_open; - serial_driver.close = wanpipe_tty_close; - serial_driver.write = wanpipe_tty_write; - - serial_driver.put_char = wanpipe_tty_put_char; - serial_driver.flush_chars = wanpipe_tty_flush_chars; - serial_driver.write_room = wanpipe_tty_write_room; - serial_driver.chars_in_buffer = wanpipe_tty_chars_in_buffer; - serial_driver.flush_buffer = wanpipe_tty_flush_buffer; - //serial_driver.ioctl = wanpipe_tty_ioctl; - serial_driver.throttle = wanpipe_tty_throttle; - serial_driver.unthrottle = wanpipe_tty_unthrottle; - serial_driver.send_xchar = wanpipe_tty_send_xchar; - serial_driver.set_termios = wanpipe_tty_set_termios; - serial_driver.stop = wanpipe_tty_stop; - serial_driver.start = wanpipe_tty_start; - serial_driver.hangup = wanpipe_tty_hangup; - serial_driver.break_ctl = wanpipe_tty_break; - serial_driver.wait_until_sent = wanpipe_tty_wait_until_sent; - serial_driver.read_proc = wanpipe_tty_read_proc; - - if (tty_register_driver(&serial_driver)){ - printk(KERN_INFO "%s: Failed to register serial driver!\n", - card->devname); - } - } - - - /* The subsequent ports must comply to the initial configuration */ - if (tty_driver_mode != card->u.c.async_mode){ - printk(KERN_INFO "%s: Error: TTY Driver operation mode mismatch!\n", - card->devname); - printk(KERN_INFO "%s: The TTY driver is configured for %s!\n", - card->devname, tty_driver_mode ? "ASYNC" : "SYNC"); - return -EINVAL; - } - - tty_init_cnt++; - - printk(KERN_INFO "%s: Initializing TTY %s Driver Minor %i\n", - card->devname, - tty_driver_mode ? "ASYNC" : "SYNC", - card->tty_minor); - - tty_card_map[card->tty_minor] = card; - state = &rs_table[card->tty_minor]; - - state->magic = SSTATE_MAGIC; - state->line = 0; - state->type = PORT_UNKNOWN; - state->custom_divisor = 0; - state->close_delay = 5*HZ/10; - state->closing_wait = 30*HZ; - state->icount.cts = state->icount.dsr = - state->icount.rng = state->icount.dcd = 0; - state->icount.rx = state->icount.tx = 0; - state->icount.frame = state->icount.parity = 0; - state->icount.overrun = state->icount.brk = 0; - state->irq = card->wandev.irq; - - INIT_WORK(&card->tty_work, tty_poll_work, (void*)card); - return 0; -} - - -MODULE_LICENSE("GPL"); - -/****** End ****************************************************************/ diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c deleted file mode 100644 index 7f1ce9d4333e..000000000000 --- a/drivers/net/wan/sdla_fr.c +++ /dev/null @@ -1,5061 +0,0 @@ -/***************************************************************************** -* sdla_fr.c WANPIPE(tm) Multiprotocol WAN Link Driver. Frame relay module. -* -* Author(s): Nenad Corbic -* Gideon Hack -* -* Copyright: (c) 1995-2001 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 23, 2000 Nenad Corbic o Added support for 2.4.X kernels -* Nov 15, 2000 David Rokavarg -* Nenad Corbic o Added frame relay bridging support. -* Original code from Mark Wells and Kristian Hoffmann has -* been integrated into the frame relay driver. -* Nov 13, 2000 Nenad Corbic o Added true interface type encoding option. -* Tcpdump doesn't support Frame Relay inteface -* types, to fix this true type option will set -* the interface type to RAW IP mode. -* Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging: -* Deny all and specify allowed requests. -* Nov 06, 2000 Nenad Corbic o Wanpipe interfaces conform to raw packet interfaces. -* Moved the if_header into the if_send() routine. -* The if_header() was breaking the libpcap -* support. i.e. support for tcpdump, ethereal ... -* Oct 12. 2000 Nenad Corbic o Added error message in fr_configure -* Jul 31, 2000 Nenad Corbic o Fixed the Router UP Time. -* Apr 28, 2000 Nenad Corbic o Added the option to shutdown an interface -* when the channel gets disconnected. -* Apr 28, 2000 Nenad Corbic o Added M.Grants patch: disallow duplicate -* interface setups. -* Apr 25, 2000 Nenad Corbic o Added M.Grants patch: dynamically add/remove -* new dlcis/interfaces. -* Mar 23, 2000 Nenad Corbic o Improved task queue, bh handling. -* Mar 16, 2000 Nenad Corbic o Added Inverse ARP support -* Mar 13, 2000 Nenad Corbic o Added new socket API support. -* Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery. -* Feb 24, 2000 Nenad Corbic o Fixed up FT1 UDP debugging problem. -* Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels -* -* Nov 08, 1999 Nenad Corbic o Combined all debug UDP calls into one function -* o Removed the ARP support. This has to be done -* in the next version. -* o Only a Node can implement NO signalling. -* Initialize DLCI during if_open() if NO -* signalling. -* o Took out IPX support, implement in next -* version -* Sep 29, 1999 Nenad Corbic o Added SMP support and changed the update -* function to use timer interrupt. -* o Fixed the CIR bug: Set the value of BC -* to CIR when the CIR is enabled. -* o Updated comments, statistics and tracing. -* Jun 02, 1999 Gideon Hack o Updated for S514 support. -* Sep 18, 1998 Jaspreet Singh o Updated for 2.2.X kernels. -* Jul 31, 1998 Jaspreet Singh o Removed wpf_poll routine. The channel/DLCI -* status is received through an event interrupt. -* Jul 08, 1998 David Fong o Added inverse ARP support. -* Mar 26, 1997 Jaspreet Singh o Returning return codes for failed UDP cmds. -* Jan 28, 1997 Jaspreet Singh o Improved handling of inactive DLCIs. -* Dec 30, 1997 Jaspreet Singh o Replaced dev_tint() with mark_bh(NET_BH) -* Dec 16, 1997 Jaspreet Singh o Implemented Multiple IPX support. -* 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 -#include /* printk(), and other useful stuff */ -#include /* offsetof(), etc. */ -#include /* return codes */ -#include /* inline memset(), etc. */ -#include /* kmalloc(), kfree() */ -#include /* WAN router definitions */ -#include /* WANPIPE common user API definitions */ -#include -#include /* ARPHRD_* defines */ -#include /* htons(), etc. */ -#include /* for inb(), outb(), etc. */ -#include /* for do_gettimeofday */ -#include /* sockaddr_in */ -#include /* time_after() macro */ -#include - -#include -#include - -#include /* Wanpipe Socket */ -#include - -#include /* frame relay firmware API definitions */ - -#include -#include -#include - -#include /* Dynamic Route Creation */ -#include /* eth_type_trans() used for bridging */ -#include - -/****** 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 - -#define FRAME_RELAY_API 1 -#define MAX_BH_BUFF 10 - -/* 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 -{ - wanpipe_common_t common; - 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() */ - 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 */ - unsigned char enable_IPX; /* Enable/Disable the use of IPX */ - unsigned long network_number; /* Internal Network Number for IPX*/ - sdla_t *card; /* -> owner */ - unsigned route_flag; /* Add/Rem dest addr in route tables */ - unsigned inarp; /* Inverse Arp Request status */ - long inarp_ready; /* Ready to send requests */ - int inarp_interval; /* Time between InArp Requests */ - unsigned long inarp_tick; /* InArp jiffies tick counter */ - long interface_down; /* Bring interface down on disconnect */ - struct net_device_stats ifstats; /* interface statistics */ - if_send_stat_t drvstats_if_send; - rx_intr_stat_t drvstats_rx_intr; - pipe_mgmt_stat_t drvstats_gen; - unsigned long router_up_time; - - unsigned short transmit_length; - struct sk_buff *delay_skb; - - bh_data_t *bh_head; /* Circular buffer for chdlc_bh */ - unsigned long tq_working; - volatile int bh_write; - volatile int bh_read; - atomic_t bh_buff_used; - - /* Polling task queue. Each interface - * has its own task queue, which is used - * to defer events from the interrupt */ - struct work_struct fr_poll_work; - struct timer_list fr_arp_timer; - - u32 ip_local; - u32 ip_remote; - long config_dlci; - long unconfig_dlci; - - /* Whether this interface should be setup as a gateway. - * Used by dynamic route setup code */ - u8 gateway; - - /* True interface type */ - u8 true_if_encoding; - u8 fr_header[FR_HEADER_LEN]; - char fr_header_len; - -} fr_channel_t; - -/* Route Flag options */ -#define NO_ROUTE 0x00 -#define ADD_ROUTE 0x01 -#define ROUTE_ADDED 0x02 -#define REMOVE_ROUTE 0x03 -#define ARP_REQ 0x04 - -/* inarp options */ -#define INARP_NONE 0x00 -#define INARP_REQUEST 0x01 -#define INARP_CONFIGURED 0x02 - -/* reasons for enabling the timer interrupt on the adapter */ -#define TMR_INT_ENABLED_UDP 0x01 -#define TMR_INT_ENABLED_UPDATE 0x02 -#define TMR_INT_ENABLED_ARP 0x04 -#define TMR_INT_ENABLED_UPDATE_STATE 0x08 -#define TMR_INT_ENABLED_CONFIG 0x10 -#define TMR_INT_ENABLED_UNCONFIG 0x20 - - -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; - -/* 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(struct wan_device *wandev); -static int new_if(struct wan_device *wandev, struct net_device *dev, - wanif_conf_t *conf); -static int del_if(struct wan_device *wandev, struct net_device *dev); -static void disable_comm (sdla_t *card); - -/* 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 net_device *dev); -static int if_open(struct net_device *dev); -static int if_close(struct net_device *dev); - -static void if_tx_timeout(struct net_device *dev); - -static int if_rebuild_hdr (struct sk_buff *skb); - -static int if_send(struct sk_buff *skb, struct net_device *dev); -static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev, - struct sk_buff *skb); -static struct net_device_stats *if_stats(struct net_device *dev); - -/* Interrupt handlers */ -static void fr_isr(sdla_t *card); -static void rx_intr(sdla_t *card); -static void tx_intr(sdla_t *card); -static void timer_intr(sdla_t *card); -static void spur_intr(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_init_dlci (sdla_t *card, fr_channel_t *chan); -static int fr_set_intr_mode (sdla_t *card, unsigned mode, unsigned mtu, unsigned short timeout); -static int fr_comm_enable(sdla_t *card); -static void 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); -static int fr_activate_dlci(sdla_t *card, int dlci); -static int fr_delete_dlci (sdla_t* card, int dlci); -static int fr_issue_isf(sdla_t *card, int isf); -static int fr_send(sdla_t *card, int dlci, unsigned char attr, int len, - void *buf); -static int fr_send_data_header(sdla_t *card, int dlci, unsigned char attr, int len, - void *buf,unsigned char hdr_len); -static unsigned int fr_send_hdr(sdla_t *card, int dlci, unsigned int offset); - -static int check_dlci_config (sdla_t *card, fr_channel_t *chan); -static void initialize_rx_tx_buffers (sdla_t *card); - - -/* 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 net_device *dev); -static void set_chan_state(struct net_device *dev, int state); -static struct net_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 ); -static int setup_for_delayed_transmit(struct net_device* dev, - struct sk_buff *skb); - -struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev); -static int check_tx_status(sdla_t *card, struct net_device *dev); - -/* Frame Relay Socket API */ -static void trigger_fr_bh (fr_channel_t *); -static void fr_bh(struct net_device *dev); -static int fr_bh_cleanup(struct net_device *dev); -static int bh_enqueue(struct net_device *dev, struct sk_buff *skb); - -static void trigger_fr_poll(struct net_device *dev); -static void fr_poll(struct net_device *dev); -//static void add_gateway(struct net_device *dev); - -static void trigger_unconfig_fr(struct net_device *dev); -static void unconfig_fr (sdla_t *); - -static void trigger_config_fr (sdla_t *); -static void config_fr (sdla_t *); - - -/* Inverse ARP and Dynamic routing functions */ -int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device *dev); -int is_arp(void *buf); -int send_inarp_request(sdla_t *card, struct net_device *dev); - -static void trigger_fr_arp(struct net_device *dev); -static void fr_arp (unsigned long data); - - -/* Udp management functions */ -static int process_udp_mgmt_pkt(sdla_t *card); -static int udp_pkt_type( struct sk_buff *skb, sdla_t *card ); -static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, int dlci); - -/* 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); - -/* Lock Functions: SMP supported */ -void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags); -void s508_s514_lock(sdla_t *card, unsigned long *smp_flags); - -unsigned short calc_checksum (char *, int); -static int setup_fr_header(struct sk_buff *skb, - struct net_device* dev, char op_mode); - - -/****** 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) -{ - - int err; - fr508_flags_t* flags; - - union - { - char str[80]; - fr_conf_t cfg; - } u; - - fr_buf_info_t* buf_info; - int i; - - - printk(KERN_INFO "\n"); - - /* 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_FR508: - card->mbox = (void*)(card->hw.dpmbase + - FR508_MBOX_OFFS); - card->flags = (void*)(card->hw.dpmbase + - FR508_FLAG_OFFS); - if(card->hw.type == SDLA_S514) { - card->mbox += FR_MB_VECTOR; - card->flags += FR_MB_VECTOR; - } - card->isr = &fr_isr; - break; - - default: - return -EINVAL; - } - - flags = card->flags; - - /* 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 += FR_HEADER_LEN; - conf->mtu = (conf->mtu >= MIN_LGTH_FR_DATA_CFG) ? - min_t(unsigned int, conf->mtu, FR_MAX_NO_DATA_BYTES_IN_FRAME) : - FR_CHANNEL_MTU + FR_HEADER_LEN; - - conf->bps = min_t(unsigned int, conf->bps, 2048000); - - /* Initialze the configuration structure sent to the board to zero */ - memset(&u.cfg, 0, sizeof(u.cfg)); - - memset(card->u.f.dlci_to_dev_map, 0, sizeof(card->u.f.dlci_to_dev_map)); - - /* Configure adapter firmware */ - - 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; - - 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_t(unsigned int, max_t(unsigned int, 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_t(unsigned int, conf->u.fr.t391, 30); - else - u.cfg.t391 = 5; - - if (conf->u.fr.t392) - u.cfg.t392 = min_t(unsigned int, conf->u.fr.t392, 30); - else - u.cfg.t392 = 15; - - if (conf->u.fr.n391) - u.cfg.n391 = min_t(unsigned int, conf->u.fr.n391, 255); - else - u.cfg.n391 = 2; - - if (conf->u.fr.n392) - u.cfg.n392 = min_t(unsigned int, conf->u.fr.n392, 10); - else - u.cfg.n392 = 3; - - if (conf->u.fr.n393) - u.cfg.n393 = min_t(unsigned int, 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; - card->disable_comm = &disable_comm; - card->u.f.arp_dev = NULL; - - /* 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 ); - - printk(KERN_INFO "%s: End of Interrupt Test rc=0x%x count=%i\n", - card->devname,err,Intr_test_counter); - - if (err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { - printk(KERN_ERR "%s: Interrupt Test Failed, Counter: %i\n", - card->devname, Intr_test_counter); - printk(KERN_ERR "Please choose another interrupt\n"); - err = -EIO; - return err; - } - - printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n", - card->devname, Intr_test_counter); - - - /* Apr 28 2000. Nenad Corbic - * Enable commnunications here, not in if_open or new_if, since - * interfaces come down when the link is disconnected. - */ - - /* 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)) { - return -EIO; - } - - flags->imask &= ~(FR_INTR_TXRDY | FR_INTR_TIMER); - - if (fr_comm_enable(card)) { - return -EIO; - } - wanpipe_set_state(card, WAN_CONNECTED); - spin_lock_init(&card->u.f.if_send_lock); - - printk(KERN_INFO "\n"); - - return 0; -} - -/******* WAN Device Driver Entry Points *************************************/ - -/*============================================================================ - * Update device status & statistics. - */ -static int update(struct wan_device* 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; - - 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 (time_after(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(struct wan_device* 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 (isdigit(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; - } - - if ((chan->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) even if it is - * a bridged DLCI, or as an API - */ - if (strcmp(conf->usedby, "WANPIPE") == 0 || - strcmp(conf->usedby, "BRIDGE") == 0 || - strcmp(conf->usedby, "BRIDGE_N") == 0){ - - if(strcmp(conf->usedby, "WANPIPE") == 0){ - chan->common.usedby = WANPIPE; - - printk(KERN_INFO "%s: Running in WANPIPE mode.\n", - card->devname); - - }else if(strcmp(conf->usedby, "BRIDGE") == 0){ - - chan->common.usedby = BRIDGE; - - printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n", - card->devname); - }else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){ - - chan->common.usedby = BRIDGE_NODE; - - printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n", - card->devname); - } - - if (!err){ - /* Dynamic interface configuration option. - * On disconnect, if the options is selected, - * the interface will be brought down */ - if (conf->if_down == WANOPT_YES){ - set_bit(DYN_OPT_ON,&chan->interface_down); - printk(KERN_INFO - "%s: Dynamic interface configuration enabled.\n", - card->devname); - } - } - - } else if(strcmp(conf->usedby, "API") == 0){ - - chan->common.usedby = API; - printk(KERN_INFO "%s: Running in API mode.\n", - wandev->name); - } - - if (err) { - - kfree(chan); - return err; - } - - /* place cir,be,bc and other channel specific information into the - * chan structure - */ - if (conf->cir) { - - chan->cir = max_t(unsigned int, 1, - min_t(unsigned int, 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_t(unsigned int, - 0, min_t(unsigned int, 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; - - if (conf->inarp == WANOPT_YES){ - printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname); - chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE; - chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10; - }else{ - printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname); - 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; - - /* Initialize FR Polling Task Queue - * We need a poll routine for each network - * interface. - */ - INIT_WORK(&chan->fr_poll_work, (void *)fr_poll, dev); - - init_timer(&chan->fr_arp_timer); - chan->fr_arp_timer.data=(unsigned long)dev; - chan->fr_arp_timer.function = fr_arp; - - wandev->new_if_cnt++; - - /* Tells us that if this interface is a - * gateway or not */ - if ((chan->gateway = conf->gateway) == WANOPT_YES){ - printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", - card->devname,dev->name); - } - - /* M. Grant Patch Apr 28 2000 - * Disallow duplicate dlci configurations. */ - if (card->u.f.dlci_to_dev_map[chan->dlci] != NULL) { - kfree(chan); - return -EBUSY; - } - - /* Configure this dlci at a later date, when - * the interface comes up. i.e. when if_open() - * executes */ - set_bit(0,&chan->config_dlci); - - printk(KERN_INFO "\n"); - - return 0; -} - -/*============================================================================ - * Delete logical channel. - */ -static int del_if(struct wan_device* wandev, struct net_device* dev) -{ - fr_channel_t* chan = dev->priv; - unsigned long smp_flags=0; - - /* This interface is dead, make sure the - * ARP timer is stopped */ - del_timer(&chan->fr_arp_timer); - - /* If we are a NODE, we must unconfigure this DLCI - * Trigger an unconfigure command that will - * be executed in timer interrupt. We must wait - * for the command to complete. */ - trigger_unconfig_fr(dev); - - lock_adapter_irq(&wandev->lock, &smp_flags); - wandev->new_if_cnt--; - unlock_adapter_irq(&wandev->lock, &smp_flags); - - return 0; -} - - -/*===================================================================== - * disable_comm - * - * Description: - * Disable communications. - * This code runs in shutdown (sdlamain.c) - * under critical flag. Therefore it is not - * necessary to set a critical flag here - * - * Usage: - * Commnunications are disabled only on a card - * shutdown. - */ - -static void disable_comm (sdla_t *card) -{ - printk(KERN_INFO "%s: Disabling Communications!\n", - card->devname); - fr_comm_disable(card); -} - -/****** WANPIPE-specific entry points ***************************************/ - -/*============================================================================ - * Execute adapter interface command. - */ -static int wpf_exec (struct sdla* card, void* u_cmd, void* u_data) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err, len; - fr_cmd_t cmd; - - if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd))) - return -EFAULT; - - /* execute command */ - do - { - memcpy(&mbox->cmd, &cmd, sizeof(cmd)); - - if (cmd.length){ - if( copy_from_user((void*)&mbox->data, u_data, cmd.length)) - return -EFAULT; - } - - if (sdla_exec(mbox)) - err = mbox->cmd.result; - - else return -EIO; - - } while (err && retry-- && fr_event(card, err, mbox)); - - /* return result */ - if (copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t))) - return -EFAULT; - - len = mbox->cmd.length; - - if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len)) - return -EFAULT; - 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) -{ - fr_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 = NULL; - 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; - - if (chan->common.usedby == WANPIPE || chan->common.usedby == API){ - - /* Initialize media-specific parameters */ - if (chan->true_if_encoding){ - dev->type = ARPHRD_DLCI; /* This breaks tcpdump */ - }else{ - dev->type = ARPHRD_PPP; /* ARP h/w type */ - } - - dev->flags |= IFF_POINTOPOINT; - dev->flags |= IFF_NOARP; - - /* Enable Multicast addressing */ - if (chan->mc == WANOPT_YES){ - dev->flags |= IFF_MULTICAST; - } - - dev->mtu = wandev->mtu - FR_HEADER_LEN; - /* For an API, the maximum number of bytes that the stack will pass - to the driver is (dev->mtu + dev->hard_header_len). So, adjust the - mtu so that a frame of maximum size can be transmitted by the API. - */ - if(chan->common.usedby == API) { - dev->mtu += (sizeof(api_tx_hdr_t) - FR_HEADER_LEN); - } - - dev->hard_header_len = FR_HEADER_LEN;/* media header length */ - dev->addr_len = 2; /* hardware address length */ - *(unsigned short*)dev->dev_addr = htons(chan->dlci); - - /* Set transmit buffer queue length */ - dev->tx_queue_len = 100; - - }else{ - - /* Setup the interface for Bridging */ - int hw_addr=0; - ether_setup(dev); - - /* Use a random number to generate the MAC address */ - memcpy(dev->dev_addr, "\xFE\xFC\x00\x00\x00\x00", 6); - get_random_bytes(&hw_addr, sizeof(hw_addr)); - *(int *)(dev->dev_addr + 2) += hw_addr; - } - - /* Initialize hardware parameters (just for reference) */ - dev->irq = wandev->irq; - dev->dma = wandev->dma; - dev->base_addr = wandev->ioport; - dev->mem_start = wandev->maddr; - dev->mem_end = wandev->maddr + wandev->msize - 1; - SET_MODULE_OWNER(dev); - - return 0; -} - -/*============================================================================ - * Open network interface. - * o if this is the first open, then enable communications and interrupts. - * o prevent module from unloading by incrementing use count - * - * Return 0 if O.k. or errno. - */ -static int if_open(struct net_device* dev) -{ - fr_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - int err = 0; - struct timeval tv; - - if (netif_running(dev)) - return -EBUSY; - - /* Initialize the task queue */ - chan->tq_working=0; - - INIT_WORK(&chan->common.wanpipe_work, (void *)fr_bh, dev); - - /* Allocate and initialize BH circular buffer */ - chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC); - memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF)); - atomic_set(&chan->bh_buff_used, 0); - - netif_start_queue(dev); - - wanpipe_open(card); - do_gettimeofday( &tv ); - chan->router_start_time = tv.tv_sec; - - if (test_bit(0,&chan->config_dlci)){ - trigger_config_fr (card); - }else if (chan->inarp == INARP_REQUEST){ - trigger_fr_arp(dev); - } - - return err; -} - -/*============================================================================ - * Close network interface. - * o if this is the last open, then disable communications and interrupts. - * o reset flags. - */ -static int if_close(struct net_device* dev) -{ - fr_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - - if (chan->inarp == INARP_CONFIGURED) { - chan->inarp = INARP_REQUEST; - } - - netif_stop_queue(dev); - wanpipe_close(card); - - return 0; -} - -/*============================================================================ - * Re-build media header. - * - * Return: 1 physical address resolved. - * 0 physical address not resolved - */ -static int if_rebuild_hdr (struct sk_buff* skb) -{ - struct net_device *dev = skb->dev; - fr_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - - printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", - card->devname, dev->name); - return 1; -} - -/*============================================================================ - * Handle transmit timeout event from netif watchdog - */ -static void if_tx_timeout(struct net_device *dev) -{ - fr_channel_t* chan = dev->priv; - sdla_t *card = chan->card; - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - - chan->drvstats_if_send.if_send_tbusy++; - ++chan->ifstats.collisions; - - printk (KERN_INFO "%s: Transmit timed out on %s\n", - card->devname, dev->name); - chan->drvstats_if_send.if_send_tbusy_timeout++; - netif_wake_queue (dev); - -} - - -/*============================================================================ - * Send a packet on a network interface. - * o set tbusy flag (marks start of the transmission) to block a timer-based - * transmit from overlapping. - * o set critical flag when accessing board. - * o check link state. If link is not up, then drop the packet. - * o check channel status. If it's down then initiate a call. - * o pass a packet to corresponding WAN device. - * o free socket buffer - * - * Return: 0 complete (socket buffer must be freed) - * non-0 packet may be re-transmitted (tbusy must be set) - * - * Notes: - * 1. This routine is called either by the protocol stack or by the "net - * bottom half" (with interrupts enabled). - * - * 2. Using netif_start_queue() and netif_stop_queue() - * will inhibit further transmit requests from the protocol stack - * and can be used for flow control with protocol layer. - */ -static int if_send(struct sk_buff* skb, struct net_device* dev) -{ - fr_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - int err; - unsigned char *sendpacket; - fr508_flags_t* adptr_flags = card->flags; - int udp_type; - long delay_tx_queued = 0; - unsigned long smp_flags=0; - unsigned char attr = 0; - - chan->drvstats_if_send.if_send_entry++; - - netif_stop_queue(dev); - - if (skb == NULL) { - /* if we get here, some higher layer thinks we've missed an - * tx-done interrupt. - */ - printk(KERN_INFO "%s: interface %s got kicked!\n", - card->devname, dev->name); - chan->drvstats_if_send.if_send_skb_null ++; - - netif_wake_queue(dev); - return 0; - } - - /* If a peripheral task is running just drop packets */ - if (test_bit(PERI_CRIT, &card->wandev.critical)){ - - printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n", - card->devname); - - dev_kfree_skb_any(skb); - netif_start_queue(dev); - return 0; - } - - /* We must set the 'tbusy' flag if we already have a packet queued for - transmission in the transmit interrupt handler. However, we must - ensure that the transmit interrupt does not reset the 'tbusy' flag - just before we set it, as this will result in a "transmit timeout". - */ - set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); - if(chan->transmit_length) { - netif_stop_queue(dev); - chan->tick_counter = jiffies; - clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); - return 1; - } - clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); - - /* Move the if_header() code to here. By inserting frame - * relay header in if_header() we would break the - * tcpdump and other packet sniffers */ - chan->fr_header_len = setup_fr_header(skb,dev,chan->common.usedby); - if (chan->fr_header_len < 0 ){ - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - - dev_kfree_skb_any(skb); - netif_start_queue(dev); - return 0; - } - - sendpacket = skb->data; - - udp_type = udp_pkt_type(skb, card); - - if(udp_type != UDP_INVALID_TYPE) { - if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, skb, - chan->dlci)) { - adptr_flags->imask |= FR_INTR_TIMER; - if (udp_type == UDP_FPIPE_TYPE){ - chan->drvstats_if_send. - if_send_PIPE_request ++; - } - } - netif_start_queue(dev); - return 0; - } - - //FIXME: can we do better than sendpacket[2]? - if ((chan->common.usedby == WANPIPE) && (sendpacket[2] == 0x45)) { - - /* check to see if the source IP address is a broadcast or */ - /* multicast IP address */ - if(chk_bcast_mcast_addr(card, dev, skb)){ - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - dev_kfree_skb_any(skb); - netif_start_queue(dev); - return 0; - } - } - - - /* Lock the S514/S508 card: SMP Supported */ - s508_s514_lock(card,&smp_flags); - - if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) { - - chan->drvstats_if_send.if_send_critical_non_ISR ++; - chan->ifstats.tx_dropped ++; - printk(KERN_INFO "%s Critical in IF_SEND: if_send() already running!\n", - card->devname); - goto if_send_start_and_exit; - } - - /* API packet check: minimum packet size must be greater than - * 16 byte API header */ - if((chan->common.usedby == API) && (skb->len <= sizeof(api_tx_hdr_t))) { - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - - - goto if_send_start_and_exit; - - }else{ - /* During API transmission, get rid of the API header */ - if (chan->common.usedby == API) { - api_tx_hdr_t* api_tx_hdr; - api_tx_hdr = (api_tx_hdr_t*)&skb->data[0x00]; - attr = api_tx_hdr->attr; - skb_pull(skb,sizeof(api_tx_hdr_t)); - } - } - - if (card->wandev.state != WAN_CONNECTED) { - chan->drvstats_if_send.if_send_wan_disconnected ++; - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - - } else if (chan->common.state != WAN_CONNECTED) { - chan->drvstats_if_send.if_send_dlci_disconnected ++; - - /* Update the DLCI state in timer interrupt */ - card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE_STATE; - adptr_flags->imask |= FR_INTR_TIMER; - - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - - } else if (!is_tx_ready(card, chan)) { - /* No tx buffers available, store for delayed transmit */ - if (!setup_for_delayed_transmit(dev, skb)){ - set_bit(1,&delay_tx_queued); - } - chan->drvstats_if_send.if_send_no_bfrs++; - - } else if (!skb->protocol) { - /* No protocols drop packet */ - chan->drvstats_if_send.if_send_protocol_error ++; - ++card->wandev.stats.tx_errors; - - } else if (test_bit(ARP_CRIT,&card->wandev.critical)){ - /* We are trying to send an ARP Packet, block IP data until - * ARP is sent */ - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - - } else { - //FIXME: IPX is not implemented in this version of Frame Relay ? - if((chan->common.usedby == WANPIPE) && - sendpacket[1] == 0x00 && - sendpacket[2] == 0x80 && - sendpacket[6] == 0x81 && - sendpacket[7] == 0x37) { - - if( chan->enable_IPX ) { - switch_net_numbers(sendpacket, - chan->network_number, 0); - } else { - //FIXME: Take this out when IPX is fixed - printk(KERN_INFO - "%s: WARNING: Unsupported IPX data in send, packet dropped\n", - card->devname); - } - - }else{ - err = fr_send_data_header(card, chan->dlci, attr, skb->len, skb->data, chan->fr_header_len); - if (err) { - switch(err) { - case FRRES_CIR_OVERFLOW: - case FRRES_BUFFER_OVERFLOW: - if (!setup_for_delayed_transmit(dev, skb)){ - set_bit(1,&delay_tx_queued); - } - chan->drvstats_if_send. - if_send_adptr_bfrs_full ++; - break; - - case FRRES_TOO_LONG: - if (net_ratelimit()){ - printk(KERN_INFO - "%s: Error: Frame too long, transmission failed %i\n", - card->devname, (unsigned int)skb->len); - } - /* Drop down to default */ - default: - chan->drvstats_if_send. - if_send_dlci_disconnected ++; - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - break; - } - } else { - chan->drvstats_if_send. - if_send_bfr_passed_to_adptr++; - ++chan->ifstats.tx_packets; - ++card->wandev.stats.tx_packets; - - chan->ifstats.tx_bytes += skb->len; - card->wandev.stats.tx_bytes += skb->len; - dev->trans_start = jiffies; - } - } - } - -if_send_start_and_exit: - - netif_start_queue(dev); - - /* If we queued the packet for transmission, we must not - * deallocate it. The packet is unlinked from the IP stack - * not copied. Therefore, we must keep the original packet */ - if (!test_bit(1,&delay_tx_queued)) { - dev_kfree_skb_any(skb); - }else{ - adptr_flags->imask |= FR_INTR_TXRDY; - card->u.f.tx_interrupts_pending ++; - } - - clear_bit(SEND_CRIT, (void*)&card->wandev.critical); - - s508_s514_unlock(card,&smp_flags); - - return 0; -} - - - -/*============================================================================ - * Setup so that a frame can be transmitted on the occurrence of a transmit - * interrupt. - */ -static int setup_for_delayed_transmit(struct net_device* dev, - struct sk_buff *skb) -{ - fr_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - fr_dlci_interface_t* dlci_interface; - int len = skb->len; - - /* Check that the dlci is properly configured, - * before using tx interrupt */ - if (!chan->dlci_int_interface){ - if (net_ratelimit()){ - printk(KERN_INFO - "%s: ERROR on DLCI %i: Not configured properly !\n", - card->devname, chan->dlci); - printk(KERN_INFO "%s: Please contact Sangoma Technologies\n", - card->devname); - } - return 1; - } - - dlci_interface = chan->dlci_int_interface; - - if(chan->transmit_length) { - printk(KERN_INFO "%s: Big mess in setup_for_del...\n", - card->devname); - return 1; - } - - if(len > FR_MAX_NO_DATA_BYTES_IN_FRAME) { - //FIXME: increment some statistic */ - return 1; - } - - chan->transmit_length = len; - chan->delay_skb = skb; - - dlci_interface->gen_interrupt |= FR_INTR_TXRDY; - dlci_interface->packet_length = len; - - /* Turn on TX interrupt at the end of if_send */ - return 0; -} - - -/*============================================================================ - * Check to see if the packet to be transmitted contains a broadcast or - * multicast source IP address. - * Return 0 if not broadcast/multicast address, otherwise return 1. - */ - -static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev, - struct sk_buff *skb) -{ - u32 src_ip_addr; - u32 broadcast_ip_addr = 0; - struct in_device *in_dev; - fr_channel_t* chan = dev->priv; - - /* read the IP source address from the outgoing packet */ - src_ip_addr = *(u32 *)(skb->data + 14); - - /* read the IP broadcast address for the device */ - in_dev = dev->ip_ptr; - if(in_dev != NULL) { - struct in_ifaddr *ifa= in_dev->ifa_list; - if(ifa != NULL) - broadcast_ip_addr = ifa->ifa_broadcast; - else - return 0; - } - - /* check if the IP Source Address is a Broadcast address */ - if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { - printk(KERN_INFO - "%s: Broadcast Source Address silently discarded\n", - card->devname); - return 1; - } - - /* check if the IP Source Address is a Multicast address */ - if((chan->mc == WANOPT_NO) && (ntohl(src_ip_addr) >= 0xE0000001) && - (ntohl(src_ip_addr) <= 0xFFFFFFFE)) { - printk(KERN_INFO - "%s: Multicast Source Address silently discarded\n", - card->devname); - return 1; - } - - return 0; -} - -/*============================================================================ - * Reply to UDP Management system. - * Return nothing. - */ -static int reply_udp( unsigned char *data, unsigned int mbox_len ) -{ - unsigned short len, udp_length, temp, ip_length; - unsigned long ip_temp; - int even_bound = 0; - - - fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)data; - - /* Set length of packet */ - len = //sizeof(fr_encap_hdr_t)+ - sizeof(ip_pkt_t)+ - sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - mbox_len; - - - /* fill in UDP reply */ - fr_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; - - /* fill in UDP length */ - udp_length = sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - mbox_len; - - - /* put it on an even boundary */ - if ( udp_length & 0x0001 ) { - udp_length += 1; - len += 1; - even_bound = 1; - } - - temp = (udp_length<<8)|(udp_length>>8); - fr_udp_pkt->udp_pkt.udp_length = temp; - - /* swap UDP ports */ - temp = fr_udp_pkt->udp_pkt.udp_src_port; - fr_udp_pkt->udp_pkt.udp_src_port = - fr_udp_pkt->udp_pkt.udp_dst_port; - fr_udp_pkt->udp_pkt.udp_dst_port = temp; - - - - /* add UDP pseudo header */ - temp = 0x1100; - *((unsigned short *) - (fr_udp_pkt->data+mbox_len+even_bound)) = temp; - temp = (udp_length<<8)|(udp_length>>8); - *((unsigned short *) - (fr_udp_pkt->data+mbox_len+even_bound+2)) = temp; - - /* calculate UDP checksum */ - fr_udp_pkt->udp_pkt.udp_checksum = 0; - - fr_udp_pkt->udp_pkt.udp_checksum = - calc_checksum(&data[UDP_OFFSET/*+sizeof(fr_encap_hdr_t)*/], - udp_length+UDP_OFFSET); - - /* fill in IP length */ - ip_length = udp_length + sizeof(ip_pkt_t); - temp = (ip_length<<8)|(ip_length>>8); - fr_udp_pkt->ip_pkt.total_length = temp; - - /* swap IP addresses */ - ip_temp = fr_udp_pkt->ip_pkt.ip_src_address; - fr_udp_pkt->ip_pkt.ip_src_address = - fr_udp_pkt->ip_pkt.ip_dst_address; - fr_udp_pkt->ip_pkt.ip_dst_address = ip_temp; - - - /* fill in IP checksum */ - fr_udp_pkt->ip_pkt.hdr_checksum = 0; - fr_udp_pkt->ip_pkt.hdr_checksum = - calc_checksum(&data[/*sizeof(fr_encap_hdr_t)*/0], - sizeof(ip_pkt_t)); - - return len; -} /* reply_udp */ - -unsigned short calc_checksum (char *data, int len) -{ - unsigned short temp; - unsigned long sum=0; - int i; - - for( i = 0; i > 16 ) { - sum = (sum & 0xffffUL) + (sum >> 16); - } - - temp = (unsigned short)sum; - temp = ~temp; - - if( temp == 0 ) - temp = 0xffff; - - return temp; -} - -/* - If incoming is 0 (outgoing)- if the net numbers is ours make it 0 - if incoming is 1 - if the net number is 0 make it ours - -*/ -static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming) -{ - unsigned long pnetwork_number; - - pnetwork_number = (unsigned long)((sendpacket[14] << 24) + - (sendpacket[15] << 16) + (sendpacket[16] << 8) + - sendpacket[17]); - - if (!incoming) { - /* If the destination network number is ours, make it 0 */ - if( pnetwork_number == network_number) { - sendpacket[14] = sendpacket[15] = sendpacket[16] = - sendpacket[17] = 0x00; - } - } else { - /* If the incoming network is 0, make it ours */ - if( pnetwork_number == 0) { - sendpacket[14] = (unsigned char)(network_number >> 24); - sendpacket[15] = (unsigned char)((network_number & - 0x00FF0000) >> 16); - sendpacket[16] = (unsigned char)((network_number & - 0x0000FF00) >> 8); - sendpacket[17] = (unsigned char)(network_number & - 0x000000FF); - } - } - - - pnetwork_number = (unsigned long)((sendpacket[26] << 24) + - (sendpacket[27] << 16) + (sendpacket[28] << 8) + - sendpacket[29]); - - if( !incoming ) { - /* If the source network is ours, make it 0 */ - if( pnetwork_number == network_number) { - sendpacket[26] = sendpacket[27] = sendpacket[28] = - sendpacket[29] = 0x00; - } - } else { - /* If the source network is 0, make it ours */ - if( pnetwork_number == 0 ) { - sendpacket[26] = (unsigned char)(network_number >> 24); - sendpacket[27] = (unsigned char)((network_number & - 0x00FF0000) >> 16); - sendpacket[28] = (unsigned char)((network_number & - 0x0000FF00) >> 8); - sendpacket[29] = (unsigned char)(network_number & - 0x000000FF); - } - } -} /* switch_net_numbers */ - -/*============================================================================ - * Get ethernet-style interface statistics. - * Return a pointer to struct enet_statistics. - */ -static struct net_device_stats *if_stats(struct net_device *dev) -{ - fr_channel_t* chan = dev->priv; - - if(chan == NULL) - return NULL; - - return &chan->ifstats; -} - -/****** Interrupt Handlers **************************************************/ - -/*============================================================================ - * fr_isr: S508 frame relay interrupt service routine. - * - * Description: - * Frame relay main interrupt service route. This - * function check the interrupt type and takes - * the appropriate action. - */ -static void fr_isr (sdla_t* card) -{ - fr508_flags_t* flags = card->flags; - char *ptr = &flags->iflag; - int i,err; - fr_mbox_t* mbox = card->mbox; - - /* This flag prevents nesting of interrupts. See sdla_isr() routine - * in sdlamain.c. */ - card->in_isr = 1; - - ++card->statistics.isr_entry; - - - /* All peripheral (configuraiton, re-configuration) events - * take presidence over the ISR. Thus, retrigger */ - if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { - ++card->statistics.isr_already_critical; - goto fr_isr_exit; - } - - if(card->hw.type != SDLA_S514) { - if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) { - printk(KERN_INFO "%s: Critical while in ISR: If Send Running!\n", - card->devname); - ++card->statistics.isr_already_critical; - goto fr_isr_exit; - } - } - - switch (flags->iflag) { - - case FR_INTR_RXRDY: /* receive interrupt */ - ++card->statistics.isr_rx; - rx_intr(card); - break; - - - case FR_INTR_TXRDY: /* transmit interrupt */ - ++ card->statistics.isr_tx; - tx_intr(card); - break; - - case FR_INTR_READY: - Intr_test_counter++; - ++card->statistics.isr_intr_test; - break; - - case FR_INTR_DLC: /* Event interrupt occurred */ - mbox->cmd.command = FR_READ_STATUS; - mbox->cmd.length = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - if (err) - fr_event(card, err, mbox); - break; - - case FR_INTR_TIMER: /* Timer interrupt */ - timer_intr(card); - break; - - default: - ++card->statistics.isr_spurious; - spur_intr(card); - printk(KERN_INFO "%s: Interrupt Type 0x%02X!\n", - card->devname, flags->iflag); - - printk(KERN_INFO "%s: ID Bytes = ",card->devname); - for(i = 0; i < 8; i ++) - printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); - printk(KERN_INFO "\n"); - - break; - } - -fr_isr_exit: - - card->in_isr = 0; - flags->iflag = 0; - return; -} - - - -/*=========================================================== - * rx_intr Receive interrupt handler. - * - * Description - * Upon receiveing an interrupt: - * 1. Check that the firmware is in sync with - * the driver. - * 2. Find an appropriate network interface - * based on the received dlci number. - * 3. Check that the netowrk interface exists - * and that it's setup properly. - * 4. Copy the data into an skb buffer. - * 5. Check the packet type and take - * appropriate acton: UPD, API, ARP or Data. - */ - -static void rx_intr (sdla_t* card) -{ - fr_rx_buf_ctl_t* frbuf = card->rxmb; - fr508_flags_t* flags = card->flags; - fr_channel_t* chan; - char *ptr = &flags->iflag; - struct sk_buff* skb; - struct net_device* dev; - void* buf; - unsigned dlci, len, offs, len_incl_hdr; - int i, udp_type; - - - /* Check that firmware buffers are in sync */ - if (frbuf->flag != 0x01) { - - printk(KERN_INFO - "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", - card->devname, (unsigned)frbuf, frbuf->flag); - - printk(KERN_INFO "%s: ID Bytes = ",card->devname); - for(i = 0; i < 8; i ++) - printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); - printk(KERN_INFO "\n"); - - ++card->statistics.rx_intr_corrupt_rx_bfr; - - /* Bug Fix: Mar 6 2000 - * If we get a corrupted mailbox, it means that driver - * is out of sync with the firmware. There is no recovery. - * If we don't turn off all interrupts for this card - * the machine will crash. - */ - printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); - printk(KERN_INFO "Please contact Sangoma Technologies !\n"); - fr_set_intr_mode(card, 0, 0, 0); - return; - } - - len = frbuf->length; - dlci = frbuf->dlci; - offs = frbuf->offset; - - /* Find the network interface for this packet */ - dev = find_channel(card, dlci); - - - /* Check that the network interface is active and - * properly setup */ - if (dev == NULL) { - if( net_ratelimit()) { - printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n", - card->devname, dlci); - } - ++card->statistics.rx_intr_on_orphaned_DLCI; - ++card->wandev.stats.rx_dropped; - goto rx_done; - } - - if ((chan = dev->priv) == NULL){ - if( net_ratelimit()) { - printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n", - card->devname, dlci); - } - ++card->statistics.rx_intr_on_orphaned_DLCI; - ++card->wandev.stats.rx_dropped; - goto rx_done; - } - - skb = dev_alloc_skb(len); - - if (!netif_running(dev) || (skb == NULL)){ - - ++chan->ifstats.rx_dropped; - - if(skb == NULL) { - if (net_ratelimit()) { - printk(KERN_INFO - "%s: no socket buffers available!\n", - card->devname); - } - chan->drvstats_rx_intr.rx_intr_no_socket ++; - } - - if (!netif_running(dev)){ - chan->drvstats_rx_intr. - rx_intr_dev_not_started ++; - if (skb){ - dev_kfree_skb_any(skb); - } - } - goto rx_done; - } - - /* Copy data from the board into the socket buffer */ - if ((offs + len) > card->u.f.rx_top + 1) { - unsigned tmp = card->u.f.rx_top - offs + 1; - - buf = skb_put(skb, tmp); - sdla_peek(&card->hw, offs, buf, tmp); - offs = card->u.f.rx_base; - len -= tmp; - } - - buf = skb_put(skb, len); - sdla_peek(&card->hw, offs, buf, len); - - - /* We got the packet from the bard. - * Check the packet type and take appropriate action */ - - udp_type = udp_pkt_type( skb, card ); - - if(udp_type != UDP_INVALID_TYPE) { - - /* UDP Debug packet received, store the - * packet and handle it in timer interrupt */ - - skb_pull(skb, 1); - if (wanrouter_type_trans(skb, dev)){ - if(store_udp_mgmt_pkt(udp_type,UDP_PKT_FRM_NETWORK,card,skb,dlci)){ - - flags->imask |= FR_INTR_TIMER; - - if (udp_type == UDP_FPIPE_TYPE){ - ++chan->drvstats_rx_intr.rx_intr_PIPE_request; - } - } - } - - }else if (chan->common.usedby == API) { - - /* We are in API mode. - * Add an API header to the RAW packet - * and queue it into a circular buffer. - * Then kick the fr_bh() bottom half handler */ - - api_rx_hdr_t* api_rx_hdr; - chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack ++; - chan->ifstats.rx_packets ++; - card->wandev.stats.rx_packets ++; - - chan->ifstats.rx_bytes += skb->len; - card->wandev.stats.rx_bytes += skb->len; - - skb_push(skb, sizeof(api_rx_hdr_t)); - api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00]; - api_rx_hdr->attr = frbuf->attr; - api_rx_hdr->time_stamp = frbuf->tmstamp; - - skb->protocol = htons(ETH_P_IP); - skb->mac.raw = skb->data; - skb->dev = dev; - skb->pkt_type = WAN_PACKET_DATA; - - bh_enqueue(dev, skb); - - trigger_fr_bh(chan); - - }else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){ - - //FIXME: Frame Relay IPX is not supported, Yet ! - //if (chan->enable_IPX) { - // fr_send(card, dlci, 0, skb->len,skb->data); - //} - dev_kfree_skb_any(skb); - - } else if (is_arp(skb->data)) { - - /* ARP support enabled Mar 16 2000 - * Process incoming ARP reply/request, setup - * dynamic routes. */ - - if (process_ARP((arphdr_1490_t *)skb->data, card, dev)) { - if (net_ratelimit()){ - printk (KERN_INFO - "%s: Error processing ARP Packet.\n", - card->devname); - } - } - dev_kfree_skb_any(skb); - - } else if (skb->data[0] != 0x03) { - - if (net_ratelimit()) { - printk(KERN_INFO "%s: Non IETF packet discarded.\n", - card->devname); - } - dev_kfree_skb_any(skb); - - } else { - - len_incl_hdr = skb->len; - /* Decapsulate packet and pass it up the - protocol stack */ - skb->dev = dev; - - if (chan->common.usedby == BRIDGE || chan->common.usedby == BRIDGE_NODE){ - - /* Make sure it's an Ethernet frame, otherwise drop it */ - if (!memcmp(skb->data, "\x03\x00\x80\x00\x80\xC2\x00\x07", 8)) { - skb_pull(skb, 8); - skb->protocol=eth_type_trans(skb,dev); - }else{ - ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack; - ++chan->ifstats.rx_errors; - ++card->wandev.stats.rx_errors; - goto rx_done; - } - }else{ - - /* remove hardware header */ - buf = skb_pull(skb, 1); - - if (!wanrouter_type_trans(skb, dev)) { - - /* can't decapsulate packet */ - dev_kfree_skb_any(skb); - - ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack; - ++chan->ifstats.rx_errors; - ++card->wandev.stats.rx_errors; - goto rx_done; - } - skb->mac.raw = skb->data; - } - - - /* Send a packet up the IP stack */ - skb->dev->last_rx = jiffies; - netif_rx(skb); - ++chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack; - ++chan->ifstats.rx_packets; - ++card->wandev.stats.rx_packets; - - chan->ifstats.rx_bytes += len_incl_hdr; - card->wandev.stats.rx_bytes += len_incl_hdr; - } - -rx_done: - - /* Release buffer element and calculate a pointer to the next one */ - frbuf->flag = 0; - card->rxmb = ++frbuf; - if ((void*)frbuf > card->u.f.rxmb_last) - card->rxmb = card->u.f.rxmb_base; - -} - -/*================================================================== - * tx_intr: Transmit interrupt handler. - * - * Rationale: - * If the board is busy transmitting, if_send() will - * buffers a single packet and turn on - * the tx interrupt. Tx interrupt will be called - * by the board, once the firmware can send more - * data. Thus, no polling is required. - * - * Description: - * Tx interrupt is called for each - * configured dlci channel. Thus: - * 1. Obtain the netowrk interface based on the - * dlci number. - * 2. Check that network interface is up and - * properly setup. - * 3. Check for a buffered packet. - * 4. Transmit the packet. - * 5. If we are in WANPIPE mode, mark the - * NET_BH handler. - * 6. If we are in API mode, kick - * the AF_WANPIPE socket for more data. - * - */ -static void tx_intr(sdla_t *card) -{ - fr508_flags_t* flags = card->flags; - fr_tx_buf_ctl_t* bctl; - struct net_device* dev; - fr_channel_t* chan; - - if(card->hw.type == SDLA_S514){ - bctl = (void*)(flags->tse_offs + card->hw.dpmbase); - }else{ - bctl = (void*)(flags->tse_offs - FR_MB_VECTOR + - card->hw.dpmbase); - } - - /* Find the structure and make it unbusy */ - dev = find_channel(card, flags->dlci); - if (dev == NULL){ - printk(KERN_INFO "NO DEV IN TX Interrupt\n"); - goto end_of_tx_intr; - } - - if ((chan = dev->priv) == NULL){ - printk(KERN_INFO "NO CHAN IN TX Interrupt\n"); - goto end_of_tx_intr; - } - - if(!chan->transmit_length || !chan->delay_skb) { - printk(KERN_INFO "%s: tx int error - transmit length zero\n", - card->wandev.name); - goto end_of_tx_intr; - } - - /* If the 'if_send()' procedure is currently checking the 'tbusy' - status, then we cannot transmit. Instead, we configure the microcode - so as to re-issue this transmit interrupt at a later stage. - */ - if (test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) { - - fr_dlci_interface_t* dlci_interface = chan->dlci_int_interface; - bctl->flag = 0xA0; - dlci_interface->gen_interrupt |= FR_INTR_TXRDY; - return; - - }else{ - bctl->dlci = flags->dlci; - bctl->length = chan->transmit_length+chan->fr_header_len; - sdla_poke(&card->hw, - fr_send_hdr(card,bctl->dlci,bctl->offset), - chan->delay_skb->data, - chan->delay_skb->len); - bctl->flag = 0xC0; - - ++chan->ifstats.tx_packets; - ++card->wandev.stats.tx_packets; - chan->ifstats.tx_bytes += chan->transmit_length; - card->wandev.stats.tx_bytes += chan->transmit_length; - - /* We must free an sk buffer, which we used - * for delayed transmission; Otherwise, the sock - * will run out of memory */ - dev_kfree_skb_any(chan->delay_skb); - - chan->delay_skb = NULL; - chan->transmit_length = 0; - - dev->trans_start = jiffies; - - if (netif_queue_stopped(dev)){ - /* If using API, than wakeup socket BH handler */ - if (chan->common.usedby == API){ - netif_start_queue(dev); - wakeup_sk_bh(dev); - }else{ - netif_wake_queue(dev); - } - } - } - -end_of_tx_intr: - - /* if any other interfaces have transmit interrupts pending, - * do not disable the global transmit interrupt */ - if(!(-- card->u.f.tx_interrupts_pending)) - flags->imask &= ~FR_INTR_TXRDY; - - -} - - -/*============================================================================ - * timer_intr: Timer interrupt handler. - * - * Rationale: - * All commans must be executed within the timer - * interrupt since no two commands should execute - * at the same time. - * - * Description: - * The timer interrupt is used to: - * 1. Processing udp calls from 'fpipemon'. - * 2. Processing update calls from /proc file system - * 3. Reading board-level statistics for - * updating the proc file system. - * 4. Sending inverse ARP request packets. - * 5. Configure a dlci/channel. - * 6. Unconfigure a dlci/channel. (Node only) - */ - -static void timer_intr(sdla_t *card) -{ - fr508_flags_t* flags = card->flags; - - /* UDP Debuging: fpipemon call */ - if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UDP) { - if(card->u.f.udp_type == UDP_FPIPE_TYPE) { - if(process_udp_mgmt_pkt(card)) { - card->u.f.timer_int_enabled &= - ~TMR_INT_ENABLED_UDP; - } - } - } - - /* /proc update call : triggered from update() */ - if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE) { - fr_get_err_stats(card); - fr_get_stats(card); - card->u.f.update_comms_stats = 0; - card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; - } - - /* Update the channel state call. This is call is - * triggered by if_send() function */ - if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE_STATE){ - struct net_device *dev; - if (card->wandev.state == WAN_CONNECTED){ - for (dev = card->wandev.dev; dev; - dev = *((struct net_device **)dev->priv)){ - fr_channel_t *chan = dev->priv; - if (chan->common.state != WAN_CONNECTED){ - update_chan_state(dev); - } - } - } - card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE_STATE; - } - - /* configure a dlci/channel */ - if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_CONFIG){ - config_fr(card); - card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG; - } - - /* unconfigure a dlci/channel */ - if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG){ - unconfig_fr(card); - card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG; - } - - - /* Transmit ARP packets */ - if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_ARP){ - int i=0; - struct net_device *dev; - - if (card->u.f.arp_dev == NULL) - card->u.f.arp_dev = card->wandev.dev; - - dev = card->u.f.arp_dev; - - for (;;){ - - fr_channel_t *chan = dev->priv; - - /* If the interface is brought down cancel sending In-ARPs */ - if (!(dev->flags&IFF_UP)){ - clear_bit(0,&chan->inarp_ready); - } - - if (test_bit(0,&chan->inarp_ready)){ - - if (check_tx_status(card,dev)){ - set_bit(ARP_CRIT,&card->wandev.critical); - break; - } - - if (!send_inarp_request(card,dev)){ - trigger_fr_arp(dev); - chan->inarp_tick = jiffies; - } - - clear_bit(0,&chan->inarp_ready); - dev = move_dev_to_next(card,dev); - break; - } - dev = move_dev_to_next(card,dev); - - if (++i == card->wandev.new_if_cnt){ - card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_ARP; - break; - } - } - card->u.f.arp_dev = dev; - } - - if(!card->u.f.timer_int_enabled) - flags->imask &= ~FR_INTR_TIMER; -} - - -/*============================================================================ - * spur_intr: Spurious interrupt handler. - * - * Description: - * We don't know this interrupt. - * Print a warning. - */ - -static void spur_intr (sdla_t* card) -{ - if (net_ratelimit()){ - printk(KERN_INFO "%s: spurious interrupt!\n", card->devname); - } -} - - -//FIXME: Fix the IPX in next version -/*=========================================================================== - * Return 0 for non-IPXWAN packet - * 1 for IPXWAN packet or IPX is not enabled! - * FIXME: Use a IPX structure here not offsets - */ -static int handle_IPXWAN(unsigned char *sendpacket, - char *devname, unsigned char enable_IPX, - unsigned long network_number) -{ - int i; - - if( sendpacket[1] == 0x00 && sendpacket[2] == 0x80 && - sendpacket[6] == 0x81 && sendpacket[7] == 0x37) { - - /* It's an IPX packet */ - if (!enable_IPX){ - /* Return 1 so we don't pass it up the stack. */ - //FIXME: Take this out when IPX is fixed - if (net_ratelimit()){ - printk (KERN_INFO - "%s: WARNING: Unsupported IPX packet received and dropped\n", - devname); - } - return 1; - } - } else { - /* It's not IPX so return and pass it up the stack. */ - return 0; - } - - if( sendpacket[24] == 0x90 && sendpacket[25] == 0x04){ - /* It's IPXWAN */ - - if( sendpacket[10] == 0x02 && sendpacket[42] == 0x00){ - - /* It's a timer request packet */ - printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n", - devname); - - /* Go through the routing options and answer no to every - * option except Unnumbered RIP/SAP - */ - for(i = 49; sendpacket[i] == 0x00; i += 5){ - /* 0x02 is the option for Unnumbered RIP/SAP */ - if( sendpacket[i + 4] != 0x02){ - sendpacket[i + 1] = 0; - } - } - - /* Skip over the extended Node ID option */ - if( sendpacket[i] == 0x04 ){ - i += 8; - } - - /* We also want to turn off all header compression opt. - */ - for(; sendpacket[i] == 0x80 ;){ - sendpacket[i + 1] = 0; - i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4; - } - - /* Set the packet type to timer response */ - sendpacket[42] = 0x01; - - printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n", - devname); - - } else if( sendpacket[42] == 0x02 ){ - - /* This is an information request packet */ - printk(KERN_INFO - "%s: Received IPXWAN Information Request packet\n", - devname); - - /* Set the packet type to information response */ - sendpacket[42] = 0x03; - - /* Set the router name */ - sendpacket[59] = 'F'; - sendpacket[60] = 'P'; - sendpacket[61] = 'I'; - sendpacket[62] = 'P'; - sendpacket[63] = 'E'; - sendpacket[64] = '-'; - sendpacket[65] = CVHexToAscii(network_number >> 28); - sendpacket[66] = CVHexToAscii((network_number & 0x0F000000)>> 24); - sendpacket[67] = CVHexToAscii((network_number & 0x00F00000)>> 20); - sendpacket[68] = CVHexToAscii((network_number & 0x000F0000)>> 16); - sendpacket[69] = CVHexToAscii((network_number & 0x0000F000)>> 12); - sendpacket[70] = CVHexToAscii((network_number & 0x00000F00)>> 8); - sendpacket[71] = CVHexToAscii((network_number & 0x000000F0)>> 4); - sendpacket[72] = CVHexToAscii(network_number & 0x0000000F); - for(i = 73; i < 107; i+= 1) - { - sendpacket[i] = 0; - } - - printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n", - devname); - } else { - - printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname); - return 0; - } - - /* Set the WNodeID to our network address */ - sendpacket[43] = (unsigned char)(network_number >> 24); - sendpacket[44] = (unsigned char)((network_number & 0x00FF0000) >> 16); - sendpacket[45] = (unsigned char)((network_number & 0x0000FF00) >> 8); - sendpacket[46] = (unsigned char)(network_number & 0x000000FF); - - return 1; - } - - /* If we get here, it's an IPX-data packet so it'll get passed up the - * stack. - * switch the network numbers - */ - switch_net_numbers(sendpacket, network_number ,1); - return 0; -} -/*============================================================================ - * process_route - * - * Rationale: - * If the interface goes down, or we receive an ARP request, - * we have to change the network interface ip addresses. - * This cannot be done within the interrupt. - * - * Description: - * - * This routine is called as a polling routine to dynamically - * add/delete routes negotiated by inverse ARP. It is in this - * "task" because we don't want routes to be added while in - * interrupt context. - * - * Usage: - * This function is called by fr_poll() polling funtion. - */ - -static void process_route(struct net_device *dev) -{ - fr_channel_t *chan = dev->priv; - sdla_t *card = chan->card; - - struct ifreq if_info; - struct sockaddr_in *if_data; - mm_segment_t fs = get_fs(); - u32 ip_tmp; - int err; - - - switch(chan->route_flag){ - - case ADD_ROUTE: - - /* Set remote addresses */ - memset(&if_info, 0, sizeof(if_info)); - strcpy(if_info.ifr_name, dev->name); - - set_fs(get_ds()); /* get user space block */ - - if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr; - if_data->sin_addr.s_addr = chan->ip_remote; - if_data->sin_family = AF_INET; - err = devinet_ioctl( SIOCSIFDSTADDR, &if_info ); - - set_fs(fs); /* restore old block */ - - if (err) { - printk(KERN_INFO - "%s: Route Add failed. Error: %d\n", - card->devname,err); - printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n", - chan->name, NIPQUAD(chan->ip_remote)); - - }else { - printk(KERN_INFO "%s: Route Added Successfully: %u.%u.%u.%u\n", - card->devname,NIPQUAD(chan->ip_remote)); - chan->route_flag = ROUTE_ADDED; - } - break; - - case REMOVE_ROUTE: - - /* Set remote addresses */ - memset(&if_info, 0, sizeof(if_info)); - strcpy(if_info.ifr_name, dev->name); - - ip_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP); - - set_fs(get_ds()); /* get user space block */ - - if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr; - if_data->sin_addr.s_addr = 0; - if_data->sin_family = AF_INET; - err = devinet_ioctl( SIOCSIFDSTADDR, &if_info ); - - set_fs(fs); - - if (err) { - printk(KERN_INFO - "%s: Deleting of route failed. Error: %d\n", - card->devname,err); - printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n", - dev->name,NIPQUAD(chan->ip_remote) ); - - } else { - printk(KERN_INFO "%s: Route Removed Sucessfuly: %u.%u.%u.%u\n", - card->devname,NIPQUAD(ip_tmp)); - chan->route_flag = NO_ROUTE; - } - break; - - } /* Case Statement */ - -} - - - -/****** Frame Relay Firmware-Specific Functions *****************************/ - -/*============================================================================ - * Read firmware code version. - * o fill string str with firmware version info. - */ -static int fr_read_version (sdla_t* card, char* str) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - mbox->cmd.command = FR_READ_CODE_VERSION; - mbox->cmd.length = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && fr_event(card, err, mbox)); - - if (!err && str) { - int len = mbox->cmd.length; - memcpy(str, mbox->data, len); - str[len] = '\0'; - } - return err; -} - -/*============================================================================ - * Set global configuration. - */ -static int fr_configure (sdla_t* card, fr_conf_t *conf) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int dlci_num = card->u.f.dlci_num; - int err, i; - - do - { - memcpy(mbox->data, conf, sizeof(fr_conf_t)); - - if (dlci_num) for (i = 0; i < dlci_num; ++i) - ((fr_conf_t*)mbox->data)->dlci[i] = - card->u.f.node_dlci[i]; - - mbox->cmd.command = FR_SET_CONFIG; - mbox->cmd.length = - sizeof(fr_conf_t) + dlci_num * sizeof(short); - - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - } while (err && retry-- && fr_event(card, err, mbox)); - - /*NC Oct 12 2000 */ - if (err != CMD_OK){ - printk(KERN_ERR "%s: Frame Relay Configuration Failed: rc=0x%x\n", - card->devname,err); - } - - return err; -} - -/*============================================================================ - * Set DLCI configuration. - */ -static int fr_dlci_configure (sdla_t* card, fr_dlc_conf_t *conf, unsigned dlci) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memcpy(mbox->data, conf, sizeof(fr_dlc_conf_t)); - mbox->cmd.dlci = (unsigned short) dlci; - mbox->cmd.command = FR_SET_CONFIG; - mbox->cmd.length = sizeof(fr_dlc_conf_t); - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry--); - - return err; -} -/*============================================================================ - * Set interrupt mode. - */ -static int fr_set_intr_mode (sdla_t* card, unsigned mode, unsigned mtu, - unsigned short timeout) -{ - fr_mbox_t* mbox = card->mbox; - fr508_intr_ctl_t* ictl = (void*)mbox->data; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(ictl, 0, sizeof(fr508_intr_ctl_t)); - ictl->mode = mode; - ictl->tx_len = mtu; - ictl->irq = card->hw.irq; - - /* indicate timeout on timer */ - if (mode & 0x20) ictl->timeout = timeout; - - mbox->cmd.length = sizeof(fr508_intr_ctl_t); - mbox->cmd.command = FR_SET_INTR_MODE; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - } while (err && retry-- && fr_event(card, err, mbox)); - - return err; -} - -/*============================================================================ - * Enable communications. - */ -static int fr_comm_enable (sdla_t* card) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - mbox->cmd.command = FR_COMM_ENABLE; - mbox->cmd.length = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && fr_event(card, err, mbox)); - - return err; -} - -/*============================================================================ - * fr_comm_disable - * - * Warning: This functin is called by the shutdown() procedure. It is void - * since dev->priv are has already been deallocated and no - * error checking is possible using fr_event() function. - */ -static void fr_comm_disable (sdla_t* card) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do { - mbox->cmd.command = FR_SET_MODEM_STATUS; - mbox->cmd.length = 1; - mbox->data[0] = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry--); - - retry = MAX_CMD_RETRY; - - do - { - mbox->cmd.command = FR_COMM_DISABLE; - mbox->cmd.length = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry--); - - return; -} - - - -/*============================================================================ - * Get communications error statistics. - */ -static int fr_get_err_stats (sdla_t* card) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - - do - { - mbox->cmd.command = FR_READ_ERROR_STATS; - mbox->cmd.length = 0; - mbox->cmd.dlci = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && fr_event(card, err, mbox)); - - if (!err) { - fr_comm_stat_t* stats = (void*)mbox->data; - card->wandev.stats.rx_over_errors = stats->rx_overruns; - card->wandev.stats.rx_crc_errors = stats->rx_bad_crc; - card->wandev.stats.rx_missed_errors = stats->rx_aborts; - card->wandev.stats.rx_length_errors = stats->rx_too_long; - card->wandev.stats.tx_aborted_errors = stats->tx_aborts; - - } - - return err; -} - -/*============================================================================ - * Get statistics. - */ -static int fr_get_stats (sdla_t* card) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - - do - { - mbox->cmd.command = FR_READ_STATISTICS; - mbox->cmd.length = 0; - mbox->cmd.dlci = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && fr_event(card, err, mbox)); - - if (!err) { - fr_link_stat_t* stats = (void*)mbox->data; - card->wandev.stats.rx_frame_errors = stats->rx_bad_format; - card->wandev.stats.rx_dropped = - stats->rx_dropped + stats->rx_dropped2; - } - - return err; -} - -/*============================================================================ - * Add DLCI(s) (Access Node only!). - * This routine will perform the ADD_DLCIs command for the specified DLCI. - */ -static int fr_add_dlci (sdla_t* card, int dlci) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - unsigned short* dlci_list = (void*)mbox->data; - - mbox->cmd.length = sizeof(short); - dlci_list[0] = dlci; - mbox->cmd.command = FR_ADD_DLCI; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - } while (err && retry-- && fr_event(card, err, mbox)); - - return err; -} - -/*============================================================================ - * Activate DLCI(s) (Access Node only!). - * This routine will perform the ACTIVATE_DLCIs command with a DLCI number. - */ -static int fr_activate_dlci (sdla_t* card, int dlci) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - unsigned short* dlci_list = (void*)mbox->data; - - mbox->cmd.length = sizeof(short); - dlci_list[0] = dlci; - mbox->cmd.command = FR_ACTIVATE_DLCI; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - } while (err && retry-- && fr_event(card, err, mbox)); - - return err; -} - -/*============================================================================ - * Delete DLCI(s) (Access Node only!). - * This routine will perform the DELETE_DLCIs command with a DLCI number. - */ -static int fr_delete_dlci (sdla_t* card, int dlci) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - unsigned short* dlci_list = (void*)mbox->data; - - mbox->cmd.length = sizeof(short); - dlci_list[0] = dlci; - mbox->cmd.command = FR_DELETE_DLCI; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - } while (err && retry-- && fr_event(card, err, mbox)); - - return err; -} - - - -/*============================================================================ - * Issue in-channel signalling frame. - */ -static int fr_issue_isf (sdla_t* card, int isf) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - mbox->data[0] = isf; - mbox->cmd.length = 1; - mbox->cmd.command = FR_ISSUE_IS_FRAME; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && fr_event(card, err, mbox)); - - return err; -} - - -static unsigned int fr_send_hdr (sdla_t*card, int dlci, unsigned int offset) -{ - struct net_device *dev = find_channel(card,dlci); - fr_channel_t *chan; - - if (!dev || !(chan=dev->priv)) - return offset; - - if (chan->fr_header_len){ - sdla_poke(&card->hw, offset, chan->fr_header, chan->fr_header_len); - } - - return offset+chan->fr_header_len; -} - -/*============================================================================ - * Send a frame on a selected DLCI. - */ -static int fr_send_data_header (sdla_t* card, int dlci, unsigned char attr, int len, - void *buf, unsigned char hdr_len) -{ - fr_mbox_t* mbox = card->mbox + 0x800; - int retry = MAX_CMD_RETRY; - int err; - - do - { - mbox->cmd.dlci = dlci; - mbox->cmd.attr = attr; - mbox->cmd.length = len+hdr_len; - mbox->cmd.command = FR_WRITE; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && fr_event(card, err, mbox)); - - if (!err) { - fr_tx_buf_ctl_t* frbuf; - - if(card->hw.type == SDLA_S514) - frbuf = (void*)(*(unsigned long*)mbox->data + - card->hw.dpmbase); - else - frbuf = (void*)(*(unsigned long*)mbox->data - - FR_MB_VECTOR + card->hw.dpmbase); - - sdla_poke(&card->hw, fr_send_hdr(card,dlci,frbuf->offset), buf, len); - frbuf->flag = 0x01; - } - - return err; -} - -static int fr_send (sdla_t* card, int dlci, unsigned char attr, int len, - void *buf) -{ - fr_mbox_t* mbox = card->mbox + 0x800; - int retry = MAX_CMD_RETRY; - int err; - - do - { - mbox->cmd.dlci = dlci; - mbox->cmd.attr = attr; - mbox->cmd.length = len; - mbox->cmd.command = FR_WRITE; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && fr_event(card, err, mbox)); - - if (!err) { - fr_tx_buf_ctl_t* frbuf; - - if(card->hw.type == SDLA_S514) - frbuf = (void*)(*(unsigned long*)mbox->data + - card->hw.dpmbase); - else - frbuf = (void*)(*(unsigned long*)mbox->data - - FR_MB_VECTOR + card->hw.dpmbase); - - sdla_poke(&card->hw, frbuf->offset, buf, len); - frbuf->flag = 0x01; - } - - return err; -} - - -/****** Firmware Asynchronous Event Handlers ********************************/ - -/*============================================================================ - * Main asyncronous event/error handler. - * This routine is called whenever firmware command returns non-zero - * return code. - * - * Return zero if previous command has to be cancelled. - */ -static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox) -{ - fr508_flags_t* flags = card->flags; - char *ptr = &flags->iflag; - int i; - - switch (event) { - - case FRRES_MODEM_FAILURE: - return fr_modem_failure(card, mbox); - - case FRRES_CHANNEL_DOWN: { - struct net_device *dev; - - /* Remove all routes from associated DLCI's */ - for (dev = card->wandev.dev; dev; - dev = *((struct net_device **)dev->priv)) { - fr_channel_t *chan = dev->priv; - if (chan->route_flag == ROUTE_ADDED) { - chan->route_flag = REMOVE_ROUTE; - } - - if (chan->inarp == INARP_CONFIGURED) { - chan->inarp = INARP_REQUEST; - } - - /* If the link becomes disconnected then, - * all channels will be disconnected - * as well. - */ - set_chan_state(dev,WAN_DISCONNECTED); - } - - wanpipe_set_state(card, WAN_DISCONNECTED); - return 1; - } - - case FRRES_CHANNEL_UP: { - struct net_device *dev; - - /* FIXME: Only startup devices that are on the list */ - - for (dev = card->wandev.dev; dev; - dev = *((struct net_device **)dev->priv)) { - - set_chan_state(dev,WAN_CONNECTED); - } - - wanpipe_set_state(card, WAN_CONNECTED); - return 1; - } - - case FRRES_DLCI_CHANGE: - return fr_dlci_change(card, mbox); - - case FRRES_DLCI_MISMATCH: - printk(KERN_INFO "%s: DLCI list mismatch!\n", - card->devname); - return 1; - - case CMD_TIMEOUT: - printk(KERN_ERR "%s: command 0x%02X timed out!\n", - card->devname, mbox->cmd.command); - printk(KERN_INFO "%s: ID Bytes = ",card->devname); - for(i = 0; i < 8; i ++) - printk(KERN_INFO "0x%02X ", *(ptr + 0x18 + i)); - printk(KERN_INFO "\n"); - - break; - - case FRRES_DLCI_INACTIVE: - break; - - case FRRES_CIR_OVERFLOW: - break; - - case FRRES_BUFFER_OVERFLOW: - break; - - default: - printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n" - , card->devname, mbox->cmd.command, event); - } - - return 0; -} - -/*============================================================================ - * Handle modem error. - * - * Return zero if previous command has to be cancelled. - */ -static int fr_modem_failure (sdla_t *card, fr_mbox_t* mbox) -{ - printk(KERN_INFO "%s: physical link down! (modem error 0x%02X)\n", - card->devname, mbox->data[0]); - - switch (mbox->cmd.command){ - case FR_WRITE: - - case FR_READ: - return 0; - } - - return 1; -} - -/*============================================================================ - * Handle DLCI status change. - * - * Return zero if previous command has to be cancelled. - */ -static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox) -{ - dlci_status_t* status = (void*)mbox->data; - int cnt = mbox->cmd.length / sizeof(dlci_status_t); - fr_channel_t *chan; - struct net_device* dev2; - - - for (; cnt; --cnt, ++status) { - - unsigned short dlci= status->dlci; - struct net_device* dev = find_channel(card, dlci); - - if (dev == NULL){ - printk(KERN_INFO - "%s: CPE contains unconfigured DLCI= %d\n", - card->devname, dlci); - - printk(KERN_INFO - "%s: unconfigured DLCI %d reported by network\n" - , card->devname, dlci); - - }else{ - if (status->state == FR_LINK_INOPER) { - printk(KERN_INFO - "%s: DLCI %u is inactive!\n", - card->devname, dlci); - - if (dev && netif_running(dev)) - set_chan_state(dev, WAN_DISCONNECTED); - } - - if (status->state & FR_DLCI_DELETED) { - - printk(KERN_INFO - "%s: DLCI %u has been deleted!\n", - card->devname, dlci); - - if (dev && netif_running(dev)){ - - fr_channel_t *chan = dev->priv; - - if (chan->route_flag == ROUTE_ADDED) { - chan->route_flag = REMOVE_ROUTE; - /* The state change will trigger - * the fr polling routine */ - } - - if (chan->inarp == INARP_CONFIGURED) { - chan->inarp = INARP_REQUEST; - } - - set_chan_state(dev, WAN_DISCONNECTED); - } - - } else if (status->state & FR_DLCI_ACTIVE) { - - chan = dev->priv; - - /* This flag is used for configuring specific - DLCI(s) when they become active. - */ - chan->dlci_configured = DLCI_CONFIG_PENDING; - - set_chan_state(dev, WAN_CONNECTED); - - } - } - } - - for (dev2 = card->wandev.dev; dev2; - dev2 = *((struct net_device **)dev2->priv)){ - - chan = dev2->priv; - - if (chan->dlci_configured == DLCI_CONFIG_PENDING) { - if (fr_init_dlci(card, chan)){ - return 1; - } - } - - } - return 1; -} - - -static int fr_init_dlci (sdla_t *card, fr_channel_t *chan) -{ - fr_dlc_conf_t cfg; - - memset(&cfg, 0, sizeof(cfg)); - - if ( chan->cir_status == CIR_DISABLED) { - - cfg.cir_fwd = cfg.cir_bwd = 16; - cfg.bc_fwd = cfg.bc_bwd = 16; - cfg.conf_flags = 0x0001; - - }else if (chan->cir_status == CIR_ENABLED) { - - cfg.cir_fwd = cfg.cir_bwd = chan->cir; - cfg.bc_fwd = cfg.bc_bwd = chan->bc; - cfg.be_fwd = cfg.be_bwd = chan->be; - cfg.conf_flags = 0x0000; - } - - if (fr_dlci_configure( card, &cfg , chan->dlci)){ - printk(KERN_INFO - "%s: DLCI Configure failed for %d\n", - card->devname, chan->dlci); - return 1; - } - - chan->dlci_configured = DLCI_CONFIGURED; - - /* Read the interface byte mapping into the channel - * structure. - */ - read_DLCI_IB_mapping( card, chan ); - - return 0; -} -/******* Miscellaneous ******************************************************/ - -/*============================================================================ - * Update channel state. - */ -static int update_chan_state(struct net_device* dev) -{ - fr_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - mbox->cmd.command = FR_LIST_ACTIVE_DLCI; - mbox->cmd.length = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && fr_event(card, err, mbox)); - - if (!err) { - - unsigned short* list = (void*)mbox->data; - int cnt = mbox->cmd.length / sizeof(short); - - err=1; - - for (; cnt; --cnt, ++list) { - - if (*list == chan->dlci) { - set_chan_state(dev, WAN_CONNECTED); - - - /* May 23 2000. NC - * When a dlci is added or restarted, - * the dlci_int_interface pointer must - * be reinitialized. */ - if (!chan->dlci_int_interface){ - err=fr_init_dlci (card,chan); - } - break; - } - } - } - - return err; -} - -/*============================================================================ - * Set channel state. - */ -static void set_chan_state(struct net_device* dev, int state) -{ - fr_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - - if (chan->common.state != state) { - - switch (state) { - - case WAN_CONNECTED: - printk(KERN_INFO - "%s: Interface %s: DLCI %d connected\n", - card->devname, dev->name, chan->dlci); - - /* If the interface was previoulsy down, - * bring it up, since the channel is active */ - - trigger_fr_poll (dev); - trigger_fr_arp (dev); - break; - - case WAN_CONNECTING: - printk(KERN_INFO - "%s: Interface %s: DLCI %d connecting\n", - card->devname, dev->name, chan->dlci); - break; - - case WAN_DISCONNECTED: - printk (KERN_INFO - "%s: Interface %s: DLCI %d disconnected!\n", - card->devname, dev->name, chan->dlci); - - /* If the interface is up, bring it down, - * since the channel is now disconnected */ - trigger_fr_poll (dev); - break; - } - - chan->common.state = state; - } - - chan->state_tick = jiffies; -} - -/*============================================================================ - * Find network device by its channel number. - * - * We need this critical flag because we change - * the dlci_to_dev_map outside the interrupt. - * - * NOTE: del_if() functions updates this array, it uses - * the spin locks to avoid corruption. - */ -static struct net_device* find_channel(sdla_t* card, unsigned dlci) -{ - if(dlci > HIGHEST_VALID_DLCI) - return NULL; - - return(card->u.f.dlci_to_dev_map[dlci]); -} - -/*============================================================================ - * Check to see if a frame can be sent. If no transmit buffers available, - * enable transmit interrupts. - * - * Return: 1 - Tx buffer(s) available - * 0 - no buffers available - */ -static int is_tx_ready (sdla_t* card, fr_channel_t* chan) -{ - unsigned char sb; - - if(card->hw.type == SDLA_S514) - return 1; - - sb = inb(card->hw.port); - if (sb & 0x02) - return 1; - - return 0; -} - -/*============================================================================ - * Convert decimal string to unsigned integer. - * If len != 0 then only 'len' characters of the string are converted. - */ -static unsigned int dec_to_uint (unsigned char* str, int len) -{ - unsigned val; - - if (!len) - len = strlen(str); - - for (val = 0; len && isdigit(*str); ++str, --len) - val = (val * 10) + (*str - (unsigned)'0'); - - return val; -} - - - -/*============================================================================= - * Store a UDP management packet for later processing. - */ - -static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, int dlci) -{ - int udp_pkt_stored = 0; - - struct net_device *dev = find_channel(card, dlci); - fr_channel_t *chan; - - if (!dev || !(chan=dev->priv)) - return 1; - - if(!card->u.f.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){ - card->u.f.udp_pkt_lgth = skb->len + chan->fr_header_len; - card->u.f.udp_type = udp_type; - card->u.f.udp_pkt_src = udp_pkt_src; - card->u.f.udp_dlci = dlci; - memcpy(card->u.f.udp_pkt_data, skb->data, skb->len); - card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UDP; - udp_pkt_stored = 1; - - }else{ - printk(KERN_INFO "ERROR: UDP packet not stored for DLCI %d\n", - dlci); - } - - if(udp_pkt_src == UDP_PKT_FRM_STACK){ - dev_kfree_skb_any(skb); - }else{ - dev_kfree_skb_any(skb); - } - - return(udp_pkt_stored); -} - - -/*============================================================================== - * Process UDP call of type FPIPE8ND - */ -static int process_udp_mgmt_pkt(sdla_t* card) -{ - - int c_retry = MAX_CMD_RETRY; - unsigned char *buf; - unsigned char frames; - unsigned int len; - unsigned short buffer_length; - struct sk_buff *new_skb; - fr_mbox_t* mbox = card->mbox; - int err; - struct timeval tv; - int udp_mgmt_req_valid = 1; - struct net_device* dev; - fr_channel_t* chan; - fr_udp_pkt_t *fr_udp_pkt; - unsigned short num_trc_els; - fr_trc_el_t* ptr_trc_el; - fr_trc_el_t trc_el; - fpipemon_trc_t* fpipemon_trc; - - char udp_pkt_src = card->u.f.udp_pkt_src; - int dlci = card->u.f.udp_dlci; - - /* Find network interface for this packet */ - dev = find_channel(card, dlci); - if (!dev){ - card->u.f.udp_pkt_lgth = 0; - return 1; - } - if ((chan = dev->priv) == NULL){ - card->u.f.udp_pkt_lgth = 0; - return 1; - } - - /* If the UDP packet is from the network, we are going to have to - transmit a response. Before doing so, we must check to see that - we are not currently transmitting a frame (in 'if_send()') and - that we are not already in a 'delayed transmit' state. - */ - if(udp_pkt_src == UDP_PKT_FRM_NETWORK) { - if (check_tx_status(card,dev)){ - card->u.f.udp_pkt_lgth = 0; - return 1; - } - } - - fr_udp_pkt = (fr_udp_pkt_t *)card->u.f.udp_pkt_data; - - if(udp_pkt_src == UDP_PKT_FRM_NETWORK) { - - switch(fr_udp_pkt->cblock.command) { - - case FR_READ_MODEM_STATUS: - case FR_READ_STATUS: - case FPIPE_ROUTER_UP_TIME: - case FR_READ_ERROR_STATS: - case FPIPE_DRIVER_STAT_GEN: - case FR_READ_STATISTICS: - case FR_READ_ADD_DLC_STATS: - case FR_READ_CONFIG: - case FR_READ_CODE_VERSION: - udp_mgmt_req_valid = 1; - break; - default: - udp_mgmt_req_valid = 0; - break; - } - } - - if(!udp_mgmt_req_valid) { - /* set length to 0 */ - fr_udp_pkt->cblock.length = 0; - /* set return code */ - fr_udp_pkt->cblock.result = 0xCD; - - chan->drvstats_gen.UDP_PIPE_mgmt_direction_err ++; - - if (net_ratelimit()){ - printk(KERN_INFO - "%s: Warning, Illegal UDP command attempted from network: %x\n", - card->devname,fr_udp_pkt->cblock.command); - } - - } else { - - switch(fr_udp_pkt->cblock.command) { - - case FPIPE_ENABLE_TRACING: - if(!card->TracingEnabled) { - do { - mbox->cmd.command = FR_SET_TRACE_CONFIG; - mbox->cmd.length = 1; - mbox->cmd.dlci = 0x00; - mbox->data[0] = fr_udp_pkt->data[0] | - RESET_TRC; - err = sdla_exec(mbox) ? - mbox->cmd.result : CMD_TIMEOUT; - } while (err && c_retry-- && fr_event(card, err, - mbox)); - - if(err) { - card->TracingEnabled = 0; - /* set the return code */ - fr_udp_pkt->cblock.result = - mbox->cmd.result; - mbox->cmd.length = 0; - break; - } - - sdla_peek(&card->hw, NO_TRC_ELEMENTS_OFF, - &num_trc_els, 2); - sdla_peek(&card->hw, BASE_TRC_ELEMENTS_OFF, - &card->u.f.trc_el_base, 4); - card->u.f.curr_trc_el = card->u.f.trc_el_base; - card->u.f.trc_el_last = card->u.f.curr_trc_el + - ((num_trc_els - 1) * - sizeof(fr_trc_el_t)); - - /* Calculate the maximum trace data area in */ - /* the UDP packet */ - card->u.f.trc_bfr_space=(MAX_LGTH_UDP_MGNT_PKT - - //sizeof(fr_encap_hdr_t) - - sizeof(ip_pkt_t) - - sizeof(udp_pkt_t) - - sizeof(wp_mgmt_t) - - sizeof(cblock_t)); - - /* set return code */ - fr_udp_pkt->cblock.result = 0; - - } else { - /* set return code to line trace already - enabled */ - fr_udp_pkt->cblock.result = 1; - } - - mbox->cmd.length = 0; - card->TracingEnabled = 1; - break; - - - case FPIPE_DISABLE_TRACING: - if(card->TracingEnabled) { - - do { - mbox->cmd.command = FR_SET_TRACE_CONFIG; - mbox->cmd.length = 1; - mbox->cmd.dlci = 0x00; - mbox->data[0] = ~ACTIVATE_TRC; - err = sdla_exec(mbox) ? - mbox->cmd.result : CMD_TIMEOUT; - } while (err && c_retry-- && fr_event(card, err, mbox)); - } - - /* set return code */ - fr_udp_pkt->cblock.result = 0; - mbox->cmd.length = 0; - card->TracingEnabled = 0; - break; - - case FPIPE_GET_TRACE_INFO: - - /* Line trace cannot be performed on the 502 */ - if(!card->TracingEnabled) { - /* set return code */ - fr_udp_pkt->cblock.result = 1; - mbox->cmd.length = 0; - break; - } - - ptr_trc_el = (void *)card->u.f.curr_trc_el; - - buffer_length = 0; - fr_udp_pkt->data[0x00] = 0x00; - - for(frames = 0; frames < MAX_FRMS_TRACED; frames ++) { - - sdla_peek(&card->hw, (unsigned long)ptr_trc_el, - (void *)&trc_el.flag, - sizeof(fr_trc_el_t)); - if(trc_el.flag == 0x00) { - break; - } - if((card->u.f.trc_bfr_space - buffer_length) - < sizeof(fpipemon_trc_hdr_t)) { - fr_udp_pkt->data[0x00] |= MORE_TRC_DATA; - break; - } - - fpipemon_trc = - (fpipemon_trc_t *)&fr_udp_pkt->data[buffer_length]; - fpipemon_trc->fpipemon_trc_hdr.status = - trc_el.attr; - fpipemon_trc->fpipemon_trc_hdr.tmstamp = - trc_el.tmstamp; - fpipemon_trc->fpipemon_trc_hdr.length = - trc_el.length; - - if(!trc_el.offset || !trc_el.length) { - - fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00; - - }else if((trc_el.length + sizeof(fpipemon_trc_hdr_t) + 1) > - (card->u.f.trc_bfr_space - buffer_length)){ - - fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00; - fr_udp_pkt->data[0x00] |= MORE_TRC_DATA; - - }else { - fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x01; - sdla_peek(&card->hw, trc_el.offset, - fpipemon_trc->data, - trc_el.length); - } - - trc_el.flag = 0x00; - sdla_poke(&card->hw, (unsigned long)ptr_trc_el, - &trc_el.flag, 1); - - ptr_trc_el ++; - if((void *)ptr_trc_el > card->u.f.trc_el_last) - ptr_trc_el = (void*)card->u.f.trc_el_base; - - buffer_length += sizeof(fpipemon_trc_hdr_t); - if(fpipemon_trc->fpipemon_trc_hdr.data_passed) { - buffer_length += trc_el.length; - } - - if(fr_udp_pkt->data[0x00] & MORE_TRC_DATA) { - break; - } - } - - if(frames == MAX_FRMS_TRACED) { - fr_udp_pkt->data[0x00] |= MORE_TRC_DATA; - } - - card->u.f.curr_trc_el = (void *)ptr_trc_el; - - /* set the total number of frames passed */ - fr_udp_pkt->data[0x00] |= - ((frames << 1) & (MAX_FRMS_TRACED << 1)); - - /* set the data length and return code */ - fr_udp_pkt->cblock.length = mbox->cmd.length = buffer_length; - fr_udp_pkt->cblock.result = 0; - break; - - case FPIPE_FT1_READ_STATUS: - sdla_peek(&card->hw, 0xF020, - &fr_udp_pkt->data[0x00] , 2); - fr_udp_pkt->cblock.length = mbox->cmd.length = 2; - fr_udp_pkt->cblock.result = 0; - break; - - case FPIPE_FLUSH_DRIVER_STATS: - init_chan_statistics(chan); - init_global_statistics(card); - mbox->cmd.length = 0; - break; - - case FPIPE_ROUTER_UP_TIME: - do_gettimeofday(&tv); - chan->router_up_time = tv.tv_sec - - chan->router_start_time; - *(unsigned long *)&fr_udp_pkt->data = - chan->router_up_time; - mbox->cmd.length = fr_udp_pkt->cblock.length = 4; - fr_udp_pkt->cblock.result = 0; - break; - - case FPIPE_DRIVER_STAT_IFSEND: - memcpy(fr_udp_pkt->data, - &chan->drvstats_if_send.if_send_entry, - sizeof(if_send_stat_t)); - mbox->cmd.length = fr_udp_pkt->cblock.length =sizeof(if_send_stat_t); - fr_udp_pkt->cblock.result = 0; - break; - - case FPIPE_DRIVER_STAT_INTR: - - memcpy(fr_udp_pkt->data, - &card->statistics.isr_entry, - sizeof(global_stats_t)); - - memcpy(&fr_udp_pkt->data[sizeof(global_stats_t)], - &chan->drvstats_rx_intr.rx_intr_no_socket, - sizeof(rx_intr_stat_t)); - - mbox->cmd.length = fr_udp_pkt->cblock.length = - sizeof(global_stats_t) + - sizeof(rx_intr_stat_t); - fr_udp_pkt->cblock.result = 0; - break; - - case FPIPE_DRIVER_STAT_GEN: - memcpy(fr_udp_pkt->data, - &chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err, - sizeof(pipe_mgmt_stat_t)); - - memcpy(&fr_udp_pkt->data[sizeof(pipe_mgmt_stat_t)], - &card->statistics, sizeof(global_stats_t)); - - mbox->cmd.length = fr_udp_pkt->cblock.length = sizeof(global_stats_t)+ - sizeof(rx_intr_stat_t); - fr_udp_pkt->cblock.result = 0; - break; - - - case FR_FT1_STATUS_CTRL: - if(fr_udp_pkt->data[0] == 1) { - if(rCount++ != 0 ){ - fr_udp_pkt->cblock.result = 0; - mbox->cmd.length = 1; - break; - } - } - - /* Disable FT1 MONITOR STATUS */ - if(fr_udp_pkt->data[0] == 0) { - if( --rCount != 0) { - fr_udp_pkt->cblock.result = 0; - mbox->cmd.length = 1; - break; - } - } - goto udp_mgmt_dflt; - - - default: -udp_mgmt_dflt: - do { - memcpy(&mbox->cmd, - &fr_udp_pkt->cblock.command, - sizeof(fr_cmd_t)); - if(mbox->cmd.length) { - memcpy(&mbox->data, - (char *)fr_udp_pkt->data, - mbox->cmd.length); - } - - err = sdla_exec(mbox) ? mbox->cmd.result : - CMD_TIMEOUT; - } while (err && c_retry-- && fr_event(card, err, mbox)); - - if(!err) - chan->drvstats_gen. - UDP_PIPE_mgmt_adptr_cmnd_OK ++; - else - chan->drvstats_gen. - UDP_PIPE_mgmt_adptr_cmnd_timeout ++; - - /* copy the result back to our buffer */ - memcpy(&fr_udp_pkt->cblock.command, - &mbox->cmd, sizeof(fr_cmd_t)); - - if(mbox->cmd.length) { - memcpy(&fr_udp_pkt->data, - &mbox->data, mbox->cmd.length); - } - } - } - - /* Fill UDP TTL */ - fr_udp_pkt->ip_pkt.ttl = card->wandev.ttl; - len = reply_udp(card->u.f.udp_pkt_data, mbox->cmd.length); - - if(udp_pkt_src == UDP_PKT_FRM_NETWORK) { - - chan->fr_header_len=2; - chan->fr_header[0]=Q922_UI; - chan->fr_header[1]=NLPID_IP; - - err = fr_send_data_header(card, dlci, 0, len, - card->u.f.udp_pkt_data,chan->fr_header_len); - if (err){ - chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_passed ++; - }else{ - chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_failed ++; - } - - } else { - /* Allocate socket buffer */ - if((new_skb = dev_alloc_skb(len)) != NULL) { - - /* copy data into new_skb */ - buf = skb_put(new_skb, len); - memcpy(buf, card->u.f.udp_pkt_data, len); - - chan->drvstats_gen. - UDP_PIPE_mgmt_passed_to_stack ++; - new_skb->dev = dev; - new_skb->protocol = htons(ETH_P_IP); - new_skb->mac.raw = new_skb->data; - netif_rx(new_skb); - - } else { - chan->drvstats_gen.UDP_PIPE_mgmt_no_socket ++; - printk(KERN_INFO - "%s: UDP mgmt cmnd, no socket buffers available!\n", - card->devname); - } - } - - card->u.f.udp_pkt_lgth = 0; - - return 1; -} - -/*============================================================================== - * Send Inverse ARP Request - */ - -int send_inarp_request(sdla_t *card, struct net_device *dev) -{ - int err=0; - - arphdr_1490_t *ArpPacket; - arphdr_fr_t *arphdr; - fr_channel_t *chan = dev->priv; - struct in_device *in_dev; - - in_dev = dev->ip_ptr; - - if(in_dev != NULL ) { - - ArpPacket = kmalloc(sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), GFP_ATOMIC); - /* SNAP Header indicating ARP */ - ArpPacket->control = 0x03; - ArpPacket->pad = 0x00; - ArpPacket->NLPID = 0x80; - ArpPacket->OUI[0] = 0; - ArpPacket->OUI[1] = 0; - ArpPacket->OUI[2] = 0; - ArpPacket->PID = 0x0608; - - arphdr = (arphdr_fr_t *)(ArpPacket + 1); // Go to ARP Packet - - /* InARP request */ - arphdr->ar_hrd = 0x0F00; /* Frame Relay HW type */ - arphdr->ar_pro = 0x0008; /* IP Protocol */ - arphdr->ar_hln = 2; /* HW addr length */ - arphdr->ar_pln = 4; /* IP addr length */ - arphdr->ar_op = htons(0x08); /* InARP Request */ - arphdr->ar_sha = 0; /* src HW DLCI - Doesn't matter */ - if(in_dev->ifa_list != NULL) - arphdr->ar_sip = in_dev->ifa_list->ifa_local; /* Local Address */else - arphdr->ar_sip = 0; - arphdr->ar_tha = 0; /* dst HW DLCI - Doesn't matter */ - arphdr->ar_tip = 0; /* Remote Address -- what we want */ - - err = fr_send(card, chan->dlci, 0, sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), - (void *)ArpPacket); - - if (!err){ - printk(KERN_INFO "\n%s: Sending InARP request on DLCI %d.\n", - card->devname, chan->dlci); - clear_bit(ARP_CRIT,&card->wandev.critical); - } - - kfree(ArpPacket); - }else{ - printk(KERN_INFO "%s: INARP ERROR: %s doesn't have a local IP address!\n", - card->devname,dev->name); - return 1; - } - - return 0; -} - - -/*============================================================================== - * Check packet for ARP Type - */ - -int is_arp(void *buf) -{ - arphdr_1490_t *arphdr = (arphdr_1490_t *)buf; - - if (arphdr->pad == 0x00 && - arphdr->NLPID == 0x80 && - arphdr->PID == 0x0608) - return 1; - else return 0; -} - -/*============================================================================== - * Process ARP Packet Type - */ - -int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device* dev) -{ - - - arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */ - fr_rx_buf_ctl_t* frbuf = card->rxmb; - struct in_device *in_dev; - fr_channel_t *chan = dev->priv; - - /* Before we transmit ARP packet, we must check - * to see that we are not currently transmitting a - * frame (in 'if_send()') and that we are not - * already in a 'delayed transmit' state. */ - if (check_tx_status(card,dev)){ - if (net_ratelimit()){ - printk(KERN_INFO "%s: Disabling comminication to process ARP\n", - card->devname); - } - set_bit(ARP_CRIT,&card->wandev.critical); - return 0; - } - - in_dev = dev->ip_ptr; - - /* Check that IP addresses exist for our network address */ - if (in_dev == NULL || in_dev->ifa_list == NULL) - return -1; - - switch (ntohs(arphdr->ar_op)) { - - case 0x08: // Inverse ARP request -- Send Reply, add route. - - /* Check for valid Address */ - printk(KERN_INFO "%s: Recvd PtP addr -InArp Req: %u.%u.%u.%u\n", - card->devname, NIPQUAD(arphdr->ar_sip)); - - - /* Check that the network address is the same as ours, only - * if the netowrk mask is not 255.255.255.255. Otherwise - * this check would not make sense */ - - if (in_dev->ifa_list->ifa_mask != 0xFFFFFFFF && - (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) != - (in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)){ - printk(KERN_INFO - "%s: Invalid PtP address. %u.%u.%u.%u InARP ignored.\n", - card->devname,NIPQUAD(arphdr->ar_sip)); - - printk(KERN_INFO "%s: mask %u.%u.%u.%u\n", - card->devname, NIPQUAD(in_dev->ifa_list->ifa_mask)); - printk(KERN_INFO "%s: local %u.%u.%u.%u\n", - card->devname,NIPQUAD(in_dev->ifa_list->ifa_local)); - return -1; - } - - if (in_dev->ifa_list->ifa_local == arphdr->ar_sip){ - printk(KERN_INFO - "%s: Local addr = PtP addr. InARP ignored.\n", - card->devname); - return -1; - } - - arphdr->ar_op = htons(0x09); /* InARP Reply */ - - /* Set addresses */ - arphdr->ar_tip = arphdr->ar_sip; - arphdr->ar_sip = in_dev->ifa_list->ifa_local; - - chan->ip_local = in_dev->ifa_list->ifa_local; - chan->ip_remote = arphdr->ar_sip; - - fr_send(card, frbuf->dlci, 0, frbuf->length, (void *)ArpPacket); - - if (test_bit(ARP_CRIT,&card->wandev.critical)){ - if (net_ratelimit()){ - printk(KERN_INFO "%s: ARP Processed Enabling Communication!\n", - card->devname); - } - } - clear_bit(ARP_CRIT,&card->wandev.critical); - - chan->ip_local = in_dev->ifa_list->ifa_local; - chan->ip_remote = arphdr->ar_sip; - - /* Add Route Flag */ - /* The route will be added in the polling routine so - that it is not interrupt context. */ - - chan->route_flag = ADD_ROUTE; - trigger_fr_poll (dev); - - break; - - case 0x09: // Inverse ARP reply - - /* Check for valid Address */ - printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Reply\n", - card->devname, NIPQUAD(arphdr->ar_sip)); - - - /* Compare network addresses, only if network mask - * is not 255.255.255.255 It would not make sense - * to perform this test if the mask was all 1's */ - - if (in_dev->ifa_list->ifa_mask != 0xffffffff && - (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) != - (in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)) { - - printk(KERN_INFO "%s: Invalid PtP address. InARP ignored.\n", - card->devname); - return -1; - } - - /* Make sure that the received IP address is not - * the same as our own local address */ - if (in_dev->ifa_list->ifa_local == arphdr->ar_sip) { - printk(KERN_INFO "%s: Local addr = PtP addr. InARP ignored.\n", - card->devname); - return -1; - } - - chan->ip_local = in_dev->ifa_list->ifa_local; - chan->ip_remote = arphdr->ar_sip; - - /* Add Route Flag */ - /* The route will be added in the polling routine so - that it is not interrupt context. */ - - chan->route_flag = ADD_ROUTE; - chan->inarp = INARP_CONFIGURED; - trigger_fr_poll(dev); - - break; - default: - break; // ARP's and RARP's -- Shouldn't happen. - } - - return 0; -} - - -/*============================================================ - * trigger_fr_arp - * - * Description: - * Add an fr_arp() task into a arp - * timer handler for a specific dlci/interface. - * This will kick the fr_arp() routine - * within the specified time interval. - * - * Usage: - * This timer is used to send ARP requests at - * certain time intervals. - * Called by an interrupt to request an action - * at a later date. - */ - -static void trigger_fr_arp(struct net_device *dev) -{ - fr_channel_t* chan = dev->priv; - - mod_timer(&chan->fr_arp_timer, jiffies + chan->inarp_interval * HZ); - return; -} - - - -/*============================================================================== - * ARP Request Action - * - * This funciton is called by timer interrupt to send an arp request - * to the remote end. - */ - -static void fr_arp (unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - fr_channel_t *chan = dev->priv; - volatile sdla_t *card = chan->card; - fr508_flags_t* flags = card->flags; - - /* Send ARP packets for all devs' until - * ARP state changes to CONFIGURED */ - - if (chan->inarp == INARP_REQUEST && - chan->common.state == WAN_CONNECTED && - card->wandev.state == WAN_CONNECTED){ - set_bit(0,&chan->inarp_ready); - card->u.f.timer_int_enabled |= TMR_INT_ENABLED_ARP; - flags->imask |= FR_INTR_TIMER; - } - - return; -} - - -/*============================================================================== - * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR_ - * TEST_COUNTER times. - */ -static int intr_test( sdla_t* card ) -{ - fr_mbox_t* mb = card->mbox; - int err,i; - - err = fr_set_intr_mode(card, FR_INTR_READY, card->wandev.mtu, 0 ); - - if (err == CMD_OK) { - - for ( i = 0; i < MAX_INTR_TEST_COUNTER; i++ ) { - /* Run command READ_CODE_VERSION */ - mb->cmd.length = 0; - mb->cmd.command = FR_READ_CODE_VERSION; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - if (err != CMD_OK) - fr_event(card, err, mb); - } - - } else { - return err; - } - - err = fr_set_intr_mode( card, 0, card->wandev.mtu, 0 ); - - if( err != CMD_OK ) - return err; - - return 0; -} - -/*============================================================================== - * Determine what type of UDP call it is. FPIPE8ND ? - */ -static int udp_pkt_type( struct sk_buff *skb, sdla_t* card ) -{ - fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)skb->data; - - /* Quick HACK */ - - - if((fr_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) && - (fr_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) && - (fr_udp_pkt->udp_pkt.udp_dst_port == - ntohs(card->wandev.udp_port)) && - (fr_udp_pkt->wp_mgmt.request_reply == - UDPMGMT_REQUEST)) { - if(!strncmp(fr_udp_pkt->wp_mgmt.signature, - UDPMGMT_FPIPE_SIGNATURE, 8)){ - return UDP_FPIPE_TYPE; - } - } - return UDP_INVALID_TYPE; -} - - -/*============================================================================== - * Initializes the Statistics values in the fr_channel structure. - */ -void init_chan_statistics( fr_channel_t* chan) -{ - memset(&chan->drvstats_if_send.if_send_entry, 0, - sizeof(if_send_stat_t)); - memset(&chan->drvstats_rx_intr.rx_intr_no_socket, 0, - sizeof(rx_intr_stat_t)); - memset(&chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err, 0, - sizeof(pipe_mgmt_stat_t)); -} - -/*============================================================================== - * Initializes the Statistics values in the Sdla_t structure. - */ -void init_global_statistics( sdla_t* card ) -{ - /* Intialize global statistics for a card */ - memset(&card->statistics.isr_entry, 0, sizeof(global_stats_t)); -} - -static void read_DLCI_IB_mapping( sdla_t* card, fr_channel_t* chan ) -{ - fr_mbox_t* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - dlci_IB_mapping_t* result; - int err, counter, found; - - do { - mbox->cmd.command = FR_READ_DLCI_IB_MAPPING; - mbox->cmd.length = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && fr_event(card, err, mbox)); - - if( mbox->cmd.result != 0){ - printk(KERN_INFO "%s: Read DLCI IB Mapping failed\n", - chan->name); - } - - counter = mbox->cmd.length / sizeof(dlci_IB_mapping_t); - result = (void *)mbox->data; - - found = 0; - for (; counter; --counter, ++result) { - if ( result->dlci == chan->dlci ) { - chan->IB_addr = result->addr_value; - if(card->hw.type == SDLA_S514){ - chan->dlci_int_interface = - (void*)(card->hw.dpmbase + - chan->IB_addr); - }else{ - chan->dlci_int_interface = - (void*)(card->hw.dpmbase + - (chan->IB_addr & 0x00001FFF)); - - } - found = 1; - break; - } - } - if (!found) - printk( KERN_INFO "%s: DLCI %d not found by IB MAPPING cmd\n", - card->devname, chan->dlci); -} - - - -void s508_s514_lock(sdla_t *card, unsigned long *smp_flags) -{ - if (card->hw.type != SDLA_S514){ - - spin_lock_irqsave(&card->wandev.lock, *smp_flags); - }else{ - spin_lock(&card->u.f.if_send_lock); - } - return; -} - - -void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags) -{ - if (card->hw.type != SDLA_S514){ - - spin_unlock_irqrestore (&card->wandev.lock, *smp_flags); - }else{ - spin_unlock(&card->u.f.if_send_lock); - } - return; -} - - - -/*---------------------------------------------------------------------- - RECEIVE INTERRUPT: BOTTOM HALF HANDLERS - ----------------------------------------------------------------------*/ - - -/*======================================================== - * bh_enqueue - * - * Description: - * Insert a received packet into a circular - * rx queue. This packet will be picked up - * by fr_bh() and sent up the stack to the - * user. - * - * Usage: - * This function is called by rx interrupt, - * in API mode. - * - */ - -static int bh_enqueue(struct net_device *dev, struct sk_buff *skb) -{ - /* Check for full */ - fr_channel_t* chan = dev->priv; - sdla_t *card = chan->card; - - - if (atomic_read(&chan->bh_buff_used) == MAX_BH_BUFF){ - ++card->wandev.stats.rx_dropped; - dev_kfree_skb_any(skb); - return 1; - } - - ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb; - - if (chan->bh_write == (MAX_BH_BUFF-1)){ - chan->bh_write=0; - }else{ - ++chan->bh_write; - } - - atomic_inc(&chan->bh_buff_used); - - return 0; -} - - -/*======================================================== - * trigger_fr_bh - * - * Description: - * Kick the fr_bh() handler - * - * Usage: - * rx interrupt calls this function during - * the API mode. - */ - -static void trigger_fr_bh (fr_channel_t *chan) -{ - if (!test_and_set_bit(0,&chan->tq_working)){ - wanpipe_queue_work(&chan->common.wanpipe_work); - } -} - - -/*======================================================== - * fr_bh - * - * Description: - * Frame relay receive BH handler. - * Dequeue data from the BH circular - * buffer and pass it up the API sock. - * - * Rationale: - * This fuction is used to offload the - * rx_interrupt during API operation mode. - * The fr_bh() function executes for each - * dlci/interface. - * - * Once receive interrupt copies data from the - * card into an skb buffer, the skb buffer - * is appended to a circular BH buffer. - * Then the interrupt kicks fr_bh() to finish the - * job at a later time (not within the interrupt). - * - * Usage: - * Interrupts use this to defer a task to - * a polling routine. - * - */ - -static void fr_bh(struct net_device * dev) -{ - fr_channel_t* chan = dev->priv; - sdla_t *card = chan->card; - struct sk_buff *skb; - - if (atomic_read(&chan->bh_buff_used) == 0){ - clear_bit(0, &chan->tq_working); - return; - } - - while (atomic_read(&chan->bh_buff_used)){ - - if (chan->common.sk == NULL || chan->common.func == NULL){ - clear_bit(0, &chan->tq_working); - return; - } - - skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb; - - if (skb != NULL){ - - if (chan->common.sk == NULL || chan->common.func == NULL){ - ++card->wandev.stats.rx_dropped; - ++chan->ifstats.rx_dropped; - dev_kfree_skb_any(skb); - fr_bh_cleanup(dev); - continue; - } - - if (chan->common.func(skb,dev,chan->common.sk) != 0){ - /* Sock full cannot send, queue us for - * another try */ - atomic_set(&chan->common.receive_block,1); - return; - }else{ - fr_bh_cleanup(dev); - } - }else{ - fr_bh_cleanup(dev); - } - } - clear_bit(0, &chan->tq_working); - - return; -} - -static int fr_bh_cleanup(struct net_device *dev) -{ - fr_channel_t* chan = dev->priv; - - ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL; - - if (chan->bh_read == (MAX_BH_BUFF-1)){ - chan->bh_read=0; - }else{ - ++chan->bh_read; - } - - atomic_dec(&chan->bh_buff_used); - return 0; -} - - -/*---------------------------------------------------------------------- - POLL BH HANDLERS AND KICK ROUTINES - ----------------------------------------------------------------------*/ - -/*============================================================ - * trigger_fr_poll - * - * Description: - * Add a fr_poll() task into a tq_scheduler bh handler - * for a specific dlci/interface. This will kick - * the fr_poll() routine at a later time. - * - * Usage: - * Interrupts use this to defer a taks to - * a polling routine. - * - */ -static void trigger_fr_poll(struct net_device *dev) -{ - fr_channel_t* chan = dev->priv; - schedule_work(&chan->fr_poll_work); - return; -} - - -/*============================================================ - * fr_poll - * - * Rationale: - * We cannot manipulate the routing tables, or - * ip addresses withing the interrupt. Therefore - * we must perform such actons outside an interrupt - * at a later time. - * - * Description: - * Frame relay polling routine, responsible for - * shutting down interfaces upon disconnect - * and adding/removing routes. - * - * Usage: - * This function is executed for each frame relay - * dlci/interface through a tq_schedule bottom half. - * - * trigger_fr_poll() function is used to kick - * the fr_poll routine. - */ - -static void fr_poll(struct net_device *dev) -{ - - fr_channel_t* chan; - sdla_t *card; - u8 check_gateway=0; - - if (!dev || (chan = dev->priv) == NULL) - return; - - card = chan->card; - - /* (Re)Configuraiton is in progress, stop what you are - * doing and get out */ - if (test_bit(PERI_CRIT,&card->wandev.critical)){ - return; - } - - switch (chan->common.state){ - - case WAN_DISCONNECTED: - - if (test_bit(DYN_OPT_ON,&chan->interface_down) && - !test_bit(DEV_DOWN, &chan->interface_down) && - dev->flags&IFF_UP){ - - printk(KERN_INFO "%s: Interface %s is Down.\n", - card->devname,dev->name); - change_dev_flags(dev,dev->flags&~IFF_UP); - set_bit(DEV_DOWN, &chan->interface_down); - chan->route_flag = NO_ROUTE; - - }else{ - if (chan->inarp != INARP_NONE) - process_route(dev); - } - break; - - case WAN_CONNECTED: - - if (test_bit(DYN_OPT_ON,&chan->interface_down) && - test_bit(DEV_DOWN, &chan->interface_down) && - !(dev->flags&IFF_UP)){ - - printk(KERN_INFO "%s: Interface %s is Up.\n", - card->devname,dev->name); - - change_dev_flags(dev,dev->flags|IFF_UP); - clear_bit(DEV_DOWN, &chan->interface_down); - check_gateway=1; - } - - if (chan->inarp != INARP_NONE){ - process_route(dev); - check_gateway=1; - } - - if (chan->gateway && check_gateway) - add_gateway(card,dev); - - break; - - } - - return; -} - -/*============================================================== - * check_tx_status - * - * Rationale: - * We cannot transmit from an interrupt while - * the if_send is transmitting data. Therefore, - * we must check whether the tx buffers are - * begin used, before we transmit from an - * interrupt. - * - * Description: - * Checks whether it's safe to use the transmit - * buffers. - * - * Usage: - * ARP and UDP handling routines use this function - * because, they need to transmit data during - * an interrupt. - */ - -static int check_tx_status(sdla_t *card, struct net_device *dev) -{ - - if (card->hw.type == SDLA_S514){ - if (test_bit(SEND_CRIT, (void*)&card->wandev.critical) || - test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) { - return 1; - } - } - - if (netif_queue_stopped(dev) || (card->u.f.tx_interrupts_pending)) - return 1; - - return 0; -} - -/*=============================================================== - * move_dev_to_next - * - * Description: - * Move the dev pointer to the next location in the - * link list. Check if we are at the end of the - * list, if so start from the begining. - * - * Usage: - * Timer interrupt uses this function to efficiently - * step through the devices that need to send ARP data. - * - */ - -struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev) -{ - if (card->wandev.new_if_cnt != 1){ - if (!*((struct net_device **)dev->priv)) - return card->wandev.dev; - else - return *((struct net_device **)dev->priv); - } - return dev; -} - -/*============================================================== - * trigger_config_fr - * - * Rationale: - * All commands must be performed inside of a - * interrupt. - * - * Description: - * Kick the config_fr() routine throught the - * timer interrupt. - */ - - -static void trigger_config_fr (sdla_t *card) -{ - fr508_flags_t* flags = card->flags; - - card->u.f.timer_int_enabled |= TMR_INT_ENABLED_CONFIG; - flags->imask |= FR_INTR_TIMER; -} - - -/*============================================================== - * config_fr - * - * Rationale: - * All commands must be performed inside of a - * interrupt. - & - * Description: - * Configure a DLCI. This function is executed - * by a timer_interrupt. The if_open() function - * triggers it. - * - * Usage: - * new_if() collects all data necessary to - * configure the DLCI. It sets the chan->dlci_ready - * bit. When the if_open() function is executed - * it checks this bit, and if its set it triggers - * the timer interrupt to execute the config_fr() - * function. - */ - -static void config_fr (sdla_t *card) -{ - struct net_device *dev; - fr_channel_t *chan; - - for (dev = card->wandev.dev; dev; - dev = *((struct net_device **)dev->priv)) { - - if ((chan=dev->priv) == NULL) - continue; - - if (!test_bit(0,&chan->config_dlci)) - continue; - - clear_bit(0,&chan->config_dlci); - - /* If signalling is set to NO, then setup - * DLCI addresses right away. Don't have to wait for - * link to connect. - */ - if (card->wandev.signalling == WANOPT_NO){ - printk(KERN_INFO "%s: Signalling set to NO: Mapping DLCI's\n", - card->wandev.name); - if (fr_init_dlci(card,chan)){ - printk(KERN_INFO "%s: ERROR: Failed to configure DLCI %i !\n", - card->devname, chan->dlci); - return; - } - } - - if (card->wandev.station == WANOPT_CPE) { - - update_chan_state(dev); - - /* CPE: issue full status enquiry */ - fr_issue_isf(card, FR_ISF_FSE); - - } else { - /* FR switch: activate DLCI(s) */ - - /* For Switch emulation we have to ADD and ACTIVATE - * the DLCI(s) that were configured with the SET_DLCI_ - * CONFIGURATION command. Add and Activate will fail if - * DLCI specified is not included in the list. - * - * Also If_open is called once for each interface. But - * it does not get in here for all the interface. So - * we have to pass the entire list of DLCI(s) to add - * activate routines. - */ - - if (!check_dlci_config (card, chan)){ - fr_add_dlci(card, chan->dlci); - fr_activate_dlci(card, chan->dlci); - } - } - - card->u.f.dlci_to_dev_map[chan->dlci] = dev; - } - return; -} - - -/*============================================================== - * config_fr - * - * Rationale: - * All commands must be executed during an interrupt. - * - * Description: - * Trigger uncofig_fr() function through - * the timer interrupt. - * - */ - -static void trigger_unconfig_fr(struct net_device *dev) -{ - fr_channel_t *chan = dev->priv; - volatile sdla_t *card = chan->card; - unsigned long timeout; - fr508_flags_t* flags = card->flags; - int reset_critical=0; - - if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){ - clear_bit(PERI_CRIT,(void*)&card->wandev.critical); - reset_critical=1; - } - - /* run unconfig_dlci() function - * throught the timer interrupt */ - set_bit(0,(void*)&chan->unconfig_dlci); - card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UNCONFIG; - flags->imask |= FR_INTR_TIMER; - - /* Wait for the command to complete */ - timeout = jiffies; - for(;;) { - - if(!(card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG)) - break; - - if (time_after(jiffies, timeout + 1 * HZ)){ - card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG; - printk(KERN_INFO "%s: Failed to delete DLCI %i\n", - card->devname,chan->dlci); - break; - } - } - - if (reset_critical){ - set_bit(PERI_CRIT,(void*)&card->wandev.critical); - } -} - -/*============================================================== - * unconfig_fr - * - * Rationale: - * All commands must be executed during an interrupt. - * - * Description: - * Remove the dlci from firmware. - * This funciton is used in NODE shutdown. - */ - -static void unconfig_fr (sdla_t *card) -{ - struct net_device *dev; - fr_channel_t *chan; - - for (dev = card->wandev.dev; dev; - dev = *((struct net_device **)dev->priv)){ - - if ((chan=dev->priv) == NULL) - continue; - - if (!test_bit(0,&chan->unconfig_dlci)) - continue; - - clear_bit(0,&chan->unconfig_dlci); - - if (card->wandev.station == WANOPT_NODE){ - printk(KERN_INFO "%s: Unconfiguring DLCI %i\n", - card->devname,chan->dlci); - fr_delete_dlci(card,chan->dlci); - } - card->u.f.dlci_to_dev_map[chan->dlci] = NULL; - } -} - -static int setup_fr_header(struct sk_buff *skb, struct net_device* dev, - char op_mode) -{ - fr_channel_t *chan=dev->priv; - - if (op_mode == WANPIPE) { - chan->fr_header[0]=Q922_UI; - - switch (htons(skb->protocol)){ - case ETH_P_IP: - chan->fr_header[1]=NLPID_IP; - break; - default: - return -EINVAL; - } - - return 2; - } - - /* If we are in bridging mode, we must apply - * an Ethernet header - */ - if (op_mode == BRIDGE || op_mode == BRIDGE_NODE) { - /* Encapsulate the packet as a bridged Ethernet frame. */ -#ifdef DEBUG - printk(KERN_INFO "%s: encapsulating skb for frame relay\n", - dev->name); -#endif - chan->fr_header[0] = 0x03; - chan->fr_header[1] = 0x00; - chan->fr_header[2] = 0x80; - chan->fr_header[3] = 0x00; - chan->fr_header[4] = 0x80; - chan->fr_header[5] = 0xC2; - chan->fr_header[6] = 0x00; - chan->fr_header[7] = 0x07; - - /* Yuck. */ - skb->protocol = ETH_P_802_3; - return 8; - } - - return 0; -} - - -static int check_dlci_config (sdla_t *card, fr_channel_t *chan) -{ - fr_mbox_t* mbox = card->mbox; - int err=0; - fr_conf_t *conf=NULL; - unsigned short dlci_num = chan->dlci; - int dlci_offset=0; - struct net_device *dev = NULL; - - mbox->cmd.command = FR_READ_CONFIG; - mbox->cmd.length = 0; - mbox->cmd.dlci = dlci_num; - - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - if (err == CMD_OK){ - return 0; - } - - for (dev = card->wandev.dev; dev; - dev=*((struct net_device **)dev->priv)) - set_chan_state(dev,WAN_DISCONNECTED); - - printk(KERN_INFO "DLCI %i Not configured, configuring\n",dlci_num); - - mbox->cmd.command = FR_COMM_DISABLE; - mbox->cmd.length = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - if (err != CMD_OK){ - fr_event(card, err, mbox); - return 2; - } - - printk(KERN_INFO "Disabled Communications \n"); - - mbox->cmd.command = FR_READ_CONFIG; - mbox->cmd.length = 0; - mbox->cmd.dlci = 0; - - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK){ - fr_event(card, err, mbox); - return 2; - } - - conf = (fr_conf_t *)mbox->data; - - dlci_offset=0; - for (dev = card->wandev.dev; dev; - dev = *((struct net_device **)dev->priv)) { - fr_channel_t *chan_tmp = dev->priv; - conf->dlci[dlci_offset] = chan_tmp->dlci; - dlci_offset++; - } - - printk(KERN_INFO "Got Fr configuration Buffer Length is %x Dlci %i Dlci Off %i\n", - mbox->cmd.length, - mbox->cmd.length > 0x20 ? conf->dlci[0] : -1, - dlci_offset ); - - mbox->cmd.length = 0x20 + dlci_offset*2; - - mbox->cmd.command = FR_SET_CONFIG; - mbox->cmd.dlci = 0; - - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK){ - fr_event(card, err, mbox); - return 2; - } - - initialize_rx_tx_buffers (card); - - - printk(KERN_INFO "Configuraiton Succeded for new DLCI %i\n",dlci_num); - - if (fr_comm_enable (card)){ - return 2; - } - - printk(KERN_INFO "Enabling Communications \n"); - - for (dev = card->wandev.dev; dev; - dev = *((struct net_device **)dev->priv)) { - fr_channel_t *chan_tmp = dev->priv; - fr_init_dlci(card,chan_tmp); - fr_add_dlci(card, chan_tmp->dlci); - fr_activate_dlci(card, chan_tmp->dlci); - } - - printk(KERN_INFO "END OF CONFIGURAITON %i\n",dlci_num); - - return 1; -} - -static void initialize_rx_tx_buffers (sdla_t *card) -{ - fr_buf_info_t* buf_info; - - 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; - - return; -} - - - -MODULE_LICENSE("GPL"); - -/****** End *****************************************************************/ diff --git a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c deleted file mode 100644 index 9d6528a50f7b..000000000000 --- a/drivers/net/wan/sdla_ft1.c +++ /dev/null @@ -1,345 +0,0 @@ -/***************************************************************************** -* sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module. -* -* Authors: Nenad Corbic -* Gideon Hack -* -* Copyright: (c) 1995-1999 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. -* ============================================================================ -* Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup. -* Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing -* Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices. -* Jun 02, 1999 Gideon Hack Added support for the S514 adapter. -* Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING). -* Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC. -* Aug 07, 1998 David Fong Initial version. -*****************************************************************************/ - -#include -#include /* printk(), and other useful stuff */ -#include /* offsetof(), etc. */ -#include /* return codes */ -#include /* inline memset(), etc. */ -#include /* kmalloc(), kfree() */ -#include /* WAN router definitions */ -#include /* WANPIPE common user API definitions */ -#include /* ARPHRD_* defines */ -#include /* time_after() macro */ - -#include -#include - -#include /* sockaddr_in */ -#include -#include -#include /* htons(), etc. */ -#include -#include - -#include /* CHDLC firmware API definitions */ - -/****** Defines & Macros ****************************************************/ - -/* reasons for enabling the timer interrupt on the adapter */ -#define TMR_INT_ENABLED_UDP 0x0001 -#define TMR_INT_ENABLED_UPDATE 0x0002 - -#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */ -#define CHDLC_HDR_LEN 1 - -#define IFF_POINTTOPOINT 0x10 - -#define WANPIPE 0x00 -#define API 0x01 -#define CHDLC_API 0x01 - -#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" ) - - -/******Data Structures*****************************************************/ - -/* This structure is placed in the private data area of the device structure. - * The card structure used to occupy the private area but now the following - * structure will incorporate the card structure along with CHDLC specific data - */ - -typedef struct chdlc_private_area -{ - struct net_device *slave; - sdla_t *card; - int TracingEnabled; /* For enabling Tracing */ - unsigned long curr_trace_addr; /* Used for Tracing */ - unsigned long start_trace_addr; - unsigned long end_trace_addr; - unsigned long base_addr_trace_buffer; - unsigned long end_addr_trace_buffer; - unsigned short number_trace_elements; - unsigned available_buffer_space; - unsigned long router_start_time; - unsigned char route_status; - unsigned char route_removed; - unsigned long tick_counter; /* For 5s timeout counter */ - unsigned long router_up_time; - u32 IP_address; /* IP addressing */ - u32 IP_netmask; - unsigned char mc; /* Mulitcast support on/off */ - unsigned short udp_pkt_lgth; /* udp packet processing */ - char udp_pkt_src; - char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; - unsigned short timer_int_enabled; - char update_comms_stats; /* updating comms stats */ - //FIXME: add driver stats as per frame relay! - -} chdlc_private_area_t; - -/* Route Status options */ -#define NO_ROUTE 0x00 -#define ADD_ROUTE 0x01 -#define ROUTE_ADDED 0x02 -#define REMOVE_ROUTE 0x03 - - -/****** Function Prototypes *************************************************/ -/* WAN link driver entry points. These are called by the WAN router module. */ -static int wpft1_exec (struct sdla *card, void *u_cmd, void *u_data); -static int chdlc_read_version (sdla_t* card, char* str); -static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb); - -/****** Public Functions ****************************************************/ - -/*============================================================================ - * Cisco HDLC 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 wpft1_init (sdla_t* card, wandev_conf_t* conf) -{ - unsigned char port_num; - int err; - - union - { - char str[80]; - } u; - volatile CHDLC_MAILBOX_STRUCT* mb; - CHDLC_MAILBOX_STRUCT* mb1; - unsigned long timeout; - - /* Verify configuration ID */ - if (conf->config_id != WANCONFIG_CHDLC) { - printk(KERN_INFO "%s: invalid configuration ID %u!\n", - card->devname, conf->config_id); - return -EINVAL; - } - - /* Use primary port */ - card->u.c.comm_port = 0; - - - /* Initialize protocol-specific fields */ - if(card->hw.type != SDLA_S514){ - card->mbox = (void *) card->hw.dpmbase; - }else{ - card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT; - } - - mb = mb1 = card->mbox; - - if (!card->configured){ - - /* The board will place an 'I' in the return code to indicate that it is - ready to accept commands. We expect this to be completed in less - than 1 second. */ - - timeout = jiffies; - while (mb->return_code != 'I') /* Wait 1s for board to initialize */ - if (time_after(jiffies, timeout + 1*HZ)) break; - - if (mb->return_code != 'I') { - printk(KERN_INFO - "%s: Initialization not completed by adapter\n", - card->devname); - printk(KERN_INFO "Please contact Sangoma representative.\n"); - return -EIO; - } - } - - /* 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 (chdlc_read_version(card, u.str)) - return -EIO; - - printk(KERN_INFO "%s: Running FT1 Configuration firmware v%s\n", - card->devname, u.str); - - card->isr = NULL; - card->poll = NULL; - card->exec = &wpft1_exec; - card->wandev.update = NULL; - card->wandev.new_if = NULL; - card->wandev.del_if = NULL; - card->wandev.state = WAN_DUALPORT; - card->wandev.udp_port = conf->udp_port; - - card->wandev.new_if_cnt = 0; - - /* This is for the ports link state */ - card->u.c.state = WAN_DISCONNECTED; - - /* reset the number of times the 'update()' proc has been called */ - card->u.c.update_call_count = 0; - - card->wandev.ttl = 0x7F; - card->wandev.interface = 0; - - card->wandev.clocking = 0; - - port_num = card->u.c.comm_port; - - /* Setup Port Bps */ - - card->wandev.bps = 0; - - card->wandev.mtu = MIN_LGTH_CHDLC_DATA_CFG; - - /* 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) { - 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)); - } - - card->wandev.state = WAN_FT1_READY; - printk(KERN_INFO "%s: FT1 Config Ready !\n",card->devname); - - return 0; -} - -static int wpft1_exec(sdla_t *card, void *u_cmd, void *u_data) -{ - CHDLC_MAILBOX_STRUCT* mbox = card->mbox; - int len; - - if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){ - return -EFAULT; - } - - len = mbox->buffer_length; - - if (len) { - if( copy_from_user((void*)&mbox->data, u_data, len)){ - return -EFAULT; - } - } - - /* execute command */ - if (!sdla_exec(mbox)){ - return -EIO; - } - - /* return result */ - if( copy_to_user(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t))){ - return -EFAULT; - } - - len = mbox->buffer_length; - - if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){ - return -EFAULT; - } - - return 0; - -} - -/*============================================================================ - * Read firmware code version. - * Put code version as ASCII string in str. - */ -static int chdlc_read_version (sdla_t* card, char* str) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - int len; - char err; - mb->buffer_length = 0; - mb->command = READ_CHDLC_CODE_VERSION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - if(err != COMMAND_OK) { - chdlc_error(card,err,mb); - } - else if (str) { /* is not null */ - len = mb->buffer_length; - memcpy(str, mb->data, len); - str[len] = '\0'; - } - return (err); -} - -/*============================================================================ - * Firmware error handler. - * This routine is called whenever firmware command returns non-zero - * return code. - * - * Return zero if previous command has to be cancelled. - */ -static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb) -{ - unsigned cmd = mb->command; - - switch (err) { - - case CMD_TIMEOUT: - printk(KERN_ERR "%s: command 0x%02X timed out!\n", - card->devname, cmd); - break; - - case S514_BOTH_PORTS_SAME_CLK_MODE: - if(cmd == SET_CHDLC_CONFIGURATION) { - printk(KERN_INFO - "%s: Configure both ports for the same clock source\n", - card->devname); - break; - } - - default: - printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n", - card->devname, cmd, err); - } - - return 0; -} - -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c deleted file mode 100644 index a4b489cccbbf..000000000000 --- a/drivers/net/wan/sdla_ppp.c +++ /dev/null @@ -1,3430 +0,0 @@ -/***************************************************************************** -* sdla_ppp.c WANPIPE(tm) Multiprotocol WAN Link Driver. PPP module. -* -* Author: Nenad Corbic -* -* Copyright: (c) 1995-2001 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. -* ============================================================================ -* Feb 28, 2001 Nenad Corbic o Updated if_tx_timeout() routine for -* 2.4.X kernels. -* Nov 29, 2000 Nenad Corbic o Added the 2.4.x kernel support: -* get_ip_address() function has moved -* into the ppp_poll() routine. It cannot -* be called from an interrupt. -* Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging: -* Deny all and specify allowed requests. -* May 02, 2000 Nenad Corbic o Added the dynamic interface shutdown -* option. When the link goes down, the -* network interface IFF_UP flag is reset. -* Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery. -* Feb 25, 2000 Nenad Corbic o Fixed the FT1 UDP debugger problem. -* Feb 09, 2000 Nenad Coribc o Shutdown bug fix. update() was called -* with NULL dev pointer: no check. -* Jan 24, 2000 Nenad Corbic o Disabled use of CMD complete inter. -* Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels -* Oct 25, 1999 Nenad Corbic o Support for 2.0.X kernels -* Moved dynamic route processing into -* a polling routine. -* Oct 07, 1999 Nenad Corbic o Support for S514 PCI card. -* Gideon Hack o UPD and Updates executed using timer interrupt -* Sep 10, 1999 Nenad Corbic o Fixed up the /proc statistics -* Jul 20, 1999 Nenad Corbic o Remove the polling routines and use -* interrupts instead. -* Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X Kernels. -* Aug 13, 1998 Jaspreet Singh o Improved Line Tracing. -* Jun 22, 1998 David Fong o Added remote IP address assignment -* Mar 15, 1998 Alan Cox o 2.1.8x basic port. -* Apr 16, 1998 Jaspreet Singh o using htons() for the IPX protocol. -* Dec 09, 1997 Jaspreet Singh o Added PAP and CHAP. -* o Implemented new routines like -* ppp_set_inbnd_auth(), ppp_set_outbnd_auth(), -* tokenize() and strstrip(). -* Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs -* while they have been disabled. -* Nov 24, 1997 Jaspreet Singh o Fixed another RACE condition caused by -* disabling and enabling of irqs. -* o Added new counters for stats on disable/enable -* IRQs. -* Nov 10, 1997 Jaspreet Singh o Initialized 'skb->mac.raw' to 'skb->data' -* before every netif_rx(). -* o Free up the device structure in del_if(). -* Nov 07, 1997 Jaspreet Singh o Changed the delay to zero for Line tracing -* command. -* 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. -* A new structure, "ppp_private_area", is added -* to provide Driver Statistics. -* Jul 21, 1997 Jaspreet Singh o Protected calls to sdla_peek() by adding -* save_flags(), cli() and restore_flags(). -* Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets -* o Added ability to discard mulitcast and -* broacast source addressed packets. -* Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities -* New case (0x25) statement in if_send routine. -* Added a global variable rCount to keep track -* of FT1 status enabled on the board. -* May 22, 1997 Jaspreet Singh o Added change in the PPP_SET_CONFIG command for -* 508 card to reflect changes in the new -* ppp508.sfm for supporting:continous transmission -* of Configure-Request packets without receiving a -* reply -* OR-ed 0x300 to conf_flags -* o Changed connect_tmout from 900 to 0 -* May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple boards -* Apr 25, 1997 Farhan Thawar o added UDP Management stuff -* Mar 11, 1997 Farhan Thawar Version 3.1.1 -* o fixed (+1) bug in rx_intr() -* o changed if_send() to return 0 if -* wandev.critical() is true -* o free socket buffer in if_send() if -* returning 0 -* Jan 15, 1997 Gene Kozin Version 3.1.0 -* o implemented exec() entry point -* Jan 06, 1997 Gene Kozin Initial version. -*****************************************************************************/ - -#include -#include /* printk(), and other useful stuff */ -#include /* offsetof(), etc. */ -#include /* return codes */ -#include /* inline memset(), etc. */ -#include /* kmalloc(), kfree() */ -#include /* WAN router definitions */ -#include /* WANPIPE common user API definitions */ -#include /* ARPHRD_* defines */ -#include /* htons(), etc. */ -#include /* sockaddr_in */ -#include /* time_after() macro */ - - -#include -#include -#include - -#include -#include /* PPP firmware API definitions */ -#include /* S514 Type Definition */ -/****** Defines & Macros ****************************************************/ - -#define PPP_DFLT_MTU 1500 /* default MTU */ -#define PPP_MAX_MTU 4000 /* maximum MTU */ -#define PPP_HDR_LEN 1 - -#define MAX_IP_ERRORS 100 - -#define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */ -#define HOLD_DOWN_TIME (5*HZ) /* link hold down time : Changed from 30 to 5 */ - -/* 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))) - -/* Macro for enabling/disabling debugging comments */ -//#define NEX_DEBUG -#ifdef NEX_DEBUG -#define NEX_PRINTK(format, a...) printk(format, ## a) -#else -#define NEX_PRINTK(format, a...) -#endif /* NEX_DEBUG */ - -#define DCD(a) ( a & 0x08 ? "HIGH" : "LOW" ) -#define CTS(a) ( a & 0x20 ? "HIGH" : "LOW" ) -#define LCP(a) ( a == 0x09 ? "OPEN" : "CLOSED" ) -#define IP(a) ( a == 0x09 ? "ENABLED" : "DISABLED" ) - -#define TMR_INT_ENABLED_UPDATE 0x01 -#define TMR_INT_ENABLED_PPP_EVENT 0x02 -#define TMR_INT_ENABLED_UDP 0x04 -#define TMR_INT_ENABLED_CONFIG 0x20 - -/* Set Configuraton Command Definitions */ -#define PERCENT_TX_BUFF 60 -#define TIME_BETWEEN_CONF_REQ 30 -#define TIME_BETWEEN_PAP_CHAP_REQ 30 -#define WAIT_PAP_CHAP_WITHOUT_REPLY 300 -#define WAIT_AFTER_DCD_CTS_LOW 5 -#define TIME_DCD_CTS_LOW_AFTER_LNK_DOWN 10 -#define WAIT_DCD_HIGH_AFTER_ENABLE_COMM 900 -#define MAX_CONF_REQ_WITHOUT_REPLY 10 -#define MAX_TERM_REQ_WITHOUT_REPLY 2 -#define NUM_CONF_NAK_WITHOUT_REPLY 5 -#define NUM_AUTH_REQ_WITHOUT_REPLY 10 - -#define END_OFFSET 0x1F0 - - -/******Data Structures*****************************************************/ - -/* This structure is placed in the private data area of the device structure. - * The card structure used to occupy the private area but now the following - * structure will incorporate the card structure along with PPP specific data - */ - -typedef struct ppp_private_area -{ - struct net_device *slave; - sdla_t* card; - unsigned long router_start_time; /*router start time in sec */ - unsigned long tick_counter; /*used for 5 second counter*/ - unsigned mc; /*multicast support on or off*/ - unsigned char enable_IPX; - unsigned long network_number; - unsigned char pap; - unsigned char chap; - unsigned char sysname[31]; /* system name for in-bnd auth*/ - unsigned char userid[511]; /* list of user ids */ - unsigned char passwd[511]; /* list of passwords */ - unsigned protocol; /* SKB Protocol */ - u32 ip_local; /* Local IP Address */ - u32 ip_remote; /* remote IP Address */ - - u32 ip_local_tmp; - u32 ip_remote_tmp; - - unsigned char timer_int_enabled; /* Who enabled the timer inter*/ - unsigned char update_comms_stats; /* Used by update function */ - unsigned long curr_trace_addr; /* Trace information */ - unsigned long start_trace_addr; - unsigned long end_trace_addr; - - unsigned char interface_down; /* Brind down interface when channel - goes down */ - unsigned long config_wait_timeout; /* After if_open() if in dynamic if mode, - wait a few seconds before configuring */ - - unsigned short udp_pkt_lgth; - char udp_pkt_src; - char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; - - /* PPP specific statistics */ - - if_send_stat_t if_send_stat; - rx_intr_stat_t rx_intr_stat; - pipe_mgmt_stat_t pipe_mgmt_stat; - - unsigned long router_up_time; - - /* Polling work queue entry. Each interface - * has its own work queue entry, which is used - * to defer events from the interrupt */ - struct work_struct poll_work; - struct timer_list poll_delay_timer; - - u8 gateway; - u8 config_ppp; - u8 ip_error; - -}ppp_private_area_t; - -/* 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); - -/****** Function Prototypes *************************************************/ - -/* WAN link driver entry points. These are called by the WAN router module. */ -static int update(struct wan_device *wandev); -static int new_if(struct wan_device *wandev, struct net_device *dev, - wanif_conf_t *conf); -static int del_if(struct wan_device *wandev, struct net_device *dev); - -/* WANPIPE-specific entry points */ -static int wpp_exec (struct sdla *card, void *u_cmd, void *u_data); - -/* Network device interface */ -static int if_init(struct net_device *dev); -static int if_open(struct net_device *dev); -static int if_close(struct net_device *dev); -static int if_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, - void *daddr, void *saddr, unsigned len); - -static void if_tx_timeout(struct net_device *dev); - -static int if_rebuild_hdr(struct sk_buff *skb); -static struct net_device_stats *if_stats(struct net_device *dev); -static int if_send(struct sk_buff *skb, struct net_device *dev); - - -/* PPP firmware interface functions */ -static int ppp_read_version(sdla_t *card, char *str); -static int ppp_set_outbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area); -static int ppp_set_inbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area); -static int ppp_configure(sdla_t *card, void *data); -static int ppp_set_intr_mode(sdla_t *card, unsigned char mode); -static int ppp_comm_enable(sdla_t *card); -static int ppp_comm_disable(sdla_t *card); -static int ppp_comm_disable_shutdown(sdla_t *card); -static int ppp_get_err_stats(sdla_t *card); -static int ppp_send(sdla_t *card, void *data, unsigned len, unsigned proto); -static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb); - -static void wpp_isr(sdla_t *card); -static void rx_intr(sdla_t *card); -static void event_intr(sdla_t *card); -static void timer_intr(sdla_t *card); - -/* Background polling routines */ -static void process_route(sdla_t *card); -static void retrigger_comm(sdla_t *card); - -/* Miscellaneous functions */ -static int read_info( sdla_t *card ); -static int read_connection_info (sdla_t *card); -static void remove_route( sdla_t *card ); -static int config508(struct net_device *dev, sdla_t *card); -static void show_disc_cause(sdla_t * card, unsigned cause); -static int reply_udp( unsigned char *data, unsigned int mbox_len ); -static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev, - ppp_private_area_t *ppp_priv_area); -static void init_ppp_tx_rx_buff( sdla_t *card ); -static int intr_test( sdla_t *card ); -static int udp_pkt_type( struct sk_buff *skb , sdla_t *card); -static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area); -static void init_global_statistics( sdla_t *card ); -static int tokenize(char *str, char **tokens); -static char* strstrip(char *str, char *s); -static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev, - struct sk_buff *skb); - -static int config_ppp (sdla_t *); -static void ppp_poll(struct net_device *dev); -static void trigger_ppp_poll(struct net_device *dev); -static void ppp_poll_delay (unsigned long dev_ptr); - - -static int Read_connection_info; -static int Intr_test_counter; -static unsigned short available_buffer_space; - - -/* 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_PX, - unsigned long network_number, unsigned short proto); - -/* Lock Functions */ -static void s508_lock (sdla_t *card, unsigned long *smp_flags); -static void s508_unlock (sdla_t *card, unsigned long *smp_flags); - -static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, struct net_device* dev, - ppp_private_area_t* ppp_priv_area ); -static unsigned short calc_checksum (char *data, int len); -static void disable_comm (sdla_t *card); -static int detect_and_fix_tx_bug (sdla_t *card); - -/****** Public Functions ****************************************************/ - -/*============================================================================ - * PPP 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 wpp_init(sdla_t *card, wandev_conf_t *conf) -{ - ppp_flags_t *flags; - union - { - char str[80]; - } u; - - /* Verify configuration ID */ - if (conf->config_id != WANCONFIG_PPP) { - - printk(KERN_INFO "%s: invalid configuration ID %u!\n", - card->devname, conf->config_id); - return -EINVAL; - - } - - /* Initialize miscellaneous pointers to structures on the adapter */ - switch (card->hw.type) { - - case SDLA_S508: - card->mbox =(void*)(card->hw.dpmbase + PPP508_MB_OFFS); - card->flags=(void*)(card->hw.dpmbase + PPP508_FLG_OFFS); - break; - - case SDLA_S514: - card->mbox =(void*)(card->hw.dpmbase + PPP514_MB_OFFS); - card->flags=(void*)(card->hw.dpmbase + PPP514_FLG_OFFS); - break; - - default: - return -EINVAL; - - } - flags = card->flags; - - /* 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 (ppp_read_version(card, NULL) || ppp_read_version(card, u.str)) - return -EIO; - - printk(KERN_INFO "%s: running PPP firmware v%s\n",card->devname, u.str); - /* Adjust configuration and set defaults */ - card->wandev.mtu = (conf->mtu) ? - min_t(unsigned int, conf->mtu, PPP_MAX_MTU) : PPP_DFLT_MTU; - - card->wandev.bps = conf->bps; - card->wandev.interface = conf->interface; - card->wandev.clocking = conf->clocking; - card->wandev.station = conf->station; - card->isr = &wpp_isr; - card->poll = NULL; - card->exec = &wpp_exec; - card->wandev.update = &update; - card->wandev.new_if = &new_if; - card->wandev.del_if = &del_if; - card->wandev.udp_port = conf->udp_port; - card->wandev.ttl = conf->ttl; - card->wandev.state = WAN_DISCONNECTED; - card->disable_comm = &disable_comm; - card->irq_dis_if_send_count = 0; - card->irq_dis_poll_count = 0; - card->u.p.authenticator = conf->u.ppp.authenticator; - card->u.p.ip_mode = conf->u.ppp.ip_mode ? - conf->u.ppp.ip_mode : WANOPT_PPP_STATIC; - card->TracingEnabled = 0; - Read_connection_info = 1; - - /* initialize global statistics */ - init_global_statistics( card ); - - - - if (!card->configured){ - int err; - - Intr_test_counter = 0; - 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( "%s: Please choose another interrupt\n",card->devname); - return -EIO; - } - - printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n", - card->devname, Intr_test_counter); - card->configured = 1; - } - - ppp_set_intr_mode(card, PPP_INTR_TIMER); - - /* Turn off the transmit and timer interrupt */ - flags->imask &= ~PPP_INTR_TIMER; - - printk(KERN_INFO "\n"); - - return 0; -} - -/******* WAN Device Driver Entry Points *************************************/ - -/*============================================================================ - * Update device status & statistics. - */ -static int update(struct wan_device *wandev) -{ - sdla_t* card = wandev->private; - struct net_device* dev; - volatile ppp_private_area_t *ppp_priv_area; - ppp_flags_t *flags = card->flags; - unsigned long timeout; - - /* sanity checks */ - if ((wandev == NULL) || (wandev->private == NULL)) - return -EFAULT; - - if (wandev->state == WAN_UNCONFIGURED) - return -ENODEV; - - /* Shutdown bug fix. This function can be - * called with NULL dev pointer during - * shutdown - */ - if ((dev=card->wandev.dev) == NULL){ - return -ENODEV; - } - - if ((ppp_priv_area=dev->priv) == NULL){ - return -ENODEV; - } - - ppp_priv_area->update_comms_stats = 2; - ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UPDATE; - flags->imask |= PPP_INTR_TIMER; - - /* wait a maximum of 1 second for the statistics to be updated */ - timeout = jiffies; - for(;;) { - if(ppp_priv_area->update_comms_stats == 0){ - break; - } - if (time_after(jiffies, timeout + 1 * HZ)){ - ppp_priv_area->update_comms_stats = 0; - ppp_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; - ppp_private_area_t *ppp_priv_area; - - if (wandev->ndev) - return -EEXIST; - - - 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 */ - ppp_priv_area = kmalloc(sizeof(ppp_private_area_t), GFP_KERNEL); - - if( ppp_priv_area == NULL ) - return -ENOMEM; - - memset(ppp_priv_area, 0, sizeof(ppp_private_area_t)); - - ppp_priv_area->card = card; - - /* initialize data */ - strcpy(card->u.p.if_name, conf->name); - - /* initialize data in ppp_private_area structure */ - - init_ppp_priv_struct( ppp_priv_area ); - - ppp_priv_area->mc = conf->mc; - ppp_priv_area->pap = conf->pap; - ppp_priv_area->chap = conf->chap; - - /* Option to bring down the interface when - * the link goes down */ - if (conf->if_down){ - set_bit(DYN_OPT_ON,&ppp_priv_area->interface_down); - printk("%s: Dynamic interface configuration enabled\n", - card->devname); - } - - /* If no user ids are specified */ - if(!strlen(conf->userid) && (ppp_priv_area->pap||ppp_priv_area->chap)){ - kfree(ppp_priv_area); - return -EINVAL; - } - - /* If no passwords are specified */ - if(!strlen(conf->passwd) && (ppp_priv_area->pap||ppp_priv_area->chap)){ - kfree(ppp_priv_area); - return -EINVAL; - } - - if(strlen(conf->sysname) > 31){ - kfree(ppp_priv_area); - return -EINVAL; - } - - /* If no system name is specified */ - if(!strlen(conf->sysname) && (card->u.p.authenticator)){ - kfree(ppp_priv_area); - return -EINVAL; - } - - /* copy the data into the ppp private structure */ - memcpy(ppp_priv_area->userid, conf->userid, strlen(conf->userid)); - memcpy(ppp_priv_area->passwd, conf->passwd, strlen(conf->passwd)); - memcpy(ppp_priv_area->sysname, conf->sysname, strlen(conf->sysname)); - - - ppp_priv_area->enable_IPX = conf->enable_IPX; - if (conf->network_number){ - ppp_priv_area->network_number = conf->network_number; - }else{ - ppp_priv_area->network_number = 0xDEADBEEF; - } - - /* Tells us that if this interface is a - * gateway or not */ - if ((ppp_priv_area->gateway = conf->gateway) == WANOPT_YES){ - printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", - card->devname,card->u.p.if_name); - } - - /* prepare network device data space for registration */ - strcpy(dev->name,card->u.p.if_name); - - dev->init = &if_init; - dev->priv = ppp_priv_area; - dev->mtu = min_t(unsigned int, dev->mtu, card->wandev.mtu); - - /* Initialize the polling work routine */ - INIT_WORK(&ppp_priv_area->poll_work, (void*)(void*)ppp_poll, dev); - - /* Initialize the polling delay timer */ - init_timer(&ppp_priv_area->poll_delay_timer); - ppp_priv_area->poll_delay_timer.data = (unsigned long)dev; - ppp_priv_area->poll_delay_timer.function = ppp_poll_delay; - - - /* Since we start with dummy IP addresses we can say - * that route exists */ - printk(KERN_INFO "\n"); - - return 0; -} - -/*============================================================================ - * Delete logical channel. - */ -static int del_if(struct wan_device *wandev, struct net_device *dev) -{ - return 0; -} - -static void disable_comm (sdla_t *card) -{ - ppp_comm_disable_shutdown(card); - return; -} - -/****** WANPIPE-specific entry points ***************************************/ - -/*============================================================================ - * Execute adapter interface command. - */ - -//FIXME: Why do we need this ???? -static int wpp_exec(struct sdla *card, void *u_cmd, void *u_data) -{ - ppp_mbox_t *mbox = card->mbox; - int len; - - if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t))) - return -EFAULT; - - len = mbox->cmd.length; - - if (len) { - - if( copy_from_user((void*)&mbox->data, u_data, len)) - return -EFAULT; - - } - - /* execute command */ - if (!sdla_exec(mbox)) - return -EIO; - - /* return result */ - if( copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t))) - return -EFAULT; - len = mbox->cmd.length; - - if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)) - return -EFAULT; - - 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) -{ - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->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; - - /* Enable Mulitcasting if specified by user*/ - if (ppp_priv_area->mc == WANOPT_YES){ - dev->flags |= IFF_MULTICAST; - } - - dev->mtu = wandev->mtu; - dev->hard_header_len = PPP_HDR_LEN; /* media header length */ - - /* Initialize hardware parameters (just for reference) */ - dev->irq = wandev->irq; - dev->dma = wandev->dma; - dev->base_addr = wandev->ioport; - dev->mem_start = wandev->maddr; - dev->mem_end = wandev->maddr + wandev->msize - 1; - - /* Set transmit buffer queue length */ - dev->tx_queue_len = 100; - SET_MODULE_OWNER(dev); - - return 0; -} - -/*============================================================================ - * Open network interface. - * o enable communications and interrupts. - * o prevent module from unloading by incrementing use count - * - * Return 0 if O.k. or errno. - */ -static int if_open(struct net_device *dev) -{ - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; - struct timeval tv; - //unsigned long smp_flags; - - if (netif_running(dev)) - return -EBUSY; - - wanpipe_open(card); - - netif_start_queue(dev); - - do_gettimeofday( &tv ); - ppp_priv_area->router_start_time = tv.tv_sec; - - /* We cannot configure the card here because we don't - * have access to the interface IP addresses. - * Once the interface initilization is complete, we will be - * able to access the IP addresses. Therefore, - * configure the ppp link in the poll routine */ - set_bit(0,&ppp_priv_area->config_ppp); - ppp_priv_area->config_wait_timeout=jiffies; - - /* Start the PPP configuration after 1sec delay. - * This will give the interface initilization time - * to finish its configuration */ - mod_timer(&ppp_priv_area->poll_delay_timer, jiffies + HZ); - return 0; -} - -/*============================================================================ - * Close network interface. - * o if this is the last open, then disable communications and interrupts. - * o reset flags. - */ -static int if_close(struct net_device *dev) -{ - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; - - netif_stop_queue(dev); - wanpipe_close(card); - - del_timer (&ppp_priv_area->poll_delay_timer); - return 0; -} - -/*============================================================================ - * Build media header. - * - * The trick here is to put packet type (Ethertype) into 'protocol' field of - * the socket buffer, so that we don't forget it. If packet type is not - * supported, set skb->protocol to 0 and discard packet later. - * - * Return: media header length. - */ -static int if_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, void *daddr, void *saddr, unsigned len) -{ - switch (type) - { - case ETH_P_IP: - case ETH_P_IPX: - skb->protocol = htons(type); - break; - - default: - skb->protocol = 0; - } - - return PPP_HDR_LEN; -} - -/*============================================================================ - * Re-build media header. - * - * Return: 1 physical address resolved. - * 0 physical address not resolved - */ -static int if_rebuild_hdr (struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; - - printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", - card->devname, dev->name); - return 1; -} - -/*============================================================================ - * Handle transmit timeout event from netif watchdog - */ -static void if_tx_timeout(struct net_device *dev) -{ - ppp_private_area_t* chan = dev->priv; - sdla_t *card = chan->card; - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - - ++ chan->if_send_stat.if_send_tbusy; - ++card->wandev.stats.collisions; - - printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); - ++chan->if_send_stat.if_send_tbusy_timeout; - netif_wake_queue (dev); -} - - - -/*============================================================================ - * Send a packet on a network interface. - * o set tbusy flag (marks start of the transmission) to block a timer-based - * transmit from overlapping. - * o check link state. If link is not up, then drop the packet. - * o execute adapter send command. - * o free socket buffer - * - * Return: 0 complete (socket buffer must be freed) - * non-0 packet may be re-transmitted (tbusy must be set) - * - * Notes: - * 1. This routine is called either by the protocol stack or by the "net - * bottom half" (with interrupts enabled). - * 2. Setting tbusy flag will inhibit further transmit requests from the - * protocol stack and can be used for flow control with protocol layer. - */ -static int if_send (struct sk_buff *skb, struct net_device *dev) -{ - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; - unsigned char *sendpacket; - unsigned long smp_flags; - ppp_flags_t *flags = card->flags; - int udp_type; - int err=0; - - ++ppp_priv_area->if_send_stat.if_send_entry; - - netif_stop_queue(dev); - - if (skb == NULL) { - - /* If we get here, some higher layer thinks we've missed an - * tx-done interrupt. - */ - printk(KERN_INFO "%s: interface %s got kicked!\n", - card->devname, dev->name); - - ++ppp_priv_area->if_send_stat.if_send_skb_null; - - netif_wake_queue(dev); - return 0; - } - - sendpacket = skb->data; - - udp_type = udp_pkt_type( skb, card ); - - - if (udp_type == UDP_PTPIPE_TYPE){ - if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, - ppp_priv_area)){ - flags->imask |= PPP_INTR_TIMER; - } - ++ppp_priv_area->if_send_stat.if_send_PIPE_request; - netif_start_queue(dev); - return 0; - } - - /* Check for broadcast and multicast addresses - * If found, drop (deallocate) a packet and return. - */ - if(chk_bcast_mcast_addr(card, dev, skb)){ - ++card->wandev.stats.tx_dropped; - dev_kfree_skb_any(skb); - netif_start_queue(dev); - return 0; - } - - - if(card->hw.type != SDLA_S514){ - s508_lock(card,&smp_flags); - } - - if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) { - - printk(KERN_INFO "%s: Critical in if_send: %lx\n", - card->wandev.name,card->wandev.critical); - - ++card->wandev.stats.tx_dropped; - ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR; - netif_start_queue(dev); - goto if_send_exit_crit; - } - - if (card->wandev.state != WAN_CONNECTED) { - - ++ppp_priv_area->if_send_stat.if_send_wan_disconnected; - ++card->wandev.stats.tx_dropped; - netif_start_queue(dev); - - } else if (!skb->protocol) { - ++ppp_priv_area->if_send_stat.if_send_protocol_error; - ++card->wandev.stats.tx_errors; - netif_start_queue(dev); - - } else { - - /*If it's IPX change the network numbers to 0 if they're ours.*/ - if( skb->protocol == htons(ETH_P_IPX) ) { - if(ppp_priv_area->enable_IPX) { - switch_net_numbers( skb->data, - ppp_priv_area->network_number, 0); - } else { - ++card->wandev.stats.tx_dropped; - netif_start_queue(dev); - goto if_send_exit_crit; - } - } - - if (ppp_send(card, skb->data, skb->len, skb->protocol)) { - netif_stop_queue(dev); - ++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full; - ++ppp_priv_area->if_send_stat.if_send_tx_int_enabled; - } else { - ++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr; - ++card->wandev.stats.tx_packets; - card->wandev.stats.tx_bytes += skb->len; - netif_start_queue(dev); - dev->trans_start = jiffies; - } - } - -if_send_exit_crit: - - if (!(err=netif_queue_stopped(dev))){ - dev_kfree_skb_any(skb); - }else{ - ppp_priv_area->tick_counter = jiffies; - flags->imask |= PPP_INTR_TXRDY; /* unmask Tx interrupts */ - } - - clear_bit(SEND_CRIT,&card->wandev.critical); - if(card->hw.type != SDLA_S514){ - s508_unlock(card,&smp_flags); - } - - return err; -} - - -/*============================================================================= - * Store a UDP management packet for later processing. - */ - -static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, struct net_device* dev, - ppp_private_area_t* ppp_priv_area ) -{ - int udp_pkt_stored = 0; - - if(!ppp_priv_area->udp_pkt_lgth && (skb->len<=MAX_LGTH_UDP_MGNT_PKT)){ - ppp_priv_area->udp_pkt_lgth = skb->len; - ppp_priv_area->udp_pkt_src = udp_pkt_src; - memcpy(ppp_priv_area->udp_pkt_data, skb->data, skb->len); - ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UDP; - ppp_priv_area->protocol = skb->protocol; - udp_pkt_stored = 1; - }else{ - if (skb->len > MAX_LGTH_UDP_MGNT_PKT){ - printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n", - card->devname, skb->len); - }else{ - printk(KERN_INFO "%s: PIPEMON UPD request already pending\n", - card->devname); - } - ppp_priv_area->udp_pkt_lgth = 0; - } - - if(udp_pkt_src == UDP_PKT_FRM_STACK){ - dev_kfree_skb_any(skb); - }else{ - dev_kfree_skb_any(skb); - } - - return(udp_pkt_stored); -} - - - -/*============================================================================ - * Reply to UDP Management system. - * Return length of reply. - */ -static int reply_udp( unsigned char *data, unsigned int mbox_len ) -{ - unsigned short len, udp_length, temp, ip_length; - unsigned long ip_temp; - int even_bound = 0; - ppp_udp_pkt_t *p_udp_pkt = (ppp_udp_pkt_t *)data; - - /* Set length of packet */ - len = sizeof(ip_pkt_t)+ - sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - mbox_len; - - /* fill in UDP reply */ - p_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; - - /* fill in UDP length */ - udp_length = sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - mbox_len; - - - /* put it on an even boundary */ - if ( udp_length & 0x0001 ) { - udp_length += 1; - len += 1; - even_bound=1; - } - - temp = (udp_length<<8)|(udp_length>>8); - p_udp_pkt->udp_pkt.udp_length = temp; - - - /* swap UDP ports */ - temp = p_udp_pkt->udp_pkt.udp_src_port; - p_udp_pkt->udp_pkt.udp_src_port = - p_udp_pkt->udp_pkt.udp_dst_port; - p_udp_pkt->udp_pkt.udp_dst_port = temp; - - - /* add UDP pseudo header */ - temp = 0x1100; - *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound)) = temp; - temp = (udp_length<<8)|(udp_length>>8); - *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound+2)) = temp; - - /* calculate UDP checksum */ - p_udp_pkt->udp_pkt.udp_checksum = 0; - p_udp_pkt->udp_pkt.udp_checksum = - calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET); - - /* fill in IP length */ - ip_length = udp_length + sizeof(ip_pkt_t); - temp = (ip_length<<8)|(ip_length>>8); - p_udp_pkt->ip_pkt.total_length = temp; - - /* swap IP addresses */ - ip_temp = p_udp_pkt->ip_pkt.ip_src_address; - p_udp_pkt->ip_pkt.ip_src_address = p_udp_pkt->ip_pkt.ip_dst_address; - p_udp_pkt->ip_pkt.ip_dst_address = ip_temp; - - /* fill in IP checksum */ - p_udp_pkt->ip_pkt.hdr_checksum = 0; - p_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t)); - - return len; - -} /* reply_udp */ - -unsigned short calc_checksum (char *data, int len) -{ - unsigned short temp; - unsigned long sum=0; - int i; - - for( i = 0; i > 16 ) { - sum = (sum & 0xffffUL) + (sum >> 16); - } - - temp = (unsigned short)sum; - temp = ~temp; - - if( temp == 0 ) - temp = 0xffff; - - return temp; -} - -/* - If incoming is 0 (outgoing)- if the net numbers is ours make it 0 - if incoming is 1 - if the net number is 0 make it ours - -*/ -static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming) -{ - unsigned long pnetwork_number; - - pnetwork_number = (unsigned long)((sendpacket[6] << 24) + - (sendpacket[7] << 16) + (sendpacket[8] << 8) + - sendpacket[9]); - - if (!incoming) { - //If the destination network number is ours, make it 0 - if( pnetwork_number == network_number) { - sendpacket[6] = sendpacket[7] = sendpacket[8] = - sendpacket[9] = 0x00; - } - } else { - //If the incoming network is 0, make it ours - if( pnetwork_number == 0) { - sendpacket[6] = (unsigned char)(network_number >> 24); - sendpacket[7] = (unsigned char)((network_number & - 0x00FF0000) >> 16); - sendpacket[8] = (unsigned char)((network_number & - 0x0000FF00) >> 8); - sendpacket[9] = (unsigned char)(network_number & - 0x000000FF); - } - } - - - pnetwork_number = (unsigned long)((sendpacket[18] << 24) + - (sendpacket[19] << 16) + (sendpacket[20] << 8) + - sendpacket[21]); - - if( !incoming ) { - //If the source network is ours, make it 0 - if( pnetwork_number == network_number) { - sendpacket[18] = sendpacket[19] = sendpacket[20] = - sendpacket[21] = 0x00; - } - } else { - //If the source network is 0, make it ours - if( pnetwork_number == 0 ) { - sendpacket[18] = (unsigned char)(network_number >> 24); - sendpacket[19] = (unsigned char)((network_number & - 0x00FF0000) >> 16); - sendpacket[20] = (unsigned char)((network_number & - 0x0000FF00) >> 8); - sendpacket[21] = (unsigned char)(network_number & - 0x000000FF); - } - } -} /* switch_net_numbers */ - -/*============================================================================ - * Get ethernet-style interface statistics. - * Return a pointer to struct net_device_stats. - */ -static struct net_device_stats *if_stats(struct net_device *dev) -{ - - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t* card; - - if( ppp_priv_area == NULL ) - return NULL; - - card = ppp_priv_area->card; - return &card->wandev.stats; -} - -/****** PPP Firmware Interface Functions ************************************/ - -/*============================================================================ - * Read firmware code version. - * Put code version as ASCII string in str. - */ -static int ppp_read_version(sdla_t *card, char *str) -{ - ppp_mbox_t *mb = card->mbox; - int err; - - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - mb->cmd.command = PPP_READ_CODE_VERSION; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK) - - ppp_error(card, err, mb); - - else if (str) { - - int len = mb->cmd.length; - - memcpy(str, mb->data, len); - str[len] = '\0'; - - } - - return err; -} -/*=========================================================================== - * Set Out-Bound Authentication. -*/ -static int ppp_set_outbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area) -{ - ppp_mbox_t *mb = card->mbox; - int err; - - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - memset(&mb->data, 0, (strlen(ppp_priv_area->userid) + - strlen(ppp_priv_area->passwd) + 2 ) ); - memcpy(mb->data, ppp_priv_area->userid, strlen(ppp_priv_area->userid)); - memcpy((mb->data + strlen(ppp_priv_area->userid) + 1), - ppp_priv_area->passwd, strlen(ppp_priv_area->passwd)); - - mb->cmd.length = strlen(ppp_priv_area->userid) + - strlen(ppp_priv_area->passwd) + 2 ; - - mb->cmd.command = PPP_SET_OUTBOUND_AUTH; - - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK) - ppp_error(card, err, mb); - - return err; -} - -/*=========================================================================== - * Set In-Bound Authentication. -*/ -static int ppp_set_inbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area) -{ - ppp_mbox_t *mb = card->mbox; - int err, i; - char* user_tokens[32]; - char* pass_tokens[32]; - int userids, passwds; - int add_ptr; - - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - memset(&mb->data, 0, 1008); - memcpy(mb->data, ppp_priv_area->sysname, - strlen(ppp_priv_area->sysname)); - - /* Parse the userid string and the password string and build a string - to copy it to the data area of the command structure. The string - will look like "SYS_NAMEUSER1PASS1USER2PASS2 - .... " - */ - userids = tokenize( ppp_priv_area->userid, user_tokens); - passwds = tokenize( ppp_priv_area->passwd, pass_tokens); - - if (userids != passwds){ - printk(KERN_INFO "%s: Number of passwords does not equal the number of user ids\n", card->devname); - return 1; - } - - add_ptr = strlen(ppp_priv_area->sysname) + 1; - for (i=0; idata + add_ptr), user_tokens[i], - strlen(user_tokens[i])); - memcpy((mb->data + add_ptr + strlen(user_tokens[i]) + 1), - pass_tokens[i], strlen(pass_tokens[i])); - add_ptr = add_ptr + strlen(user_tokens[i]) + 1 + - strlen(pass_tokens[i]) + 1; - } - - mb->cmd.length = add_ptr + 1; - mb->cmd.command = PPP_SET_INBOUND_AUTH; - - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK) - ppp_error(card, err, mb); - - return err; -} - - -/*============================================================================ - * Tokenize string. - * Parse a string of the following syntax: - * ,,... - * and fill array of tokens with pointers to string elements. - * - */ -static int tokenize (char *str, char **tokens) -{ - int cnt = 0; - - tokens[0] = strsep(&str, "/"); - while (tokens[cnt] && (cnt < 32 - 1)) - { - tokens[cnt] = strstrip(tokens[cnt], " \t"); - tokens[++cnt] = strsep(&str, "/"); - } - return cnt; -} - -/*============================================================================ - * Strip leading and trailing spaces off the string str. - */ -static char* strstrip (char *str, char* s) -{ - char *eos = str + strlen(str); /* -> end of string */ - - while (*str && strchr(s, *str)) - ++str /* strip leading spaces */ - ; - while ((eos > str) && strchr(s, *(eos - 1))) - --eos /* strip trailing spaces */ - ; - *eos = '\0'; - return str; -} -/*============================================================================ - * Configure PPP firmware. - */ -static int ppp_configure(sdla_t *card, void *data) -{ - ppp_mbox_t *mb = card->mbox; - int data_len = sizeof(ppp508_conf_t); - int err; - - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - memcpy(mb->data, data, data_len); - mb->cmd.length = data_len; - mb->cmd.command = PPP_SET_CONFIG; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK) - ppp_error(card, err, mb); - - return err; -} - -/*============================================================================ - * Set interrupt mode. - */ -static int ppp_set_intr_mode(sdla_t *card, unsigned char mode) -{ - ppp_mbox_t *mb = card->mbox; - ppp_intr_info_t *ppp_intr_data = (ppp_intr_info_t *) &mb->data[0]; - int err; - - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - ppp_intr_data->i_enable = mode; - - ppp_intr_data->irq = card->hw.irq; - mb->cmd.length = 2; - - /* If timer has been enabled, set the timer delay to 1sec */ - if (mode & 0x80){ - ppp_intr_data->timer_len = 250; //5;//100; //250; - mb->cmd.length = 4; - } - - mb->cmd.command = PPP_SET_INTR_FLAGS; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK) - ppp_error(card, err, mb); - - - return err; -} - -/*============================================================================ - * Enable communications. - */ -static int ppp_comm_enable(sdla_t *card) -{ - ppp_mbox_t *mb = card->mbox; - int err; - - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - mb->cmd.command = PPP_COMM_ENABLE; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK) - ppp_error(card, err, mb); - else - card->u.p.comm_enabled = 1; - - return err; -} - -/*============================================================================ - * Disable communications. - */ -static int ppp_comm_disable(sdla_t *card) -{ - ppp_mbox_t *mb = card->mbox; - int err; - - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - mb->cmd.command = PPP_COMM_DISABLE; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - if (err != CMD_OK) - ppp_error(card, err, mb); - else - card->u.p.comm_enabled = 0; - - return err; -} - -static int ppp_comm_disable_shutdown(sdla_t *card) -{ - ppp_mbox_t *mb = card->mbox; - ppp_intr_info_t *ppp_intr_data; - int err; - - if (!mb){ - return 1; - } - - ppp_intr_data = (ppp_intr_info_t *) &mb->data[0]; - - /* Disable all interrupts */ - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - ppp_intr_data->i_enable = 0; - - ppp_intr_data->irq = card->hw.irq; - mb->cmd.length = 2; - - mb->cmd.command = PPP_SET_INTR_FLAGS; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - /* Disable communicatinons */ - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - mb->cmd.command = PPP_COMM_DISABLE; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - card->u.p.comm_enabled = 0; - - return 0; -} - - - -/*============================================================================ - * Get communications error statistics. - */ -static int ppp_get_err_stats(sdla_t *card) -{ - ppp_mbox_t *mb = card->mbox; - int err; - - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - mb->cmd.command = PPP_READ_ERROR_STATS; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - if (err == CMD_OK) { - - ppp_err_stats_t* stats = (void*)mb->data; - card->wandev.stats.rx_over_errors = stats->rx_overrun; - card->wandev.stats.rx_crc_errors = stats->rx_bad_crc; - card->wandev.stats.rx_missed_errors = stats->rx_abort; - card->wandev.stats.rx_length_errors = stats->rx_lost; - card->wandev.stats.tx_aborted_errors = stats->tx_abort; - - } else - ppp_error(card, err, mb); - - return err; -} - -/*============================================================================ - * Send packet. - * Return: 0 - o.k. - * 1 - no transmit buffers available - */ -static int ppp_send (sdla_t *card, void *data, unsigned len, unsigned proto) -{ - ppp_buf_ctl_t *txbuf = card->u.p.txbuf; - - if (txbuf->flag) - return 1; - - sdla_poke(&card->hw, txbuf->buf.ptr, data, len); - - txbuf->length = len; /* frame length */ - - if (proto == htons(ETH_P_IPX)) - txbuf->proto = 0x01; /* protocol ID */ - else - txbuf->proto = 0x00; /* protocol ID */ - - txbuf->flag = 1; /* start transmission */ - - /* Update transmit buffer control fields */ - card->u.p.txbuf = ++txbuf; - - if ((void*)txbuf > card->u.p.txbuf_last) - card->u.p.txbuf = card->u.p.txbuf_base; - - return 0; -} - -/****** Firmware Error Handler **********************************************/ - -/*============================================================================ - * Firmware error handler. - * This routine is called whenever firmware command returns non-zero - * return code. - * - * Return zero if previous command has to be cancelled. - */ -static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb) -{ - unsigned cmd = mb->cmd.command; - - switch (err) { - - case CMD_TIMEOUT: - printk(KERN_ERR "%s: command 0x%02X timed out!\n", - card->devname, cmd); - break; - - default: - printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n" - , card->devname, cmd, err); - } - - return 0; -} - -/****** Interrupt Handlers **************************************************/ - -/*============================================================================ - * PPP interrupt service routine. - */ -static void wpp_isr (sdla_t *card) -{ - ppp_flags_t *flags = card->flags; - char *ptr = &flags->iflag; - struct net_device *dev = card->wandev.dev; - int i; - - card->in_isr = 1; - ++card->statistics.isr_entry; - - if (!dev && flags->iflag != PPP_INTR_CMD){ - card->in_isr = 0; - flags->iflag = 0; - return; - } - - if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { - card->in_isr = 0; - flags->iflag = 0; - return; - } - - - if(card->hw.type != SDLA_S514){ - if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) { - ++card->statistics.isr_already_critical; - printk (KERN_INFO "%s: Critical while in ISR!\n", - card->devname); - card->in_isr = 0; - flags->iflag = 0; - return; - } - } - - switch (flags->iflag) { - - case PPP_INTR_RXRDY: /* receive interrupt 0x01 (bit 0)*/ - ++card->statistics.isr_rx; - rx_intr(card); - break; - - case PPP_INTR_TXRDY: /* transmit interrupt 0x02 (bit 1)*/ - ++card->statistics.isr_tx; - flags->imask &= ~PPP_INTR_TXRDY; - netif_wake_queue(dev); - break; - - case PPP_INTR_CMD: /* interface command completed */ - ++Intr_test_counter; - ++card->statistics.isr_intr_test; - break; - - case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/ - case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/ - case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/ - case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */ - event_intr(card); - break; - - case PPP_INTR_TIMER: - timer_intr(card); - break; - - default: /* unexpected interrupt */ - ++card->statistics.isr_spurious; - printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", - card->devname, flags->iflag); - printk(KERN_INFO "%s: ID Bytes = ",card->devname); - for(i = 0; i < 8; i ++) - printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); - printk(KERN_INFO "\n"); - } - - card->in_isr = 0; - flags->iflag = 0; - return; -} - -/*============================================================================ - * Receive interrupt handler. - */ -static void rx_intr(sdla_t *card) -{ - ppp_buf_ctl_t *rxbuf = card->rxmb; - struct net_device *dev = card->wandev.dev; - ppp_private_area_t *ppp_priv_area; - struct sk_buff *skb; - unsigned len; - void *buf; - int i; - ppp_flags_t *flags = card->flags; - char *ptr = &flags->iflag; - int udp_type; - - - if (rxbuf->flag != 0x01) { - - printk(KERN_INFO - "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", - card->devname, (unsigned)rxbuf, rxbuf->flag); - - printk(KERN_INFO "%s: ID Bytes = ",card->devname); - - for(i = 0; i < 8; i ++) - printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); - printk(KERN_INFO "\n"); - - ++card->statistics.rx_intr_corrupt_rx_bfr; - - - /* Bug Fix: Mar 6 2000 - * If we get a corrupted mailbox, it means that driver - * is out of sync with the firmware. There is no recovery. - * If we don't turn off all interrupts for this card - * the machine will crash. - */ - printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); - printk(KERN_INFO "Please contact Sangoma Technologies !\n"); - ppp_set_intr_mode(card,0); - return; - } - - if (dev && netif_running(dev) && dev->priv){ - - len = rxbuf->length; - ppp_priv_area = dev->priv; - - /* Allocate socket buffer */ - skb = dev_alloc_skb(len); - - if (skb != NULL) { - - /* Copy data to the socket buffer */ - unsigned addr = rxbuf->buf.ptr; - - if ((addr + len) > card->u.p.rx_top + 1) { - - unsigned tmp = card->u.p.rx_top - addr + 1; - buf = skb_put(skb, tmp); - sdla_peek(&card->hw, addr, buf, tmp); - addr = card->u.p.rx_base; - len -= tmp; - } - buf = skb_put(skb, len); - sdla_peek(&card->hw, addr, buf, len); - - /* Decapsulate packet */ - switch (rxbuf->proto) { - - case 0x00: - skb->protocol = htons(ETH_P_IP); - break; - - case 0x01: - skb->protocol = htons(ETH_P_IPX); - break; - } - - udp_type = udp_pkt_type( skb, card ); - - if (udp_type == UDP_PTPIPE_TYPE){ - - /* Handle a UDP Request in Timer Interrupt */ - if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, card, skb, dev, - ppp_priv_area)){ - flags->imask |= PPP_INTR_TIMER; - } - ++ppp_priv_area->rx_intr_stat.rx_intr_PIPE_request; - - - } else if (handle_IPXWAN(skb->data,card->devname, - ppp_priv_area->enable_IPX, - ppp_priv_area->network_number, - skb->protocol)) { - - /* Handle an IPXWAN packet */ - if( ppp_priv_area->enable_IPX) { - - /* Make sure we are not already sending */ - if (!test_bit(SEND_CRIT, &card->wandev.critical)){ - ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX)); - } - dev_kfree_skb_any(skb); - - } else { - ++card->wandev.stats.rx_dropped; - } - } else { - /* Pass data up the protocol stack */ - skb->dev = dev; - skb->mac.raw = skb->data; - - ++card->wandev.stats.rx_packets; - card->wandev.stats.rx_bytes += skb->len; - ++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack; - netif_rx(skb); - dev->last_rx = jiffies; - } - - } else { - - if (net_ratelimit()){ - printk(KERN_INFO "%s: no socket buffers available!\n", - card->devname); - } - ++card->wandev.stats.rx_dropped; - ++ppp_priv_area->rx_intr_stat.rx_intr_no_socket; - } - - } else { - ++card->statistics.rx_intr_dev_not_started; - } - - /* Release buffer element and calculate a pointer to the next one */ - rxbuf->flag = 0x00; - card->rxmb = ++rxbuf; - if ((void*)rxbuf > card->u.p.rxbuf_last) - card->rxmb = card->u.p.rxbuf_base; -} - - -void event_intr (sdla_t *card) -{ - - struct net_device* dev = card->wandev.dev; - ppp_private_area_t* ppp_priv_area = dev->priv; - volatile ppp_flags_t *flags = card->flags; - - switch (flags->iflag){ - - case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/ - - if (net_ratelimit()){ - printk (KERN_INFO "%s: Modem status: DCD=%s CTS=%s\n", - card->devname, DCD(flags->mstatus), CTS(flags->mstatus)); - } - break; - - case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/ - - NEX_PRINTK (KERN_INFO "Data link disconnected intr Cause %X\n", - flags->disc_cause); - - if (flags->disc_cause & - (PPP_LOCAL_TERMINATION | PPP_DCD_CTS_DROP | - PPP_REMOTE_TERMINATION)) { - - if (card->u.p.ip_mode == WANOPT_PPP_PEER) { - set_bit(0,&Read_connection_info); - } - wanpipe_set_state(card, WAN_DISCONNECTED); - - show_disc_cause(card, flags->disc_cause); - ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; - flags->imask |= PPP_INTR_TIMER; - trigger_ppp_poll(dev); - } - break; - - case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/ - - NEX_PRINTK (KERN_INFO "%s: PPP Link Open, LCP=%s IP=%s\n", - card->devname,LCP(flags->lcp_state), - IP(flags->ip_state)); - - if (flags->lcp_state == 0x09 && - (flags->ip_state == 0x09 || flags->ipx_state == 0x09)){ - - /* Initialize the polling timer and set the state - * to WAN_CONNNECTED */ - - - /* BUG FIX: When the protocol restarts, during heavy - * traffic, board tx buffers and driver tx buffers - * can go out of sync. This checks the condition - * and if the tx buffers are out of sync, the - * protocols are restarted. - * I don't know why the board tx buffer is out - * of sync. It could be that a packets is tx - * while the link is down, but that is not - * possible. The other possiblility is that the - * firmware doesn't reinitialize properly. - * FIXME: A better fix should be found. - */ - if (detect_and_fix_tx_bug(card)){ - - ppp_comm_disable(card); - - wanpipe_set_state(card, WAN_DISCONNECTED); - - ppp_priv_area->timer_int_enabled |= - TMR_INT_ENABLED_PPP_EVENT; - flags->imask |= PPP_INTR_TIMER; - break; - } - - card->state_tick = jiffies; - wanpipe_set_state(card, WAN_CONNECTED); - - NEX_PRINTK(KERN_INFO "CON: L Tx: %lx B Tx: %lx || L Rx %lx B Rx %lx\n", - (unsigned long)card->u.p.txbuf, *card->u.p.txbuf_next, - (unsigned long)card->rxmb, *card->u.p.rxbuf_next); - - /* Tell timer interrupt that PPP event occurred */ - ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; - flags->imask |= PPP_INTR_TIMER; - - /* If we are in PEER mode, we must first obtain the - * IP information and then go into the poll routine */ - if (card->u.p.ip_mode != WANOPT_PPP_PEER){ - trigger_ppp_poll(dev); - } - } - break; - - case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */ - - NEX_PRINTK(KERN_INFO "DTR Drop Timeout Interrrupt \n"); - - if (card->u.p.ip_mode == WANOPT_PPP_PEER) { - set_bit(0,&Read_connection_info); - } - - wanpipe_set_state(card, WAN_DISCONNECTED); - - show_disc_cause(card, flags->disc_cause); - ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; - flags->imask |= PPP_INTR_TIMER; - trigger_ppp_poll(dev); - break; - - default: - printk(KERN_INFO "%s: Error, Invalid PPP Event\n",card->devname); - } -} - - - -/* TIMER INTERRUPT */ - -void timer_intr (sdla_t *card) -{ - - struct net_device* dev = card->wandev.dev; - ppp_private_area_t* ppp_priv_area = dev->priv; - ppp_flags_t *flags = card->flags; - - - if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG){ - if (!config_ppp(card)){ - ppp_priv_area->timer_int_enabled &= - ~TMR_INT_ENABLED_CONFIG; - } - } - - /* Update statistics */ - if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE){ - ppp_get_err_stats(card); - if(!(--ppp_priv_area->update_comms_stats)){ - ppp_priv_area->timer_int_enabled &= - ~TMR_INT_ENABLED_UPDATE; - } - } - - /* PPIPEMON UDP request */ - - if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP){ - process_udp_mgmt_pkt(card,dev, ppp_priv_area); - ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP; - } - - /* PPP Event */ - if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_PPP_EVENT){ - - if (card->wandev.state == WAN_DISCONNECTED){ - retrigger_comm(card); - } - - /* If the state is CONNECTING, it means that communicatins were - * enabled. When the remote side enables its comminication we - * should get an interrupt PPP_INTR_OPEN, thus turn off polling - */ - - else if (card->wandev.state == WAN_CONNECTING){ - /* Turn off the timer interrupt */ - ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT; - } - - /* If state is connected and we are in PEER mode - * poll for an IP address which will be provided by remote end. - */ - else if ((card->wandev.state == WAN_CONNECTED && - card->u.p.ip_mode == WANOPT_PPP_PEER) && - test_bit(0,&Read_connection_info)){ - - card->state_tick = jiffies; - if (read_connection_info (card)){ - printk(KERN_INFO "%s: Failed to read PEER IP Addresses\n", - card->devname); - }else{ - clear_bit(0,&Read_connection_info); - set_bit(1,&Read_connection_info); - trigger_ppp_poll(dev); - } - }else{ - //FIXME Put the comment back int - ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT; - } - - }/* End of PPP_EVENT */ - - - /* Only disable the timer interrupt if there are no udp, statistic */ - /* updates or events pending */ - if(!ppp_priv_area->timer_int_enabled) { - flags->imask &= ~PPP_INTR_TIMER; - } -} - - -static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto) -{ - int i; - - if( proto == htons(ETH_P_IPX) ) { - //It's an IPX packet - if(!enable_IPX) { - //Return 1 so we don't pass it up the stack. - return 1; - } - } else { - //It's not IPX so pass it up the stack. - return 0; - } - - if( sendpacket[16] == 0x90 && - sendpacket[17] == 0x04) - { - //It's IPXWAN - - if( sendpacket[2] == 0x02 && - sendpacket[34] == 0x00) - { - //It's a timer request packet - printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname); - - //Go through the routing options and answer no to every - //option except Unnumbered RIP/SAP - for(i = 41; sendpacket[i] == 0x00; i += 5) - { - //0x02 is the option for Unnumbered RIP/SAP - if( sendpacket[i + 4] != 0x02) - { - sendpacket[i + 1] = 0; - } - } - - //Skip over the extended Node ID option - if( sendpacket[i] == 0x04 ) - { - i += 8; - } - - //We also want to turn off all header compression opt. - for(; sendpacket[i] == 0x80 ;) - { - sendpacket[i + 1] = 0; - i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4; - } - - //Set the packet type to timer response - sendpacket[34] = 0x01; - - printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname); - } - else if( sendpacket[34] == 0x02 ) - { - //This is an information request packet - printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname); - - //Set the packet type to information response - sendpacket[34] = 0x03; - - //Set the router name - sendpacket[51] = 'P'; - sendpacket[52] = 'T'; - sendpacket[53] = 'P'; - sendpacket[54] = 'I'; - sendpacket[55] = 'P'; - sendpacket[56] = 'E'; - sendpacket[57] = '-'; - sendpacket[58] = CVHexToAscii(network_number >> 28); - sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24); - sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20); - sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16); - sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12); - sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8); - sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4); - sendpacket[65] = CVHexToAscii(network_number & 0x0000000F); - for(i = 66; i < 99; i+= 1) - { - sendpacket[i] = 0; - } - - printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname); - } - else - { - printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname); - return 0; - } - - //Set the WNodeID to our network address - sendpacket[35] = (unsigned char)(network_number >> 24); - sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16); - sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8); - sendpacket[38] = (unsigned char)(network_number & 0x000000FF); - - return 1; - } else { - //If we get here it's an IPX-data packet, so it'll get passed up the stack. - - //switch the network numbers - switch_net_numbers(sendpacket, network_number, 1); - return 0; - } -} - -/****** Background Polling Routines ****************************************/ - -/* All polling functions are invoked by the TIMER interrupt in the wpp_isr - * routine. - */ - -/*============================================================================ - * Monitor active link phase. - */ -static void process_route (sdla_t *card) -{ - ppp_flags_t *flags = card->flags; - struct net_device *dev = card->wandev.dev; - ppp_private_area_t *ppp_priv_area = dev->priv; - - if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && - (flags->ip_state == 0x09)){ - - /* We get ip_local from the firmware in PEER mode. - * Therefore, if ip_local is 0, we failed to obtain - * the remote IP address. */ - if (ppp_priv_area->ip_local == 0) - return; - - printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname); - if (read_info( card )) { - printk(KERN_INFO - "%s: An error occurred in IP assignment.\n", - card->devname); - } else { - struct in_device *in_dev = dev->ip_ptr; - if (in_dev != NULL ) { - struct in_ifaddr *ifa = in_dev->ifa_list; - - printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n", - card->devname, NIPQUAD(ifa->ifa_local)); - printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%u\n", - card->devname, NIPQUAD(ifa->ifa_address)); - }else{ - printk(KERN_INFO - "%s: Error: Failed to add a route for PPP interface %s\n", - card->devname,dev->name); - } - } - } -} - -/*============================================================================ - * Monitor physical link disconnected phase. - * o if interface is up and the hold-down timeout has expired, then retry - * connection. - */ -static void retrigger_comm(sdla_t *card) -{ - struct net_device *dev = card->wandev.dev; - - if (dev && ((jiffies - card->state_tick) > HOLD_DOWN_TIME)) { - - wanpipe_set_state(card, WAN_CONNECTING); - - if(ppp_comm_enable(card) == CMD_OK){ - init_ppp_tx_rx_buff( card ); - } - } -} - -/****** Miscellaneous Functions *********************************************/ - -/*============================================================================ - * Configure S508 adapter. - */ -static int config508(struct net_device *dev, sdla_t *card) -{ - ppp508_conf_t cfg; - struct in_device *in_dev = dev->ip_ptr; - ppp_private_area_t *ppp_priv_area = dev->priv; - - /* Prepare PPP configuration structure */ - memset(&cfg, 0, sizeof(ppp508_conf_t)); - - if (card->wandev.clocking) - cfg.line_speed = card->wandev.bps; - - if (card->wandev.interface == WANOPT_RS232) - cfg.conf_flags |= INTERFACE_LEVEL_RS232; - - - cfg.conf_flags |= DONT_TERMINATE_LNK_MAX_CONFIG; /*send Configure-Request packets forever*/ - cfg.txbuf_percent = PERCENT_TX_BUFF; /* % of Tx bufs */ - cfg.mtu_local = card->wandev.mtu; - cfg.mtu_remote = card->wandev.mtu; /* Default */ - cfg.restart_tmr = TIME_BETWEEN_CONF_REQ; /* 30 = 3sec */ - cfg.auth_rsrt_tmr = TIME_BETWEEN_PAP_CHAP_REQ; /* 30 = 3sec */ - cfg.auth_wait_tmr = WAIT_PAP_CHAP_WITHOUT_REPLY; /* 300 = 30s */ - cfg.mdm_fail_tmr = WAIT_AFTER_DCD_CTS_LOW; /* 5 = 0.5s */ - cfg.dtr_drop_tmr = TIME_DCD_CTS_LOW_AFTER_LNK_DOWN; /* 10 = 1s */ - cfg.connect_tmout = WAIT_DCD_HIGH_AFTER_ENABLE_COMM; /* 900 = 90s */ - cfg.conf_retry = MAX_CONF_REQ_WITHOUT_REPLY; /* 10 = 1s */ - cfg.term_retry = MAX_TERM_REQ_WITHOUT_REPLY; /* 2 times */ - cfg.fail_retry = NUM_CONF_NAK_WITHOUT_REPLY; /* 5 times */ - cfg.auth_retry = NUM_AUTH_REQ_WITHOUT_REPLY; /* 10 times */ - - - if( !card->u.p.authenticator ) { - printk(KERN_INFO "%s: Device is not configured as an authenticator\n", - card->devname); - cfg.auth_options = NO_AUTHENTICATION; - }else{ - printk(KERN_INFO "%s: Device is configured as an authenticator\n", - card->devname); - cfg.auth_options = INBOUND_AUTH; - } - - if( ppp_priv_area->pap == WANOPT_YES){ - cfg.auth_options |=PAP_AUTH; - printk(KERN_INFO "%s: Pap enabled\n", card->devname); - } - if( ppp_priv_area->chap == WANOPT_YES){ - cfg.auth_options |= CHAP_AUTH; - printk(KERN_INFO "%s: Chap enabled\n", card->devname); - } - - - if (ppp_priv_area->enable_IPX == WANOPT_YES){ - printk(KERN_INFO "%s: Enabling IPX Protocol\n",card->devname); - cfg.ipx_options = ENABLE_IPX | ROUTING_PROT_DEFAULT; - }else{ - cfg.ipx_options = DISABLE_IPX; - } - - switch (card->u.p.ip_mode) { - - case WANOPT_PPP_STATIC: - - printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname); - cfg.ip_options = L_AND_R_IP_NO_ASSIG | - ENABLE_IP; - cfg.ip_local = in_dev->ifa_list->ifa_local; - cfg.ip_remote = in_dev->ifa_list->ifa_address; - /* Debugging code used to check that IP addresses - * obtained from the kernel are correct */ - - NEX_PRINTK(KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n", - NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name); - break; - - case WANOPT_PPP_HOST: - - printk(KERN_INFO "%s: PPP IP Mode: HOST\n",card->devname); - cfg.ip_options = L_IP_LOCAL_ASSIG | - R_IP_LOCAL_ASSIG | - ENABLE_IP; - cfg.ip_local = in_dev->ifa_list->ifa_local; - cfg.ip_remote = in_dev->ifa_list->ifa_address; - /* Debugging code used to check that IP addresses - * obtained from the kernel are correct */ - NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n", - NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name); - - break; - - case WANOPT_PPP_PEER: - - printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname); - cfg.ip_options = L_IP_REMOTE_ASSIG | - R_IP_REMOTE_ASSIG | - ENABLE_IP; - cfg.ip_local = 0x00; - cfg.ip_remote = 0x00; - break; - - default: - printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n", - card->devname); - printk(KERN_INFO "%s: PPP IP Modes: STATIC, PEER or HOST\n", - card->devname); - return 1; - } - - return ppp_configure(card, &cfg); -} - -/*============================================================================ - * Show disconnection cause. - */ -static void show_disc_cause(sdla_t *card, unsigned cause) -{ - if (cause & 0x0802) - - printk(KERN_INFO "%s: link terminated by peer\n", - card->devname); - - else if (cause & 0x0004) - - printk(KERN_INFO "%s: link terminated by user\n", - card->devname); - - else if (cause & 0x0008) - - printk(KERN_INFO "%s: authentication failed\n", card->devname); - - else if (cause & 0x0010) - - printk(KERN_INFO - "%s: authentication protocol negotiation failed\n", - card->devname); - - else if (cause & 0x0020) - - printk(KERN_INFO - "%s: peer's request for authentication rejected\n", - card->devname); - - else if (cause & 0x0040) - - printk(KERN_INFO "%s: MRU option rejected by peer\n", - card->devname); - - else if (cause & 0x0080) - - printk(KERN_INFO "%s: peer's MRU was too small\n", - card->devname); - - else if (cause & 0x0100) - - printk(KERN_INFO "%s: failed to negotiate peer's LCP options\n", - card->devname); - - else if (cause & 0x0200) - - printk(KERN_INFO "%s: failed to negotiate peer's IPCP options\n" - , card->devname); - - else if (cause & 0x0400) - - printk(KERN_INFO - "%s: failed to negotiate peer's IPXCP options\n", - card->devname); -} - -/*============================================================================= - * Process UDP call of type PTPIPEAB. - */ -static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev, - ppp_private_area_t *ppp_priv_area ) -{ - unsigned char buf2[5]; - unsigned char *buf; - unsigned int frames, len; - struct sk_buff *new_skb; - unsigned short data_length, buffer_length, real_len; - unsigned long data_ptr; - int udp_mgmt_req_valid = 1; - ppp_mbox_t *mbox = card->mbox; - struct timeval tv; - int err; - ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t*)&ppp_priv_area->udp_pkt_data; - - memcpy(&buf2, &card->wandev.udp_port, 2 ); - - - if(ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { - - switch(ppp_udp_pkt->cblock.command) { - - case PPIPE_GET_IBA_DATA: - case PPP_READ_CONFIG: - case PPP_GET_CONNECTION_INFO: - case PPIPE_ROUTER_UP_TIME: - case PPP_READ_STATISTICS: - case PPP_READ_ERROR_STATS: - case PPP_READ_PACKET_STATS: - case PPP_READ_LCP_STATS: - case PPP_READ_IPCP_STATS: - case PPP_READ_IPXCP_STATS: - case PPP_READ_PAP_STATS: - case PPP_READ_CHAP_STATS: - case PPP_READ_CODE_VERSION: - udp_mgmt_req_valid = 1; - break; - - default: - udp_mgmt_req_valid = 0; - break; - } - } - - if(!udp_mgmt_req_valid) { - - /* set length to 0 */ - ppp_udp_pkt->cblock.length = 0x00; - - /* set return code */ - ppp_udp_pkt->cblock.result = 0xCD; - ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err; - - if (net_ratelimit()){ - printk(KERN_INFO - "%s: Warning, Illegal UDP command attempted from network: %x\n", - card->devname,ppp_udp_pkt->cblock.command); - } - } else { - /* Initialize the trace element */ - trace_element_t trace_element; - - switch (ppp_udp_pkt->cblock.command){ - - /* PPIPE_ENABLE_TRACING */ - case PPIPE_ENABLE_TRACING: - if (!card->TracingEnabled) { - - /* OPERATE_DATALINE_MONITOR */ - mbox->cmd.command = PPP_DATALINE_MONITOR; - mbox->cmd.length = 0x01; - mbox->data[0] = ppp_udp_pkt->data[0]; - err = sdla_exec(mbox) ? - mbox->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK) { - - ppp_error(card, err, mbox); - card->TracingEnabled = 0; - - /* set the return code */ - - ppp_udp_pkt->cblock.result = mbox->cmd.result; - mbox->cmd.length = 0; - break; - } - - sdla_peek(&card->hw, 0xC000, &buf2, 2); - - ppp_priv_area->curr_trace_addr = 0; - memcpy(&ppp_priv_area->curr_trace_addr, &buf2, 2); - ppp_priv_area->start_trace_addr = - ppp_priv_area->curr_trace_addr; - ppp_priv_area->end_trace_addr = - ppp_priv_area->start_trace_addr + END_OFFSET; - - /* MAX_SEND_BUFFER_SIZE - 28 (IP header) - - 32 (ppipemon CBLOCK) */ - available_buffer_space = MAX_LGTH_UDP_MGNT_PKT - - sizeof(ip_pkt_t)- - sizeof(udp_pkt_t)- - sizeof(wp_mgmt_t)- - sizeof(cblock_t); - } - ppp_udp_pkt->cblock.result = 0; - mbox->cmd.length = 0; - card->TracingEnabled = 1; - break; - - /* PPIPE_DISABLE_TRACING */ - case PPIPE_DISABLE_TRACING: - - if(card->TracingEnabled) { - - /* OPERATE_DATALINE_MONITOR */ - mbox->cmd.command = 0x33; - mbox->cmd.length = 1; - mbox->data[0] = 0x00; - err = sdla_exec(mbox) ? - mbox->cmd.result : CMD_TIMEOUT; - - } - - /*set return code*/ - ppp_udp_pkt->cblock.result = 0; - mbox->cmd.length = 0; - card->TracingEnabled = 0; - break; - - /* PPIPE_GET_TRACE_INFO */ - case PPIPE_GET_TRACE_INFO: - - if(!card->TracingEnabled) { - /* set return code */ - ppp_udp_pkt->cblock.result = 1; - mbox->cmd.length = 0; - } - - buffer_length = 0; - - /* frames < 62, where 62 is the number of trace - information elements. There is in total 496 - bytes of space and each trace information - element is 8 bytes. - */ - for ( frames=0; frames<62; frames++) { - - trace_pkt_t *trace_pkt = (trace_pkt_t *) - &ppp_udp_pkt->data[buffer_length]; - - /* Read the whole trace packet */ - sdla_peek(&card->hw, ppp_priv_area->curr_trace_addr, - &trace_element, sizeof(trace_element_t)); - - /* no data on board so exit */ - if( trace_element.opp_flag == 0x00 ) - break; - - data_ptr = trace_element.trace_data_ptr; - - /* See if there is actual data on the trace buffer */ - if (data_ptr){ - data_length = trace_element.trace_length; - }else{ - data_length = 0; - ppp_udp_pkt->data[0] |= 0x02; - } - - //FIXME: Do we need this check - if ((available_buffer_space - buffer_length) - < (sizeof(trace_element_t)+1)){ - - /*indicate we have more frames - * on board and exit - */ - ppp_udp_pkt->data[0] |= 0x02; - break; - } - - trace_pkt->status = trace_element.trace_type; - trace_pkt->time_stamp = trace_element.trace_time_stamp; - trace_pkt->real_length = trace_element.trace_length; - - real_len = trace_element.trace_length; - - if(data_ptr == 0){ - trace_pkt->data_avail = 0x00; - }else{ - /* we can take it next time */ - if ((available_buffer_space - buffer_length)< - (real_len + sizeof(trace_pkt_t))){ - - ppp_udp_pkt->data[0] |= 0x02; - break; - } - trace_pkt->data_avail = 0x01; - - /* get the data */ - sdla_peek(&card->hw, data_ptr, - &trace_pkt->data, - real_len); - } - /* zero the opp flag to - show we got the frame */ - buf2[0] = 0x00; - sdla_poke(&card->hw, ppp_priv_area->curr_trace_addr, - &buf2, 1); - - /* now move onto the next - frame */ - ppp_priv_area->curr_trace_addr += 8; - - /* check if we passed the last address */ - if ( ppp_priv_area->curr_trace_addr >= - ppp_priv_area->end_trace_addr){ - - ppp_priv_area->curr_trace_addr = - ppp_priv_area->start_trace_addr; - } - - /* update buffer length and make sure its even */ - - if ( trace_pkt->data_avail == 0x01 ) { - buffer_length += real_len - 1; - } - - /* for the header */ - buffer_length += 8; - - if( buffer_length & 0x0001 ) - buffer_length += 1; - } - - /* ok now set the total number of frames passed - in the high 5 bits */ - ppp_udp_pkt->data[0] |= (frames << 2); - - /* set the data length */ - mbox->cmd.length = buffer_length; - ppp_udp_pkt->cblock.length = buffer_length; - - /* set return code */ - ppp_udp_pkt->cblock.result = 0; - break; - - /* PPIPE_GET_IBA_DATA */ - case PPIPE_GET_IBA_DATA: - - mbox->cmd.length = 0x09; - - sdla_peek(&card->hw, 0xF003, &ppp_udp_pkt->data, - mbox->cmd.length); - - /* set the length of the data */ - ppp_udp_pkt->cblock.length = 0x09; - - /* set return code */ - ppp_udp_pkt->cblock.result = 0x00; - ppp_udp_pkt->cblock.result = 0; - break; - - /* PPIPE_FT1_READ_STATUS */ - case PPIPE_FT1_READ_STATUS: - sdla_peek(&card->hw, 0xF020, &ppp_udp_pkt->data[0], 2); - ppp_udp_pkt->cblock.length = mbox->cmd.length = 2; - ppp_udp_pkt->cblock.result = 0; - break; - - case PPIPE_FLUSH_DRIVER_STATS: - init_ppp_priv_struct( ppp_priv_area ); - init_global_statistics( card ); - mbox->cmd.length = 0; - ppp_udp_pkt->cblock.result = 0; - break; - - - case PPIPE_ROUTER_UP_TIME: - - do_gettimeofday( &tv ); - ppp_priv_area->router_up_time = tv.tv_sec - - ppp_priv_area->router_start_time; - *(unsigned long *)&ppp_udp_pkt->data = ppp_priv_area->router_up_time; - mbox->cmd.length = 4; - ppp_udp_pkt->cblock.result = 0; - break; - - /* PPIPE_DRIVER_STATISTICS */ - case PPIPE_DRIVER_STAT_IFSEND: - memcpy(&ppp_udp_pkt->data, &ppp_priv_area->if_send_stat, - sizeof(if_send_stat_t)); - - - ppp_udp_pkt->cblock.result = 0; - ppp_udp_pkt->cblock.length = sizeof(if_send_stat_t); - mbox->cmd.length = sizeof(if_send_stat_t); - break; - - case PPIPE_DRIVER_STAT_INTR: - memcpy(&ppp_udp_pkt->data, &card->statistics, - sizeof(global_stats_t)); - - memcpy(&ppp_udp_pkt->data+sizeof(global_stats_t), - &ppp_priv_area->rx_intr_stat, - sizeof(rx_intr_stat_t)); - - ppp_udp_pkt->cblock.result = 0; - ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+ - sizeof(rx_intr_stat_t); - mbox->cmd.length = ppp_udp_pkt->cblock.length; - break; - - case PPIPE_DRIVER_STAT_GEN: - memcpy( &ppp_udp_pkt->data, - &ppp_priv_area->pipe_mgmt_stat, - sizeof(pipe_mgmt_stat_t)); - - memcpy(&ppp_udp_pkt->data+sizeof(pipe_mgmt_stat_t), - &card->statistics, sizeof(global_stats_t)); - - ppp_udp_pkt->cblock.result = 0; - ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+ - sizeof(rx_intr_stat_t); - mbox->cmd.length = ppp_udp_pkt->cblock.length; - break; - - - /* FT1 MONITOR STATUS */ - case FT1_MONITOR_STATUS_CTRL: - - /* Enable FT1 MONITOR STATUS */ - if( ppp_udp_pkt->data[0] == 1) { - - if( rCount++ != 0 ) { - ppp_udp_pkt->cblock.result = 0; - mbox->cmd.length = 1; - break; - } - } - - /* Disable FT1 MONITOR STATUS */ - if( ppp_udp_pkt->data[0] == 0) { - - if( --rCount != 0) { - ppp_udp_pkt->cblock.result = 0; - mbox->cmd.length = 1; - break; - } - } - goto udp_dflt_cmd; - - /* WARNING: FIXME: This should be fixed. - * The FT1 Status Ctrl doesn't have a break - * statment. Thus, no code must be inserted - * HERE: between default and above case statement */ - - default: -udp_dflt_cmd: - - /* it's a board command */ - mbox->cmd.command = ppp_udp_pkt->cblock.command; - mbox->cmd.length = ppp_udp_pkt->cblock.length; - - if(mbox->cmd.length) { - memcpy(&mbox->data,(unsigned char *)ppp_udp_pkt->data, - mbox->cmd.length); - } - - /* run the command on the board */ - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK) { - - ppp_error(card, err, mbox); - ++ppp_priv_area->pipe_mgmt_stat. - UDP_PIPE_mgmt_adptr_cmnd_timeout; - break; - } - - ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK; - - /* copy the result back to our buffer */ - memcpy(&ppp_udp_pkt->cblock,mbox, sizeof(cblock_t)); - - if(mbox->cmd.length) { - memcpy(&ppp_udp_pkt->data,&mbox->data,mbox->cmd.length); - } - - } /* end of switch */ - } /* end of else */ - - /* Fill UDP TTL */ - ppp_udp_pkt->ip_pkt.ttl = card->wandev.ttl; - len = reply_udp(ppp_priv_area->udp_pkt_data, mbox->cmd.length); - - if (ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { - - /* Make sure we are not already sending */ - if (!test_bit(SEND_CRIT,&card->wandev.critical)){ - ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_adptr; - ppp_send(card,ppp_priv_area->udp_pkt_data,len,ppp_priv_area->protocol); - } - - } else { - - /* Pass it up the stack - Allocate socket buffer */ - if ((new_skb = dev_alloc_skb(len)) != NULL) { - - /* copy data into new_skb */ - - buf = skb_put(new_skb, len); - memcpy(buf,ppp_priv_area->udp_pkt_data, len); - - ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack; - - /* Decapsulate packet and pass it up the protocol - stack */ - new_skb->protocol = htons(ETH_P_IP); - new_skb->dev = dev; - new_skb->mac.raw = new_skb->data; - netif_rx(new_skb); - dev->last_rx = jiffies; - - } else { - - ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket; - printk(KERN_INFO "no socket buffers available!\n"); - } - } - - ppp_priv_area->udp_pkt_lgth = 0; - - return; -} - -/*============================================================================= - * Initial the ppp_private_area structure. - */ -static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area ) -{ - - memset(&ppp_priv_area->if_send_stat, 0, sizeof(if_send_stat_t)); - memset(&ppp_priv_area->rx_intr_stat, 0, sizeof(rx_intr_stat_t)); - memset(&ppp_priv_area->pipe_mgmt_stat, 0, sizeof(pipe_mgmt_stat_t)); -} - -/*============================================================================ - * Initialize Global Statistics - */ -static void init_global_statistics( sdla_t *card ) -{ - memset(&card->statistics, 0, sizeof(global_stats_t)); -} - -/*============================================================================ - * Initialize Receive and Transmit Buffers. - */ -static void init_ppp_tx_rx_buff( sdla_t *card ) -{ - ppp508_buf_info_t* info; - - if (card->hw.type == SDLA_S514) { - - info = (void*)(card->hw.dpmbase + PPP514_BUF_OFFS); - - card->u.p.txbuf_base = (void*)(card->hw.dpmbase + - info->txb_ptr); - - card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base + - (info->txb_num - 1); - - card->u.p.rxbuf_base = (void*)(card->hw.dpmbase + - info->rxb_ptr); - - card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base + - (info->rxb_num - 1); - - } else { - - info = (void*)(card->hw.dpmbase + PPP508_BUF_OFFS); - - card->u.p.txbuf_base = (void*)(card->hw.dpmbase + - (info->txb_ptr - PPP508_MB_VECT)); - - card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base + - (info->txb_num - 1); - - card->u.p.rxbuf_base = (void*)(card->hw.dpmbase + - (info->rxb_ptr - PPP508_MB_VECT)); - - card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base + - (info->rxb_num - 1); - } - - card->u.p.txbuf_next = (unsigned long*)&info->txb_nxt; - card->u.p.rxbuf_next = (unsigned long*)&info->rxb1_ptr; - - card->u.p.rx_base = info->rxb_base; - card->u.p.rx_top = info->rxb_end; - - card->u.p.txbuf = card->u.p.txbuf_base; - card->rxmb = card->u.p.rxbuf_base; - -} - -/*============================================================================= - * Read Connection Information (ie for Remote IP address assginment). - * Called when ppp interface connected. - */ -static int read_info( sdla_t *card ) -{ - struct net_device *dev = card->wandev.dev; - ppp_private_area_t *ppp_priv_area = dev->priv; - int err; - - struct ifreq if_info; - struct sockaddr_in *if_data1, *if_data2; - mm_segment_t fs; - - /* Set Local and remote addresses */ - memset(&if_info, 0, sizeof(if_info)); - strcpy(if_info.ifr_name, dev->name); - - - fs = get_fs(); - set_fs(get_ds()); /* get user space block */ - - /* Change the local and remote ip address of the interface. - * This will also add in the destination route. - */ - if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; - if_data1->sin_addr.s_addr = ppp_priv_area->ip_local; - if_data1->sin_family = AF_INET; - err = devinet_ioctl( SIOCSIFADDR, &if_info ); - if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; - if_data2->sin_addr.s_addr = ppp_priv_area->ip_remote; - if_data2->sin_family = AF_INET; - err = devinet_ioctl( SIOCSIFDSTADDR, &if_info ); - - set_fs(fs); /* restore old block */ - - if (err) { - printk (KERN_INFO "%s: Adding of route failed: %i\n", - card->devname,err); - printk (KERN_INFO "%s: Local : %u.%u.%u.%u\n", - card->devname,NIPQUAD(ppp_priv_area->ip_local)); - printk (KERN_INFO "%s: Remote: %u.%u.%u.%u\n", - card->devname,NIPQUAD(ppp_priv_area->ip_remote)); - } - return err; -} - -/*============================================================================= - * Remove Dynamic Route. - * Called when ppp interface disconnected. - */ - -static void remove_route( sdla_t *card ) -{ - - struct net_device *dev = card->wandev.dev; - long ip_addr; - int err; - - mm_segment_t fs; - struct ifreq if_info; - struct sockaddr_in *if_data1; - struct in_device *in_dev = dev->ip_ptr; - struct in_ifaddr *ifa = in_dev->ifa_list; - - ip_addr = ifa->ifa_local; - - /* Set Local and remote addresses */ - memset(&if_info, 0, sizeof(if_info)); - strcpy(if_info.ifr_name, dev->name); - - fs = get_fs(); - set_fs(get_ds()); /* get user space block */ - - /* Change the local ip address of the interface to 0. - * This will also delete the destination route. - */ - if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; - if_data1->sin_addr.s_addr = 0; - if_data1->sin_family = AF_INET; - err = devinet_ioctl( SIOCSIFADDR, &if_info ); - - set_fs(fs); /* restore old block */ - - - if (err) { - printk (KERN_INFO "%s: Deleting dynamic route failed %d!\n", - card->devname, err); - return; - }else{ - printk (KERN_INFO "%s: PPP Deleting dynamic route %u.%u.%u.%u successfuly\n", - card->devname, NIPQUAD(ip_addr)); - } - return; -} - -/*============================================================================= - * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR - * _TEST_COUNTER times. - */ -static int intr_test( sdla_t *card ) -{ - ppp_mbox_t *mb = card->mbox; - int err,i; - - err = ppp_set_intr_mode( card, 0x08 ); - - if (err == CMD_OK) { - - for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) { - /* Run command READ_CODE_VERSION */ - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - mb->cmd.length = 0; - mb->cmd.command = PPP_READ_CODE_VERSION; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - if (err != CMD_OK) - ppp_error(card, err, mb); - } - } - else return err; - - err = ppp_set_intr_mode( card, 0 ); - if (err != CMD_OK) - return err; - - return 0; -} - -/*============================================================================== - * Determine what type of UDP call it is. DRVSTATS or PTPIPEAB ? - */ -static int udp_pkt_type( struct sk_buff *skb, sdla_t *card ) -{ - unsigned char *sendpacket; - unsigned char buf2[5]; - ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t *)skb->data; - - sendpacket = skb->data; - memcpy(&buf2, &card->wandev.udp_port, 2); - - if( ppp_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45 && /* IP packet */ - sendpacket[9] == 0x11 && /* UDP packet */ - sendpacket[22] == buf2[1] && /* UDP Port */ - sendpacket[23] == buf2[0] && - sendpacket[36] == 0x01 ) { - - if ( sendpacket[28] == 0x50 && /* PTPIPEAB: Signature */ - sendpacket[29] == 0x54 && - sendpacket[30] == 0x50 && - sendpacket[31] == 0x49 && - sendpacket[32] == 0x50 && - sendpacket[33] == 0x45 && - sendpacket[34] == 0x41 && - sendpacket[35] == 0x42 ){ - - return UDP_PTPIPE_TYPE; - - } else if(sendpacket[28] == 0x44 && /* DRVSTATS: Signature */ - sendpacket[29] == 0x52 && - sendpacket[30] == 0x56 && - sendpacket[31] == 0x53 && - sendpacket[32] == 0x54 && - sendpacket[33] == 0x41 && - sendpacket[34] == 0x54 && - sendpacket[35] == 0x53 ){ - - return UDP_DRVSTATS_TYPE; - - } else - return UDP_INVALID_TYPE; - - } else - return UDP_INVALID_TYPE; - -} - -/*============================================================================ - * Check to see if the packet to be transmitted contains a broadcast or - * multicast source IP address. - */ - -static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev, - struct sk_buff *skb) -{ - u32 src_ip_addr; - u32 broadcast_ip_addr = 0; - struct in_device *in_dev; - - /* read the IP source address from the outgoing packet */ - src_ip_addr = *(u32 *)(skb->data + 12); - - /* read the IP broadcast address for the device */ - in_dev = dev->ip_ptr; - if(in_dev != NULL) { - struct in_ifaddr *ifa= in_dev->ifa_list; - if(ifa != NULL) - broadcast_ip_addr = ifa->ifa_broadcast; - else - return 0; - } - - /* check if the IP Source Address is a Broadcast address */ - if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { - printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n", - card->devname); - return 1; - } - - /* check if the IP Source Address is a Multicast address */ - if((ntohl(src_ip_addr) >= 0xE0000001) && - (ntohl(src_ip_addr) <= 0xFFFFFFFE)) { - printk(KERN_INFO "%s: Multicast Source Address silently discarded\n", - card->devname); - return 1; - } - - return 0; -} - -void s508_lock (sdla_t *card, unsigned long *smp_flags) -{ - spin_lock_irqsave(&card->wandev.lock, *smp_flags); -} - -void s508_unlock (sdla_t *card, unsigned long *smp_flags) -{ - spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -} - -static int read_connection_info (sdla_t *card) -{ - ppp_mbox_t *mb = card->mbox; - struct net_device *dev = card->wandev.dev; - ppp_private_area_t *ppp_priv_area = dev->priv; - ppp508_connect_info_t *ppp508_connect_info; - int err; - - memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); - mb->cmd.length = 0; - mb->cmd.command = PPP_GET_CONNECTION_INFO; - err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK) { - ppp_error(card, err, mb); - ppp_priv_area->ip_remote = 0; - ppp_priv_area->ip_local = 0; - } - else { - ppp508_connect_info = (ppp508_connect_info_t *)mb->data; - ppp_priv_area->ip_remote = ppp508_connect_info->ip_remote; - ppp_priv_area->ip_local = ppp508_connect_info->ip_local; - - NEX_PRINTK(KERN_INFO "READ CONNECTION GOT IP ADDRESS %x, %x\n", - ppp_priv_area->ip_remote, - ppp_priv_area->ip_local); - } - - return err; -} - -/*=============================================================================== - * config_ppp - * - * Configure the ppp protocol and enable communications. - * - * The if_open function binds this function to the poll routine. - * Therefore, this function will run every time the ppp interface - * is brought up. - * - * If the communications are not enabled, proceed to configure - * the card and enable communications. - * - * If the communications are enabled, it means that the interface - * was shutdown by ether the user or driver. In this case, we - * have to check that the IP addresses have not changed. If - * the IP addresses changed, we have to reconfigure the firmware - * and update the changed IP addresses. Otherwise, just exit. - */ -static int config_ppp (sdla_t *card) -{ - - struct net_device *dev = card->wandev.dev; - ppp_flags_t *flags = card->flags; - ppp_private_area_t *ppp_priv_area = dev->priv; - - if (card->u.p.comm_enabled){ - - if (ppp_priv_area->ip_local_tmp != ppp_priv_area->ip_local || - ppp_priv_area->ip_remote_tmp != ppp_priv_area->ip_remote){ - - /* The IP addersses have changed, we must - * stop the communications and reconfigure - * the card. Reason: the firmware must know - * the local and remote IP addresses. */ - disable_comm(card); - wanpipe_set_state(card, WAN_DISCONNECTED); - printk(KERN_INFO - "%s: IP addresses changed!\n", - card->devname); - printk(KERN_INFO "%s: Restarting communications ...\n", - card->devname); - }else{ - /* IP addresses are the same and the link is up, - * we don't have to do anything here. Therefore, exit */ - return 0; - } - } - - /* Record the new IP addreses */ - ppp_priv_area->ip_local = ppp_priv_area->ip_local_tmp; - ppp_priv_area->ip_remote = ppp_priv_area->ip_remote_tmp; - - if (config508(dev, card)){ - printk(KERN_INFO "%s: Failed to configure PPP device\n", - card->devname); - return 0; - } - - if (ppp_set_intr_mode(card, PPP_INTR_RXRDY| - PPP_INTR_TXRDY| - PPP_INTR_MODEM| - PPP_INTR_DISC | - PPP_INTR_OPEN | - PPP_INTR_DROP_DTR | - PPP_INTR_TIMER)) { - - printk(KERN_INFO "%s: Failed to configure board interrupts !\n", - card->devname); - return 0; - } - - /* Turn off the transmit and timer interrupt */ - flags->imask &= ~(PPP_INTR_TXRDY | PPP_INTR_TIMER) ; - - - /* If you are not the authenticator and any one of the protocol is - * enabled then we call the set_out_bound_authentication. - */ - if ( !card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)) { - if ( ppp_set_outbnd_auth(card, ppp_priv_area) ){ - printk(KERN_INFO "%s: Outbound authentication failed !\n", - card->devname); - return 0; - } - } - - /* If you are the authenticator and any one of the protocol is enabled - * then we call the set_in_bound_authentication. - */ - if (card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)){ - if (ppp_set_inbnd_auth(card, ppp_priv_area)){ - printk(KERN_INFO "%s: Inbound authentication failed !\n", - card->devname); - return 0; - } - } - - /* If we fail to enable communications here it's OK, - * since the DTR timer will cause a disconnected, which - * will retrigger communication in timer_intr() */ - if (ppp_comm_enable(card) == CMD_OK) { - wanpipe_set_state(card, WAN_CONNECTING); - init_ppp_tx_rx_buff(card); - } - - return 0; -} - -/*============================================================ - * ppp_poll - * - * Rationale: - * We cannot manipulate the routing tables, or - * ip addresses withing the interrupt. Therefore - * we must perform such actons outside an interrupt - * at a later time. - * - * Description: - * PPP polling routine, responsible for - * shutting down interfaces upon disconnect - * and adding/removing routes. - * - * Usage: - * This function is executed for each ppp - * interface through a tq_schedule bottom half. - * - * trigger_ppp_poll() function is used to kick - * the ppp_poll routine. - */ -static void ppp_poll(struct net_device *dev) -{ - ppp_private_area_t *ppp_priv_area; - sdla_t *card; - u8 check_gateway=0; - ppp_flags_t *flags; - - if (!dev || (ppp_priv_area = dev->priv) == NULL) - return; - - card = ppp_priv_area->card; - flags = card->flags; - - /* Shutdown is in progress, stop what you are - * doing and get out */ - if (test_bit(PERI_CRIT,&card->wandev.critical)){ - clear_bit(POLL_CRIT,&card->wandev.critical); - return; - } - - /* if_open() function has triggered the polling routine - * to determine the configured IP addresses. Once the - * addresses are found, trigger the chdlc configuration */ - if (test_bit(0,&ppp_priv_area->config_ppp)){ - - ppp_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP); - ppp_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP); - - if (ppp_priv_area->ip_local_tmp == ppp_priv_area->ip_remote_tmp && - card->u.p.ip_mode == WANOPT_PPP_HOST){ - - if (++ppp_priv_area->ip_error > MAX_IP_ERRORS){ - printk(KERN_INFO "\n%s: --- WARNING ---\n", - card->devname); - printk(KERN_INFO "%s: The local IP address is the same as the\n", - card->devname); - printk(KERN_INFO "%s: Point-to-Point IP address.\n", - card->devname); - printk(KERN_INFO "%s: --- WARNING ---\n\n", - card->devname); - }else{ - clear_bit(POLL_CRIT,&card->wandev.critical); - ppp_priv_area->poll_delay_timer.expires = jiffies+HZ; - add_timer(&ppp_priv_area->poll_delay_timer); - return; - } - } - - ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG; - flags->imask |= PPP_INTR_TIMER; - ppp_priv_area->ip_error=0; - - clear_bit(0,&ppp_priv_area->config_ppp); - clear_bit(POLL_CRIT,&card->wandev.critical); - return; - } - - /* Dynamic interface implementation, as well as dynamic - * routing. */ - - switch (card->wandev.state) { - - case WAN_DISCONNECTED: - - /* If the dynamic interface configuration is on, and interface - * is up, then bring down the netowrk interface */ - - if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) && - !test_bit(DEV_DOWN,&ppp_priv_area->interface_down) && - card->wandev.dev->flags & IFF_UP){ - - printk(KERN_INFO "%s: Interface %s down.\n", - card->devname,card->wandev.dev->name); - change_dev_flags(card->wandev.dev, - (card->wandev.dev->flags&~IFF_UP)); - set_bit(DEV_DOWN,&ppp_priv_area->interface_down); - }else{ - /* We need to check if the local IP address is - * zero. If it is, we shouldn't try to remove it. - * For some reason the kernel crashes badly if - * we try to remove the route twice */ - - if (card->wandev.dev->flags & IFF_UP && - get_ip_address(card->wandev.dev,WAN_LOCAL_IP) && - card->u.p.ip_mode == WANOPT_PPP_PEER){ - - remove_route(card); - } - } - break; - - case WAN_CONNECTED: - - /* In SMP machine this code can execute before the interface - * comes up. In this case, we must make sure that we do not - * try to bring up the interface before dev_open() is finished */ - - - /* DEV_DOWN will be set only when we bring down the interface - * for the very first time. This way we know that it was us - * that brought the interface down */ - - if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) && - test_bit(DEV_DOWN, &ppp_priv_area->interface_down) && - !(card->wandev.dev->flags & IFF_UP)){ - - printk(KERN_INFO "%s: Interface %s up.\n", - card->devname,card->wandev.dev->name); - - change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP)); - clear_bit(DEV_DOWN,&ppp_priv_area->interface_down); - check_gateway=1; - } - - if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && - test_bit(1,&Read_connection_info)) { - - process_route(card); - clear_bit(1,&Read_connection_info); - check_gateway=1; - } - - if (ppp_priv_area->gateway && check_gateway) - add_gateway(card,dev); - - break; - } - clear_bit(POLL_CRIT,&card->wandev.critical); - return; -} - -/*============================================================ - * trigger_ppp_poll - * - * Description: - * Add a ppp_poll() task into a tq_scheduler bh handler - * for a specific interface. This will kick - * the ppp_poll() routine at a later time. - * - * Usage: - * Interrupts use this to defer a taks to - * a polling routine. - * - */ - -static void trigger_ppp_poll(struct net_device *dev) -{ - ppp_private_area_t *ppp_priv_area; - if ((ppp_priv_area=dev->priv) != NULL){ - - sdla_t *card = ppp_priv_area->card; - - if (test_bit(PERI_CRIT,&card->wandev.critical)){ - return; - } - - if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){ - return; - } - - schedule_work(&ppp_priv_area->poll_work); - } - return; -} - -static void ppp_poll_delay (unsigned long dev_ptr) -{ - struct net_device *dev = (struct net_device *)dev_ptr; - trigger_ppp_poll(dev); -} - -/*============================================================ - * detect_and_fix_tx_bug - * - * Description: - * On connect, if the board tx buffer ptr is not the same - * as the driver tx buffer ptr, we found a firmware bug. - * Report the bug to the above layer. To fix the - * error restart communications again. - * - * Usage: - * - */ - -static int detect_and_fix_tx_bug (sdla_t *card) -{ - if (((unsigned long)card->u.p.txbuf_base&0xFFF) != ((*card->u.p.txbuf_next)&0xFFF)){ - NEX_PRINTK(KERN_INFO "Major Error, Fix the bug\n"); - return 1; - } - return 0; -} - -MODULE_LICENSE("GPL"); - -/****** End *****************************************************************/ diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c deleted file mode 100644 index 63f846d6f3a6..000000000000 --- a/drivers/net/wan/sdla_x25.c +++ /dev/null @@ -1,5497 +0,0 @@ -/***************************************************************************** -* sdla_x25.c WANPIPE(tm) Multiprotocol WAN Link Driver. X.25 module. -* -* Author: Nenad Corbic -* -* Copyright: (c) 1995-2001 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. -* ============================================================================ -* Apr 03, 2001 Nenad Corbic o Fixed the rx_skb=NULL bug in x25 in rx_intr(). -* Dec 26, 2000 Nenad Corbic o Added a new polling routine, that uses -* a kernel timer (more efficient). -* Dec 25, 2000 Nenad Corbic o Updated for 2.4.X kernel -* Jul 26, 2000 Nenad Corbic o Increased the local packet buffering -* for API to 4096+header_size. -* Jul 17, 2000 Nenad Corbic o Fixed the x25 startup bug. Enable -* communications only after all interfaces -* come up. HIGH SVC/PVC is used to calculate -* the number of channels. -* Enable protocol only after all interfaces -* are enabled. -* Jul 10, 2000 Nenad Corbic o Fixed the M_BIT bug. -* Apr 25, 2000 Nenad Corbic o Pass Modem messages to the API. -* Disable idle timeout in X25 API. -* Apr 14, 2000 Nenad Corbic o Fixed: Large LCN number support. -* Maximum LCN number is 4095. -* Maximum number of X25 channels is 255. -* Apr 06, 2000 Nenad Corbic o Added SMP Support. -* Mar 29, 2000 Nenad Corbic o Added support for S514 PCI Card -* Mar 23, 2000 Nenad Corbic o Improved task queue, BH handling. -* Mar 14, 2000 Nenad Corbic o Updated Protocol Violation handling -* routines. Bug Fix. -* Mar 10, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery. -* Mar 09, 2000 Nenad Corbic o Fixed the auto HDLC bug. -* Mar 08, 2000 Nenad Corbic o Fixed LAPB HDLC startup problems. -* Application must bring the link up -* before tx/rx, and bring the -* link down on close(). -* Mar 06, 2000 Nenad Corbic o Added an option for logging call setup -* information. -* Feb 29, 2000 Nenad Corbic o Added support for LAPB HDLC API -* Feb 25, 2000 Nenad Corbic o Fixed the modem failure handling. -* No Modem OOB message will be passed -* to the user. -* Feb 21, 2000 Nenad Corbic o Added Xpipemon Debug Support -* Dec 30, 1999 Nenad Corbic o Socket based X25API -* Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X kernel -* Mar 15, 1998 Alan Cox o 2.1.x porting -* Dec 19, 1997 Jaspreet Singh o Added multi-channel IPX support -* Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs -* when they are disabled. -* Nov 17, 1997 Farhan Thawar o Added IPX support -* o Changed if_send() to now buffer packets when -* the board is busy -* o Removed queueing of packets via the polling -* routing -* o Changed if_send() critical flags to properly -* handle race conditions -* Nov 06, 1997 Farhan Thawar o Added support for SVC timeouts -* o Changed PVC encapsulation to ETH_P_IP -* Jul 21, 1997 Jaspreet Singh o Fixed freeing up of buffers using kfree() -* when packets are received. -* Mar 11, 1997 Farhan Thawar Version 3.1.1 -* o added support for V35 -* o changed if_send() to return 0 if -* wandev.critical() is true -* o free socket buffer in if_send() if -* returning 0 -* o added support for single '@' address to -* accept all incoming calls -* o fixed bug in set_chan_state() to disconnect -* Jan 15, 1997 Gene Kozin Version 3.1.0 -* o implemented exec() entry point -* Jan 07, 1997 Gene Kozin Initial version. -*****************************************************************************/ - -/*====================================================== - * Includes - *=====================================================*/ - -#include -#include /* printk(), and other useful stuff */ -#include /* offsetof(), etc. */ -#include /* return codes */ -#include /* inline memset(), etc. */ -#include -#include /* kmalloc(), kfree() */ -#include /* WAN router definitions */ -#include /* WANPIPE common user API definitions */ -#include -#include /* time_after() macro */ -#include /* htons(), etc. */ -#include -#include /* Experimental delay */ - -#include - -#include -#include -#include /* X.25 firmware API definitions */ -#include -#include - - -/*====================================================== - * Defines & Macros - *=====================================================*/ - - -#define CMD_OK 0 /* normal firmware return code */ -#define CMD_TIMEOUT 0xFF /* firmware command timed out */ -#define MAX_CMD_RETRY 10 /* max number of firmware retries */ - -#define X25_CHAN_MTU 4096 /* unfragmented logical channel MTU */ -#define X25_HRDHDR_SZ 7 /* max encapsulation header size */ -#define X25_CONCT_TMOUT (90*HZ) /* link connection timeout */ -#define X25_RECON_TMOUT (10*HZ) /* link connection timeout */ -#define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */ -#define HOLD_DOWN_TIME (30*HZ) /* link hold down time */ -#define MAX_BH_BUFF 10 -#define M_BIT 0x01 - -//#define PRINT_DEBUG 1 -#ifdef PRINT_DEBUG -#define DBG_PRINTK(format, a...) printk(format, ## a) -#else -#define DBG_PRINTK(format, a...) -#endif - -#define TMR_INT_ENABLED_POLL_ACTIVE 0x01 -#define TMR_INT_ENABLED_POLL_CONNECT_ON 0x02 -#define TMR_INT_ENABLED_POLL_CONNECT_OFF 0x04 -#define TMR_INT_ENABLED_POLL_DISCONNECT 0x08 -#define TMR_INT_ENABLED_CMD_EXEC 0x10 -#define TMR_INT_ENABLED_UPDATE 0x20 -#define TMR_INT_ENABLED_UDP_PKT 0x40 - -#define MAX_X25_ADDR_SIZE 16 -#define MAX_X25_DATA_SIZE 129 -#define MAX_X25_FACL_SIZE 110 - -#define TRY_CMD_AGAIN 2 -#define DELAY_RESULT 1 -#define RETURN_RESULT 0 - -#define DCD(x) (x & 0x03 ? "HIGH" : "LOW") -#define CTS(x) (x & 0x05 ? "HIGH" : "LOW") - - -/* Driver will not write log messages about - * modem status if defined.*/ -#define MODEM_NOT_LOG 1 - -/*==================================================== - * For 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))) - - -/*==================================================== - * MEMORY DEBUGGING FUNCTION - *==================================================== - -#define KMEM_SAFETYZONE 8 - -static void * dbg_kmalloc(unsigned int size, int prio, int line) { - int i = 0; - void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio); - char * c1 = v; - c1 += sizeof(unsigned int); - *((unsigned int *)v) = size; - - for (i = 0; i < KMEM_SAFETYZONE; i++) { - c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D'; - c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F'; - c1 += 8; - } - c1 += size; - for (i = 0; i < KMEM_SAFETYZONE; i++) { - c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G'; - c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L'; - c1 += 8; - } - v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8; - printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v); - return v; -} -static void dbg_kfree(void * v, int line) { - unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8)); - unsigned int size = *sp; - char * c1 = ((char *)v) - KMEM_SAFETYZONE*8; - int i = 0; - for (i = 0; i < KMEM_SAFETYZONE; i++) { - if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D' - || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') { - printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v); - printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, - c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); - } - c1 += 8; - } - c1 += size; - for (i = 0; i < KMEM_SAFETYZONE; i++) { - if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G' - || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L' - ) { - printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v); - printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, - c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); - } - c1 += 8; - } - printk(KERN_INFO "line %d kfree(%p)\n",line,v); - v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8); - kfree(v); -} - -#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__) -#define kfree(x) dbg_kfree(x,__LINE__) - -==============================================================*/ - - - -/*=============================================== - * Data Structures - *===============================================*/ - - -/*======================================================== - * Name: x25_channel - * - * Purpose: To hold private informaton for each - * logical channel. - * - * Rationale: Per-channel debugging is possible if each - * channel has its own private area. - * - * Assumptions: - * - * Description: This is an extention of the struct net_device - * we create for each network interface to keep - * the rest of X.25 channel-specific data. - * - * Construct: Typedef - */ -typedef struct x25_channel -{ - wanpipe_common_t common; /* common area for x25api and socket */ - char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */ - char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */ - unsigned tx_pkt_size; - unsigned short protocol; /* ethertype, 0 - multiplexed */ - char drop_sequence; /* mark sequence for dropping */ - unsigned long state_tick; /* time of the last state change */ - unsigned idle_timeout; /* sec, before disconnecting */ - unsigned long i_timeout_sofar; /* # of sec's we've been idle */ - unsigned hold_timeout; /* sec, before re-connecting */ - unsigned long tick_counter; /* counter for transmit time out */ - char devtint; /* Weather we should dev_tint() */ - struct sk_buff* rx_skb; /* receive socket buffer */ - struct sk_buff* tx_skb; /* transmit socket buffer */ - - bh_data_t *bh_head; /* Circular buffer for x25api_bh */ - unsigned long tq_working; - volatile int bh_write; - volatile int bh_read; - atomic_t bh_buff_used; - - sdla_t* card; /* -> owner */ - struct net_device *dev; /* -> bound devce */ - - int ch_idx; - unsigned char enable_IPX; - unsigned long network_number; - struct net_device_stats ifstats; /* interface statistics */ - unsigned short transmit_length; - unsigned short tx_offset; - char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)]; - - if_send_stat_t if_send_stat; - rx_intr_stat_t rx_intr_stat; - pipe_mgmt_stat_t pipe_mgmt_stat; - - unsigned long router_start_time; /* Router start time in seconds */ - unsigned long router_up_time; - -} x25_channel_t; - -/* FIXME Take this out */ - -#ifdef NEX_OLD_CALL_INFO -typedef struct x25_call_info -{ - char dest[17]; PACKED;/* ASCIIZ destination address */ - char src[17]; PACKED;/* ASCIIZ source address */ - char nuser; PACKED;/* number of user data bytes */ - unsigned char user[127]; PACKED;/* user data */ - char nfacil; PACKED;/* number of facilities */ - struct - { - unsigned char code; PACKED; - unsigned char parm; PACKED; - } facil[64]; /* facilities */ -} x25_call_info_t; -#else -typedef struct x25_call_info -{ - char dest[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ destination address */ - char src[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ source address */ - unsigned char nuser PACKED; - unsigned char user[MAX_X25_DATA_SIZE] PACKED;/* user data */ - unsigned char nfacil PACKED; - unsigned char facil[MAX_X25_FACL_SIZE] PACKED; - unsigned short lcn PACKED; -} x25_call_info_t; -#endif - - - -/*=============================================== - * Private Function Prototypes - *==============================================*/ - - -/*================================================= - * WAN link driver entry points. These are - * called by the WAN router module. - */ -static int update(struct wan_device* wandev); -static int new_if(struct wan_device* wandev, struct net_device* dev, - wanif_conf_t* conf); -static int del_if(struct wan_device* wandev, struct net_device* dev); -static void disable_comm (sdla_t* card); -static void disable_comm_shutdown(sdla_t *card); - - - -/*================================================= - * WANPIPE-specific entry points - */ -static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data); -static void x25api_bh(struct net_device *dev); -static int x25api_bh_cleanup(struct net_device *dev); -static int bh_enqueue(struct net_device *dev, struct sk_buff *skb); - - -/*================================================= - * Network device interface - */ -static int if_init(struct net_device* dev); -static int if_open(struct net_device* dev); -static int if_close(struct net_device* dev); -static int if_header(struct sk_buff* skb, struct net_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 net_device* dev); -static struct net_device_stats *if_stats(struct net_device* dev); - -static void if_tx_timeout(struct net_device *dev); - -/*================================================= - * Interrupt handlers - */ -static void wpx_isr (sdla_t *); -static void rx_intr (sdla_t *); -static void tx_intr (sdla_t *); -static void status_intr (sdla_t *); -static void event_intr (sdla_t *); -static void spur_intr (sdla_t *); -static void timer_intr (sdla_t *); - -static int tx_intr_send(sdla_t *card, struct net_device *dev); -static struct net_device *move_dev_to_next(sdla_t *card, - struct net_device *dev); - -/*================================================= - * Background polling routines - */ -static void wpx_poll (sdla_t* card); -static void poll_disconnected (sdla_t* card); -static void poll_connecting (sdla_t* card); -static void poll_active (sdla_t* card); -static void trigger_x25_poll(sdla_t *card); -static void x25_timer_routine(unsigned long data); - - - -/*================================================= - * X.25 firmware interface functions - */ -static int x25_get_version (sdla_t* card, char* str); -static int x25_configure (sdla_t* card, TX25Config* conf); -static int hdlc_configure (sdla_t* card, TX25Config* conf); -static int set_hdlc_level (sdla_t* card); -static int x25_get_err_stats (sdla_t* card); -static int x25_get_stats (sdla_t* card); -static int x25_set_intr_mode (sdla_t* card, int mode); -static int x25_close_hdlc (sdla_t* card); -static int x25_open_hdlc (sdla_t* card); -static int x25_setup_hdlc (sdla_t* card); -static int x25_set_dtr (sdla_t* card, int dtr); -static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan); -static int x25_place_call (sdla_t* card, x25_channel_t* chan); -static int x25_accept_call (sdla_t* card, int lcn, int qdm); -static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn); -static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf); -static int x25_fetch_events (sdla_t* card); -static int x25_error (sdla_t* card, int err, int cmd, int lcn); - -/*================================================= - * X.25 asynchronous event handlers - */ -static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); -static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); -static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); -static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); -static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); - - -/*================================================= - * Miscellaneous functions - */ -static int connect (sdla_t* card); -static int disconnect (sdla_t* card); -static struct net_device* get_dev_by_lcn(struct wan_device* wandev, - unsigned lcn); -static int chan_connect(struct net_device* dev); -static int chan_disc(struct net_device* dev); -static void set_chan_state(struct net_device* dev, int state); -static int chan_send(struct net_device *dev, void* buff, unsigned data_len, - unsigned char tx_intr); -static unsigned char bps_to_speed_code (unsigned long bps); -static unsigned int dec_to_uint (unsigned char* str, int len); -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; -} - - -/*=================================================================== - * 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 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; -} - -/*====================================================================== - * Build media header. - * o encapsulate packet according to encapsulation type. - * - * The trick here is to put packet type (Ethertype) into 'protocol' - * field of the socket buffer, so that we don't forget it. - * If encapsulation fails, set skb->protocol to 0 and discard - * packet later. - * - * Return: media header length. - *======================================================================*/ - -static int if_header(struct sk_buff* skb, struct net_device* dev, - unsigned short type, void* daddr, void* saddr, - unsigned len) -{ - x25_channel_t* chan = dev->priv; - int hdr_len = dev->hard_header_len; - - skb->protocol = htons(type); - if (!chan->protocol){ - hdr_len = wanrouter_encapsulate(skb, dev, type); - if (hdr_len < 0){ - hdr_len = 0; - skb->protocol = htons(0); - } - } - return hdr_len; -} - -/*=============================================================== - * Re-build media header. - * - * Return: 1 physical address resolved. - * 0 physical address not resolved - *==============================================================*/ - -static int if_rebuild_hdr (struct sk_buff* skb) -{ - struct net_device *dev = skb->dev; - x25_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - - printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", - card->devname, dev->name); - return 1; -} - - -/*============================================================================ - * Handle transmit timeout event from netif watchdog - */ -static void if_tx_timeout(struct net_device *dev) -{ - x25_channel_t* chan = dev->priv; - sdla_t *card = chan->card; - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - - ++chan->if_send_stat.if_send_tbusy_timeout; - printk (KERN_INFO "%s: Transmit timed out on %s\n", - card->devname, dev->name); - netif_wake_queue (dev); -} - - -/*========================================================================= - * Send a packet on a network interface. - * o set tbusy flag (marks start of the transmission). - * o check link state. If link is not up, then drop the packet. - * o check channel status. If it's down then initiate a call. - * o pass a packet to corresponding WAN device. - * o free socket buffer - * - * Return: 0 complete (socket buffer must be freed) - * non-0 packet may be re-transmitted (tbusy must be set) - * - * Notes: - * 1. This routine is called either by the protocol stack or by the "net - * bottom half" (with interrupts enabled). - * 2. Setting tbusy flag will inhibit further transmit requests from the - * protocol stack and can be used for flow control with protocol layer. - * - *========================================================================*/ - -static int if_send(struct sk_buff* skb, struct net_device* dev) -{ - x25_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - TX25Status* status = card->flags; - int udp_type; - unsigned long smp_flags=0; - - ++chan->if_send_stat.if_send_entry; - - netif_stop_queue(dev); - - /* No need to check frame length, since socket code - * will perform the check for us */ - - chan->tick_counter = jiffies; - - /* Critical region starts here */ - S508_S514_lock(card, &smp_flags); - - if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){ - printk(KERN_INFO "Hit critical in if_send()! %lx\n",card->wandev.critical); - goto if_send_crit_exit; - } - - udp_type = udp_pkt_type(skb, card); - - if(udp_type != UDP_INVALID_TYPE) { - - if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, dev, skb, - chan->common.lcn)) { - - status->imask |= INTR_ON_TIMER; - if (udp_type == UDP_XPIPE_TYPE){ - chan->if_send_stat.if_send_PIPE_request++; - } - } - netif_start_queue(dev); - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - S508_S514_unlock(card, &smp_flags); - return 0; - } - - if (chan->transmit_length){ - //FIXME: This check doesn't make sense any more - if (chan->common.state != WAN_CONNECTED){ - chan->transmit_length=0; - atomic_set(&chan->common.driver_busy,0); - }else{ - netif_stop_queue(dev); - ++card->u.x.tx_interrupts_pending; - status->imask |= INTR_ON_TX_FRAME; - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - S508_S514_unlock(card, &smp_flags); - return 1; - } - } - - if (card->wandev.state != WAN_CONNECTED){ - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - ++chan->if_send_stat.if_send_wan_disconnected; - - }else if ( chan->protocol && (chan->protocol != skb->protocol)){ - printk(KERN_INFO - "%s: unsupported Ethertype 0x%04X on interface %s!\n", - chan->name, htons(skb->protocol), dev->name); - - printk(KERN_INFO "PROTO %Xn", htons(chan->protocol)); - ++chan->ifstats.tx_errors; - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - ++chan->if_send_stat.if_send_protocol_error; - - }else switch (chan->common.state){ - - case WAN_DISCONNECTED: - /* Try to establish connection. If succeded, then start - * transmission, else drop a packet. - */ - if (chan->common.usedby == API){ - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - break; - }else{ - if (chan_connect(dev) != 0){ - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - break; - } - } - /* fall through */ - - case WAN_CONNECTED: - if( skb->protocol == htons(ETH_P_IPX)) { - if(chan->enable_IPX) { - switch_net_numbers( skb->data, - chan->network_number, 0); - } else { - ++card->wandev.stats.tx_dropped; - ++chan->ifstats.tx_dropped; - ++chan->if_send_stat.if_send_protocol_error; - goto if_send_crit_exit; - } - } - /* We never drop here, if cannot send than, copy - * a packet into a transmit buffer - */ - chan_send(dev, skb->data, skb->len, 0); - break; - - default: - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - break; - } - - -if_send_crit_exit: - - dev_kfree_skb_any(skb); - - netif_start_queue(dev); - clear_bit(SEND_CRIT,(void*)&card->wandev.critical); - S508_S514_unlock(card, &smp_flags); - return 0; -} - -/*============================================================================ - * Setup so that a frame can be transmitted on the occurrence of a transmit - * interrupt. - *===========================================================================*/ - -static void setup_for_delayed_transmit(struct net_device* dev, void* buf, - unsigned len) -{ - x25_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - TX25Status* status = card->flags; - - ++chan->if_send_stat.if_send_adptr_bfrs_full; - - if(chan->transmit_length) { - printk(KERN_INFO "%s: Error, transmit length set in delayed transmit!\n", - card->devname); - return; - } - - if (chan->common.usedby == API){ - if (len > X25_CHAN_MTU+sizeof(x25api_hdr_t)) { - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - printk(KERN_INFO "%s: Length is too big for delayed transmit\n", - card->devname); - return; - } - }else{ - if (len > X25_MAX_DATA) { - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - printk(KERN_INFO "%s: Length is too big for delayed transmit\n", - card->devname); - return; - } - } - - chan->transmit_length = len; - atomic_set(&chan->common.driver_busy,1); - memcpy(chan->transmit_buffer, buf, len); - - ++chan->if_send_stat.if_send_tx_int_enabled; - - /* Enable Transmit Interrupt */ - ++card->u.x.tx_interrupts_pending; - status->imask |= INTR_ON_TX_FRAME; -} - - -/*=============================================================== - * net_device_stats - * - * Get ethernet-style interface statistics. - * Return a pointer to struct enet_statistics. - * - *==============================================================*/ -static struct net_device_stats *if_stats(struct net_device* dev) -{ - x25_channel_t *chan = dev->priv; - - if(chan == NULL) - return NULL; - - return &chan->ifstats; -} - - -/* - * Interrupt Handlers - */ - -/* - * X.25 Interrupt Service Routine. - */ - -static void wpx_isr (sdla_t* card) -{ - TX25Status* status = card->flags; - - card->in_isr = 1; - ++card->statistics.isr_entry; - - if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){ - card->in_isr=0; - status->iflags = 0; - return; - } - - if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)){ - - printk(KERN_INFO "%s: wpx_isr: wandev.critical set to 0x%02lx, int type = 0x%02x\n", - card->devname, card->wandev.critical, status->iflags); - card->in_isr = 0; - status->iflags = 0; - return; - } - - /* For all interrupts set the critical flag to CRITICAL_RX_INTR. - * If the if_send routine is called with this flag set it will set - * the enable transmit flag to 1. (for a delayed interrupt) - */ - switch (status->iflags){ - - case RX_INTR_PENDING: /* receive interrupt */ - rx_intr(card); - break; - - case TX_INTR_PENDING: /* transmit interrupt */ - tx_intr(card); - break; - - case MODEM_INTR_PENDING: /* modem status interrupt */ - status_intr(card); - break; - - case X25_ASY_TRANS_INTR_PENDING: /* network event interrupt */ - event_intr(card); - break; - - case TIMER_INTR_PENDING: - timer_intr(card); - break; - - default: /* unwanted interrupt */ - spur_intr(card); - } - - card->in_isr = 0; - status->iflags = 0; /* clear interrupt condition */ -} - -/* - * Receive interrupt handler. - * This routine handles fragmented IP packets using M-bit according to the - * RFC1356. - * o map ligical channel number to network interface. - * o allocate socket buffer or append received packet to the existing one. - * o if M-bit is reset (i.e. it's the last packet in a sequence) then - * decapsulate packet and pass socket buffer to the protocol stack. - * - * Notes: - * 1. When allocating a socket buffer, if M-bit is set then more data is - * coming and we have to allocate buffer for the maximum IP packet size - * expected on this channel. - * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no - * socket buffers available) the whole packet sequence must be discarded. - */ - -static void rx_intr (sdla_t* card) -{ - TX25Mbox* rxmb = card->rxmb; - unsigned lcn = rxmb->cmd.lcn; - struct net_device* dev = find_channel(card,lcn); - x25_channel_t* chan; - struct sk_buff* skb=NULL; - - if (dev == NULL){ - /* Invalid channel, discard packet */ - printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n", - card->devname, lcn); - return; - } - - chan = dev->priv; - chan->i_timeout_sofar = jiffies; - - - /* Copy the data from the board, into an - * skb buffer - */ - if (wanpipe_pull_data_in_skb(card,dev,&skb)){ - ++chan->ifstats.rx_dropped; - ++card->wandev.stats.rx_dropped; - ++chan->rx_intr_stat.rx_intr_no_socket; - ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; - return; - } - - dev->last_rx = jiffies; /* timestamp */ - - - /* ------------ API ----------------*/ - - if (chan->common.usedby == API){ - - if (bh_enqueue(dev, skb)){ - ++chan->ifstats.rx_dropped; - ++card->wandev.stats.rx_dropped; - ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; - dev_kfree_skb_any(skb); - return; - } - - ++chan->ifstats.rx_packets; - chan->ifstats.rx_bytes += skb->len; - - - chan->rx_skb = NULL; - if (!test_and_set_bit(0, &chan->tq_working)){ - wanpipe_queue_work(&chan->common.wanpipe_work); - } - return; - } - - - /* ------------- WANPIPE -------------------*/ - - /* set rx_skb to NULL so we won't access it later when kernel already owns it */ - chan->rx_skb=NULL; - - /* Decapsulate packet, if necessary */ - if (!skb->protocol && !wanrouter_type_trans(skb, dev)){ - /* can't decapsulate packet */ - dev_kfree_skb_any(skb); - ++chan->ifstats.rx_errors; - ++chan->ifstats.rx_dropped; - ++card->wandev.stats.rx_dropped; - ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; - - }else{ - if( handle_IPXWAN(skb->data, chan->name, - chan->enable_IPX, chan->network_number, - skb->protocol)){ - - if( chan->enable_IPX ){ - if(chan_send(dev, skb->data, skb->len,0)){ - chan->tx_skb = skb; - }else{ - dev_kfree_skb_any(skb); - ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; - } - }else{ - /* increment IPX packet dropped statistic */ - ++chan->ifstats.rx_dropped; - ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; - } - }else{ - skb->mac.raw = skb->data; - chan->ifstats.rx_bytes += skb->len; - ++chan->ifstats.rx_packets; - ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack; - netif_rx(skb); - } - } - - return; -} - - -static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev, - struct sk_buff **skb) -{ - void *bufptr; - TX25Mbox* rxmb = card->rxmb; - unsigned len = rxmb->cmd.length; /* packet length */ - unsigned qdm = rxmb->cmd.qdm; /* Q,D and M bits */ - x25_channel_t *chan = dev->priv; - struct sk_buff *new_skb = *skb; - - if (chan->common.usedby == WANPIPE){ - if (chan->drop_sequence){ - if (!(qdm & 0x01)){ - chan->drop_sequence = 0; - } - return 1; - } - new_skb = chan->rx_skb; - }else{ - /* Add on the API header to the received - * data - */ - len += sizeof(x25api_hdr_t); - } - - if (new_skb == NULL){ - int bufsize; - - if (chan->common.usedby == WANPIPE){ - bufsize = (qdm & 0x01) ? dev->mtu : len; - }else{ - bufsize = len; - } - - /* Allocate new socket buffer */ - new_skb = dev_alloc_skb(bufsize + dev->hard_header_len); - if (new_skb == NULL){ - printk(KERN_INFO "%s: no socket buffers available!\n", - card->devname); - chan->drop_sequence = 1; /* set flag */ - ++chan->ifstats.rx_dropped; - return 1; - } - } - - if (skb_tailroom(new_skb) < len){ - /* No room for the packet. Call off the whole thing! */ - dev_kfree_skb_any(new_skb); - if (chan->common.usedby == WANPIPE){ - chan->rx_skb = NULL; - if (qdm & 0x01){ - chan->drop_sequence = 1; - } - } - - printk(KERN_INFO "%s: unexpectedly long packet sequence " - "on interface %s!\n", card->devname, dev->name); - ++chan->ifstats.rx_length_errors; - return 1; - } - - bufptr = skb_put(new_skb,len); - - - if (chan->common.usedby == API){ - /* Fill in the x25api header - */ - x25api_t * api_data = (x25api_t*)bufptr; - api_data->hdr.qdm = rxmb->cmd.qdm; - api_data->hdr.cause = rxmb->cmd.cause; - api_data->hdr.diagn = rxmb->cmd.diagn; - api_data->hdr.length = rxmb->cmd.length; - memcpy(api_data->data, rxmb->data, rxmb->cmd.length); - }else{ - memcpy(bufptr, rxmb->data, len); - } - - new_skb->dev = dev; - - if (chan->common.usedby == API){ - new_skb->mac.raw = new_skb->data; - new_skb->protocol = htons(X25_PROT); - new_skb->pkt_type = WAN_PACKET_DATA; - }else{ - new_skb->protocol = chan->protocol; - chan->rx_skb = new_skb; - } - - /* If qdm bit is set, more data is coming - * thus, exit and wait for more data before - * sending the packet up. (Used by router only) - */ - if ((qdm & 0x01) && (chan->common.usedby == WANPIPE)) - return 1; - - *skb = new_skb; - - return 0; -} - -/*=============================================================== - * tx_intr - * - * Transmit interrupt handler. - * For each dev, check that there is something to send. - * If data available, transmit. - * - *===============================================================*/ - -static void tx_intr (sdla_t* card) -{ - struct net_device *dev; - TX25Status* status = card->flags; - unsigned char more_to_tx=0; - x25_channel_t *chan=NULL; - int i=0; - - if (card->u.x.tx_dev == NULL){ - card->u.x.tx_dev = card->wandev.dev; - } - - dev = card->u.x.tx_dev; - - for (;;){ - - chan = dev->priv; - if (chan->transmit_length){ - /* Device was set to transmit, check if the TX - * buffers are available - */ - if (chan->common.state != WAN_CONNECTED){ - chan->transmit_length = 0; - atomic_set(&chan->common.driver_busy,0); - chan->tx_offset=0; - if (netif_queue_stopped(dev)){ - if (chan->common.usedby == API){ - netif_start_queue(dev); - wakeup_sk_bh(dev); - }else{ - netif_wake_queue(dev); - } - } - dev = move_dev_to_next(card,dev); - break; - } - - if ((status->cflags[chan->ch_idx] & 0x40 || card->u.x.LAPB_hdlc) && - (*card->u.x.hdlc_buf_status & 0x40) ){ - /* Tx buffer available, we can send */ - - if (tx_intr_send(card, dev)){ - more_to_tx=1; - } - - /* If more than one interface present, move the - * device pointer to the next interface, so on the - * next TX interrupt we will try sending from it. - */ - dev = move_dev_to_next(card,dev); - break; - }else{ - /* Tx buffers not available, but device set - * the TX interrupt. Set more_to_tx and try - * to transmit for other devices. - */ - more_to_tx=1; - dev = move_dev_to_next(card,dev); - } - - }else{ - /* This device was not set to transmit, - * go to next - */ - dev = move_dev_to_next(card,dev); - } - - if (++i == card->u.x.no_dev){ - if (!more_to_tx){ - DBG_PRINTK(KERN_INFO "%s: Nothing to Send in TX INTR\n", - card->devname); - } - break; - } - - } //End of FOR - - card->u.x.tx_dev = dev; - - if (!more_to_tx){ - /* if any other interfaces have transmit interrupts pending, */ - /* do not disable the global transmit interrupt */ - if (!(--card->u.x.tx_interrupts_pending)){ - status->imask &= ~INTR_ON_TX_FRAME; - } - } - return; -} - -/*=============================================================== - * move_dev_to_next - * - * - *===============================================================*/ - - -struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev) -{ - if (card->u.x.no_dev != 1){ - if (!*((struct net_device **)dev->priv)) - return card->wandev.dev; - else - return *((struct net_device **)dev->priv); - } - return dev; -} - -/*=============================================================== - * tx_intr_send - * - * - *===============================================================*/ - -static int tx_intr_send(sdla_t *card, struct net_device *dev) -{ - x25_channel_t* chan = dev->priv; - - if (chan_send (dev,chan->transmit_buffer,chan->transmit_length,1)){ - - /* Packet was split up due to its size, do not disable - * tx_intr - */ - return 1; - } - - chan->transmit_length=0; - atomic_set(&chan->common.driver_busy,0); - chan->tx_offset=0; - - /* If we are in API mode, wakeup the - * sock BH handler, not the NET_BH */ - if (netif_queue_stopped(dev)){ - if (chan->common.usedby == API){ - netif_start_queue(dev); - wakeup_sk_bh(dev); - }else{ - netif_wake_queue(dev); - } - } - return 0; -} - - -/*=============================================================== - * timer_intr - * - * Timer interrupt handler. - * Check who called the timer interrupt and perform - * action accordingly. - * - *===============================================================*/ - -static void timer_intr (sdla_t *card) -{ - TX25Status* status = card->flags; - - if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC){ - - if (timer_intr_cmd_exec(card) == 0){ - card->u.x.timer_int_enabled &= - ~TMR_INT_ENABLED_CMD_EXEC; - } - - }else if(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UDP_PKT) { - - if ((*card->u.x.hdlc_buf_status & 0x40) && - card->u.x.udp_type == UDP_XPIPE_TYPE){ - - if(process_udp_mgmt_pkt(card)) { - card->u.x.timer_int_enabled &= - ~TMR_INT_ENABLED_UDP_PKT; - } - } - - }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_ACTIVE) { - - struct net_device *dev = card->u.x.poll_device; - x25_channel_t *chan = NULL; - - if (!dev){ - card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE; - return; - } - chan = dev->priv; - - printk(KERN_INFO - "%s: Closing down Idle link %s on LCN %d\n", - card->devname,chan->name,chan->common.lcn); - chan->i_timeout_sofar = jiffies; - chan_disc(dev); - card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE; - card->u.x.poll_device=NULL; - - }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_ON) { - - wanpipe_set_state(card, WAN_CONNECTED); - if (card->u.x.LAPB_hdlc){ - struct net_device *dev = card->wandev.dev; - set_chan_state(dev,WAN_CONNECTED); - send_delayed_cmd_result(card,dev,card->mbox); - } - - /* 0x8F enable all interrupts */ - x25_set_intr_mode(card, INTR_ON_RX_FRAME| - INTR_ON_TX_FRAME| - INTR_ON_MODEM_STATUS_CHANGE| - //INTR_ON_COMMAND_COMPLETE| - X25_ASY_TRANS_INTR_PENDING | - INTR_ON_TIMER | - DIRECT_RX_INTR_USAGE - ); - - status->imask &= ~INTR_ON_TX_FRAME; /* mask Tx interrupts */ - card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_ON; - - }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_OFF) { - - //printk(KERN_INFO "Poll connect, Turning OFF\n"); - disconnect(card); - card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_OFF; - - }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_DISCONNECT) { - - //printk(KERN_INFO "POll disconnect, trying to connect\n"); - connect(card); - card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_DISCONNECT; - - }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE){ - - if (*card->u.x.hdlc_buf_status & 0x40){ - x25_get_err_stats(card); - x25_get_stats(card); - card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; - } - } - - if(!card->u.x.timer_int_enabled){ - //printk(KERN_INFO "Turning Timer Off \n"); - status->imask &= ~INTR_ON_TIMER; - } -} - -/*==================================================================== - * Modem status interrupt handler. - *===================================================================*/ -static void status_intr (sdla_t* card) -{ - - /* Added to avoid Modem status message flooding */ - static TX25ModemStatus last_stat; - - TX25Mbox* mbox = card->mbox; - TX25ModemStatus *modem_status; - struct net_device *dev; - x25_channel_t *chan; - int err; - - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = X25_READ_MODEM_STATUS; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - if (err){ - x25_error(card, err, X25_READ_MODEM_STATUS, 0); - }else{ - - modem_status = (TX25ModemStatus*)mbox->data; - - /* Check if the last status was the same - * if it was, do NOT print message again */ - - if (last_stat.status != modem_status->status){ - - printk(KERN_INFO "%s: Modem Status Change: DCD=%s, CTS=%s\n", - card->devname,DCD(modem_status->status),CTS(modem_status->status)); - - last_stat.status = modem_status->status; - - if (card->u.x.oob_on_modem){ - - mbox->cmd.pktType = mbox->cmd.command; - mbox->cmd.result = 0x08; - - /* Send a OOB to all connected sockets */ - for (dev = card->wandev.dev; dev; - dev = *((struct net_device**)dev->priv)) { - chan=dev->priv; - if (chan->common.usedby == API){ - send_oob_msg(card,dev,mbox); - } - } - - /* The modem OOB message will probably kill the - * the link. If we don't clear the flag here, - * a deadlock could occur */ - if (atomic_read(&card->u.x.command_busy)){ - atomic_set(&card->u.x.command_busy,0); - } - } - } - } - - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = X25_HDLC_LINK_STATUS; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - if (err){ - x25_error(card, err, X25_HDLC_LINK_STATUS, 0); - } - -} - -/*==================================================================== - * Network event interrupt handler. - *===================================================================*/ -static void event_intr (sdla_t* card) -{ - x25_fetch_events(card); -} - -/*==================================================================== - * Spurious interrupt handler. - * o print a warning - * o - *====================================================================*/ - -static void spur_intr (sdla_t* card) -{ - printk(KERN_INFO "%s: spurious interrupt!\n", card->devname); -} - - -/* - * Background Polling Routines - */ - -/*==================================================================== - * Main polling routine. - * This routine is repeatedly called by the WANPIPE 'thread' to allow for - * time-dependent housekeeping work. - * - * Notes: - * 1. This routine may be called on interrupt context with all interrupts - * enabled. Beware! - *====================================================================*/ - -static void wpx_poll (sdla_t *card) -{ - if (!card->wandev.dev){ - goto wpx_poll_exit; - } - - if (card->open_cnt != card->u.x.num_of_ch){ - goto wpx_poll_exit; - } - - if (test_bit(PERI_CRIT,&card->wandev.critical)){ - goto wpx_poll_exit; - } - - if (test_bit(SEND_CRIT,&card->wandev.critical)){ - goto wpx_poll_exit; - } - - switch(card->wandev.state){ - case WAN_CONNECTED: - poll_active(card); - break; - - case WAN_CONNECTING: - poll_connecting(card); - break; - - case WAN_DISCONNECTED: - poll_disconnected(card); - break; - } - -wpx_poll_exit: - clear_bit(POLL_CRIT,&card->wandev.critical); - return; -} - -static void trigger_x25_poll(sdla_t *card) -{ - schedule_work(&card->u.x.x25_poll_work); -} - -/*==================================================================== - * Handle physical link establishment phase. - * o if connection timed out, disconnect the link. - *===================================================================*/ - -static void poll_connecting (sdla_t* card) -{ - volatile TX25Status* status = card->flags; - - if (status->gflags & X25_HDLC_ABM){ - - timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_ON); - - }else if ((jiffies - card->state_tick) > CONNECT_TIMEOUT){ - - timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_OFF); - - } -} - -/*==================================================================== - * Handle physical link disconnected phase. - * o if hold-down timeout has expired and there are open interfaces, - * connect link. - *===================================================================*/ - -static void poll_disconnected (sdla_t* card) -{ - struct net_device *dev; - x25_channel_t *chan; - TX25Status* status = card->flags; - - if (!card->u.x.LAPB_hdlc && card->open_cnt && - ((jiffies - card->state_tick) > HOLD_DOWN_TIME)){ - timer_intr_exec(card, TMR_INT_ENABLED_POLL_DISCONNECT); - } - - - if ((dev=card->wandev.dev) == NULL) - return; - - if ((chan=dev->priv) == NULL) - return; - - if (chan->common.usedby == API && - atomic_read(&chan->common.command) && - card->u.x.LAPB_hdlc){ - - if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC)) - card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC; - - if (!(status->imask & INTR_ON_TIMER)) - status->imask |= INTR_ON_TIMER; - } - -} - -/*==================================================================== - * Handle active link phase. - * o fetch X.25 asynchronous events. - * o kick off transmission on all interfaces. - *===================================================================*/ - -static void poll_active (sdla_t* card) -{ - struct net_device* dev; - TX25Status* status = card->flags; - - for (dev = card->wandev.dev; dev; - dev = *((struct net_device **)dev->priv)){ - x25_channel_t* chan = dev->priv; - - /* If SVC has been idle long enough, close virtual circuit */ - if ( chan->common.svc && - chan->common.state == WAN_CONNECTED && - chan->common.usedby == WANPIPE ){ - - if( (jiffies - chan->i_timeout_sofar) / HZ > chan->idle_timeout ){ - /* Close svc */ - card->u.x.poll_device=dev; - timer_intr_exec (card, TMR_INT_ENABLED_POLL_ACTIVE); - } - } - -#ifdef PRINT_DEBUG - chan->ifstats.tx_compressed = atomic_read(&chan->common.command); - chan->ifstats.tx_errors = chan->common.state; - chan->ifstats.rx_fifo_errors = atomic_read(&card->u.x.command_busy); - ++chan->ifstats.tx_bytes; - - chan->ifstats.rx_fifo_errors=atomic_read(&chan->common.disconnect); - chan->ifstats.multicast=atomic_read(&chan->bh_buff_used); - chan->ifstats.rx_length_errors=*card->u.x.hdlc_buf_status; -#endif - - if (chan->common.usedby == API && - atomic_read(&chan->common.command) && - !card->u.x.LAPB_hdlc){ - - if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC)) - card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC; - - if (!(status->imask & INTR_ON_TIMER)) - status->imask |= INTR_ON_TIMER; - } - - if ((chan->common.usedby == API) && - atomic_read(&chan->common.disconnect)){ - - if (chan->common.state == WAN_DISCONNECTED){ - atomic_set(&chan->common.disconnect,0); - return; - } - - atomic_set(&chan->common.command,X25_CLEAR_CALL); - if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC)) - card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC; - - if (!(status->imask & INTR_ON_TIMER)) - status->imask |= INTR_ON_TIMER; - } - } -} - -static void timer_intr_exec(sdla_t *card, unsigned char TYPE) -{ - TX25Status* status = card->flags; - card->u.x.timer_int_enabled |= TYPE; - if (!(status->imask & INTR_ON_TIMER)) - status->imask |= INTR_ON_TIMER; -} - - -/*==================================================================== - * SDLA Firmware-Specific Functions - * - * Almost all X.25 commands can unexpetedly fail due to so called 'X.25 - * asynchronous events' such as restart, interrupt, incoming call request, - * call clear request, etc. They can't be ignored and have to be delt with - * immediately. To tackle with this problem we execute each interface - * command in a loop until good return code is received or maximum number - * of retries is reached. Each interface command returns non-zero return - * code, an asynchronous event/error handler x25_error() is called. - *====================================================================*/ - -/*==================================================================== - * Read X.25 firmware version. - * Put code version as ASCII string in str. - *===================================================================*/ - -static int x25_get_version (sdla_t* card, char* str) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = X25_READ_CODE_VERSION; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && - x25_error(card, err, X25_READ_CODE_VERSION, 0)); - - if (!err && str) - { - int len = mbox->cmd.length; - - memcpy(str, mbox->data, len); - str[len] = '\0'; - } - return err; -} - -/*==================================================================== - * Configure adapter. - *===================================================================*/ - -static int x25_configure (sdla_t* card, TX25Config* conf) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do{ - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - memcpy(mbox->data, (void*)conf, sizeof(TX25Config)); - mbox->cmd.length = sizeof(TX25Config); - mbox->cmd.command = X25_SET_CONFIGURATION; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0)); - return err; -} - -/*==================================================================== - * Configure adapter for HDLC only. - *===================================================================*/ - -static int hdlc_configure (sdla_t* card, TX25Config* conf) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do{ - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - memcpy(mbox->data, (void*)conf, sizeof(TX25Config)); - mbox->cmd.length = sizeof(TX25Config); - mbox->cmd.command = X25_HDLC_SET_CONFIG; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0)); - - return err; -} - -static int set_hdlc_level (sdla_t* card) -{ - - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do{ - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = SET_PROTOCOL_LEVEL; - mbox->cmd.length = 1; - mbox->data[0] = HDLC_LEVEL; //| DO_HDLC_LEVEL_ERROR_CHECKING; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, SET_PROTOCOL_LEVEL, 0)); - - return err; -} - - - -/*==================================================================== - * Get communications error statistics. - *====================================================================*/ - -static int x25_get_err_stats (sdla_t* card) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = X25_HDLC_READ_COMM_ERR; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_HDLC_READ_COMM_ERR, 0)); - - if (!err) - { - THdlcCommErr* stats = (void*)mbox->data; - - card->wandev.stats.rx_over_errors = stats->rxOverrun; - card->wandev.stats.rx_crc_errors = stats->rxBadCrc; - card->wandev.stats.rx_missed_errors = stats->rxAborted; - card->wandev.stats.tx_aborted_errors = stats->txAborted; - } - return err; -} - -/*==================================================================== - * Get protocol statistics. - *===================================================================*/ - -static int x25_get_stats (sdla_t* card) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = X25_READ_STATISTICS; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_READ_STATISTICS, 0)) ; - - if (!err) - { - TX25Stats* stats = (void*)mbox->data; - - card->wandev.stats.rx_packets = stats->rxData; - card->wandev.stats.tx_packets = stats->txData; - } - return err; -} - -/*==================================================================== - * Close HDLC link. - *===================================================================*/ - -static int x25_close_hdlc (sdla_t* card) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = X25_HDLC_LINK_CLOSE; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_CLOSE, 0)); - - return err; -} - - -/*==================================================================== - * Open HDLC link. - *===================================================================*/ - -static int x25_open_hdlc (sdla_t* card) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = X25_HDLC_LINK_OPEN; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_OPEN, 0)); - - return err; -} - -/*===================================================================== - * Setup HDLC link. - *====================================================================*/ -static int x25_setup_hdlc (sdla_t* card) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = X25_HDLC_LINK_SETUP; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_SETUP, 0)); - - return err; -} - -/*==================================================================== - * Set (raise/drop) DTR. - *===================================================================*/ - -static int x25_set_dtr (sdla_t* card, int dtr) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->data[0] = 0; - mbox->data[2] = 0; - mbox->data[1] = dtr ? 0x02 : 0x01; - mbox->cmd.length = 3; - mbox->cmd.command = X25_SET_GLOBAL_VARS; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_SET_GLOBAL_VARS, 0)); - - return err; -} - -/*==================================================================== - * Set interrupt mode. - *===================================================================*/ - -static int x25_set_intr_mode (sdla_t* card, int mode) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->data[0] = mode; - if (card->hw.fwid == SFID_X25_508){ - mbox->data[1] = card->hw.irq; - mbox->data[2] = 2; - mbox->cmd.length = 3; - }else { - mbox->cmd.length = 1; - } - mbox->cmd.command = X25_SET_INTERRUPT_MODE; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_SET_INTERRUPT_MODE, 0)); - - return err; -} - -/*==================================================================== - * Read X.25 channel configuration. - *===================================================================*/ - -static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int lcn = chan->common.lcn; - int err; - - do{ - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.lcn = lcn; - mbox->cmd.command = X25_READ_CHANNEL_CONFIG; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_READ_CHANNEL_CONFIG, lcn)); - - if (!err) - { - TX25Status* status = card->flags; - - /* calculate an offset into the array of status bytes */ - if (card->u.x.hi_svc <= X25_MAX_CHAN){ - - chan->ch_idx = lcn - 1; - - }else{ - int offset; - - /* FIX: Apr 14 2000 : Nenad Corbic - * The data field was being compared to 0x1F using - * '&&' instead of '&'. - * This caused X25API to fail for LCNs greater than 255. - */ - switch (mbox->data[0] & 0x1F) - { - case 0x01: - offset = status->pvc_map; break; - case 0x03: - offset = status->icc_map; break; - case 0x07: - offset = status->twc_map; break; - case 0x0B: - offset = status->ogc_map; break; - default: - offset = 0; - } - chan->ch_idx = lcn - 1 - offset; - } - - /* get actual transmit packet size on this channel */ - switch(mbox->data[1] & 0x38) - { - case 0x00: - chan->tx_pkt_size = 16; - break; - case 0x08: - chan->tx_pkt_size = 32; - break; - case 0x10: - chan->tx_pkt_size = 64; - break; - case 0x18: - chan->tx_pkt_size = 128; - break; - case 0x20: - chan->tx_pkt_size = 256; - break; - case 0x28: - chan->tx_pkt_size = 512; - break; - case 0x30: - chan->tx_pkt_size = 1024; - break; - } - if (card->u.x.logging) - printk(KERN_INFO "%s: X.25 packet size on LCN %d is %d.\n", - card->devname, lcn, chan->tx_pkt_size); - } - return err; -} - -/*==================================================================== - * Place X.25 call. - *====================================================================*/ - -static int x25_place_call (sdla_t* card, x25_channel_t* chan) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - char str[64]; - - - if (chan->protocol == htons(ETH_P_IP)){ - sprintf(str, "-d%s -uCC", chan->addr); - - }else if (chan->protocol == htons(ETH_P_IPX)){ - sprintf(str, "-d%s -u800000008137", chan->addr); - - } - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - strcpy(mbox->data, str); - mbox->cmd.length = strlen(str); - mbox->cmd.command = X25_PLACE_CALL; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_PLACE_CALL, 0)); - - if (!err){ - bind_lcn_to_dev (card, chan->dev, mbox->cmd.lcn); - } - return err; -} - -/*==================================================================== - * Accept X.25 call. - *====================================================================*/ - -static int x25_accept_call (sdla_t* card, int lcn, int qdm) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.lcn = lcn; - mbox->cmd.qdm = qdm; - mbox->cmd.command = X25_ACCEPT_CALL; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_ACCEPT_CALL, lcn)); - - return err; -} - -/*==================================================================== - * Clear X.25 call. - *====================================================================*/ - -static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.lcn = lcn; - mbox->cmd.cause = cause; - mbox->cmd.diagn = diagn; - mbox->cmd.command = X25_CLEAR_CALL; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, X25_CLEAR_CALL, lcn)); - - return err; -} - -/*==================================================================== - * Send X.25 data packet. - *====================================================================*/ - -static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf) -{ - TX25Mbox* mbox = card->mbox; - int retry = MAX_CMD_RETRY; - int err; - unsigned char cmd; - - if (card->u.x.LAPB_hdlc) - cmd = X25_HDLC_WRITE; - else - cmd = X25_WRITE; - - do - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - memcpy(mbox->data, buf, len); - mbox->cmd.length = len; - mbox->cmd.lcn = lcn; - - if (card->u.x.LAPB_hdlc){ - mbox->cmd.pf = qdm; - }else{ - mbox->cmd.qdm = qdm; - } - - mbox->cmd.command = cmd; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && retry-- && x25_error(card, err, cmd , lcn)); - - - /* If buffers are busy the return code for LAPB HDLC is - * 1. The above functions are looking for return code - * of X25RES_NOT_READY if busy. */ - - if (card->u.x.LAPB_hdlc && err == 1){ - err = X25RES_NOT_READY; - } - - return err; -} - -/*==================================================================== - * Fetch X.25 asynchronous events. - *===================================================================*/ - -static int x25_fetch_events (sdla_t* card) -{ - TX25Status* status = card->flags; - TX25Mbox* mbox = card->mbox; - int err = 0; - - if (status->gflags & 0x20) - { - memset(&mbox->cmd, 0, sizeof(TX25Cmd)); - mbox->cmd.command = X25_IS_DATA_AVAILABLE; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - if (err) x25_error(card, err, X25_IS_DATA_AVAILABLE, 0); - } - return err; -} - -/*==================================================================== - * X.25 asynchronous event/error handler. - * This routine is called each time interface command returns - * non-zero return code to handle X.25 asynchronous events and - * common errors. Return non-zero to repeat command or zero to - * cancel it. - * - * Notes: - * 1. This function may be called recursively, as handling some of the - * asynchronous events (e.g. call request) requires execution of the - * interface command(s) that, in turn, may also return asynchronous - * events. To avoid re-entrancy problems we copy mailbox to dynamically - * allocated memory before processing events. - *====================================================================*/ - -static int x25_error (sdla_t* card, int err, int cmd, int lcn) -{ - int retry = 1; - unsigned dlen = ((TX25Mbox*)card->mbox)->cmd.length; - TX25Mbox* mb; - - mb = kmalloc(sizeof(TX25Mbox) + dlen, GFP_ATOMIC); - if (mb == NULL) - { - printk(KERN_ERR "%s: x25_error() out of memory!\n", - card->devname); - return 0; - } - memcpy(mb, card->mbox, sizeof(TX25Mbox) + dlen); - switch (err){ - - case X25RES_ASYNC_PACKET: /* X.25 asynchronous packet was received */ - - mb->data[dlen] = '\0'; - - switch (mb->cmd.pktType & 0x7F){ - - case ASE_CALL_RQST: /* incoming call */ - retry = incoming_call(card, cmd, lcn, mb); - break; - - case ASE_CALL_ACCEPTED: /* connected */ - retry = call_accepted(card, cmd, lcn, mb); - break; - - case ASE_CLEAR_RQST: /* call clear request */ - retry = call_cleared(card, cmd, lcn, mb); - break; - - case ASE_RESET_RQST: /* reset request */ - printk(KERN_INFO "%s: X.25 reset request on LCN %d! " - "Cause:0x%02X Diagn:0x%02X\n", - card->devname, mb->cmd.lcn, mb->cmd.cause, - mb->cmd.diagn); - api_oob_event (card,mb); - break; - - case ASE_RESTART_RQST: /* restart request */ - retry = restart_event(card, cmd, lcn, mb); - break; - - case ASE_CLEAR_CONFRM: - if (clear_confirm_event (card,mb)) - break; - - /* I use the goto statement here so if - * somebody inserts code between the - * case and default, we will not have - * ghost problems */ - - goto dflt_1; - - default: -dflt_1: - printk(KERN_INFO "%s: X.25 event 0x%02X on LCN %d! " - "Cause:0x%02X Diagn:0x%02X\n", - card->devname, mb->cmd.pktType, - mb->cmd.lcn, mb->cmd.cause, mb->cmd.diagn); - } - break; - - case X25RES_PROTO_VIOLATION: /* X.25 protocol violation indication */ - - /* Bug Fix: Mar 14 2000 - * The Protocol violation error conditions were - * not handled previously */ - - switch (mb->cmd.pktType & 0x7F){ - - case PVE_CLEAR_RQST: /* Clear request */ - retry = call_cleared(card, cmd, lcn, mb); - break; - - case PVE_RESET_RQST: /* Reset request */ - printk(KERN_INFO "%s: X.25 reset request on LCN %d! " - "Cause:0x%02X Diagn:0x%02X\n", - card->devname, mb->cmd.lcn, mb->cmd.cause, - mb->cmd.diagn); - api_oob_event (card,mb); - break; - - case PVE_RESTART_RQST: /* Restart request */ - retry = restart_event(card, cmd, lcn, mb); - break; - - default : - printk(KERN_INFO - "%s: X.25 protocol violation on LCN %d! " - "Packet:0x%02X Cause:0x%02X Diagn:0x%02X\n", - card->devname, mb->cmd.lcn, - mb->cmd.pktType & 0x7F, mb->cmd.cause, mb->cmd.diagn); - api_oob_event(card,mb); - } - break; - - case 0x42: /* X.25 timeout */ - retry = timeout_event(card, cmd, lcn, mb); - break; - - case 0x43: /* X.25 retry limit exceeded */ - printk(KERN_INFO - "%s: exceeded X.25 retry limit on LCN %d! " - "Packet:0x%02X Diagn:0x%02X\n", card->devname, - mb->cmd.lcn, mb->cmd.pktType, mb->cmd.diagn) - ; - break; - - case 0x08: /* modem failure */ -#ifndef MODEM_NOT_LOG - printk(KERN_INFO "%s: modem failure!\n", card->devname); -#endif /* MODEM_NOT_LOG */ - api_oob_event(card,mb); - break; - - case 0x09: /* N2 retry limit */ - printk(KERN_INFO "%s: exceeded HDLC retry limit!\n", - card->devname); - api_oob_event(card,mb); - break; - - case 0x06: /* unnumbered frame was received while in ABM */ - printk(KERN_INFO "%s: received Unnumbered frame 0x%02X!\n", - card->devname, mb->data[0]); - api_oob_event(card,mb); - break; - - case CMD_TIMEOUT: - printk(KERN_ERR "%s: command 0x%02X timed out!\n", - card->devname, cmd) - ; - retry = 0; /* abort command */ - break; - - case X25RES_NOT_READY: - retry = 1; - break; - - case 0x01: - if (card->u.x.LAPB_hdlc) - break; - - if (mb->cmd.command == 0x16) - break; - /* I use the goto statement here so if - * somebody inserts code between the - * case and default, we will not have - * ghost problems */ - goto dflt_2; - - default: -dflt_2: - printk(KERN_INFO "%s: command 0x%02X returned 0x%02X! Lcn %i\n", - card->devname, cmd, err, mb->cmd.lcn) - ; - retry = 0; /* abort command */ - } - kfree(mb); - return retry; -} - -/*==================================================================== - * X.25 Asynchronous Event Handlers - * These functions are called by the x25_error() and should return 0, if - * the command resulting in the asynchronous event must be aborted. - *====================================================================*/ - - - -/*==================================================================== - *Handle X.25 incoming call request. - * RFC 1356 establishes the following rules: - * 1. The first octet in the Call User Data (CUD) field of the call - * request packet contains NLPID identifying protocol encapsulation - * 2. Calls MUST NOT be accepted unless router supports requested - * protocol encapsulation. - * 3. A diagnostic code 249 defined by ISO/IEC 8208 may be used - * when clearing a call because protocol encapsulation is not - * supported. - * 4. If an incoming call is received while a call request is - * pending (i.e. call collision has occurred), the incoming call - * shall be rejected and call request shall be retried. - *====================================================================*/ - -static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) -{ - struct wan_device* wandev = &card->wandev; - int new_lcn = mb->cmd.lcn; - struct net_device* dev = get_dev_by_lcn(wandev, new_lcn); - x25_channel_t* chan = NULL; - int accept = 0; /* set to '1' if o.k. to accept call */ - unsigned int user_data; - x25_call_info_t* info; - - /* Make sure there is no call collision */ - if (dev != NULL) - { - printk(KERN_INFO - "%s: X.25 incoming call collision on LCN %d!\n", - card->devname, new_lcn); - - x25_clear_call(card, new_lcn, 0, 0); - return 1; - } - - /* Make sure D bit is not set in call request */ -//FIXME: THIS IS NOT TURE !!!! TAKE IT OUT -// if (mb->cmd.qdm & 0x02) -// { -// printk(KERN_INFO -// "%s: X.25 incoming call on LCN %d with D-bit set!\n", -// card->devname, new_lcn); -// -// x25_clear_call(card, new_lcn, 0, 0); -// return 1; -// } - - /* Parse call request data */ - info = kmalloc(sizeof(x25_call_info_t), GFP_ATOMIC); - if (info == NULL) - { - printk(KERN_ERR - "%s: not enough memory to parse X.25 incoming call " - "on LCN %d!\n", card->devname, new_lcn); - x25_clear_call(card, new_lcn, 0, 0); - return 1; - } - - parse_call_info(mb->data, info); - - if (card->u.x.logging) - printk(KERN_INFO "\n%s: X.25 incoming call on LCN %d!\n", - card->devname, new_lcn); - - /* Conver the first two ASCII characters into an - * interger. Used to check the incoming protocol - */ - user_data = hex_to_uint(info->user,2); - - /* Find available channel */ - for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) { - chan = dev->priv; - - if (chan->common.usedby == API) - continue; - - if (!chan->common.svc || (chan->common.state != WAN_DISCONNECTED)) - continue; - - if (user_data == NLPID_IP && chan->protocol != htons(ETH_P_IP)){ - printk(KERN_INFO "IP packet but configured for IPX : %x, %x\n", - htons(chan->protocol), info->user[0]); - continue; - } - - if (user_data == NLPID_SNAP && chan->protocol != htons(ETH_P_IPX)){ - printk(KERN_INFO "IPX packet but configured for IP: %x\n", - htons(chan->protocol)); - continue; - } - if (strcmp(info->src, chan->addr) == 0) - break; - - /* If just an '@' is specified, accept all incoming calls */ - if (strcmp(chan->addr, "") == 0) - break; - } - - if (dev == NULL){ - - /* If the call is not for any WANPIPE interfaces - * check to see if there is an API listening queue - * waiting for data. If there is send the packet - * up the stack. - */ - if (card->sk != NULL && card->func != NULL){ - if (api_incoming_call(card,mb,new_lcn)){ - x25_clear_call(card, new_lcn, 0, 0); - } - accept = 0; - }else{ - printk(KERN_INFO "%s: no channels available!\n", - card->devname); - - x25_clear_call(card, new_lcn, 0, 0); - } - - }else if (info->nuser == 0){ - - printk(KERN_INFO - "%s: no user data in incoming call on LCN %d!\n", - card->devname, new_lcn) - ; - x25_clear_call(card, new_lcn, 0, 0); - - }else switch (info->user[0]){ - - case 0: /* multiplexed */ - chan->protocol = htons(0); - accept = 1; - break; - - case NLPID_IP: /* IP datagrams */ - accept = 1; - break; - - case NLPID_SNAP: /* IPX datagrams */ - accept = 1; - break; - - default: - printk(KERN_INFO - "%s: unsupported NLPID 0x%02X in incoming call " - "on LCN %d!\n", card->devname, info->user[0], new_lcn); - x25_clear_call(card, new_lcn, 0, 249); - } - - if (accept && (x25_accept_call(card, new_lcn, 0) == CMD_OK)){ - - bind_lcn_to_dev (card, chan->dev, new_lcn); - - if (x25_get_chan_conf(card, chan) == CMD_OK) - set_chan_state(dev, WAN_CONNECTED); - else - x25_clear_call(card, new_lcn, 0, 0); - } - kfree(info); - return 1; -} - -/*==================================================================== - * Handle accepted call. - *====================================================================*/ - -static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) -{ - unsigned new_lcn = mb->cmd.lcn; - struct net_device* dev = find_channel(card, new_lcn); - x25_channel_t* chan; - - if (dev == NULL){ - printk(KERN_INFO - "%s: clearing orphaned connection on LCN %d!\n", - card->devname, new_lcn); - x25_clear_call(card, new_lcn, 0, 0); - return 1; - } - - if (card->u.x.logging) - printk(KERN_INFO "%s: X.25 call accepted on Dev %s and LCN %d!\n", - card->devname, dev->name, new_lcn); - - /* Get channel configuration and notify router */ - chan = dev->priv; - if (x25_get_chan_conf(card, chan) != CMD_OK) - { - x25_clear_call(card, new_lcn, 0, 0); - return 1; - } - - set_chan_state(dev, WAN_CONNECTED); - - if (chan->common.usedby == API){ - send_delayed_cmd_result(card,dev,mb); - bind_lcn_to_dev (card, dev, new_lcn); - } - - return 1; -} - -/*==================================================================== - * Handle cleared call. - *====================================================================*/ - -static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) -{ - unsigned new_lcn = mb->cmd.lcn; - struct net_device* dev = find_channel(card, new_lcn); - x25_channel_t *chan; - unsigned char old_state; - - if (card->u.x.logging){ - printk(KERN_INFO "%s: X.25 clear request on LCN %d! Cause:0x%02X " - "Diagn:0x%02X\n", - card->devname, new_lcn, mb->cmd.cause, mb->cmd.diagn); - } - - if (dev == NULL){ - printk(KERN_INFO "%s: X.25 clear request : No device for clear\n", - card->devname); - return 1; - } - - chan=dev->priv; - - old_state = chan->common.state; - - set_chan_state(dev, WAN_DISCONNECTED); - - if (chan->common.usedby == API){ - - switch (old_state){ - - case WAN_CONNECTING: - send_delayed_cmd_result(card,dev,mb); - break; - case WAN_CONNECTED: - send_oob_msg(card,dev,mb); - break; - } - } - - return ((cmd == X25_WRITE) && (lcn == new_lcn)) ? 0 : 1; -} - -/*==================================================================== - * Handle X.25 restart event. - *====================================================================*/ - -static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) -{ - struct wan_device* wandev = &card->wandev; - struct net_device* dev; - x25_channel_t *chan; - unsigned char old_state; - - printk(KERN_INFO - "%s: X.25 restart request! Cause:0x%02X Diagn:0x%02X\n", - card->devname, mb->cmd.cause, mb->cmd.diagn); - - /* down all logical channels */ - for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) { - chan=dev->priv; - old_state = chan->common.state; - - set_chan_state(dev, WAN_DISCONNECTED); - - if (chan->common.usedby == API){ - switch (old_state){ - - case WAN_CONNECTING: - send_delayed_cmd_result(card,dev,mb); - break; - case WAN_CONNECTED: - send_oob_msg(card,dev,mb); - break; - } - } - } - return (cmd == X25_WRITE) ? 0 : 1; -} - -/*==================================================================== - * Handle timeout event. - *====================================================================*/ - -static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) -{ - unsigned new_lcn = mb->cmd.lcn; - - if (mb->cmd.pktType == 0x05) /* call request time out */ - { - struct net_device* dev = find_channel(card,new_lcn); - - printk(KERN_INFO "%s: X.25 call timed timeout on LCN %d!\n", - card->devname, new_lcn); - - if (dev){ - x25_channel_t *chan = dev->priv; - set_chan_state(dev, WAN_DISCONNECTED); - - if (chan->common.usedby == API){ - send_delayed_cmd_result(card,dev,card->mbox); - } - } - }else{ - printk(KERN_INFO "%s: X.25 packet 0x%02X timeout on LCN %d!\n", - card->devname, mb->cmd.pktType, new_lcn); - } - return 1; -} - -/* - * Miscellaneous - */ - -/*==================================================================== - * Establish physical connection. - * o open HDLC and raise DTR - * - * Return: 0 connection established - * 1 connection is in progress - * <0 error - *===================================================================*/ - -static int connect (sdla_t* card) -{ - TX25Status* status = card->flags; - - if (x25_open_hdlc(card) || x25_setup_hdlc(card)) - return -EIO; - - wanpipe_set_state(card, WAN_CONNECTING); - - x25_set_intr_mode(card, INTR_ON_TIMER); - status->imask &= ~INTR_ON_TIMER; - - return 1; -} - -/* - * Tear down physical connection. - * o close HDLC link - * o drop DTR - * - * Return: 0 - * <0 error - */ - -static int disconnect (sdla_t* card) -{ - wanpipe_set_state(card, WAN_DISCONNECTED); - x25_set_intr_mode(card, INTR_ON_TIMER); /* disable all interrupt except timer */ - x25_close_hdlc(card); /* close HDLC link */ - x25_set_dtr(card, 0); /* drop DTR */ - return 0; -} - -/* - * Find network device by its channel number. - */ - -static struct net_device* get_dev_by_lcn(struct wan_device* wandev, - unsigned lcn) -{ - struct net_device* dev; - - for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) - if (((x25_channel_t*)dev->priv)->common.lcn == lcn) - break; - return dev; -} - -/* - * Initiate connection on the logical channel. - * o for PVC we just get channel configuration - * o for SVCs place an X.25 call - * - * Return: 0 connected - * >0 connection in progress - * <0 failure - */ - -static int chan_connect(struct net_device* dev) -{ - x25_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - - if (chan->common.svc && chan->common.usedby == WANPIPE){ - if (!chan->addr[0]){ - printk(KERN_INFO "%s: No Destination Address\n", - card->devname); - return -EINVAL; /* no destination address */ - } - printk(KERN_INFO "%s: placing X.25 call to %s ...\n", - card->devname, chan->addr); - - if (x25_place_call(card, chan) != CMD_OK) - return -EIO; - - set_chan_state(dev, WAN_CONNECTING); - return 1; - }else{ - if (x25_get_chan_conf(card, chan) != CMD_OK) - return -EIO; - - set_chan_state(dev, WAN_CONNECTED); - } - return 0; -} - -/* - * Disconnect logical channel. - * o if SVC then clear X.25 call - */ - -static int chan_disc(struct net_device* dev) -{ - x25_channel_t* chan = dev->priv; - - if (chan->common.svc){ - x25_clear_call(chan->card, chan->common.lcn, 0, 0); - - /* For API we disconnect on clear - * confirmation. - */ - if (chan->common.usedby == API) - return 0; - } - - set_chan_state(dev, WAN_DISCONNECTED); - - return 0; -} - -/* - * Set logical channel state. - */ - -static void set_chan_state(struct net_device* dev, int state) -{ - x25_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - unsigned long flags; - - save_flags(flags); - cli(); - if (chan->common.state != state) - { - switch (state) - { - case WAN_CONNECTED: - if (card->u.x.logging){ - printk (KERN_INFO - "%s: interface %s connected, lcn %i !\n", - card->devname, dev->name,chan->common.lcn); - } - *(unsigned short*)dev->dev_addr = htons(chan->common.lcn); - chan->i_timeout_sofar = jiffies; - - /* LAPB is PVC Based */ - if (card->u.x.LAPB_hdlc) - chan->common.svc=0; - break; - - case WAN_CONNECTING: - if (card->u.x.logging){ - printk (KERN_INFO - "%s: interface %s connecting, lcn %i ...\n", - card->devname, dev->name, chan->common.lcn); - } - break; - - case WAN_DISCONNECTED: - if (card->u.x.logging){ - printk (KERN_INFO - "%s: interface %s disconnected, lcn %i !\n", - card->devname, dev->name,chan->common.lcn); - } - atomic_set(&chan->common.disconnect,0); - - if (chan->common.svc) { - *(unsigned short*)dev->dev_addr = 0; - card->u.x.svc_to_dev_map[(chan->common.lcn%X25_MAX_CHAN)]=NULL; - chan->common.lcn = 0; - } - - if (chan->transmit_length){ - chan->transmit_length=0; - atomic_set(&chan->common.driver_busy,0); - chan->tx_offset=0; - if (netif_queue_stopped(dev)){ - netif_wake_queue(dev); - } - } - atomic_set(&chan->common.command,0); - break; - - case WAN_DISCONNECTING: - if (card->u.x.logging){ - printk (KERN_INFO - "\n%s: interface %s disconnecting, lcn %i ...\n", - card->devname, dev->name,chan->common.lcn); - } - atomic_set(&chan->common.disconnect,0); - break; - } - chan->common.state = state; - } - chan->state_tick = jiffies; - restore_flags(flags); -} - -/* - * Send packet on a logical channel. - * When this function is called, tx_skb field of the channel data - * space points to the transmit socket buffer. When transmission - * is complete, release socket buffer and reset 'tbusy' flag. - * - * Return: 0 - transmission complete - * 1 - busy - * - * Notes: - * 1. If packet length is greater than MTU for this channel, we'll fragment - * the packet into 'complete sequence' using M-bit. - * 2. When transmission is complete, an event notification should be issued - * to the router. - */ - -static int chan_send(struct net_device* dev, void* buff, unsigned data_len, - unsigned char tx_intr) -{ - x25_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - TX25Status* status = card->flags; - unsigned len=0, qdm=0, res=0, orig_len = 0; - void *data; - - /* Check to see if channel is ready */ - if ((!(status->cflags[chan->ch_idx] & 0x40) && !card->u.x.LAPB_hdlc) || - !(*card->u.x.hdlc_buf_status & 0x40)){ - - if (!tx_intr){ - setup_for_delayed_transmit (dev, buff, data_len); - return 0; - }else{ - /* By returning 0 to tx_intr the packet will be dropped */ - ++card->wandev.stats.tx_dropped; - ++chan->ifstats.tx_dropped; - printk(KERN_INFO "%s: ERROR, Tx intr could not send, dropping %s:\n", - card->devname,dev->name); - ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr; - return 0; - } - } - - if (chan->common.usedby == API){ - /* Remove the API Header */ - x25api_hdr_t *api_data = (x25api_hdr_t *)buff; - - /* Set the qdm bits from the packet header - * User has the option to set the qdm bits - */ - qdm = api_data->qdm; - - orig_len = len = data_len - sizeof(x25api_hdr_t); - data = (unsigned char*)buff + sizeof(x25api_hdr_t); - }else{ - data = buff; - orig_len = len = data_len; - } - - if (tx_intr){ - /* We are in tx_intr, minus the tx_offset from - * the total length. The tx_offset part of the - * data has already been sent. Also, move the - * data pointer to proper offset location. - */ - len -= chan->tx_offset; - data = (unsigned char*)data + chan->tx_offset; - } - - /* Check if the packet length is greater than MTU - * If YES: Cut the len to MTU and set the M bit - */ - if (len > chan->tx_pkt_size && !card->u.x.LAPB_hdlc){ - len = chan->tx_pkt_size; - qdm |= M_BIT; - } - - - /* Pass only first three bits of the qdm byte to the send - * routine. In case user sets any other bit which might - * cause errors. - */ - - switch(x25_send(card, chan->common.lcn, (qdm&0x07), len, data)){ - case 0x00: /* success */ - chan->i_timeout_sofar = jiffies; - - dev->trans_start=jiffies; - - if ((qdm & M_BIT) && !card->u.x.LAPB_hdlc){ - if (!tx_intr){ - /* The M bit was set, which means that part of the - * packet has been sent. Copy the packet into a buffer - * and set the offset to len, so on next tx_inter - * the packet will be sent using the below offset. - */ - chan->tx_offset += len; - - ++chan->ifstats.tx_packets; - chan->ifstats.tx_bytes += len; - - if (chan->tx_offset < orig_len){ - setup_for_delayed_transmit (dev, buff, data_len); - } - res=0; - }else{ - /* We are already in tx_inter, thus data is already - * in the buffer. Update the offset and wait for - * next tx_intr. We add on to the offset, since data can - * be X number of times larger than max data size. - */ - ++chan->ifstats.tx_packets; - chan->ifstats.tx_bytes += len; - - ++chan->if_send_stat.if_send_bfr_passed_to_adptr; - chan->tx_offset += len; - - /* The user can set the qdm bit as well. - * If the entire packet was sent and qdm is still - * set, than it's the user who has set the M bit. In that, - * case indicate that the packet was send by returning - * 0 and wait for a new packet. Otherwise, wait for next - * tx interrupt to send the rest of the packet */ - - if (chan->tx_offset < orig_len){ - res=1; - }else{ - res=0; - } - } - }else{ - ++chan->ifstats.tx_packets; - chan->ifstats.tx_bytes += len; - ++chan->if_send_stat.if_send_bfr_passed_to_adptr; - res=0; - } - break; - - case 0x33: /* Tx busy */ - if (tx_intr){ - printk(KERN_INFO "%s: Tx_intr: Big Error dropping packet %s\n", - card->devname,dev->name); - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr; - res=0; - }else{ - DBG_PRINTK(KERN_INFO - "%s: Send: Big Error should have tx: storring %s\n", - card->devname,dev->name); - setup_for_delayed_transmit (dev, buff, data_len); - res=1; - } - break; - - default: /* failure */ - ++chan->ifstats.tx_errors; - if (tx_intr){ - printk(KERN_INFO "%s: Tx_intr: Failure to send, dropping %s\n", - card->devname,dev->name); - ++chan->ifstats.tx_dropped; - ++card->wandev.stats.tx_dropped; - ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr; - res=0; - }else{ - DBG_PRINTK(KERN_INFO "%s: Send: Failure to send !!!, storing %s\n", - card->devname,dev->name); - setup_for_delayed_transmit (dev, buff, data_len); - res=1; - } - break; - } - return res; -} - - -/* - * Parse X.25 call request data and fill x25_call_info_t structure. - */ - -static void parse_call_info (unsigned char* str, x25_call_info_t* info) -{ - memset(info, 0, sizeof(x25_call_info_t)); - for (; *str; ++str) - { - int i; - unsigned char ch; - - if (*str == '-') switch (str[1]) { - - /* Take minus 2 off the maximum size so that - * last byte is 0. This way we can use string - * manipulaton functions on call information. - */ - - case 'd': /* destination address */ - for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){ - ch = str[2+i]; - if (isspace(ch)) break; - info->dest[i] = ch; - } - break; - - case 's': /* source address */ - for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){ - ch = str[2+i]; - if (isspace(ch)) break; - info->src[i] = ch; - } - break; - - case 'u': /* user data */ - for (i = 0; i < (MAX_X25_DATA_SIZE-2); ++i){ - ch = str[2+i]; - if (isspace(ch)) break; - info->user[i] = ch; - } - info->nuser = i; - break; - - case 'f': /* facilities */ - for (i = 0; i < (MAX_X25_FACL_SIZE-2); ++i){ - ch = str[2+i]; - if (isspace(ch)) break; - info->facil[i] = ch; - } - info->nfacil = i; - break; - } - } -} - -/* - * Convert line speed in bps to a number used by S502 code. - */ - -static unsigned char bps_to_speed_code (unsigned long bps) -{ - unsigned char number; - - if (bps <= 1200) number = 0x01; - else if (bps <= 2400) number = 0x02; - else if (bps <= 4800) number = 0x03; - else if (bps <= 9600) number = 0x04; - else if (bps <= 19200) number = 0x05; - else if (bps <= 38400) number = 0x06; - else if (bps <= 45000) number = 0x07; - else if (bps <= 56000) number = 0x08; - else if (bps <= 64000) number = 0x09; - else if (bps <= 74000) number = 0x0A; - else if (bps <= 112000) number = 0x0B; - else if (bps <= 128000) number = 0x0C; - else number = 0x0D; - - return number; -} - -/* - * Convert decimal string to unsigned integer. - * If len != 0 then only 'len' characters of the string are converted. - */ - -static unsigned int dec_to_uint (unsigned char* str, int len) -{ - unsigned val; - - if (!len) - len = strlen(str); - - for (val = 0; len && isdigit(*str); ++str, --len) - val = (val * 10) + (*str - (unsigned)'0'); - - return val; -} - -/* - * Convert hex string to unsigned integer. - * If len != 0 then only 'len' characters of the string are conferted. - */ - -static unsigned int hex_to_uint (unsigned char* str, int len) -{ - unsigned val, ch; - - if (!len) - len = strlen(str); - - for (val = 0; len; ++str, --len) - { - ch = *str; - if (isdigit(ch)) - val = (val << 4) + (ch - (unsigned)'0'); - else if (isxdigit(ch)) - val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10); - else break; - } - return val; -} - - -static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto) -{ - int i; - - if( proto == ETH_P_IPX) { - /* It's an IPX packet */ - if(!enable_IPX) { - /* Return 1 so we don't pass it up the stack. */ - return 1; - } - } else { - /* It's not IPX so pass it up the stack.*/ - return 0; - } - - if( sendpacket[16] == 0x90 && - sendpacket[17] == 0x04) - { - /* It's IPXWAN */ - - if( sendpacket[2] == 0x02 && - sendpacket[34] == 0x00) - { - /* It's a timer request packet */ - printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname); - - /* Go through the routing options and answer no to every - * option except Unnumbered RIP/SAP - */ - for(i = 41; sendpacket[i] == 0x00; i += 5) - { - /* 0x02 is the option for Unnumbered RIP/SAP */ - if( sendpacket[i + 4] != 0x02) - { - sendpacket[i + 1] = 0; - } - } - - /* Skip over the extended Node ID option */ - if( sendpacket[i] == 0x04 ) - { - i += 8; - } - - /* We also want to turn off all header compression opt. */ - for(; sendpacket[i] == 0x80 ;) - { - sendpacket[i + 1] = 0; - i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4; - } - - /* Set the packet type to timer response */ - sendpacket[34] = 0x01; - - printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname); - } - else if( sendpacket[34] == 0x02 ) - { - /* This is an information request packet */ - printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname); - - /* Set the packet type to information response */ - sendpacket[34] = 0x03; - - /* Set the router name */ - sendpacket[51] = 'X'; - sendpacket[52] = 'T'; - sendpacket[53] = 'P'; - sendpacket[54] = 'I'; - sendpacket[55] = 'P'; - sendpacket[56] = 'E'; - sendpacket[57] = '-'; - sendpacket[58] = CVHexToAscii(network_number >> 28); - sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24); - sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20); - sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16); - sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12); - sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8); - sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4); - sendpacket[65] = CVHexToAscii(network_number & 0x0000000F); - for(i = 66; i < 99; i+= 1) - { - sendpacket[i] = 0; - } - - printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname); - } - else - { - printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname); - return 0; - } - - /* Set the WNodeID to our network address */ - sendpacket[35] = (unsigned char)(network_number >> 24); - sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16); - sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8); - sendpacket[38] = (unsigned char)(network_number & 0x000000FF); - - return 1; - } else { - /*If we get here it's an IPX-data packet, so it'll get passed up the stack. - */ - /* switch the network numbers */ - switch_net_numbers(sendpacket, network_number, 1); - return 0; - } -} - -/* - * If incoming is 0 (outgoing)- if the net numbers is ours make it 0 - * if incoming is 1 - if the net number is 0 make it ours - */ - -static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming) -{ - unsigned long pnetwork_number; - - pnetwork_number = (unsigned long)((sendpacket[6] << 24) + - (sendpacket[7] << 16) + (sendpacket[8] << 8) + - sendpacket[9]); - - - if (!incoming) { - /*If the destination network number is ours, make it 0 */ - if( pnetwork_number == network_number) { - sendpacket[6] = sendpacket[7] = sendpacket[8] = - sendpacket[9] = 0x00; - } - } else { - /* If the incoming network is 0, make it ours */ - if( pnetwork_number == 0) { - sendpacket[6] = (unsigned char)(network_number >> 24); - sendpacket[7] = (unsigned char)((network_number & - 0x00FF0000) >> 16); - sendpacket[8] = (unsigned char)((network_number & - 0x0000FF00) >> 8); - sendpacket[9] = (unsigned char)(network_number & - 0x000000FF); - } - } - - - pnetwork_number = (unsigned long)((sendpacket[18] << 24) + - (sendpacket[19] << 16) + (sendpacket[20] << 8) + - sendpacket[21]); - - - if( !incoming ) { - /* If the source network is ours, make it 0 */ - if( pnetwork_number == network_number) { - sendpacket[18] = sendpacket[19] = sendpacket[20] = - sendpacket[21] = 0x00; - } - } else { - /* If the source network is 0, make it ours */ - if( pnetwork_number == 0 ) { - sendpacket[18] = (unsigned char)(network_number >> 24); - sendpacket[19] = (unsigned char)((network_number & - 0x00FF0000) >> 16); - sendpacket[20] = (unsigned char)((network_number & - 0x0000FF00) >> 8); - sendpacket[21] = (unsigned char)(network_number & - 0x000000FF); - } - } -} /* switch_net_numbers */ - - - - -/********************* X25API SPECIFIC FUNCTIONS ****************/ - - -/*=============================================================== - * find_channel - * - * Manages the lcn to device map. It increases performance - * because it eliminates the need to search through the link - * list for a device which is bounded to a specific lcn. - * - *===============================================================*/ - - -struct net_device *find_channel(sdla_t *card, unsigned lcn) -{ - if (card->u.x.LAPB_hdlc){ - - return card->wandev.dev; - - }else{ - /* We don't know whether the incoming lcn - * is a PVC or an SVC channel. But we do know that - * the lcn cannot be for both the PVC and the SVC - * channel. - - * If the lcn number is greater or equal to 255, - * take the modulo 255 of that number. We only have - * 255 locations, thus higher numbers must be mapped - * to a number between 0 and 245. - - * We must separate pvc's and svc's since two don't - * have to be contiguous. Meaning pvc's can start - * from 1 to 10 and svc's can start from 256 to 266. - * But 256%255 is 1, i.e. CONFLICT. - */ - - - /* Highest LCN number must be less or equal to 4096 */ - if ((lcn <= MAX_LCN_NUM) && (lcn > 0)){ - - if (lcn < X25_MAX_CHAN){ - if (card->u.x.svc_to_dev_map[lcn]) - return card->u.x.svc_to_dev_map[lcn]; - - if (card->u.x.pvc_to_dev_map[lcn]) - return card->u.x.pvc_to_dev_map[lcn]; - - }else{ - int new_lcn = lcn%X25_MAX_CHAN; - if (card->u.x.svc_to_dev_map[new_lcn]) - return card->u.x.svc_to_dev_map[new_lcn]; - - if (card->u.x.pvc_to_dev_map[new_lcn]) - return card->u.x.pvc_to_dev_map[new_lcn]; - } - } - return NULL; - } -} - -void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn) -{ - x25_channel_t *chan = dev->priv; - - /* Modulo the lcn number by X25_MAX_CHAN (255) - * because the lcn number can be greater than 255 - * - * We need to split svc and pvc since they don't have - * to be contigous. - */ - - if (chan->common.svc){ - card->u.x.svc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev; - }else{ - card->u.x.pvc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev; - } - chan->common.lcn = lcn; -} - - - -/*=============================================================== - * x25api_bh - * - * - *==============================================================*/ - -static void x25api_bh(struct net_device* dev) -{ - x25_channel_t* chan = dev->priv; - sdla_t* card = chan->card; - struct sk_buff *skb; - - if (atomic_read(&chan->bh_buff_used) == 0){ - printk(KERN_INFO "%s: BH Buffer Empty in BH\n", - card->devname); - clear_bit(0, &chan->tq_working); - return; - } - - while (atomic_read(&chan->bh_buff_used)){ - - /* If the sock is in the process of unlinking the - * driver from the socket, we must get out. - * This never happends but is a sanity check. */ - if (test_bit(0,&chan->common.common_critical)){ - clear_bit(0, &chan->tq_working); - return; - } - - /* If LAPB HDLC, do not drop packets if socket is - * not connected. Let the buffer fill up and - * turn off rx interrupt */ - if (card->u.x.LAPB_hdlc){ - if (chan->common.sk == NULL || chan->common.func == NULL){ - clear_bit(0, &chan->tq_working); - return; - } - } - - skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb; - - if (skb == NULL){ - printk(KERN_INFO "%s: BH Skb empty for read %i\n", - card->devname,chan->bh_read); - }else{ - - if (chan->common.sk == NULL || chan->common.func == NULL){ - printk(KERN_INFO "%s: BH: Socket disconnected, dropping\n", - card->devname); - dev_kfree_skb_any(skb); - x25api_bh_cleanup(dev); - ++chan->ifstats.rx_dropped; - ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; - continue; - } - - - if (chan->common.func(skb,dev,chan->common.sk) != 0){ - /* Sock full cannot send, queue us for another - * try - */ - printk(KERN_INFO "%s: BH: !!! Packet failed to send !!!!! \n", - card->devname); - atomic_set(&chan->common.receive_block,1); - return; - }else{ - x25api_bh_cleanup(dev); - ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack; - } - } - } - clear_bit(0, &chan->tq_working); - - return; -} - -/*=============================================================== - * x25api_bh_cleanup - * - * - *==============================================================*/ - -static int x25api_bh_cleanup(struct net_device *dev) -{ - x25_channel_t* chan = dev->priv; - sdla_t *card = chan->card; - TX25Status* status = card->flags; - - - ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL; - - if (chan->bh_read == MAX_BH_BUFF){ - chan->bh_read=0; - }else{ - ++chan->bh_read; - } - - /* If the Receive interrupt was off, it means - * that we filled up our circular buffer. Check - * that we have space in the buffer. If so - * turn the RX interrupt back on. - */ - if (!(status->imask & INTR_ON_RX_FRAME)){ - if (atomic_read(&chan->bh_buff_used) < (MAX_BH_BUFF+1)){ - printk(KERN_INFO "%s: BH: Turning on the interrupt\n", - card->devname); - status->imask |= INTR_ON_RX_FRAME; - } - } - - atomic_dec(&chan->bh_buff_used); - return 0; -} - - -/*=============================================================== - * bh_enqueue - * - * - *==============================================================*/ - -static int bh_enqueue(struct net_device *dev, struct sk_buff *skb) -{ - x25_channel_t* chan = dev->priv; - sdla_t *card = chan->card; - TX25Status* status = card->flags; - - if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){ - printk(KERN_INFO "%s: Bottom half buffer FULL\n", - card->devname); - return 1; - } - - ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb; - - if (chan->bh_write == MAX_BH_BUFF){ - chan->bh_write=0; - }else{ - ++chan->bh_write; - } - - atomic_inc(&chan->bh_buff_used); - - if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){ - printk(KERN_INFO "%s: Buffer is now full, Turning off RX Intr\n", - card->devname); - status->imask &= ~INTR_ON_RX_FRAME; - } - - return 0; -} - - -/*=============================================================== - * timer_intr_cmd_exec - * - * Called by timer interrupt to execute a command - *===============================================================*/ - -static int timer_intr_cmd_exec (sdla_t* card) -{ - struct net_device *dev; - unsigned char more_to_exec=0; - volatile x25_channel_t *chan=NULL; - int i=0,bad_cmd=0,err=0; - - if (card->u.x.cmd_dev == NULL){ - card->u.x.cmd_dev = card->wandev.dev; - } - - dev = card->u.x.cmd_dev; - - for (;;){ - - chan = dev->priv; - - if (atomic_read(&chan->common.command)){ - - bad_cmd = check_bad_command(card,dev); - - if ((!chan->common.mbox || atomic_read(&chan->common.disconnect)) && - !bad_cmd){ - - /* Socket has died or exited, We must bring the - * channel down before anybody else tries to - * use it */ - err = channel_disconnect(card,dev); - }else{ - err = execute_delayed_cmd(card, dev, - (mbox_cmd_t*)chan->common.mbox, - bad_cmd); - } - - switch (err){ - - case RETURN_RESULT: - - /* Return the result to the socket without - * delay. NO_WAIT Command */ - atomic_set(&chan->common.command,0); - if (atomic_read(&card->u.x.command_busy)) - atomic_set(&card->u.x.command_busy,0); - - send_delayed_cmd_result(card,dev,card->mbox); - - more_to_exec=0; - break; - case DELAY_RESULT: - - /* Wait for the remote to respond, before - * sending the result up to the socket. - * WAIT command */ - if (atomic_read(&card->u.x.command_busy)) - atomic_set(&card->u.x.command_busy,0); - - atomic_set(&chan->common.command,0); - more_to_exec=0; - break; - default: - - /* If command could not be executed for - * some reason (i.e return code 0x33 busy) - * set the more_to_exec bit which will - * indicate that this command must be exectued - * again during next timer interrupt - */ - more_to_exec=1; - if (atomic_read(&card->u.x.command_busy) == 0) - atomic_set(&card->u.x.command_busy,1); - break; - } - - bad_cmd=0; - - /* If flags is set, there are no hdlc buffers, - * thus, wait for the next pass and try the - * same command again. Otherwise, start searching - * from next device on the next pass. - */ - if (!more_to_exec){ - dev = move_dev_to_next(card,dev); - } - break; - }else{ - /* This device has nothing to execute, - * go to next. - */ - if (atomic_read(&card->u.x.command_busy)) - atomic_set(&card->u.x.command_busy,0); - dev = move_dev_to_next(card,dev); - } - - if (++i == card->u.x.no_dev){ - if (!more_to_exec){ - DBG_PRINTK(KERN_INFO "%s: Nothing to execute in Timer\n", - card->devname); - if (atomic_read(&card->u.x.command_busy)){ - atomic_set(&card->u.x.command_busy,0); - } - } - break; - } - - } //End of FOR - - card->u.x.cmd_dev = dev; - - if (more_to_exec){ - /* If more commands are pending, do not turn off timer - * interrupt */ - return 1; - }else{ - /* No more commands, turn off timer interrupt */ - return 0; - } -} - -/*=============================================================== - * execute_delayed_cmd - * - * Execute an API command which was passed down from the - * sock. Sock is very limited in which commands it can - * execute. Wait and No Wait commands are supported. - * Place Call, Clear Call and Reset wait commands, where - * Accept Call is a no_wait command. - * - *===============================================================*/ - -static int execute_delayed_cmd(sdla_t* card, struct net_device *dev, - mbox_cmd_t *usr_cmd, char bad_cmd) -{ - TX25Mbox* mbox = card->mbox; - int err; - x25_channel_t *chan = dev->priv; - int delay=RETURN_RESULT; - - if (!(*card->u.x.hdlc_buf_status & 0x40) && !bad_cmd){ - return TRY_CMD_AGAIN; - } - - /* This way a command is guaranteed to be executed for - * a specific lcn, the network interface is bound to. */ - usr_cmd->cmd.lcn = chan->common.lcn; - - - /* If channel is pvc, instead of place call - * run x25_channel configuration. If running LAPB HDLC - * enable communications. - */ - if ((!chan->common.svc) && (usr_cmd->cmd.command == X25_PLACE_CALL)){ - - if (card->u.x.LAPB_hdlc){ - DBG_PRINTK(KERN_INFO "LAPB: Connecting\n"); - connect(card); - set_chan_state(dev,WAN_CONNECTING); - return DELAY_RESULT; - }else{ - DBG_PRINTK(KERN_INFO "%s: PVC is CONNECTING\n",card->devname); - if (x25_get_chan_conf(card, chan) == CMD_OK){ - set_chan_state(dev, WAN_CONNECTED); - }else{ - set_chan_state(dev, WAN_DISCONNECTED); - } - return RETURN_RESULT; - } - } - - /* Copy the socket mbox command onto the board */ - - memcpy(&mbox->cmd, &usr_cmd->cmd, sizeof(TX25Cmd)); - if (usr_cmd->cmd.length){ - memcpy(mbox->data, usr_cmd->data, usr_cmd->cmd.length); - } - - /* Check if command is bad. We need to copy the cmd into - * the buffer regardless since we return the, mbox to - * the user */ - if (bad_cmd){ - mbox->cmd.result=0x01; - return RETURN_RESULT; - } - - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - if (err != CMD_OK && err != X25RES_NOT_READY) - x25_error(card, err, usr_cmd->cmd.command, usr_cmd->cmd.lcn); - - if (mbox->cmd.result == X25RES_NOT_READY){ - return TRY_CMD_AGAIN; - } - - switch (mbox->cmd.command){ - - case X25_PLACE_CALL: - - switch (mbox->cmd.result){ - - case CMD_OK: - - /* Check if Place call is a wait command or a - * no wait command */ - if (atomic_read(&chan->common.command) & 0x80) - delay=RETURN_RESULT; - else - delay=DELAY_RESULT; - - - DBG_PRINTK(KERN_INFO "\n%s: PLACE CALL Binding dev %s to lcn %i\n", - card->devname,dev->name, mbox->cmd.lcn); - - bind_lcn_to_dev (card, dev, mbox->cmd.lcn); - set_chan_state(dev, WAN_CONNECTING); - break; - - - default: - delay=RETURN_RESULT; - set_chan_state(dev, WAN_DISCONNECTED); - break; - } - break; - - case X25_ACCEPT_CALL: - - switch (mbox->cmd.result){ - - case CMD_OK: - - DBG_PRINTK(KERN_INFO "\n%s: ACCEPT Binding dev %s to lcn %i\n", - card->devname,dev->name,mbox->cmd.lcn); - - bind_lcn_to_dev (card, dev, mbox->cmd.lcn); - - if (x25_get_chan_conf(card, chan) == CMD_OK){ - - set_chan_state(dev, WAN_CONNECTED); - delay=RETURN_RESULT; - - }else{ - if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){ - /* if clear is successful, wait for clear confirm - */ - delay=DELAY_RESULT; - }else{ - /* Do not change the state here. If we fail - * the accept the return code is send up - *the stack, which will ether retry - * or clear the call - */ - DBG_PRINTK(KERN_INFO - "%s: ACCEPT: STATE MAY BE CURRUPTED 2 !!!!!\n", - card->devname); - delay=RETURN_RESULT; - } - } - break; - - - case X25RES_ASYNC_PACKET: - delay=TRY_CMD_AGAIN; - break; - - default: - DBG_PRINTK(KERN_INFO "%s: ACCEPT FAILED\n",card->devname); - if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){ - delay=DELAY_RESULT; - }else{ - /* Do not change the state here. If we fail the accept. The - * return code is send up the stack, which will ether retry - * or clear the call */ - DBG_PRINTK(KERN_INFO - "%s: ACCEPT: STATE MAY BE CORRUPTED 1 !!!!!\n", - card->devname); - delay=RETURN_RESULT; - } - } - break; - - case X25_CLEAR_CALL: - - switch (mbox->cmd.result){ - - case CMD_OK: - DBG_PRINTK(KERN_INFO - "CALL CLEAR OK: Dev %s Mbox Lcn %i Chan Lcn %i\n", - dev->name,mbox->cmd.lcn,chan->common.lcn); - set_chan_state(dev, WAN_DISCONNECTING); - delay = DELAY_RESULT; - break; - - case X25RES_CHANNEL_IN_USE: - case X25RES_ASYNC_PACKET: - delay = TRY_CMD_AGAIN; - break; - - case X25RES_LINK_NOT_IN_ABM: - case X25RES_INVAL_LCN: - case X25RES_INVAL_STATE: - set_chan_state(dev, WAN_DISCONNECTED); - delay = RETURN_RESULT; - break; - - default: - /* If command did not execute because of user - * fault, do not change the state. This will - * signal the socket that clear command failed. - * User can retry or close the socket. - * When socket gets killed, it will set the - * chan->disconnect which will signal - * driver to clear the call */ - printk(KERN_INFO "%s: Clear Command Failed, Rc %x\n", - card->devname,mbox->cmd.command); - delay = RETURN_RESULT; - } - break; - } - - return delay; -} - -/*=============================================================== - * api_incoming_call - * - * Pass an incoming call request up the listening - * sock. If the API sock is not listening reject the - * call. - * - *===============================================================*/ - -static int api_incoming_call (sdla_t* card, TX25Mbox *mbox, int lcn) -{ - struct sk_buff *skb; - int len = sizeof(TX25Cmd)+mbox->cmd.length; - - if (alloc_and_init_skb_buf(card, &skb, len)){ - printk(KERN_INFO "%s: API incoming call, no memory\n",card->devname); - return 1; - } - - memcpy(skb_put(skb,len),&mbox->cmd,len); - - skb->mac.raw = skb->data; - skb->protocol = htons(X25_PROT); - skb->pkt_type = WAN_PACKET_ASYNC; - - if (card->func(skb,card->sk) < 0){ - printk(KERN_INFO "%s: MAJOR ERROR: Failed to send up place call \n",card->devname); - dev_kfree_skb_any(skb); - return 1; - } - - return 0; -} - -/*=============================================================== - * send_delayed_cmd_result - * - * Wait commands like PLEACE CALL or CLEAR CALL must wait - * until the result arrives. This function passes - * the result to a waiting sock. - * - *===============================================================*/ -static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev, - TX25Mbox* mbox) -{ - x25_channel_t *chan = dev->priv; - mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox; - struct sk_buff *skb; - int len=sizeof(unsigned char); - - atomic_set(&chan->common.command,0); - - /* If the sock is in the process of unlinking the - * driver from the socket, we must get out. - * This never happends but is a sanity check. */ - if (test_bit(0,&chan->common.common_critical)){ - return; - } - - if (!usr_cmd || !chan->common.sk || !chan->common.func){ - DBG_PRINTK(KERN_INFO "Delay result: Sock not bounded sk: %u, func: %u, mbox: %u\n", - (unsigned int)chan->common.sk, - (unsigned int)chan->common.func, - (unsigned int)usr_cmd); - return; - } - - memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd)); - if (mbox->cmd.length > 0){ - memcpy(usr_cmd->data, mbox->data, mbox->cmd.length); - } - - if (alloc_and_init_skb_buf(card,&skb,len)){ - printk(KERN_INFO "Delay result: No sock buffers\n"); - return; - } - - memcpy(skb_put(skb,len),&mbox->cmd.command,len); - - skb->mac.raw = skb->data; - skb->pkt_type = WAN_PACKET_CMD; - - chan->common.func(skb,dev,chan->common.sk); -} - -/*=============================================================== - * clear_confirm_event - * - * Pass the clear confirmation event up the sock. The - * API will disconnect only after the clear confirmation - * has been received. - * - * Depending on the state, clear confirmation could - * be an OOB event, or a result of an API command. - *===============================================================*/ - -static int clear_confirm_event (sdla_t *card, TX25Mbox* mb) -{ - struct net_device *dev; - x25_channel_t *chan; - unsigned char old_state; - - dev = find_channel(card,mb->cmd.lcn); - if (!dev){ - DBG_PRINTK(KERN_INFO "%s: *** GOT CLEAR BUT NO DEV %i\n", - card->devname,mb->cmd.lcn); - return 0; - } - - chan=dev->priv; - DBG_PRINTK(KERN_INFO "%s: GOT CLEAR CONFIRM %s: Mbox lcn %i Chan lcn %i\n", - card->devname, dev->name, mb->cmd.lcn, chan->common.lcn); - - /* If not API fall through to default. - * If API, send the result to a waiting - * socket. - */ - - old_state = chan->common.state; - set_chan_state(dev, WAN_DISCONNECTED); - - if (chan->common.usedby == API){ - switch (old_state) { - - case WAN_DISCONNECTING: - case WAN_CONNECTING: - send_delayed_cmd_result(card,dev,mb); - break; - case WAN_CONNECTED: - send_oob_msg(card,dev,mb); - break; - } - return 1; - } - - return 0; -} - -/*=============================================================== - * send_oob_msg - * - * Construct an NEM Message and pass it up the connected - * sock. If the sock is not bounded discard the NEM. - * - *===============================================================*/ - -static void send_oob_msg(sdla_t *card, struct net_device *dev, TX25Mbox *mbox) -{ - x25_channel_t *chan = dev->priv; - mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox; - struct sk_buff *skb; - int len=sizeof(x25api_hdr_t)+mbox->cmd.length; - x25api_t *api_hdr; - - /* If the sock is in the process of unlinking the - * driver from the socket, we must get out. - * This never happends but is a sanity check. */ - if (test_bit(0,&chan->common.common_critical)){ - return; - } - - if (!usr_cmd || !chan->common.sk || !chan->common.func){ - DBG_PRINTK(KERN_INFO "OOB MSG: Sock not bounded\n"); - return; - } - - memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd)); - if (mbox->cmd.length > 0){ - memcpy(usr_cmd->data, mbox->data, mbox->cmd.length); - } - - if (alloc_and_init_skb_buf(card,&skb,len)){ - printk(KERN_INFO "%s: OOB MSG: No sock buffers\n",card->devname); - return; - } - - api_hdr = (x25api_t*)skb_put(skb,len); - api_hdr->hdr.pktType = mbox->cmd.pktType & 0x7F; - api_hdr->hdr.qdm = mbox->cmd.qdm; - api_hdr->hdr.cause = mbox->cmd.cause; - api_hdr->hdr.diagn = mbox->cmd.diagn; - api_hdr->hdr.length = mbox->cmd.length; - api_hdr->hdr.result = mbox->cmd.result; - api_hdr->hdr.lcn = mbox->cmd.lcn; - - if (mbox->cmd.length > 0){ - memcpy(api_hdr->data,mbox->data,mbox->cmd.length); - } - - skb->mac.raw = skb->data; - skb->pkt_type = WAN_PACKET_ERR; - - if (chan->common.func(skb,dev,chan->common.sk) < 0){ - if (bh_enqueue(dev,skb)){ - printk(KERN_INFO "%s: Dropping OOB MSG\n",card->devname); - dev_kfree_skb_any(skb); - } - } - - DBG_PRINTK(KERN_INFO "%s: OOB MSG OK, %s, lcn %i\n", - card->devname, dev->name, mbox->cmd.lcn); -} - -/*=============================================================== - * alloc_and_init_skb_buf - * - * Allocate and initialize an skb buffer. - * - *===============================================================*/ - -static int alloc_and_init_skb_buf (sdla_t *card, struct sk_buff **skb, int len) -{ - struct sk_buff *new_skb = *skb; - - new_skb = dev_alloc_skb(len + X25_HRDHDR_SZ); - if (new_skb == NULL){ - printk(KERN_INFO "%s: no socket buffers available!\n", - card->devname); - return 1; - } - - if (skb_tailroom(new_skb) < len){ - /* No room for the packet. Call off the whole thing! */ - dev_kfree_skb_any(new_skb); - printk(KERN_INFO "%s: Listen: unexpectedly long packet sequence\n" - ,card->devname); - *skb = NULL; - return 1; - } - - *skb = new_skb; - return 0; - -} - -/*=============================================================== - * api_oob_event - * - * Send an OOB event up to the sock - * - *===============================================================*/ - -static void api_oob_event (sdla_t *card,TX25Mbox *mbox) -{ - struct net_device *dev = find_channel(card, mbox->cmd.lcn); - x25_channel_t *chan; - - if (!dev) - return; - - chan=dev->priv; - - if (chan->common.usedby == API) - send_oob_msg(card,dev,mbox); - -} - - - - -static int channel_disconnect(sdla_t* card, struct net_device *dev) -{ - - int err; - x25_channel_t *chan = dev->priv; - - DBG_PRINTK(KERN_INFO "%s: TIMER: %s, Device down disconnecting\n", - card->devname,dev->name); - - if (chan->common.svc){ - err = x25_clear_call(card,chan->common.lcn,0,0); - }else{ - /* If channel is PVC or LAPB HDLC, there is no call - * to be cleared, thus drop down to the default - * area - */ - err = 1; - } - - switch (err){ - - case X25RES_CHANNEL_IN_USE: - case X25RES_NOT_READY: - err = TRY_CMD_AGAIN; - break; - case CMD_OK: - DBG_PRINTK(KERN_INFO "CALL CLEAR OK: Dev %s Chan Lcn %i\n", - dev->name,chan->common.lcn); - - set_chan_state(dev,WAN_DISCONNECTING); - atomic_set(&chan->common.command,0); - err = DELAY_RESULT; - break; - default: - /* If LAPB HDLC protocol, bring the whole link down - * once the application terminates - */ - - set_chan_state(dev,WAN_DISCONNECTED); - - if (card->u.x.LAPB_hdlc){ - DBG_PRINTK(KERN_INFO "LAPB: Disconnecting Link\n"); - hdlc_link_down (card); - } - atomic_set(&chan->common.command,0); - err = RETURN_RESULT; - break; - } - - return err; -} - -static void hdlc_link_down (sdla_t *card) -{ - TX25Mbox* mbox = card->mbox; - int retry = 5; - int err=0; - - do { - memset(mbox,0,sizeof(TX25Mbox)); - mbox->cmd.command = X25_HDLC_LINK_DISC; - mbox->cmd.length = 1; - mbox->data[0]=0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - - } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_DISC, 0)); - - if (err) - printk(KERN_INFO "%s: Hdlc Link Down Failed %x\n",card->devname,err); - - disconnect (card); - -} - -static int check_bad_command(sdla_t* card, struct net_device *dev) -{ - x25_channel_t *chan = dev->priv; - int bad_cmd = 0; - - switch (atomic_read(&chan->common.command)&0x7F){ - - case X25_PLACE_CALL: - if (chan->common.state != WAN_DISCONNECTED) - bad_cmd=1; - break; - case X25_CLEAR_CALL: - if (chan->common.state == WAN_DISCONNECTED) - bad_cmd=1; - break; - case X25_ACCEPT_CALL: - if (chan->common.state != WAN_CONNECTING) - bad_cmd=1; - break; - case X25_RESET: - if (chan->common.state != WAN_CONNECTED) - bad_cmd=1; - break; - default: - bad_cmd=1; - break; - } - - if (bad_cmd){ - printk(KERN_INFO "%s: Invalid State, BAD Command %x, dev %s, lcn %i, st %i\n", - card->devname,atomic_read(&chan->common.command),dev->name, - chan->common.lcn, chan->common.state); - } - - return bad_cmd; -} - - - -/*************************** XPIPEMON FUNCTIONS **************************/ - -/*============================================================================== - * Process UDP call of type XPIPE - */ - -static int process_udp_mgmt_pkt(sdla_t *card) -{ - int c_retry = MAX_CMD_RETRY; - unsigned int len; - struct sk_buff *new_skb; - TX25Mbox *mbox = card->mbox; - int err; - int udp_mgmt_req_valid = 1; - struct net_device *dev; - x25_channel_t *chan; - unsigned short lcn; - struct timeval tv; - - - x25_udp_pkt_t *x25_udp_pkt; - x25_udp_pkt = (x25_udp_pkt_t *)card->u.x.udp_pkt_data; - - dev = card->u.x.udp_dev; - chan = dev->priv; - lcn = chan->common.lcn; - - switch(x25_udp_pkt->cblock.command) { - - /* XPIPE_ENABLE_TRACE */ - case XPIPE_ENABLE_TRACING: - - /* XPIPE_GET_TRACE_INFO */ - case XPIPE_GET_TRACE_INFO: - - /* SET FT1 MODE */ - case XPIPE_SET_FT1_MODE: - - if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) { - ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err; - udp_mgmt_req_valid = 0; - break; - } - - /* XPIPE_FT1_READ_STATUS */ - case XPIPE_FT1_READ_STATUS: - - /* FT1 MONITOR STATUS */ - case XPIPE_FT1_STATUS_CTRL: - if(card->hw.fwid != SFID_X25_508) { - ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_type_err; - udp_mgmt_req_valid = 0; - break; - } - default: - break; - } - - if(!udp_mgmt_req_valid) { - /* set length to 0 */ - x25_udp_pkt->cblock.length = 0; - /* set return code */ - x25_udp_pkt->cblock.result = (card->hw.fwid != SFID_X25_508) ? 0x1F : 0xCD; - - } else { - - switch (x25_udp_pkt->cblock.command) { - - - case XPIPE_FLUSH_DRIVER_STATS: - init_x25_channel_struct(chan); - init_global_statistics(card); - mbox->cmd.length = 0; - break; - - - case XPIPE_DRIVER_STAT_IFSEND: - memcpy(x25_udp_pkt->data, &chan->if_send_stat, sizeof(if_send_stat_t)); - mbox->cmd.length = sizeof(if_send_stat_t); - x25_udp_pkt->cblock.length = mbox->cmd.length; - break; - - case XPIPE_DRIVER_STAT_INTR: - memcpy(&x25_udp_pkt->data[0], &card->statistics, sizeof(global_stats_t)); - memcpy(&x25_udp_pkt->data[sizeof(global_stats_t)], - &chan->rx_intr_stat, sizeof(rx_intr_stat_t)); - - mbox->cmd.length = sizeof(global_stats_t) + - sizeof(rx_intr_stat_t); - x25_udp_pkt->cblock.length = mbox->cmd.length; - break; - - case XPIPE_DRIVER_STAT_GEN: - memcpy(x25_udp_pkt->data, - &chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err, - sizeof(pipe_mgmt_stat_t)); - - memcpy(&x25_udp_pkt->data[sizeof(pipe_mgmt_stat_t)], - &card->statistics, sizeof(global_stats_t)); - - x25_udp_pkt->cblock.result = 0; - x25_udp_pkt->cblock.length = sizeof(global_stats_t)+ - sizeof(rx_intr_stat_t); - mbox->cmd.length = x25_udp_pkt->cblock.length; - break; - - case XPIPE_ROUTER_UP_TIME: - do_gettimeofday(&tv); - chan->router_up_time = tv.tv_sec - chan->router_start_time; - *(unsigned long *)&x25_udp_pkt->data = chan->router_up_time; - x25_udp_pkt->cblock.length = mbox->cmd.length = 4; - x25_udp_pkt->cblock.result = 0; - break; - - default : - - do { - memcpy(&mbox->cmd, &x25_udp_pkt->cblock.command, sizeof(TX25Cmd)); - if(mbox->cmd.length){ - memcpy(&mbox->data, - (char *)x25_udp_pkt->data, - mbox->cmd.length); - } - - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - } while (err && c_retry-- && x25_error(card, err, mbox->cmd.command, 0)); - - - if ( err == CMD_OK || - (err == 1 && - (mbox->cmd.command == 0x06 || - mbox->cmd.command == 0x16) ) ){ - - ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK; - } else { - ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_timeout; - } - - /* copy the result back to our buffer */ - memcpy(&x25_udp_pkt->cblock.command, &mbox->cmd, sizeof(TX25Cmd)); - - if(mbox->cmd.length) { - memcpy(&x25_udp_pkt->data, &mbox->data, mbox->cmd.length); - } - break; - - } //switch - - } - - /* Fill UDP TTL */ - - x25_udp_pkt->ip_pkt.ttl = card->wandev.ttl; - len = reply_udp(card->u.x.udp_pkt_data, mbox->cmd.length); - - - if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) { - - err = x25_send(card, lcn, 0, len, card->u.x.udp_pkt_data); - if (!err) - ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_passed; - else - ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_failed; - - } else { - - /* Allocate socket buffer */ - if((new_skb = dev_alloc_skb(len)) != NULL) { - void *buf; - - /* copy data into new_skb */ - buf = skb_put(new_skb, len); - memcpy(buf, card->u.x.udp_pkt_data, len); - - /* Decapsulate packet and pass it up the protocol - stack */ - new_skb->dev = dev; - - if (chan->common.usedby == API) - new_skb->protocol = htons(X25_PROT); - else - new_skb->protocol = htons(ETH_P_IP); - - new_skb->mac.raw = new_skb->data; - - netif_rx(new_skb); - ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack; - - } else { - ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket; - printk(KERN_INFO - "%s: UDP mgmt cmnd, no socket buffers available!\n", - card->devname); - } - } - - card->u.x.udp_pkt_lgth = 0; - - return 1; -} - - -/*============================================================================== - * Determine what type of UDP call it is. DRVSTATS or XPIPE8ND ? - */ -static int udp_pkt_type( struct sk_buff *skb, sdla_t* card ) -{ - x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)skb->data; - - if((x25_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) && - (x25_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) && - (x25_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) && - (x25_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) { - - if(!strncmp(x25_udp_pkt->wp_mgmt.signature, - UDPMGMT_XPIPE_SIGNATURE, 8)){ - return UDP_XPIPE_TYPE; - }else{ - printk(KERN_INFO "%s: UDP Packet, Failed Signature !\n", - card->devname); - } - } - - return UDP_INVALID_TYPE; -} - - -/*============================================================================ - * Reply to UDP Management system. - * Return nothing. - */ -static int reply_udp( unsigned char *data, unsigned int mbox_len ) -{ - unsigned short len, udp_length, temp, ip_length; - unsigned long ip_temp; - int even_bound = 0; - - - x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)data; - - /* Set length of packet */ - len = sizeof(ip_pkt_t)+ - sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - mbox_len; - - - /* fill in UDP reply */ - x25_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; - - /* fill in UDP length */ - udp_length = sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - mbox_len; - - - /* put it on an even boundary */ - if ( udp_length & 0x0001 ) { - udp_length += 1; - len += 1; - even_bound = 1; - } - - temp = (udp_length<<8)|(udp_length>>8); - x25_udp_pkt->udp_pkt.udp_length = temp; - - /* swap UDP ports */ - temp = x25_udp_pkt->udp_pkt.udp_src_port; - x25_udp_pkt->udp_pkt.udp_src_port = - x25_udp_pkt->udp_pkt.udp_dst_port; - x25_udp_pkt->udp_pkt.udp_dst_port = temp; - - - - /* add UDP pseudo header */ - temp = 0x1100; - *((unsigned short *) - (x25_udp_pkt->data+mbox_len+even_bound)) = temp; - temp = (udp_length<<8)|(udp_length>>8); - *((unsigned short *) - (x25_udp_pkt->data+mbox_len+even_bound+2)) = temp; - - /* calculate UDP checksum */ - x25_udp_pkt->udp_pkt.udp_checksum = 0; - - x25_udp_pkt->udp_pkt.udp_checksum = - calc_checksum(&data[UDP_OFFSET], udp_length+UDP_OFFSET); - - /* fill in IP length */ - ip_length = len; - temp = (ip_length<<8)|(ip_length>>8); - x25_udp_pkt->ip_pkt.total_length = temp; - - /* swap IP addresses */ - ip_temp = x25_udp_pkt->ip_pkt.ip_src_address; - x25_udp_pkt->ip_pkt.ip_src_address = - x25_udp_pkt->ip_pkt.ip_dst_address; - x25_udp_pkt->ip_pkt.ip_dst_address = ip_temp; - - - /* fill in IP checksum */ - x25_udp_pkt->ip_pkt.hdr_checksum = 0; - x25_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data, sizeof(ip_pkt_t)); - - return len; -} /* reply_udp */ - -unsigned short calc_checksum (char *data, int len) -{ - unsigned short temp; - unsigned long sum=0; - int i; - - for( i = 0; i > 16 ) { - sum = (sum & 0xffffUL) + (sum >> 16); - } - - temp = (unsigned short)sum; - temp = ~temp; - - if( temp == 0 ) - temp = 0xffff; - - return temp; -} - -/*============================================================================= - * Store a UDP management packet for later processing. - */ - -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) -{ - int udp_pkt_stored = 0; - - if(!card->u.x.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){ - card->u.x.udp_pkt_lgth = skb->len; - card->u.x.udp_type = udp_type; - card->u.x.udp_pkt_src = udp_pkt_src; - card->u.x.udp_lcn = lcn; - card->u.x.udp_dev = dev; - memcpy(card->u.x.udp_pkt_data, skb->data, skb->len); - card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UDP_PKT; - udp_pkt_stored = 1; - - }else{ - printk(KERN_INFO "%s: ERROR: UDP packet not stored for LCN %d\n", - card->devname,lcn); - } - - if(udp_pkt_src == UDP_PKT_FRM_STACK){ - dev_kfree_skb_any(skb); - }else{ - dev_kfree_skb_any(skb); - } - - return(udp_pkt_stored); -} - - - -/*============================================================================= - * Initial the ppp_private_area structure. - */ -static void init_x25_channel_struct( x25_channel_t *chan ) -{ - memset(&chan->if_send_stat.if_send_entry,0,sizeof(if_send_stat_t)); - memset(&chan->rx_intr_stat.rx_intr_no_socket,0,sizeof(rx_intr_stat_t)); - memset(&chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err,0,sizeof(pipe_mgmt_stat_t)); -} - -/*============================================================================ - * Initialize Global Statistics - */ -static void init_global_statistics( sdla_t *card ) -{ - memset(&card->statistics.isr_entry,0,sizeof(global_stats_t)); -} - - -/*=============================================================== - * SMP Support - * ==============================================================*/ - -static void S508_S514_lock(sdla_t *card, unsigned long *smp_flags) -{ - spin_lock_irqsave(&card->wandev.lock, *smp_flags); -} -static void S508_S514_unlock(sdla_t *card, unsigned long *smp_flags) -{ - spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -} - -/*=============================================================== - * x25_timer_routine - * - * A more efficient polling routine. Each half a second - * queue a polling task. We want to do the polling in a - * task not timer, because timer runs in interrupt time. - * - * FIXME Polling should be rethinked. - *==============================================================*/ - -static void x25_timer_routine(unsigned long data) -{ - sdla_t *card = (sdla_t*)data; - - if (!card->wandev.dev){ - printk(KERN_INFO "%s: Stopping the X25 Poll Timer: No Dev.\n", - card->devname); - return; - } - - if (card->open_cnt != card->u.x.num_of_ch){ - printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Interface down.\n", - card->devname); - return; - } - - if (test_bit(PERI_CRIT,&card->wandev.critical)){ - printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Shutting down.\n", - card->devname); - return; - } - - if (!test_and_set_bit(POLL_CRIT,&card->wandev.critical)){ - trigger_x25_poll(card); - } - - card->u.x.x25_timer.expires=jiffies+(HZ>>1); - add_timer(&card->u.x.x25_timer); - return; -} - -void disable_comm_shutdown(sdla_t *card) -{ - TX25Mbox* mbox = card->mbox; - int err; - - /* Turn of interrutps */ - mbox->data[0] = 0; - if (card->hw.fwid == SFID_X25_508){ - mbox->data[1] = card->hw.irq; - mbox->data[2] = 2; - mbox->cmd.length = 3; - }else { - mbox->cmd.length = 1; - } - mbox->cmd.command = X25_SET_INTERRUPT_MODE; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - if (err) - printk(KERN_INFO "INTERRUPT OFF FAIED %x\n",err); - - /* Bring down HDLC */ - mbox->cmd.command = X25_HDLC_LINK_CLOSE; - mbox->cmd.length = 0; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - if (err) - printk(KERN_INFO "LINK CLOSED FAILED %x\n",err); - - - /* Brind down DTR */ - mbox->data[0] = 0; - mbox->data[2] = 0; - mbox->data[1] = 0x01; - mbox->cmd.length = 3; - mbox->cmd.command = X25_SET_GLOBAL_VARS; - err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; - if (err) - printk(KERN_INFO "DTR DOWN FAILED %x\n",err); - -} - -MODULE_LICENSE("GPL"); - -/****** End *****************************************************************/ diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c deleted file mode 100644 index 032c0f81928e..000000000000 --- a/drivers/net/wan/sdladrv.c +++ /dev/null @@ -1,2314 +0,0 @@ -/***************************************************************************** -* sdladrv.c SDLA Support Module. Main module. -* -* This module is a library of common hardware-specific functions -* used by all Sangoma drivers. -* -* Author: Gideon Hack -* -* Copyright: (c) 1995-2000 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. -* ============================================================================ -* Mar 20, 2001 Nenad Corbic Added the auto_pci_cfg filed, to support -* the PCISLOT #0. -* Apr 04, 2000 Nenad Corbic Fixed the auto memory detection code. -* The memory test at address 0xC8000. -* Mar 09, 2000 Nenad Corbic Added Gideon's Bug Fix: clear pci -* interrupt flags on initial load. -* Jun 02, 1999 Gideon Hack Added support for the S514 adapter. -* Updates for Linux 2.2.X kernels. -* Sep 17, 1998 Jaspreet Singh Updates for linux 2.2.X kernels -* Dec 20, 1996 Gene Kozin Version 3.0.0. Complete overhaul. -* Jul 12, 1996 Gene Kozin Changes for Linux 2.0 compatibility. -* Jun 12, 1996 Gene Kozin Added support for S503 card. -* Apr 30, 1996 Gene Kozin SDLA hardware interrupt is acknowledged before -* calling protocolspecific ISR. -* Register I/O ports with Linux kernel. -* Miscellaneous bug fixes. -* Dec 20, 1995 Gene Kozin Fixed a bug in interrupt routine. -* Oct 14, 1995 Gene Kozin Initial version. -*****************************************************************************/ - -/***************************************************************************** - * Notes: - * ------ - * 1. This code is ment to be system-independent (as much as possible). To - * achive this, various macros are used to hide system-specific interfaces. - * To compile this code, one of the following constants must be defined: - * - * Platform Define - * -------- ------ - * Linux _LINUX_ - * SCO Unix _SCO_UNIX_ - * - * 2. Supported adapter types: - * - * S502A - * ES502A (S502E) - * S503 - * S507 - * S508 (S509) - * - * 3. S502A Notes: - * - * There is no separate DPM window enable/disable control in S502A. It - * opens immediately after a window number it written to the HMCR - * register. To close the window, HMCR has to be written a value - * ????1111b (e.g. 0x0F or 0xFF). - * - * S502A DPM window cannot be located at offset E000 (e.g. 0xAE000). - * - * There should be a delay of ??? before reading back S502A status - * register. - * - * 4. S502E Notes: - * - * S502E has a h/w bug: although default IRQ line state is HIGH, enabling - * interrupts by setting bit 1 of the control register (BASE) to '1' - * causes it to go LOW! Therefore, disabling interrupts by setting that - * bit to '0' causes low-to-high transition on IRQ line (ghosty - * interrupt). The same occurs when disabling CPU by resetting bit 0 of - * CPU control register (BASE+3) - see the next note. - * - * S502E CPU and DPM control is limited: - * - * o CPU cannot be stopped independently. Resetting bit 0 of the CPUi - * control register (BASE+3) shuts the board down entirely, including - * DPM; - * - * o DPM access cannot be controlled dynamically. Ones CPU is started, - * bit 1 of the control register (BASE) is used to enable/disable IRQ, - * so that access to shared memory cannot be disabled while CPU is - * running. - ****************************************************************************/ - -#define _LINUX_ - -#if defined(_LINUX_) /****** Linux *******************************/ - -#include -#include /* printk(), and other useful stuff */ -#include /* offsetof(), etc. */ -#include /* return codes */ -#include /* inline memset(), etc. */ -#include /* support for loadable modules */ -#include /* for jiffies, HZ, etc. */ -#include /* API definitions */ -#include /* SDLA firmware module definitions */ -#include /* SDLA PCI hardware definitions */ -#include /* PCI defines and function prototypes */ -#include /* for inb(), outb(), etc. */ - -#define _INB(port) (inb(port)) -#define _OUTB(port, byte) (outb((byte),(port))) -#define SYSTEM_TICK jiffies - -#include - - -#elif defined(_SCO_UNIX_) /****** SCO Unix ****************************/ - -#if !defined(INKERNEL) -#error This code MUST be compiled in kernel mode! -#endif -#include /* API definitions */ -#include /* SDLA firmware module definitions */ -#include /* for inb(), outb(), etc. */ -#define _INB(port) (inb(port)) -#define _OUTB(port, byte) (outb((port),(byte))) -#define SYSTEM_TICK lbolt - -#else -#error Unknown system type! -#endif - -#define MOD_VERSION 3 -#define MOD_RELEASE 0 - -#define SDLA_IODELAY 100 /* I/O Rd/Wr delay, 10 works for 486DX2-66 */ -#define EXEC_DELAY 20 /* shared memory access delay, mks */ -#define EXEC_TIMEOUT (HZ*2) /* command timeout, in ticks */ - -/* I/O port address range */ -#define S502A_IORANGE 3 -#define S502E_IORANGE 4 -#define S503_IORANGE 3 -#define S507_IORANGE 4 -#define S508_IORANGE 4 - -/* Maximum amount of memory */ -#define S502_MAXMEM 0x10000L -#define S503_MAXMEM 0x10000L -#define S507_MAXMEM 0x40000L -#define S508_MAXMEM 0x40000L - -/* Minimum amount of memory */ -#define S502_MINMEM 0x8000L -#define S503_MINMEM 0x8000L -#define S507_MINMEM 0x20000L -#define S508_MINMEM 0x20000L -#define NO_PORT -1 - - - - - -/****** Function Prototypes *************************************************/ - -/* Hardware-specific functions */ -static int sdla_detect (sdlahw_t* hw); -static int sdla_autodpm (sdlahw_t* hw); -static int sdla_setdpm (sdlahw_t* hw); -static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len); -static int sdla_init (sdlahw_t* hw); -static unsigned long sdla_memtest (sdlahw_t* hw); -static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo); -static unsigned char make_config_byte (sdlahw_t* hw); -static int sdla_start (sdlahw_t* hw, unsigned addr); - -static int init_s502a (sdlahw_t* hw); -static int init_s502e (sdlahw_t* hw); -static int init_s503 (sdlahw_t* hw); -static int init_s507 (sdlahw_t* hw); -static int init_s508 (sdlahw_t* hw); - -static int detect_s502a (int port); -static int detect_s502e (int port); -static int detect_s503 (int port); -static int detect_s507 (int port); -static int detect_s508 (int port); -static int detect_s514 (sdlahw_t* hw); -static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card); - -/* Miscellaneous functions */ -static void peek_by_4 (unsigned long src, void* buf, unsigned len); -static void poke_by_4 (unsigned long dest, void* buf, unsigned len); -static int calibrate_delay (int mks); -static int get_option_index (unsigned* optlist, unsigned optval); -static unsigned check_memregion (void* ptr, unsigned len); -static unsigned test_memregion (void* ptr, unsigned len); -static unsigned short checksum (unsigned char* buf, unsigned len); -static int init_pci_slot(sdlahw_t *); - -static int pci_probe(sdlahw_t *hw); - -/****** Global Data ********************************************************** - * Note: All data must be explicitly initialized!!! - */ - -static struct pci_device_id sdladrv_pci_tbl[] = { - { V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(pci, sdladrv_pci_tbl); - -MODULE_LICENSE("GPL"); - -/* private data */ -static char modname[] = "sdladrv"; -static char fullname[] = "SDLA Support Module"; -static char copyright[] = "(c) 1995-1999 Sangoma Technologies Inc."; -static unsigned exec_idle; - -/* Hardware configuration options. - * These are arrays of configuration options used by verification routines. - * The first element of each array is its size (i.e. number of options). - */ -static unsigned s502_port_options[] = - { 4, 0x250, 0x300, 0x350, 0x360 } -; -static unsigned s503_port_options[] = - { 8, 0x250, 0x254, 0x300, 0x304, 0x350, 0x354, 0x360, 0x364 } -; -static unsigned s508_port_options[] = - { 8, 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390 } -; - -static unsigned s502a_irq_options[] = { 0 }; -static unsigned s502e_irq_options[] = { 4, 2, 3, 5, 7 }; -static unsigned s503_irq_options[] = { 5, 2, 3, 4, 5, 7 }; -static unsigned s508_irq_options[] = { 8, 3, 4, 5, 7, 10, 11, 12, 15 }; - -static unsigned s502a_dpmbase_options[] = -{ - 28, - 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, - 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, - 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, - 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, -}; -static unsigned s507_dpmbase_options[] = -{ - 32, - 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000, - 0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000, - 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000, - 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000, -}; -static unsigned s508_dpmbase_options[] = /* incl. S502E and S503 */ -{ - 32, - 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000, - 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000, - 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000, - 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000, -}; - -/* -static unsigned s502_dpmsize_options[] = { 2, 0x2000, 0x10000 }; -static unsigned s507_dpmsize_options[] = { 2, 0x2000, 0x4000 }; -static unsigned s508_dpmsize_options[] = { 1, 0x2000 }; -*/ - -static unsigned s502a_pclk_options[] = { 2, 3600, 7200 }; -static unsigned s502e_pclk_options[] = { 5, 3600, 5000, 7200, 8000, 10000 }; -static unsigned s503_pclk_options[] = { 3, 7200, 8000, 10000 }; -static unsigned s507_pclk_options[] = { 1, 12288 }; -static unsigned s508_pclk_options[] = { 1, 16000 }; - -/* Host memory control register masks */ -static unsigned char s502a_hmcr[] = -{ - 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, /* A0000 - AC000 */ - 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, /* C0000 - CC000 */ - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, /* D0000 - DC000 */ - 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, /* E0000 - EC000 */ -}; -static unsigned char s502e_hmcr[] = -{ - 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, /* A0000 - AE000 */ - 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, /* C0000 - CE000 */ - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* D0000 - DE000 */ - 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E, /* E0000 - EE000 */ -}; -static unsigned char s507_hmcr[] = -{ - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* A0000 - AE000 */ - 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, /* B0000 - BE000 */ - 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, /* C0000 - CE000 */ - 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, /* E0000 - EE000 */ -}; -static unsigned char s508_hmcr[] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* A0000 - AE000 */ - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* C0000 - CE000 */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* D0000 - DE000 */ - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* E0000 - EE000 */ -}; - -static unsigned char s507_irqmask[] = -{ - 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0 -}; - -static int pci_slot_ar[MAX_S514_CARDS]; - -/******* Kernel Loadable Module Entry Points ********************************/ - -/*============================================================================ - * Module 'insert' entry point. - * o print announcement - * o initialize static data - * o calibrate SDLA shared memory access delay. - * - * Return: 0 Ok - * < 0 error. - * Context: process - */ - -static int __init sdladrv_init(void) -{ - int i=0; - - printk(KERN_INFO "%s v%u.%u %s\n", - fullname, MOD_VERSION, MOD_RELEASE, copyright); - exec_idle = calibrate_delay(EXEC_DELAY); -#ifdef WANDEBUG - printk(KERN_DEBUG "%s: exec_idle = %d\n", modname, exec_idle); -#endif - - /* Initialize the PCI Card array, which - * will store flags, used to mark - * card initialization state */ - for (i=0; itype != SDLA_S514) - printk(KERN_INFO "%s: no SDLA card found at port 0x%X\n", - modname, hw->port); - return -EINVAL; - } - - if(hw->type != SDLA_S514) { - printk(KERN_INFO "%s: found S%04u card at port 0x%X.\n", - modname, hw->type, hw->port); - - hw->dpmsize = SDLA_WINDOWSIZE; - switch (hw->type) { - case SDLA_S502A: - hw->io_range = S502A_IORANGE; - irq_opt = s502a_irq_options; - dpmbase_opt = s502a_dpmbase_options; - pclk_opt = s502a_pclk_options; - break; - - case SDLA_S502E: - hw->io_range = S502E_IORANGE; - irq_opt = s502e_irq_options; - dpmbase_opt = s508_dpmbase_options; - pclk_opt = s502e_pclk_options; - break; - - case SDLA_S503: - hw->io_range = S503_IORANGE; - irq_opt = s503_irq_options; - dpmbase_opt = s508_dpmbase_options; - pclk_opt = s503_pclk_options; - break; - - case SDLA_S507: - hw->io_range = S507_IORANGE; - irq_opt = s508_irq_options; - dpmbase_opt = s507_dpmbase_options; - pclk_opt = s507_pclk_options; - break; - - case SDLA_S508: - hw->io_range = S508_IORANGE; - irq_opt = s508_irq_options; - dpmbase_opt = s508_dpmbase_options; - pclk_opt = s508_pclk_options; - break; - } - - /* Verify IRQ configuration options */ - if (!get_option_index(irq_opt, hw->irq)) { - printk(KERN_INFO "%s: IRQ %d is invalid!\n", - modname, hw->irq); - return -EINVAL; - } - - /* Verify CPU clock rate configuration options */ - if (hw->pclk == 0) - hw->pclk = pclk_opt[1]; /* use default */ - - else if (!get_option_index(pclk_opt, hw->pclk)) { - printk(KERN_INFO "%s: CPU clock %u is invalid!\n", - modname, hw->pclk); - return -EINVAL; - } - printk(KERN_INFO "%s: assuming CPU clock rate of %u kHz.\n", - modname, hw->pclk); - - /* Setup adapter dual-port memory window and test memory */ - if (hw->dpmbase == 0) { - err = sdla_autodpm(hw); - if (err) { - printk(KERN_INFO - "%s: can't find available memory region!\n", - modname); - return err; - } - } - else if (!get_option_index(dpmbase_opt, - virt_to_phys(hw->dpmbase))) { - printk(KERN_INFO - "%s: memory address 0x%lX is invalid!\n", - modname, virt_to_phys(hw->dpmbase)); - return -EINVAL; - } - else if (sdla_setdpm(hw)) { - printk(KERN_INFO - "%s: 8K memory region at 0x%lX is not available!\n", - modname, virt_to_phys(hw->dpmbase)); - return -EINVAL; - } - printk(KERN_INFO - "%s: dual-port memory window is set at 0x%lX.\n", - modname, virt_to_phys(hw->dpmbase)); - - - /* If we find memory in 0xE**** Memory region, - * warn the user to disable the SHADOW RAM. - * Since memory corruption can occur if SHADOW is - * enabled. This can causes random crashes ! */ - if (virt_to_phys(hw->dpmbase) >= 0xE0000){ - printk(KERN_WARNING "\n%s: !!!!!!!! WARNING !!!!!!!!\n",modname); - printk(KERN_WARNING "%s: WANPIPE is using 0x%lX memory region !!!\n", - modname, virt_to_phys(hw->dpmbase)); - printk(KERN_WARNING " Please disable the SHADOW RAM, otherwise\n"); - printk(KERN_WARNING " your system might crash randomly from time to time !\n"); - printk(KERN_WARNING "%s: !!!!!!!! WARNING !!!!!!!!\n\n",modname); - } - } - - else { - hw->memory = test_memregion((void*)hw->dpmbase, - MAX_SIZEOF_S514_MEMORY); - if(hw->memory < (256 * 1024)) { - printk(KERN_INFO - "%s: error in testing S514 memory (0x%lX)\n", - modname, hw->memory); - sdla_down(hw); - return -EINVAL; - } - } - - printk(KERN_INFO "%s: found %luK bytes of on-board memory\n", - modname, hw->memory / 1024); - - /* Load firmware. If loader fails then shut down adapter */ - err = sdla_load(hw, sfm, len); - if (err) sdla_down(hw); /* shutdown adapter */ - - return err; -} - -/*============================================================================ - * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc. - */ - -EXPORT_SYMBOL(sdla_down); - -int sdla_down (sdlahw_t* hw) -{ - unsigned port = hw->port; - int i; - unsigned char CPU_no; - u32 int_config, int_status; - - if(!port && (hw->type != SDLA_S514)) - return -EFAULT; - - switch (hw->type) { - case SDLA_S502A: - _OUTB(port, 0x08); /* halt CPU */ - _OUTB(port, 0x08); - _OUTB(port, 0x08); - hw->regs[0] = 0x08; - _OUTB(port + 1, 0xFF); /* close memory window */ - hw->regs[1] = 0xFF; - break; - - case SDLA_S502E: - _OUTB(port + 3, 0); /* stop CPU */ - _OUTB(port, 0); /* reset board */ - for (i = 0; i < S502E_IORANGE; ++i) - hw->regs[i] = 0 - ; - break; - - case SDLA_S503: - case SDLA_S507: - case SDLA_S508: - _OUTB(port, 0); /* reset board logic */ - hw->regs[0] = 0; - break; - - case SDLA_S514: - /* halt the adapter */ - *(char *)hw->vector = S514_CPU_HALT; - CPU_no = hw->S514_cpu_no[0]; - - /* disable the PCI IRQ and disable memory access */ - pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config); - int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A : ~PCI_DISABLE_IRQ_CPU_B; - pci_write_config_dword(hw->pci_dev, PCI_INT_CONFIG, int_config); - read_S514_int_stat(hw, &int_status); - S514_intack(hw, int_status); - if(CPU_no == S514_CPU_A) - pci_write_config_dword(hw->pci_dev, PCI_MAP0_DWORD, - PCI_CPU_A_MEM_DISABLE); - else - pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD, - PCI_CPU_B_MEM_DISABLE); - - /* free up the allocated virtual memory */ - iounmap((void *)hw->dpmbase); - iounmap((void *)hw->vector); - break; - - - default: - return -EINVAL; - } - return 0; -} - -/*============================================================================ - * Map shared memory window into SDLA address space. - */ - -EXPORT_SYMBOL(sdla_mapmem); - -int sdla_mapmem (sdlahw_t* hw, unsigned long addr) -{ - unsigned port = hw->port; - register int tmp; - - switch (hw->type) { - case SDLA_S502A: - case SDLA_S502E: - if (addr < S502_MAXMEM) { /* verify parameter */ - tmp = addr >> 13; /* convert to register mask */ - _OUTB(port + 2, tmp); - hw->regs[2] = tmp; - } - else return -EINVAL; - break; - - case SDLA_S503: - if (addr < S503_MAXMEM) { /* verify parameter */ - tmp = (hw->regs[0] & 0x8F) | ((addr >> 9) & 0x70); - _OUTB(port, tmp); - hw->regs[0] = tmp; - } - else return -EINVAL; - break; - - case SDLA_S507: - if (addr < S507_MAXMEM) { - if (!(_INB(port) & 0x02)) - return -EIO; - tmp = addr >> 13; /* convert to register mask */ - _OUTB(port + 2, tmp); - hw->regs[2] = tmp; - } - else return -EINVAL; - break; - - case SDLA_S508: - if (addr < S508_MAXMEM) { - tmp = addr >> 13; /* convert to register mask */ - _OUTB(port + 2, tmp); - hw->regs[2] = tmp; - } - else return -EINVAL; - break; - - case SDLA_S514: - return 0; - - default: - return -EINVAL; - } - hw->vector = addr & 0xFFFFE000L; - return 0; -} - -/*============================================================================ - * Enable interrupt generation. - */ - -static int sdla_inten (sdlahw_t* hw) -{ - unsigned port = hw->port; - int tmp, i; - - switch (hw->type) { - case SDLA_S502E: - /* Note thar interrupt control operations on S502E are allowed - * only if CPU is enabled (bit 0 of status register is set). - */ - if (_INB(port) & 0x01) { - _OUTB(port, 0x02); /* bit1 = 1, bit2 = 0 */ - _OUTB(port, 0x06); /* bit1 = 1, bit2 = 1 */ - hw->regs[0] = 0x06; - } - else return -EIO; - break; - - case SDLA_S503: - tmp = hw->regs[0] | 0x04; - _OUTB(port, tmp); - hw->regs[0] = tmp; /* update mirror */ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (!(_INB(port) & 0x02)) /* verify */ - return -EIO; - break; - - case SDLA_S508: - tmp = hw->regs[0] | 0x10; - _OUTB(port, tmp); - hw->regs[0] = tmp; /* update mirror */ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (!(_INB(port + 1) & 0x10)) /* verify */ - return -EIO; - break; - - case SDLA_S502A: - case SDLA_S507: - break; - - case SDLA_S514: - break; - - default: - return -EINVAL; - - } - return 0; -} - -/*============================================================================ - * Disable interrupt generation. - */ - -#if 0 -int sdla_intde (sdlahw_t* hw) -{ - unsigned port = hw->port; - int tmp, i; - - switch (hw->type) { - case SDLA_S502E: - /* Notes: - * 1) interrupt control operations are allowed only if CPU is - * enabled (bit 0 of status register is set). - * 2) disabling interrupts using bit 1 of control register - * causes IRQ line go high, therefore we are going to use - * 0x04 instead: lower it to inhibit interrupts to PC. - */ - if (_INB(port) & 0x01) { - _OUTB(port, hw->regs[0] & ~0x04); - hw->regs[0] &= ~0x04; - } - else return -EIO; - break; - - case SDLA_S503: - tmp = hw->regs[0] & ~0x04; - _OUTB(port, tmp); - hw->regs[0] = tmp; /* update mirror */ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (_INB(port) & 0x02) /* verify */ - return -EIO; - break; - - case SDLA_S508: - tmp = hw->regs[0] & ~0x10; - _OUTB(port, tmp); - hw->regs[0] = tmp; /* update mirror */ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (_INB(port) & 0x10) /* verify */ - return -EIO; - break; - - case SDLA_S502A: - case SDLA_S507: - break; - - default: - return -EINVAL; - } - return 0; -} -#endif /* 0 */ - -/*============================================================================ - * Acknowledge SDLA hardware interrupt. - */ - -static int sdla_intack (sdlahw_t* hw) -{ - unsigned port = hw->port; - int tmp; - - switch (hw->type) { - case SDLA_S502E: - /* To acknoledge hardware interrupt we have to toggle bit 3 of - * control register: \_/ - * Note that interrupt control operations on S502E are allowed - * only if CPU is enabled (bit 1 of status register is set). - */ - if (_INB(port) & 0x01) { - tmp = hw->regs[0] & ~0x04; - _OUTB(port, tmp); - tmp |= 0x04; - _OUTB(port, tmp); - hw->regs[0] = tmp; - } - else return -EIO; - break; - - case SDLA_S503: - if (_INB(port) & 0x04) { - tmp = hw->regs[0] & ~0x08; - _OUTB(port, tmp); - tmp |= 0x08; - _OUTB(port, tmp); - hw->regs[0] = tmp; - } - break; - - case SDLA_S502A: - case SDLA_S507: - case SDLA_S508: - break; - - default: - return -EINVAL; - } - return 0; -} - - -/*============================================================================ - * Acknowledge S514 hardware interrupt. - */ - -EXPORT_SYMBOL(S514_intack); - -void S514_intack (sdlahw_t* hw, u32 int_status) -{ - pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status); -} - - -/*============================================================================ - * Read the S514 hardware interrupt status. - */ - -EXPORT_SYMBOL(read_S514_int_stat); - -void read_S514_int_stat (sdlahw_t* hw, u32* int_status) -{ - pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status); -} - - -/*============================================================================ - * Generate an interrupt to adapter's CPU. - */ - -#if 0 -int sdla_intr (sdlahw_t* hw) -{ - unsigned port = hw->port; - - switch (hw->type) { - case SDLA_S502A: - if (!(_INB(port) & 0x40)) { - _OUTB(port, 0x10); /* issue NMI to CPU */ - hw->regs[0] = 0x10; - } - else return -EIO; - break; - - case SDLA_S507: - if ((_INB(port) & 0x06) == 0x06) { - _OUTB(port + 3, 0); - } - else return -EIO; - break; - - case SDLA_S508: - if (_INB(port + 1) & 0x02) { - _OUTB(port, 0x08); - } - else return -EIO; - break; - - case SDLA_S502E: - case SDLA_S503: - default: - return -EINVAL; - } - return 0; -} -#endif /* 0 */ - -/*============================================================================ - * Execute Adapter Command. - * o Set exec flag. - * o Busy-wait until flag is reset. - * o Return number of loops made, or 0 if command timed out. - */ - -EXPORT_SYMBOL(sdla_exec); - -int sdla_exec (void* opflag) -{ - volatile unsigned char* flag = opflag; - unsigned long tstop; - int nloops; - - if(readb(flag) != 0x00) { - printk(KERN_INFO - "WANPIPE: opp flag set on entry to sdla_exec\n"); - return 0; - } - - writeb(0x01, flag); - - tstop = SYSTEM_TICK + EXEC_TIMEOUT; - - for (nloops = 1; (readb(flag) == 0x01); ++ nloops) { - unsigned delay = exec_idle; - while (-- delay); /* delay */ - if (SYSTEM_TICK > tstop) return 0; /* time is up! */ - } - return nloops; -} - -/*============================================================================ - * Read absolute adapter memory. - * Transfer data from adapter's memory to data buffer. - * - * Note: - * Care should be taken when crossing dual-port memory window boundary. - * This function is not atomic, so caller must disable interrupt if - * interrupt routines are accessing adapter shared memory. - */ - -EXPORT_SYMBOL(sdla_peek); - -int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) -{ - - if (addr + len > hw->memory) /* verify arguments */ - return -EINVAL; - - if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */ - peek_by_4 ((unsigned long)hw->dpmbase + addr, buf, len); - return 0; - } - - else { /* copy data for the S508 adapter */ - unsigned long oldvec = hw->vector; - unsigned winsize = hw->dpmsize; - unsigned curpos, curlen; /* current offset and block size */ - unsigned long curvec; /* current DPM window vector */ - int err = 0; - - while (len && !err) { - curpos = addr % winsize; /* current window offset */ - curvec = addr - curpos; /* current window vector */ - curlen = (len > (winsize - curpos)) ? - (winsize - curpos) : len; - /* Relocate window and copy block of data */ - err = sdla_mapmem(hw, curvec); - peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf, - curlen); - addr += curlen; - buf = (char*)buf + curlen; - len -= curlen; - } - - /* Restore DPM window position */ - sdla_mapmem(hw, oldvec); - return err; - } -} - - -/*============================================================================ - * Read data from adapter's memory to a data buffer in 4-byte chunks. - * Note that we ensure that the SDLA memory address is on a 4-byte boundary - * before we begin moving the data in 4-byte chunks. -*/ - -static void peek_by_4 (unsigned long src, void* buf, unsigned len) -{ - - /* byte copy data until we get to a 4-byte boundary */ - while (len && (src & 0x03)) { - *(char *)buf ++ = readb(src ++); - len --; - } - - /* copy data in 4-byte chunks */ - while (len >= 4) { - *(unsigned long *)buf = readl(src); - buf += 4; - src += 4; - len -= 4; - } - - /* byte copy any remaining data */ - while (len) { - *(char *)buf ++ = readb(src ++); - len --; - } -} - - -/*============================================================================ - * Write Absolute Adapter Memory. - * Transfer data from data buffer to adapter's memory. - * - * Note: - * Care should be taken when crossing dual-port memory window boundary. - * This function is not atomic, so caller must disable interrupt if - * interrupt routines are accessing adapter shared memory. - */ - -EXPORT_SYMBOL(sdla_poke); - -int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) -{ - - if (addr + len > hw->memory) /* verify arguments */ - return -EINVAL; - - if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */ - poke_by_4 ((unsigned long)hw->dpmbase + addr, buf, len); - return 0; - } - - else { /* copy data for the S508 adapter */ - unsigned long oldvec = hw->vector; - unsigned winsize = hw->dpmsize; - unsigned curpos, curlen; /* current offset and block size */ - unsigned long curvec; /* current DPM window vector */ - int err = 0; - - while (len && !err) { - curpos = addr % winsize; /* current window offset */ - curvec = addr - curpos; /* current window vector */ - curlen = (len > (winsize - curpos)) ? - (winsize - curpos) : len; - /* Relocate window and copy block of data */ - sdla_mapmem(hw, curvec); - poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf, - curlen); - addr += curlen; - buf = (char*)buf + curlen; - len -= curlen; - } - - /* Restore DPM window position */ - sdla_mapmem(hw, oldvec); - return err; - } -} - - -/*============================================================================ - * Write from a data buffer to adapter's memory in 4-byte chunks. - * Note that we ensure that the SDLA memory address is on a 4-byte boundary - * before we begin moving the data in 4-byte chunks. -*/ - -static void poke_by_4 (unsigned long dest, void* buf, unsigned len) -{ - - /* byte copy data until we get to a 4-byte boundary */ - while (len && (dest & 0x03)) { - writeb (*(char *)buf ++, dest ++); - len --; - } - - /* copy data in 4-byte chunks */ - while (len >= 4) { - writel (*(unsigned long *)buf, dest); - dest += 4; - buf += 4; - len -= 4; - } - - /* byte copy any remaining data */ - while (len) { - writeb (*(char *)buf ++ , dest ++); - len --; - } -} - - -#ifdef DONT_COMPIPLE_THIS -#endif /* DONT_COMPIPLE_THIS */ - -/****** Hardware-Specific Functions *****************************************/ - -/*============================================================================ - * Detect adapter type. - * o if adapter type is specified then call detection routine for that adapter - * type. Otherwise call detection routines for every adapter types until - * adapter is detected. - * - * Notes: - * 1) Detection tests are destructive! Adapter will be left in shutdown state - * after the test. - */ -static int sdla_detect (sdlahw_t* hw) -{ - unsigned port = hw->port; - int err = 0; - - if (!port && (hw->type != SDLA_S514)) - return -EFAULT; - - switch (hw->type) { - case SDLA_S502A: - if (!detect_s502a(port)) err = -ENODEV; - break; - - case SDLA_S502E: - if (!detect_s502e(port)) err = -ENODEV; - break; - - case SDLA_S503: - if (!detect_s503(port)) err = -ENODEV; - break; - - case SDLA_S507: - if (!detect_s507(port)) err = -ENODEV; - break; - - case SDLA_S508: - if (!detect_s508(port)) err = -ENODEV; - break; - - case SDLA_S514: - if (!detect_s514(hw)) err = -ENODEV; - break; - - default: - if (detect_s502a(port)) - hw->type = SDLA_S502A; - else if (detect_s502e(port)) - hw->type = SDLA_S502E; - else if (detect_s503(port)) - hw->type = SDLA_S503; - else if (detect_s507(port)) - hw->type = SDLA_S507; - else if (detect_s508(port)) - hw->type = SDLA_S508; - else err = -ENODEV; - } - return err; -} - -/*============================================================================ - * Autoselect memory region. - * o try all available DMP address options from the top down until success. - */ -static int sdla_autodpm (sdlahw_t* hw) -{ - int i, err = -EINVAL; - unsigned* opt; - - switch (hw->type) { - case SDLA_S502A: - opt = s502a_dpmbase_options; - break; - - case SDLA_S502E: - case SDLA_S503: - case SDLA_S508: - opt = s508_dpmbase_options; - break; - - case SDLA_S507: - opt = s507_dpmbase_options; - break; - - default: - return -EINVAL; - } - - /* Start testing from 8th position, address - * 0xC8000 from the 508 address table. - * We don't want to test A**** addresses, since - * they are usually used for Video */ - for (i = 8; i <= opt[0] && err; i++) { - hw->dpmbase = phys_to_virt(opt[i]); - err = sdla_setdpm(hw); - } - return err; -} - -/*============================================================================ - * Set up adapter dual-port memory window. - * o shut down adapter - * o make sure that no physical memory exists in this region, i.e entire - * region reads 0xFF and is not writable when adapter is shut down. - * o initialize adapter hardware - * o make sure that region is usable with SDLA card, i.e. we can write to it - * when adapter is configured. - */ -static int sdla_setdpm (sdlahw_t* hw) -{ - int err; - - /* Shut down card and verify memory region */ - sdla_down(hw); - if (check_memregion(hw->dpmbase, hw->dpmsize)) - return -EINVAL; - - /* Initialize adapter and test on-board memory segment by segment. - * If memory size appears to be less than shared memory window size, - * assume that memory region is unusable. - */ - err = sdla_init(hw); - if (err) return err; - - if (sdla_memtest(hw) < hw->dpmsize) { /* less than window size */ - sdla_down(hw); - return -EIO; - } - sdla_mapmem(hw, 0L); /* set window vector at bottom */ - return 0; -} - -/*============================================================================ - * Load adapter from the memory image of the SDLA firmware module. - * o verify firmware integrity and compatibility - * o start adapter up - */ -static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len) -{ - - int i; - - /* Verify firmware signature */ - if (strcmp(sfm->signature, SFM_SIGNATURE)) { - printk(KERN_INFO "%s: not SDLA firmware!\n", - modname); - return -EINVAL; - } - - /* Verify firmware module format version */ - if (sfm->version != SFM_VERSION) { - printk(KERN_INFO - "%s: firmware format %u rejected! Expecting %u.\n", - modname, sfm->version, SFM_VERSION); - return -EINVAL; - } - - /* Verify firmware module length and checksum */ - if ((len - offsetof(sfm_t, image) != sfm->info.codesize) || - (checksum((void*)&sfm->info, - sizeof(sfm_info_t) + sfm->info.codesize) != sfm->checksum)) { - printk(KERN_INFO "%s: firmware corrupted!\n", modname); - return -EINVAL; - } - - /* Announce */ - printk(KERN_INFO "%s: loading %s (ID=%u)...\n", modname, - (sfm->descr[0] != '\0') ? sfm->descr : "unknown firmware", - sfm->info.codeid); - - if(hw->type == SDLA_S514) - printk(KERN_INFO "%s: loading S514 adapter, CPU %c\n", - modname, hw->S514_cpu_no[0]); - - /* Scan through the list of compatible adapters and make sure our - * adapter type is listed. - */ - for (i = 0; - (i < SFM_MAX_SDLA) && (sfm->info.adapter[i] != hw->type); - ++i); - - if (i == SFM_MAX_SDLA) { - printk(KERN_INFO "%s: firmware is not compatible with S%u!\n", - modname, hw->type); - return -EINVAL; - } - - - /* Make sure there is enough on-board memory */ - if (hw->memory < sfm->info.memsize) { - printk(KERN_INFO - "%s: firmware needs %lu bytes of on-board memory!\n", - modname, sfm->info.memsize); - return -EINVAL; - } - - /* Move code onto adapter */ - if (sdla_poke(hw, sfm->info.codeoffs, sfm->image, sfm->info.codesize)) { - printk(KERN_INFO "%s: failed to load code segment!\n", - modname); - return -EIO; - } - - /* Prepare boot-time configuration data and kick-off CPU */ - sdla_bootcfg(hw, &sfm->info); - if (sdla_start(hw, sfm->info.startoffs)) { - printk(KERN_INFO "%s: Damn... Adapter won't start!\n", - modname); - return -EIO; - } - - /* position DPM window over the mailbox and enable interrupts */ - if (sdla_mapmem(hw, sfm->info.winoffs) || sdla_inten(hw)) { - printk(KERN_INFO "%s: adapter hardware failure!\n", - modname); - return -EIO; - } - hw->fwid = sfm->info.codeid; /* set firmware ID */ - return 0; -} - -/*============================================================================ - * Initialize SDLA hardware: setup memory window, IRQ, etc. - */ -static int sdla_init (sdlahw_t* hw) -{ - int i; - - for (i = 0; i < SDLA_MAXIORANGE; ++i) - hw->regs[i] = 0; - - switch (hw->type) { - case SDLA_S502A: return init_s502a(hw); - case SDLA_S502E: return init_s502e(hw); - case SDLA_S503: return init_s503(hw); - case SDLA_S507: return init_s507(hw); - case SDLA_S508: return init_s508(hw); - } - return -EINVAL; -} - -/*============================================================================ - * Test adapter on-board memory. - * o slide DPM window from the bottom up and test adapter memory segment by - * segment. - * Return adapter memory size. - */ -static unsigned long sdla_memtest (sdlahw_t* hw) -{ - unsigned long memsize; - unsigned winsize; - - for (memsize = 0, winsize = hw->dpmsize; - !sdla_mapmem(hw, memsize) && - (test_memregion(hw->dpmbase, winsize) == winsize) - ; - memsize += winsize) - ; - hw->memory = memsize; - return memsize; -} - -/*============================================================================ - * Prepare boot-time firmware configuration data. - * o position DPM window - * o initialize configuration data area - */ -static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo) -{ - unsigned char* data; - - if (!sfminfo->datasize) return 0; /* nothing to do */ - - if (sdla_mapmem(hw, sfminfo->dataoffs) != 0) - return -EIO; - - if(hw->type == SDLA_S514) - data = (void*)(hw->dpmbase + sfminfo->dataoffs); - else - data = (void*)((u8 *)hw->dpmbase + - (sfminfo->dataoffs - hw->vector)); - - memset_io (data, 0, sfminfo->datasize); - - writeb (make_config_byte(hw), &data[0x00]); - - switch (sfminfo->codeid) { - case SFID_X25_502: - case SFID_X25_508: - writeb (3, &data[0x01]); /* T1 timer */ - writeb (10, &data[0x03]); /* N2 */ - writeb (7, &data[0x06]); /* HDLC window size */ - writeb (1, &data[0x0B]); /* DTE */ - writeb (2, &data[0x0C]); /* X.25 packet window size */ - writew (128, &data[0x0D]); /* default X.25 data size */ - writew (128, &data[0x0F]); /* maximum X.25 data size */ - break; - } - return 0; -} - -/*============================================================================ - * Prepare configuration byte identifying adapter type and CPU clock rate. - */ -static unsigned char make_config_byte (sdlahw_t* hw) -{ - unsigned char byte = 0; - - switch (hw->pclk) { - case 5000: byte = 0x01; break; - case 7200: byte = 0x02; break; - case 8000: byte = 0x03; break; - case 10000: byte = 0x04; break; - case 16000: byte = 0x05; break; - } - - switch (hw->type) { - case SDLA_S502E: byte |= 0x80; break; - case SDLA_S503: byte |= 0x40; break; - } - return byte; -} - -/*============================================================================ - * Start adapter's CPU. - * o calculate a pointer to adapter's cold boot entry point - * o position DPM window - * o place boot instruction (jp addr) at cold boot entry point - * o start CPU - */ -static int sdla_start (sdlahw_t* hw, unsigned addr) -{ - unsigned port = hw->port; - unsigned char *bootp; - int err, tmp, i; - - if (!port && (hw->type != SDLA_S514)) return -EFAULT; - - switch (hw->type) { - case SDLA_S502A: - bootp = hw->dpmbase; - bootp += 0x66; - break; - - case SDLA_S502E: - case SDLA_S503: - case SDLA_S507: - case SDLA_S508: - case SDLA_S514: - bootp = hw->dpmbase; - break; - - default: - return -EINVAL; - } - - err = sdla_mapmem(hw, 0); - if (err) return err; - - writeb (0xC3, bootp); /* Z80: 'jp' opcode */ - bootp ++; - writew (addr, bootp); - - switch (hw->type) { - case SDLA_S502A: - _OUTB(port, 0x10); /* issue NMI to CPU */ - hw->regs[0] = 0x10; - break; - - case SDLA_S502E: - _OUTB(port + 3, 0x01); /* start CPU */ - hw->regs[3] = 0x01; - for (i = 0; i < SDLA_IODELAY; ++i); - if (_INB(port) & 0x01) { /* verify */ - /* - * Enabling CPU changes functionality of the - * control register, so we have to reset its - * mirror. - */ - _OUTB(port, 0); /* disable interrupts */ - hw->regs[0] = 0; - } - else return -EIO; - break; - - case SDLA_S503: - tmp = hw->regs[0] | 0x09; /* set bits 0 and 3 */ - _OUTB(port, tmp); - hw->regs[0] = tmp; /* update mirror */ - for (i = 0; i < SDLA_IODELAY; ++i); - if (!(_INB(port) & 0x01)) /* verify */ - return -EIO; - break; - - case SDLA_S507: - tmp = hw->regs[0] | 0x02; - _OUTB(port, tmp); - hw->regs[0] = tmp; /* update mirror */ - for (i = 0; i < SDLA_IODELAY; ++i); - if (!(_INB(port) & 0x04)) /* verify */ - return -EIO; - break; - - case SDLA_S508: - tmp = hw->regs[0] | 0x02; - _OUTB(port, tmp); - hw->regs[0] = tmp; /* update mirror */ - for (i = 0; i < SDLA_IODELAY; ++i); - if (!(_INB(port + 1) & 0x02)) /* verify */ - return -EIO; - break; - - case SDLA_S514: - writeb (S514_CPU_START, hw->vector); - break; - - default: - return -EINVAL; - } - return 0; -} - -/*============================================================================ - * Initialize S502A adapter. - */ -static int init_s502a (sdlahw_t* hw) -{ - unsigned port = hw->port; - int tmp, i; - - if (!detect_s502a(port)) - return -ENODEV; - - hw->regs[0] = 0x08; - hw->regs[1] = 0xFF; - - /* Verify configuration options */ - i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase)); - if (i == 0) - return -EINVAL; - - tmp = s502a_hmcr[i - 1]; - switch (hw->dpmsize) { - case 0x2000: - tmp |= 0x01; - break; - - case 0x10000L: - break; - - default: - return -EINVAL; - } - - /* Setup dual-port memory window (this also enables memory access) */ - _OUTB(port + 1, tmp); - hw->regs[1] = tmp; - hw->regs[0] = 0x08; - return 0; -} - -/*============================================================================ - * Initialize S502E adapter. - */ -static int init_s502e (sdlahw_t* hw) -{ - unsigned port = hw->port; - int tmp, i; - - if (!detect_s502e(port)) - return -ENODEV; - - /* Verify configuration options */ - i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase)); - if (i == 0) - return -EINVAL; - - tmp = s502e_hmcr[i - 1]; - switch (hw->dpmsize) { - case 0x2000: - tmp |= 0x01; - break; - - case 0x10000L: - break; - - default: - return -EINVAL; - } - - /* Setup dual-port memory window */ - _OUTB(port + 1, tmp); - hw->regs[1] = tmp; - - /* Enable memory access */ - _OUTB(port, 0x02); - hw->regs[0] = 0x02; - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - return (_INB(port) & 0x02) ? 0 : -EIO; -} - -/*============================================================================ - * Initialize S503 adapter. - * --------------------------------------------------------------------------- - */ -static int init_s503 (sdlahw_t* hw) -{ - unsigned port = hw->port; - int tmp, i; - - if (!detect_s503(port)) - return -ENODEV; - - /* Verify configuration options */ - i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase)); - if (i == 0) - return -EINVAL; - - tmp = s502e_hmcr[i - 1]; - switch (hw->dpmsize) { - case 0x2000: - tmp |= 0x01; - break; - - case 0x10000L: - break; - - default: - return -EINVAL; - } - - /* Setup dual-port memory window */ - _OUTB(port + 1, tmp); - hw->regs[1] = tmp; - - /* Enable memory access */ - _OUTB(port, 0x02); - hw->regs[0] = 0x02; /* update mirror */ - return 0; -} - -/*============================================================================ - * Initialize S507 adapter. - */ -static int init_s507 (sdlahw_t* hw) -{ - unsigned port = hw->port; - int tmp, i; - - if (!detect_s507(port)) - return -ENODEV; - - /* Verify configuration options */ - i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase)); - if (i == 0) - return -EINVAL; - - tmp = s507_hmcr[i - 1]; - switch (hw->dpmsize) { - case 0x2000: - tmp |= 0x01; - break; - - case 0x10000L: - break; - - default: - return -EINVAL; - } - - /* Enable adapter's logic */ - _OUTB(port, 0x01); - hw->regs[0] = 0x01; - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (!(_INB(port) & 0x20)) - return -EIO; - - /* Setup dual-port memory window */ - _OUTB(port + 1, tmp); - hw->regs[1] = tmp; - - /* Enable memory access */ - tmp = hw->regs[0] | 0x04; - if (hw->irq) { - i = get_option_index(s508_irq_options, hw->irq); - if (i) tmp |= s507_irqmask[i - 1]; - } - _OUTB(port, tmp); - hw->regs[0] = tmp; /* update mirror */ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - return (_INB(port) & 0x08) ? 0 : -EIO; -} - -/*============================================================================ - * Initialize S508 adapter. - */ -static int init_s508 (sdlahw_t* hw) -{ - unsigned port = hw->port; - int tmp, i; - - if (!detect_s508(port)) - return -ENODEV; - - /* Verify configuration options */ - i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase)); - if (i == 0) - return -EINVAL; - - /* Setup memory configuration */ - tmp = s508_hmcr[i - 1]; - _OUTB(port + 1, tmp); - hw->regs[1] = tmp; - - /* Enable memory access */ - _OUTB(port, 0x04); - hw->regs[0] = 0x04; /* update mirror */ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - return (_INB(port + 1) & 0x04) ? 0 : -EIO; -} - -/*============================================================================ - * Detect S502A adapter. - * Following tests are used to detect S502A adapter: - * 1. All registers other than status (BASE) should read 0xFF - * 2. After writing 00001000b to control register, status register should - * read 01000000b. - * 3. After writing 0 to control register, status register should still - * read 01000000b. - * 4. After writing 00000100b to control register, status register should - * read 01000100b. - * Return 1 if detected o.k. or 0 if failed. - * Note: This test is destructive! Adapter will be left in shutdown - * state after the test. - */ -static int detect_s502a (int port) -{ - int i, j; - - if (!get_option_index(s502_port_options, port)) - return 0; - - for (j = 1; j < SDLA_MAXIORANGE; ++j) { - if (_INB(port + j) != 0xFF) - return 0; - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - } - - _OUTB(port, 0x08); /* halt CPU */ - _OUTB(port, 0x08); - _OUTB(port, 0x08); - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (_INB(port) != 0x40) - return 0; - _OUTB(port, 0x00); - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (_INB(port) != 0x40) - return 0; - _OUTB(port, 0x04); - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (_INB(port) != 0x44) - return 0; - - /* Reset adapter */ - _OUTB(port, 0x08); - _OUTB(port, 0x08); - _OUTB(port, 0x08); - _OUTB(port + 1, 0xFF); - return 1; -} - -/*============================================================================ - * Detect S502E adapter. - * Following tests are used to verify adapter presence: - * 1. All registers other than status (BASE) should read 0xFF. - * 2. After writing 0 to CPU control register (BASE+3), status register - * (BASE) should read 11111000b. - * 3. After writing 00000100b to port BASE (set bit 2), status register - * (BASE) should read 11111100b. - * Return 1 if detected o.k. or 0 if failed. - * Note: This test is destructive! Adapter will be left in shutdown - * state after the test. - */ -static int detect_s502e (int port) -{ - int i, j; - - if (!get_option_index(s502_port_options, port)) - return 0; - for (j = 1; j < SDLA_MAXIORANGE; ++j) { - if (_INB(port + j) != 0xFF) - return 0; - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - } - - _OUTB(port + 3, 0); /* CPU control reg. */ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (_INB(port) != 0xF8) /* read status */ - return 0; - _OUTB(port, 0x04); /* set bit 2 */ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (_INB(port) != 0xFC) /* verify */ - return 0; - - /* Reset adapter */ - _OUTB(port, 0); - return 1; -} - -/*============================================================================ - * Detect s503 adapter. - * Following tests are used to verify adapter presence: - * 1. All registers other than status (BASE) should read 0xFF. - * 2. After writing 0 to control register (BASE), status register (BASE) - * should read 11110000b. - * 3. After writing 00000100b (set bit 2) to control register (BASE), - * status register should read 11110010b. - * Return 1 if detected o.k. or 0 if failed. - * Note: This test is destructive! Adapter will be left in shutdown - * state after the test. - */ -static int detect_s503 (int port) -{ - int i, j; - - if (!get_option_index(s503_port_options, port)) - return 0; - for (j = 1; j < SDLA_MAXIORANGE; ++j) { - if (_INB(port + j) != 0xFF) - return 0; - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - } - - _OUTB(port, 0); /* reset control reg.*/ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (_INB(port) != 0xF0) /* read status */ - return 0; - _OUTB(port, 0x04); /* set bit 2 */ - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if (_INB(port) != 0xF2) /* verify */ - return 0; - - /* Reset adapter */ - _OUTB(port, 0); - return 1; -} - -/*============================================================================ - * Detect s507 adapter. - * Following tests are used to detect s507 adapter: - * 1. All ports should read the same value. - * 2. After writing 0x00 to control register, status register should read - * ?011000?b. - * 3. After writing 0x01 to control register, status register should read - * ?011001?b. - * Return 1 if detected o.k. or 0 if failed. - * Note: This test is destructive! Adapter will be left in shutdown - * state after the test. - */ -static int detect_s507 (int port) -{ - int tmp, i, j; - - if (!get_option_index(s508_port_options, port)) - return 0; - tmp = _INB(port); - for (j = 1; j < S507_IORANGE; ++j) { - if (_INB(port + j) != tmp) - return 0; - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - } - - _OUTB(port, 0x00); - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if ((_INB(port) & 0x7E) != 0x30) - return 0; - _OUTB(port, 0x01); - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if ((_INB(port) & 0x7E) != 0x32) - return 0; - - /* Reset adapter */ - _OUTB(port, 0x00); - return 1; -} - -/*============================================================================ - * Detect s508 adapter. - * Following tests are used to detect s508 adapter: - * 1. After writing 0x00 to control register, status register should read - * ??000000b. - * 2. After writing 0x10 to control register, status register should read - * ??010000b - * Return 1 if detected o.k. or 0 if failed. - * Note: This test is destructive! Adapter will be left in shutdown - * state after the test. - */ -static int detect_s508 (int port) -{ - int i; - - if (!get_option_index(s508_port_options, port)) - return 0; - _OUTB(port, 0x00); - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if ((_INB(port + 1) & 0x3F) != 0x00) - return 0; - _OUTB(port, 0x10); - for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ - if ((_INB(port + 1) & 0x3F) != 0x10) - return 0; - - /* Reset adapter */ - _OUTB(port, 0x00); - return 1; -} - -/*============================================================================ - * Detect s514 PCI adapter. - * Return 1 if detected o.k. or 0 if failed. - * Note: This test is destructive! Adapter will be left in shutdown - * state after the test. - */ -static int detect_s514 (sdlahw_t* hw) -{ - unsigned char CPU_no, slot_no, auto_slot_cfg; - int number_S514_cards = 0; - u32 S514_mem_base_addr = 0; - u32 ut_u32; - struct pci_dev *pci_dev; - - -#ifndef CONFIG_PCI - printk(KERN_INFO "%s: Linux not compiled for PCI usage!\n", modname); - return 0; -#endif - - /* - The 'setup()' procedure in 'sdlamain.c' passes the CPU number and the - slot number defined in 'router.conf' via the 'port' definition. - */ - CPU_no = hw->S514_cpu_no[0]; - slot_no = hw->S514_slot_no; - auto_slot_cfg = hw->auto_pci_cfg; - - if (auto_slot_cfg){ - printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot=Auto\n", - modname, CPU_no); - - }else{ - printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot #%d\n", - modname, CPU_no, slot_no); - } - - /* check to see that CPU A or B has been selected in 'router.conf' */ - switch(CPU_no) { - case S514_CPU_A: - case S514_CPU_B: - break; - - default: - printk(KERN_INFO "%s: S514 CPU definition invalid.\n", - modname); - printk(KERN_INFO "Must be 'A' or 'B'\n"); - return 0; - } - - number_S514_cards = find_s514_adapter(hw, 0); - if(!number_S514_cards) - return 0; - - /* we are using a single S514 adapter with a slot of 0 so re-read the */ - /* location of this adapter */ - if((number_S514_cards == 1) && auto_slot_cfg) { - number_S514_cards = find_s514_adapter(hw, 1); - if(!number_S514_cards) { - printk(KERN_INFO "%s: Error finding PCI card\n", - modname); - return 0; - } - } - - pci_dev = hw->pci_dev; - /* read the physical memory base address */ - S514_mem_base_addr = (CPU_no == S514_CPU_A) ? - (pci_dev->resource[1].start) : - (pci_dev->resource[2].start); - - printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n", - modname, S514_mem_base_addr); - if(!S514_mem_base_addr) { - if(CPU_no == S514_CPU_B) - printk(KERN_INFO "%s: CPU #B not present on the card\n", modname); - else - printk(KERN_INFO "%s: No PCI memory allocated to card\n", modname); - return 0; - } - - /* enable the PCI memory */ - pci_read_config_dword(pci_dev, - (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, - &ut_u32); - pci_write_config_dword(pci_dev, - (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, - (ut_u32 | PCI_MEMORY_ENABLE)); - - /* check the IRQ allocated and enable IRQ usage */ - if(!(hw->irq = pci_dev->irq)) { - printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n", - modname); - return 0; - } - - /* BUG FIX : Mar 6 2000 - * On a initial loading of the card, we must check - * and clear PCI interrupt bits, due to a reset - * problem on some other boards. i.e. An interrupt - * might be pending, even after system bootup, - * in which case, when starting wanrouter the machine - * would crash. - */ - if (init_pci_slot(hw)) - return 0; - - pci_read_config_dword(pci_dev, PCI_INT_CONFIG, &ut_u32); - ut_u32 |= (CPU_no == S514_CPU_A) ? - PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B; - pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32); - - printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n", - modname, hw->irq); - - /* map the physical PCI memory to virtual memory */ - hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr, - (unsigned long)MAX_SIZEOF_S514_MEMORY); - /* map the physical control register memory to virtual memory */ - hw->vector = (unsigned long)ioremap( - (unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE), - (unsigned long)16); - - if(!hw->dpmbase || !hw->vector) { - printk(KERN_INFO "%s: PCI virtual memory allocation failed\n", - modname); - return 0; - } - - /* halt the adapter */ - writeb (S514_CPU_HALT, hw->vector); - - return 1; -} - -/*============================================================================ - * Find the S514 PCI adapter in the PCI bus. - * Return the number of S514 adapters found (0 if no adapter found). - */ -static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card) -{ - unsigned char slot_no; - int number_S514_cards = 0; - char S514_found_in_slot = 0; - u16 PCI_subsys_vendor; - - struct pci_dev *pci_dev = NULL; - - slot_no = hw->S514_slot_no; - - while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev)) - != NULL) { - - pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD, - &PCI_subsys_vendor); - - if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR) - continue; - - hw->pci_dev = pci_dev; - - if(find_first_S514_card) - return(1); - - number_S514_cards ++; - - printk(KERN_INFO - "%s: S514 card found, slot #%d (devfn 0x%X)\n", - modname, ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK), - pci_dev->devfn); - - if (hw->auto_pci_cfg){ - hw->S514_slot_no = ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK); - slot_no = hw->S514_slot_no; - - }else if (((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK) == slot_no){ - S514_found_in_slot = 1; - break; - } - } - - /* if no S514 adapter has been found, then exit */ - if (!number_S514_cards) { - printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname); - return 0; - } - /* if more than one S514 card has been found, then the user must have */ /* defined a slot number so that the correct adapter is used */ - else if ((number_S514_cards > 1) && hw->auto_pci_cfg) { - printk(KERN_INFO "%s: Error, PCI Slot autodetect Failed! \n" - "%s: More than one S514 adapter found.\n" - "%s: Disable the Autodetect feature and supply\n" - "%s: the PCISLOT numbers for each card.\n", - modname,modname,modname,modname); - return 0; - } - /* if the user has specified a slot number and the S514 adapter has */ - /* not been found in that slot, then exit */ - else if (!hw->auto_pci_cfg && !S514_found_in_slot) { - printk(KERN_INFO - "%s: Error, S514 card not found in specified slot #%d\n", - modname, slot_no); - return 0; - } - - return (number_S514_cards); -} - - - -/******* Miscellaneous ******************************************************/ - -/*============================================================================ - * Calibrate SDLA memory access delay. - * Count number of idle loops made within 1 second and then calculate the - * number of loops that should be made to achive desired delay. - */ -static int calibrate_delay (int mks) -{ - unsigned int delay; - unsigned long stop; - - for (delay = 0, stop = SYSTEM_TICK + HZ; SYSTEM_TICK < stop; ++delay); - return (delay/(1000000L/mks) + 1); -} - -/*============================================================================ - * Get option's index into the options list. - * Return option's index (1 .. N) or zero if option is invalid. - */ -static int get_option_index (unsigned* optlist, unsigned optval) -{ - int i; - - for (i = 1; i <= optlist[0]; ++i) - if ( optlist[i] == optval) - return i; - return 0; -} - -/*============================================================================ - * Check memory region to see if it's available. - * Return: 0 ok. - */ -static unsigned check_memregion (void* ptr, unsigned len) -{ - volatile unsigned char* p = ptr; - - for (; len && (readb (p) == 0xFF); --len, ++p) { - writeb (0, p); /* attempt to write 0 */ - if (readb(p) != 0xFF) { /* still has to read 0xFF */ - writeb (0xFF, p);/* restore original value */ - break; /* not good */ - } - } - - return len; -} - -/*============================================================================ - * Test memory region. - * Return: size of the region that passed the test. - * Note: Region size must be multiple of 2 ! - */ -static unsigned test_memregion (void* ptr, unsigned len) -{ - volatile unsigned short* w_ptr; - unsigned len_w = len >> 1; /* region len in words */ - unsigned i; - - for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) - writew (0xAA55, w_ptr); - - for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) - if (readw (w_ptr) != 0xAA55) { - len_w = i; - break; - } - - for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) - writew (0x55AA, w_ptr); - - for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) - if (readw(w_ptr) != 0x55AA) { - len_w = i; - break; - } - - for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) - writew (0, w_ptr); - - return len_w << 1; -} - -/*============================================================================ - * Calculate 16-bit CRC using CCITT polynomial. - */ -static unsigned short checksum (unsigned char* buf, unsigned len) -{ - unsigned short crc = 0; - unsigned mask, flag; - - for (; len; --len, ++buf) { - for (mask = 0x80; mask; mask >>= 1) { - flag = (crc & 0x8000); - crc <<= 1; - crc |= ((*buf & mask) ? 1 : 0); - if (flag) crc ^= 0x1021; - } - } - return crc; -} - -static int init_pci_slot(sdlahw_t *hw) -{ - - u32 int_status; - int volatile found=0; - int i=0; - - /* Check if this is a very first load for a specific - * pci card. If it is, clear the interrput bits, and - * set the flag indicating that this card was initialized. - */ - - for (i=0; (iS514_slot_no){ - found=1; - break; - } - if (pci_slot_ar[i] == 0xFF){ - break; - } - } - - if (!found){ - read_S514_int_stat(hw,&int_status); - S514_intack(hw,int_status); - if (i == MAX_S514_CARDS){ - printk(KERN_INFO "%s: Critical Error !!!\n",modname); - printk(KERN_INFO - "%s: Number of Sangoma PCI cards exceeded maximum limit.\n", - modname); - printk(KERN_INFO "Please contact Sangoma Technologies\n"); - return 1; - } - pci_slot_ar[i] = hw->S514_slot_no; - } - return 0; -} - -static int pci_probe(sdlahw_t *hw) -{ - - unsigned char slot_no; - int number_S514_cards = 0; - u16 PCI_subsys_vendor; - u16 PCI_card_type; - - struct pci_dev *pci_dev = NULL; - struct pci_bus *bus = NULL; - - slot_no = 0; - - while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev)) - != NULL) { - - pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD, - &PCI_subsys_vendor); - - if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR) - continue; - - pci_read_config_word(pci_dev, PCI_CARD_TYPE, - &PCI_card_type); - - bus = pci_dev->bus; - - /* A dual cpu card can support up to 4 physical connections, - * where a single cpu card can support up to 2 physical - * connections. The FT1 card can only support a single - * connection, however we cannot distinguish between a Single - * CPU card and an FT1 card. */ - if (PCI_card_type == S514_DUAL_CPU){ - number_S514_cards += 4; - printk(KERN_INFO - "wanpipe: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n", - bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK), - pci_dev->irq); - }else{ - number_S514_cards += 2; - printk(KERN_INFO - "wanpipe: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n", - bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK), - pci_dev->irq); - } - } - - return number_S514_cards; - -} - - - -EXPORT_SYMBOL(wanpipe_hw_probe); - -unsigned wanpipe_hw_probe(void) -{ - sdlahw_t hw; - unsigned* opt = s508_port_options; - unsigned cardno=0; - int i; - - memset(&hw, 0, sizeof(hw)); - - for (i = 1; i <= opt[0]; i++) { - if (detect_s508(opt[i])){ - /* S508 card can support up to two physical links */ - cardno+=2; - printk(KERN_INFO "wanpipe: S508-ISA card found, port 0x%x\n",opt[i]); - } - } - - #ifdef CONFIG_PCI - hw.S514_slot_no = 0; - cardno += pci_probe(&hw); - #else - printk(KERN_INFO "wanpipe: Warning, Kernel not compiled for PCI support!\n"); - printk(KERN_INFO "wanpipe: PCI Hardware Probe Failed!\n"); - #endif - - return cardno; -} - -/****** End *****************************************************************/ diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c deleted file mode 100644 index 7a8b22a7ea31..000000000000 --- a/drivers/net/wan/sdlamain.c +++ /dev/null @@ -1,1346 +0,0 @@ -/**************************************************************************** -* sdlamain.c WANPIPE(tm) Multiprotocol WAN Link Driver. Main module. -* -* Author: Nenad Corbic -* Gideon Hack -* -* Copyright: (c) 1995-2000 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. -* ============================================================================ -* Dec 22, 2000 Nenad Corbic Updated for 2.4.X kernels. -* Removed the polling routine. -* Nov 13, 2000 Nenad Corbic Added hw probing on module load and dynamic -* device allocation. -* Nov 7, 2000 Nenad Corbic Fixed the Multi-Port PPP for kernels -* 2.2.16 and above. -* Aug 2, 2000 Nenad Corbic Block the Multi-Port PPP from running on -* kernels 2.2.16 or greater. The SyncPPP -* has changed. -* Jul 25, 2000 Nenad Corbic Updated the Piggiback support for MultPPPP. -* Jul 13, 2000 Nenad Corbic Added Multi-PPP support. -* Feb 02, 2000 Nenad Corbic Fixed up piggyback probing and selection. -* Sep 23, 1999 Nenad Corbic Added support for SMP -* Sep 13, 1999 Nenad Corbic Each port is treated as a separate device. -* Jun 02, 1999 Gideon Hack Added support for the S514 adapter. -* Updates for Linux 2.2.X kernels. -* Sep 17, 1998 Jaspreet Singh Updated for 2.1.121+ kernel -* Nov 28, 1997 Jaspreet Singh Changed DRV_RELEASE to 1 -* Nov 10, 1997 Jaspreet Singh Changed sti() to restore_flags(); -* Nov 06, 1997 Jaspreet Singh Changed DRV_VERSION to 4 and DRV_RELEASE to 0 -* Oct 20, 1997 Jaspreet Singh Modified sdla_isr routine so that card->in_isr -* assignments are taken out and placed in the -* sdla_ppp.c, sdla_fr.c and sdla_x25.c isr -* routines. Took out 'wandev->tx_int_enabled' and -* replaced it with 'wandev->enable_tx_int'. -* May 29, 1997 Jaspreet Singh Flow Control Problem -* added "wandev->tx_int_enabled=1" line in the -* init module. This line initializes the flag for -* preventing Interrupt disabled with device set to -* busy -* Jan 15, 1997 Gene Kozin Version 3.1.0 -* o added UDP management stuff -* Jan 02, 1997 Gene Kozin Initial version. -*****************************************************************************/ - -#include /* OS configuration options */ -#include /* offsetof(), etc. */ -#include /* return codes */ -#include /* inline memset(), etc. */ -#include -#include /* kmalloc(), kfree() */ -#include /* printk(), and other useful stuff */ -#include /* support for loadable modules */ -#include /* request_region(), release_region() */ -#include /* WAN router definitions */ -#include /* WANPIPE common user API definitions */ -#include - -#include -#include /* phys_to_virt() */ -#include -#include -#include - -#include /* kernel <-> user copy */ -#include - -#include -#include - -#define KMEM_SAFETYZONE 8 - - -#ifndef CONFIG_WANPIPE_FR - #define wpf_init(a,b) (-EPROTONOSUPPORT) -#endif - -#ifndef CONFIG_WANPIPE_CHDLC - #define wpc_init(a,b) (-EPROTONOSUPPORT) -#endif - -#ifndef CONFIG_WANPIPE_X25 - #define wpx_init(a,b) (-EPROTONOSUPPORT) -#endif - -#ifndef CONFIG_WANPIPE_PPP - #define wpp_init(a,b) (-EPROTONOSUPPORT) -#endif - -#ifndef CONFIG_WANPIPE_MULTPPP - #define wsppp_init(a,b) (-EPROTONOSUPPORT) -#endif - - -/***********FOR DEBUGGING PURPOSES********************************************* -static void * dbg_kmalloc(unsigned int size, int prio, int line) { - int i = 0; - void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio); - char * c1 = v; - c1 += sizeof(unsigned int); - *((unsigned int *)v) = size; - - for (i = 0; i < KMEM_SAFETYZONE; i++) { - c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D'; - c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F'; - c1 += 8; - } - c1 += size; - for (i = 0; i < KMEM_SAFETYZONE; i++) { - c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G'; - c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L'; - c1 += 8; - } - v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8; - printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v); - return v; -} -static void dbg_kfree(void * v, int line) { - unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8)); - unsigned int size = *sp; - char * c1 = ((char *)v) - KMEM_SAFETYZONE*8; - int i = 0; - for (i = 0; i < KMEM_SAFETYZONE; i++) { - if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D' - || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') { - printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v); - printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, - c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); - } - c1 += 8; - } - c1 += size; - for (i = 0; i < KMEM_SAFETYZONE; i++) { - if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G' - || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L' - ) { - printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v); - printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, - c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); - } - c1 += 8; - } - printk(KERN_INFO "line %d kfree(%p)\n",line,v); - v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8); - kfree(v); -} - -#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__) -#define kfree(x) dbg_kfree(x,__LINE__) -******************************************************************************/ - - - -/****** Defines & Macros ****************************************************/ - -#ifdef _DEBUG_ -#define STATIC -#else -#define STATIC static -#endif - -#define DRV_VERSION 5 /* version number */ -#define DRV_RELEASE 0 /* release (minor version) number */ -#define MAX_CARDS 16 /* max number of adapters */ - -#ifndef CONFIG_WANPIPE_CARDS /* configurable option */ -#define CONFIG_WANPIPE_CARDS 1 -#endif - -#define CMD_OK 0 /* normal firmware return code */ -#define CMD_TIMEOUT 0xFF /* firmware command timed out */ -#define MAX_CMD_RETRY 10 /* max number of firmware retries */ -/****** Function Prototypes *************************************************/ - -extern void disable_irq(unsigned int); -extern void enable_irq(unsigned int); - -/* WAN link driver entry points */ -static int setup(struct wan_device* wandev, wandev_conf_t* conf); -static int shutdown(struct wan_device* wandev); -static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg); - -/* IOCTL handlers */ -static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump); -static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int); - -/* Miscellaneous functions */ -STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs); -static void release_hw (sdla_t *card); - -static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int*); -static int check_s514_conflicts (sdla_t* card,wandev_conf_t* conf, int*); - - -/****** Global Data ********************************************************** - * Note: All data must be explicitly initialized!!! - */ - -/* private data */ -static char drvname[] = "wanpipe"; -static char fullname[] = "WANPIPE(tm) Multiprotocol Driver"; -static char copyright[] = "(c) 1995-2000 Sangoma Technologies Inc."; -static int ncards; -static sdla_t* card_array; /* adapter data space */ - -/* Wanpipe's own workqueue, used for all API's. - * All protocol specific tasks will be inserted - * into the "wanpipe_wq" workqueue. - - * The kernel workqueue mechanism will execute - * all pending tasks in the "wanpipe_wq" workqueue. - */ - -struct workqueue_struct *wanpipe_wq; -DECLARE_WORK(wanpipe_work, NULL, NULL); - -static int wanpipe_bh_critical; - -/******* Kernel Loadable Module Entry Points ********************************/ - -/*============================================================================ - * Module 'insert' entry point. - * o print announcement - * o allocate adapter data space - * o initialize static data - * o register all cards with WAN router - * o calibrate SDLA shared memory access delay. - * - * Return: 0 Ok - * < 0 error. - * Context: process - */ - -static int __init wanpipe_init(void) -{ - int cnt, err = 0; - - printk(KERN_INFO "%s v%u.%u %s\n", - fullname, DRV_VERSION, DRV_RELEASE, copyright); - - wanpipe_wq = create_workqueue("wanpipe_wq"); - if (!wanpipe_wq) - return -ENOMEM; - - /* Probe for wanpipe cards and return the number found */ - printk(KERN_INFO "wanpipe: Probing for WANPIPE hardware.\n"); - ncards = wanpipe_hw_probe(); - if (ncards){ - printk(KERN_INFO "wanpipe: Allocating maximum %i devices: wanpipe%i - wanpipe%i.\n",ncards,1,ncards); - }else{ - printk(KERN_INFO "wanpipe: No S514/S508 cards found, unloading modules!\n"); - destroy_workqueue(wanpipe_wq); - return -ENODEV; - } - - /* Verify number of cards and allocate adapter data space */ - card_array = kmalloc(sizeof(sdla_t) * ncards, GFP_KERNEL); - if (card_array == NULL) { - destroy_workqueue(wanpipe_wq); - return -ENOMEM; - } - - memset(card_array, 0, sizeof(sdla_t) * ncards); - - /* Register adapters with WAN router */ - for (cnt = 0; cnt < ncards; ++ cnt) { - sdla_t* card = &card_array[cnt]; - struct wan_device* wandev = &card->wandev; - - card->next = NULL; - sprintf(card->devname, "%s%d", drvname, cnt + 1); - wandev->magic = ROUTER_MAGIC; - wandev->name = card->devname; - wandev->private = card; - wandev->enable_tx_int = 0; - wandev->setup = &setup; - wandev->shutdown = &shutdown; - wandev->ioctl = &ioctl; - err = register_wan_device(wandev); - if (err) { - printk(KERN_INFO - "%s: %s registration failed with error %d!\n", - drvname, card->devname, err); - break; - } - } - if (cnt){ - ncards = cnt; /* adjust actual number of cards */ - }else { - kfree(card_array); - destroy_workqueue(wanpipe_wq); - printk(KERN_INFO "IN Init Module: NO Cards registered\n"); - err = -ENODEV; - } - - return err; -} - -/*============================================================================ - * Module 'remove' entry point. - * o unregister all adapters from the WAN router - * o release all remaining system resources - */ -static void __exit wanpipe_cleanup(void) -{ - int i; - - if (!ncards) - return; - - for (i = 0; i < ncards; ++i) { - sdla_t* card = &card_array[i]; - unregister_wan_device(card->devname); - } - destroy_workqueue(wanpipe_wq); - kfree(card_array); - - printk(KERN_INFO "\nwanpipe: WANPIPE Modules Unloaded.\n"); -} - -module_init(wanpipe_init); -module_exit(wanpipe_cleanup); - -/******* WAN Device Driver Entry Points *************************************/ - -/*============================================================================ - * Setup/configure WAN link driver. - * o check adapter state - * o make sure firmware is present in configuration - * o make sure I/O port and IRQ are specified - * o make sure I/O region is available - * o allocate interrupt vector - * o setup SDLA hardware - * o call appropriate routine to perform protocol-specific initialization - * o mark I/O region as used - * o if this is the first active card, then schedule background task - * - * This function is called when router handles ROUTER_SETUP IOCTL. The - * configuration structure is in kernel memory (including extended data, if - * any). - */ - -static int setup(struct wan_device* wandev, wandev_conf_t* conf) -{ - sdla_t* card; - int err = 0; - int irq=0; - - /* Sanity checks */ - if ((wandev == NULL) || (wandev->private == NULL) || (conf == NULL)){ - printk(KERN_INFO - "%s: Failed Sdlamain Setup wandev %u, card %u, conf %u !\n", - wandev->name, - (unsigned int)wandev,(unsigned int)wandev->private, - (unsigned int)conf); - return -EFAULT; - } - - printk(KERN_INFO "%s: Starting WAN Setup\n", wandev->name); - - card = wandev->private; - if (wandev->state != WAN_UNCONFIGURED){ - printk(KERN_INFO "%s: failed sdlamain setup, busy!\n", - wandev->name); - return -EBUSY; /* already configured */ - } - - printk(KERN_INFO "\nProcessing WAN device %s...\n", wandev->name); - - /* Initialize the counters for each wandev - * Used for counting number of times new_if and - * del_if get called. - */ - wandev->del_if_cnt = 0; - wandev->new_if_cnt = 0; - wandev->config_id = conf->config_id; - - if (!conf->data_size || (conf->data == NULL)) { - printk(KERN_INFO - "%s: firmware not found in configuration data!\n", - wandev->name); - return -EINVAL; - } - - /* Check for resource conflicts and setup the - * card for piggibacking if necessary */ - if(!conf->S514_CPU_no[0]) { - if ((err=check_s508_conflicts(card,conf,&irq)) != 0){ - return err; - } - }else { - if ((err=check_s514_conflicts(card,conf,&irq)) != 0){ - return err; - } - } - - /* If the current card has already been configured - * or it's a piggyback card, do not try to allocate - * resources. - */ - if (!card->wandev.piggyback && !card->configured){ - - /* Configure hardware, load firmware, etc. */ - memset(&card->hw, 0, sizeof(sdlahw_t)); - - /* for an S514 adapter, pass the CPU number and the slot number read */ - /* from 'router.conf' to the 'sdla_setup()' function via the 'port' */ - /* parameter */ - if (conf->S514_CPU_no[0]){ - - card->hw.S514_cpu_no[0] = conf->S514_CPU_no[0]; - card->hw.S514_slot_no = conf->PCI_slot_no; - card->hw.auto_pci_cfg = conf->auto_pci_cfg; - - if (card->hw.auto_pci_cfg == WANOPT_YES){ - printk(KERN_INFO "%s: Setting CPU to %c and Slot to Auto\n", - card->devname, card->hw.S514_cpu_no[0]); - }else{ - printk(KERN_INFO "%s: Setting CPU to %c and Slot to %i\n", - card->devname, card->hw.S514_cpu_no[0], card->hw.S514_slot_no); - } - - }else{ - /* 508 Card io port and irq initialization */ - card->hw.port = conf->ioport; - card->hw.irq = (conf->irq == 9) ? 2 : conf->irq; - } - - - /* Compute the virtual address of the card in kernel space */ - if(conf->maddr){ - card->hw.dpmbase = phys_to_virt(conf->maddr); - }else{ - card->hw.dpmbase = (void *)conf->maddr; - } - - card->hw.dpmsize = SDLA_WINDOWSIZE; - - /* set the adapter type if using an S514 adapter */ - card->hw.type = (conf->S514_CPU_no[0]) ? SDLA_S514 : conf->hw_opt[0]; - card->hw.pclk = conf->hw_opt[1]; - - err = sdla_setup(&card->hw, conf->data, conf->data_size); - if (err){ - printk(KERN_INFO "%s: Hardware setup Failed %i\n", - card->devname,err); - return err; - } - - if(card->hw.type != SDLA_S514) - irq = (conf->irq == 2) ? 9 : conf->irq; /* IRQ2 -> IRQ9 */ - else - irq = card->hw.irq; - - /* request an interrupt vector - note that interrupts may be shared */ - /* when using the S514 PCI adapter */ - - if(request_irq(irq, sdla_isr, - (card->hw.type == SDLA_S514) ? SA_SHIRQ : 0, - wandev->name, card)){ - - printk(KERN_INFO "%s: Can't reserve IRQ %d!\n", wandev->name, irq); - return -EINVAL; - } - - }else{ - printk(KERN_INFO "%s: Card Configured %lu or Piggybacking %i!\n", - wandev->name,card->configured,card->wandev.piggyback); - } - - - if (!card->configured){ - - /* Initialize the Spin lock */ - printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name); - - /* Piggyback spin lock has already been initialized, - * in check_s514/s508_conflicts() */ - if (!card->wandev.piggyback){ - spin_lock_init(&card->wandev.lock); - } - - /* Intialize WAN device data space */ - wandev->irq = irq; - wandev->dma = 0; - if(card->hw.type != SDLA_S514){ - wandev->ioport = card->hw.port; - }else{ - wandev->S514_cpu_no[0] = card->hw.S514_cpu_no[0]; - wandev->S514_slot_no = card->hw.S514_slot_no; - } - wandev->maddr = (unsigned long)card->hw.dpmbase; - wandev->msize = card->hw.dpmsize; - wandev->hw_opt[0] = card->hw.type; - wandev->hw_opt[1] = card->hw.pclk; - wandev->hw_opt[2] = card->hw.memory; - wandev->hw_opt[3] = card->hw.fwid; - } - - /* Protocol-specific initialization */ - switch (card->hw.fwid) { - - case SFID_X25_502: - case SFID_X25_508: - printk(KERN_INFO "%s: Starting X.25 Protocol Init.\n", - card->devname); - err = wpx_init(card, conf); - break; - case SFID_FR502: - case SFID_FR508: - printk(KERN_INFO "%s: Starting Frame Relay Protocol Init.\n", - card->devname); - err = wpf_init(card, conf); - break; - case SFID_PPP502: - case SFID_PPP508: - printk(KERN_INFO "%s: Starting PPP Protocol Init.\n", - card->devname); - err = wpp_init(card, conf); - break; - - case SFID_CHDLC508: - case SFID_CHDLC514: - if (conf->ft1){ - printk(KERN_INFO "%s: Starting FT1 CSU/DSU Config Driver.\n", - card->devname); - err = wpft1_init(card, conf); - break; - - }else if (conf->config_id == WANCONFIG_MPPP){ - printk(KERN_INFO "%s: Starting Multi-Port PPP Protocol Init.\n", - card->devname); - err = wsppp_init(card,conf); - break; - - }else{ - printk(KERN_INFO "%s: Starting CHDLC Protocol Init.\n", - card->devname); - err = wpc_init(card, conf); - break; - } - default: - printk(KERN_INFO "%s: Error, Firmware is not supported %X %X!\n", - wandev->name,card->hw.fwid,SFID_CHDLC508); - err = -EPROTONOSUPPORT; - } - - if (err != 0){ - if (err == -EPROTONOSUPPORT){ - printk(KERN_INFO - "%s: Error, Protocol selected has not been compiled!\n", - card->devname); - printk(KERN_INFO - "%s: Re-configure the kernel and re-build the modules!\n", - card->devname); - } - - release_hw(card); - wandev->state = WAN_UNCONFIGURED; - return err; - } - - - /* Reserve I/O region and schedule background task */ - if(card->hw.type != SDLA_S514 && !card->wandev.piggyback) - if (!request_region(card->hw.port, card->hw.io_range, - wandev->name)) { - printk(KERN_WARNING "port 0x%04x busy\n", card->hw.port); - release_hw(card); - wandev->state = WAN_UNCONFIGURED; - return -EBUSY; - } - - /* Only use the polling routine for the X25 protocol */ - - card->wandev.critical=0; - return 0; -} - -/*================================================================== - * configure_s508_card - * - * For a S508 adapter, check for a possible configuration error in that - * we are loading an adapter in the same IO port as a previously loaded S508 - * card. - */ - -static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int *irq) -{ - unsigned long smp_flags; - int i; - - if (conf->ioport <= 0) { - printk(KERN_INFO - "%s: can't configure without I/O port address!\n", - card->wandev.name); - return -EINVAL; - } - - if (conf->irq <= 0) { - printk(KERN_INFO "%s: can't configure without IRQ!\n", - card->wandev.name); - return -EINVAL; - } - - if (test_bit(0,&card->configured)) - return 0; - - - /* Check for already loaded card with the same IO port and IRQ - * If found, copy its hardware configuration and use its - * resources (i.e. piggybacking) - */ - - for (i = 0; i < ncards; i++) { - sdla_t *nxt_card = &card_array[i]; - - /* Skip the current card ptr */ - if (nxt_card == card) - continue; - - - /* Find a card that is already configured with the - * same IO Port */ - if ((nxt_card->hw.type == SDLA_S508) && - (nxt_card->hw.port == conf->ioport) && - (nxt_card->next == NULL)){ - - /* We found a card the card that has same configuration - * as us. This means, that we must setup this card in - * piggibacking mode. However, only CHDLC and MPPP protocol - * support this setup */ - - if ((conf->config_id == WANCONFIG_CHDLC || - conf->config_id == WANCONFIG_MPPP) && - (nxt_card->wandev.config_id == WANCONFIG_CHDLC || - nxt_card->wandev.config_id == WANCONFIG_MPPP)){ - - *irq = nxt_card->hw.irq; - memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t)); - - /* The master could already be running, we must - * set this as a critical area */ - lock_adapter_irq(&nxt_card->wandev.lock, &smp_flags); - - nxt_card->next = card; - card->next = nxt_card; - - card->wandev.piggyback = WANOPT_YES; - - /* We must initialise the piggiback spin lock here - * since isr will try to lock card->next if it - * exists */ - spin_lock_init(&card->wandev.lock); - - unlock_adapter_irq(&nxt_card->wandev.lock, &smp_flags); - break; - }else{ - /* Trying to run piggibacking with a wrong protocol */ - printk(KERN_INFO "%s: ERROR: Resource busy, ioport: 0x%x\n" - "%s: This protocol doesn't support\n" - "%s: multi-port operation!\n", - card->devname,nxt_card->hw.port, - card->devname,card->devname); - return -EEXIST; - } - } - } - - - /* Make sure I/O port region is available only if we are the - * master device. If we are running in piggybacking mode, - * we will use the resources of the master card. */ - if (!card->wandev.piggyback) { - struct resource *rr = - request_region(conf->ioport, SDLA_MAXIORANGE, "sdlamain"); - release_region(conf->ioport, SDLA_MAXIORANGE); - - if (!rr) { - printk(KERN_INFO - "%s: I/O region 0x%X - 0x%X is in use!\n", - card->wandev.name, conf->ioport, - conf->ioport + SDLA_MAXIORANGE - 1); - return -EINVAL; - } - } - - return 0; -} - -/*================================================================== - * configure_s514_card - * - * For a S514 adapter, check for a possible configuration error in that - * we are loading an adapter in the same slot as a previously loaded S514 - * card. - */ - - -static int check_s514_conflicts(sdla_t* card,wandev_conf_t* conf, int *irq) -{ - unsigned long smp_flags; - int i; - - if (test_bit(0,&card->configured)) - return 0; - - - /* Check for already loaded card with the same IO port and IRQ - * If found, copy its hardware configuration and use its - * resources (i.e. piggybacking) - */ - - for (i = 0; i < ncards; i ++) { - - sdla_t* nxt_card = &card_array[i]; - if(nxt_card == card) - continue; - - if((nxt_card->hw.type == SDLA_S514) && - (nxt_card->hw.S514_slot_no == conf->PCI_slot_no) && - (nxt_card->hw.S514_cpu_no[0] == conf->S514_CPU_no[0])&& - (nxt_card->next == NULL)){ - - - if ((conf->config_id == WANCONFIG_CHDLC || - conf->config_id == WANCONFIG_MPPP) && - (nxt_card->wandev.config_id == WANCONFIG_CHDLC || - nxt_card->wandev.config_id == WANCONFIG_MPPP)){ - - *irq = nxt_card->hw.irq; - memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t)); - - /* The master could already be running, we must - * set this as a critical area */ - lock_adapter_irq(&nxt_card->wandev.lock,&smp_flags); - nxt_card->next = card; - card->next = nxt_card; - - card->wandev.piggyback = WANOPT_YES; - - /* We must initialise the piggiback spin lock here - * since isr will try to lock card->next if it - * exists */ - spin_lock_init(&card->wandev.lock); - - unlock_adapter_irq(&nxt_card->wandev.lock,&smp_flags); - - }else{ - /* Trying to run piggibacking with a wrong protocol */ - printk(KERN_INFO "%s: ERROR: Resource busy: CPU %c PCISLOT %i\n" - "%s: This protocol doesn't support\n" - "%s: multi-port operation!\n", - card->devname, - conf->S514_CPU_no[0],conf->PCI_slot_no, - card->devname,card->devname); - return -EEXIST; - } - } - } - - return 0; -} - - - -/*============================================================================ - * Shut down WAN link driver. - * o shut down adapter hardware - * o release system resources. - * - * This function is called by the router when device is being unregistered or - * when it handles ROUTER_DOWN IOCTL. - */ -static int shutdown(struct wan_device* wandev) -{ - sdla_t *card; - int err=0; - - /* sanity checks */ - if ((wandev == NULL) || (wandev->private == NULL)){ - return -EFAULT; - } - - if (wandev->state == WAN_UNCONFIGURED){ - return 0; - } - - card = wandev->private; - - if (card->tty_opt){ - if (card->tty_open){ - printk(KERN_INFO - "%s: Shutdown Failed: TTY is still open\n", - card->devname); - return -EBUSY; - } - } - - wandev->state = WAN_UNCONFIGURED; - - set_bit(PERI_CRIT,(void*)&wandev->critical); - - /* In case of piggibacking, make sure that - * we never try to shutdown both devices at the same - * time, because they depend on one another */ - - if (card->disable_comm){ - card->disable_comm(card); - } - - /* Release Resources */ - release_hw(card); - - /* only free the allocated I/O range if not an S514 adapter */ - if (wandev->hw_opt[0] != SDLA_S514 && !card->configured){ - release_region(card->hw.port, card->hw.io_range); - } - - if (!card->configured){ - memset(&card->hw, 0, sizeof(sdlahw_t)); - if (card->next){ - memset(&card->next->hw, 0, sizeof(sdlahw_t)); - } - } - - - clear_bit(PERI_CRIT,(void*)&wandev->critical); - return err; -} - -static void release_hw (sdla_t *card) -{ - sdla_t *nxt_card; - - - /* Check if next device exists */ - if (card->next){ - nxt_card = card->next; - /* If next device is down then release resources */ - if (nxt_card->wandev.state == WAN_UNCONFIGURED){ - if (card->wandev.piggyback){ - /* If this device is piggyback then use - * information of the master device - */ - printk(KERN_INFO "%s: Piggyback shutting down\n",card->devname); - sdla_down(&card->next->hw); - free_irq(card->wandev.irq, card->next); - card->configured = 0; - card->next->configured = 0; - card->wandev.piggyback = 0; - }else{ - /* Master device shutting down */ - printk(KERN_INFO "%s: Master shutting down\n",card->devname); - sdla_down(&card->hw); - free_irq(card->wandev.irq, card); - card->configured = 0; - card->next->configured = 0; - } - }else{ - printk(KERN_INFO "%s: Device still running %i\n", - nxt_card->devname,nxt_card->wandev.state); - - card->configured = 1; - } - }else{ - printk(KERN_INFO "%s: Master shutting down\n",card->devname); - sdla_down(&card->hw); - free_irq(card->wandev.irq, card); - card->configured = 0; - } - return; -} - - -/*============================================================================ - * Driver I/O control. - * o verify arguments - * o perform requested action - * - * This function is called when router handles one of the reserved user - * IOCTLs. Note that 'arg' stil points to user address space. - */ -static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg) -{ - sdla_t* card; - int err; - - /* sanity checks */ - if ((wandev == NULL) || (wandev->private == NULL)) - return -EFAULT; - if (wandev->state == WAN_UNCONFIGURED) - return -ENODEV; - - card = wandev->private; - - if(card->hw.type != SDLA_S514){ - disable_irq(card->hw.irq); - } - - if (test_bit(SEND_CRIT, (void*)&wandev->critical)) { - return -EAGAIN; - } - - switch (cmd) { - case WANPIPE_DUMP: - err = ioctl_dump(wandev->private, (void*)arg); - break; - - case WANPIPE_EXEC: - err = ioctl_exec(wandev->private, (void*)arg, cmd); - break; - default: - err = -EINVAL; - } - - return err; -} - -/****** Driver IOCTL Handlers ***********************************************/ - -/*============================================================================ - * Dump adapter memory to user buffer. - * o verify request structure - * o copy request structure to kernel data space - * o verify length/offset - * o verify user buffer - * o copy adapter memory image to user buffer - * - * Note: when dumping memory, this routine switches curent dual-port memory - * vector, so care must be taken to avoid racing conditions. - */ -static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump) -{ - sdla_dump_t dump; - unsigned winsize; - unsigned long oldvec; /* DPM window vector */ - unsigned long smp_flags; - int err = 0; - - if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t))) - return -EFAULT; - - if ((dump.magic != WANPIPE_MAGIC) || - (dump.offset + dump.length > card->hw.memory)) - return -EINVAL; - - winsize = card->hw.dpmsize; - - if(card->hw.type != SDLA_S514) { - - lock_adapter_irq(&card->wandev.lock, &smp_flags); - - oldvec = card->hw.vector; - while (dump.length) { - /* current offset */ - unsigned pos = dump.offset % winsize; - /* current vector */ - unsigned long vec = dump.offset - pos; - unsigned len = (dump.length > (winsize - pos)) ? - (winsize - pos) : dump.length; - /* relocate window */ - if (sdla_mapmem(&card->hw, vec) != 0) { - err = -EIO; - break; - } - - if(copy_to_user((void *)dump.ptr, - (u8 *)card->hw.dpmbase + pos, len)){ - - unlock_adapter_irq(&card->wandev.lock, &smp_flags); - return -EFAULT; - } - - dump.length -= len; - dump.offset += len; - dump.ptr = (char*)dump.ptr + len; - } - - sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */ - unlock_adapter_irq(&card->wandev.lock, &smp_flags); - - }else { - - if(copy_to_user((void *)dump.ptr, - (u8 *)card->hw.dpmbase + dump.offset, dump.length)){ - return -EFAULT; - } - } - - return err; -} - -/*============================================================================ - * Execute adapter firmware command. - * o verify request structure - * o copy request structure to kernel data space - * o call protocol-specific 'exec' function - */ -static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int cmd) -{ - sdla_exec_t exec; - int err=0; - - if (card->exec == NULL && cmd == WANPIPE_EXEC){ - return -ENODEV; - } - - if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t))) - return -EFAULT; - - if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL)) - return -EINVAL; - - switch (cmd) { - case WANPIPE_EXEC: - err = card->exec(card, exec.cmd, exec.data); - break; - } - return err; -} - -/******* Miscellaneous ******************************************************/ - -/*============================================================================ - * SDLA Interrupt Service Routine. - * o acknowledge SDLA hardware interrupt. - * o call protocol-specific interrupt service routine, if any. - */ -STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs) -{ -#define card ((sdla_t*)dev_id) - - if(card->hw.type == SDLA_S514) { /* handle interrrupt on S514 */ - u32 int_status; - unsigned char CPU_no = card->hw.S514_cpu_no[0]; - unsigned char card_found_for_IRQ; - u8 IRQ_count = 0; - - for(;;) { - - read_S514_int_stat(&card->hw, &int_status); - - /* check if the interrupt is for this device */ - if(!((unsigned char)int_status & - (IRQ_CPU_A | IRQ_CPU_B))) - return IRQ_HANDLED; - - /* if the IRQ is for both CPUs on the same adapter, */ - /* then alter the interrupt status so as to handle */ - /* one CPU at a time */ - if(((unsigned char)int_status & (IRQ_CPU_A | IRQ_CPU_B)) - == (IRQ_CPU_A | IRQ_CPU_B)) { - int_status &= (CPU_no == S514_CPU_A) ? - ~IRQ_CPU_B : ~IRQ_CPU_A; - } - - card_found_for_IRQ = 0; - - /* check to see that the CPU number for this device */ - /* corresponds to the interrupt status read */ - switch (CPU_no) { - case S514_CPU_A: - if((unsigned char)int_status & - IRQ_CPU_A) - card_found_for_IRQ = 1; - break; - - case S514_CPU_B: - if((unsigned char)int_status & - IRQ_CPU_B) - card_found_for_IRQ = 1; - break; - } - - /* exit if the interrupt is for another CPU on the */ - /* same IRQ */ - if(!card_found_for_IRQ) - return IRQ_HANDLED; - - if (!card || - (card->wandev.state == WAN_UNCONFIGURED && !card->configured)){ - printk(KERN_INFO - "Received IRQ %d for CPU #%c\n", - irq, CPU_no); - printk(KERN_INFO - "IRQ for unconfigured adapter\n"); - S514_intack(&card->hw, int_status); - return IRQ_HANDLED; - } - - if (card->in_isr) { - printk(KERN_INFO - "%s: interrupt re-entrancy on IRQ %d\n", - card->devname, card->wandev.irq); - S514_intack(&card->hw, int_status); - return IRQ_HANDLED; - } - - spin_lock(&card->wandev.lock); - if (card->next){ - spin_lock(&card->next->wandev.lock); - } - - S514_intack(&card->hw, int_status); - if (card->isr) - card->isr(card); - - if (card->next){ - spin_unlock(&card->next->wandev.lock); - } - spin_unlock(&card->wandev.lock); - - /* handle a maximum of two interrupts (one for each */ - /* CPU on the adapter) before returning */ - if((++ IRQ_count) == 2) - return IRQ_HANDLED; - } - } - - else { /* handle interrupt on S508 adapter */ - - if (!card || ((card->wandev.state == WAN_UNCONFIGURED) && !card->configured)) - return IRQ_HANDLED; - - if (card->in_isr) { - printk(KERN_INFO - "%s: interrupt re-entrancy on IRQ %d!\n", - card->devname, card->wandev.irq); - return IRQ_HANDLED; - } - - spin_lock(&card->wandev.lock); - if (card->next){ - spin_lock(&card->next->wandev.lock); - } - - sdla_intack(&card->hw); - if (card->isr) - card->isr(card); - - if (card->next){ - spin_unlock(&card->next->wandev.lock); - } - spin_unlock(&card->wandev.lock); - - } - return IRQ_HANDLED; -#undef card -} - -/*============================================================================ - * This routine is called by the protocol-specific modules when network - * interface is being open. The only reason we need this, is because we - * have to call MOD_INC_USE_COUNT, but cannot include 'module.h' where it's - * defined more than once into the same kernel module. - */ -void wanpipe_open (sdla_t* card) -{ - ++card->open_cnt; -} - -/*============================================================================ - * This routine is called by the protocol-specific modules when network - * interface is being closed. The only reason we need this, is because we - * have to call MOD_DEC_USE_COUNT, but cannot include 'module.h' where it's - * defined more than once into the same kernel module. - */ -void wanpipe_close (sdla_t* card) -{ - --card->open_cnt; -} - -/*============================================================================ - * Set WAN device state. - */ -void wanpipe_set_state (sdla_t* card, int state) -{ - if (card->wandev.state != state) { - switch (state) { - case WAN_CONNECTED: - printk (KERN_INFO "%s: link connected!\n", - card->devname); - break; - - case WAN_CONNECTING: - printk (KERN_INFO "%s: link connecting...\n", - card->devname); - break; - - case WAN_DISCONNECTED: - printk (KERN_INFO "%s: link disconnected!\n", - card->devname); - break; - } - card->wandev.state = state; - } - card->state_tick = jiffies; -} - -sdla_t * wanpipe_find_card (char *name) -{ - int cnt; - for (cnt = 0; cnt < ncards; ++ cnt) { - sdla_t* card = &card_array[cnt]; - if (!strcmp(card->devname,name)) - return card; - } - return NULL; -} - -sdla_t * wanpipe_find_card_num (int num) -{ - if (num < 1 || num > ncards) - return NULL; - num--; - return &card_array[num]; -} - -/* - * @work_pointer: work_struct to be done; - * should already have PREPARE_WORK() or - * INIT_WORK() done on it by caller; - */ -void wanpipe_queue_work (struct work_struct *work_pointer) -{ - if (test_and_set_bit(1, (void*)&wanpipe_bh_critical)) - printk(KERN_INFO "CRITICAL IN QUEUING WORK\n"); - - queue_work(wanpipe_wq, work_pointer); - clear_bit(1,(void*)&wanpipe_bh_critical); -} - -void wakeup_sk_bh(struct net_device *dev) -{ - wanpipe_common_t *chan = dev->priv; - - if (test_bit(0,&chan->common_critical)) - return; - - if (chan->sk && chan->tx_timer){ - chan->tx_timer->expires=jiffies+1; - add_timer(chan->tx_timer); - } -} - -int change_dev_flags(struct net_device *dev, unsigned flags) -{ - struct ifreq if_info; - mm_segment_t fs = get_fs(); - int err; - - memset(&if_info, 0, sizeof(if_info)); - strcpy(if_info.ifr_name, dev->name); - if_info.ifr_flags = flags; - - set_fs(get_ds()); /* get user space block */ - err = devinet_ioctl(SIOCSIFFLAGS, &if_info); - set_fs(fs); - - return err; -} - -unsigned long get_ip_address(struct net_device *dev, int option) -{ - - struct in_ifaddr *ifaddr; - struct in_device *in_dev; - unsigned long addr = 0; - - rcu_read_lock(); - if ((in_dev = __in_dev_get_rcu(dev)) == NULL){ - goto out; - } - - if ((ifaddr = in_dev->ifa_list)== NULL ){ - goto out; - } - - switch (option){ - - case WAN_LOCAL_IP: - addr = ifaddr->ifa_local; - break; - - case WAN_POINTOPOINT_IP: - addr = ifaddr->ifa_address; - break; - - case WAN_NETMASK_IP: - addr = ifaddr->ifa_mask; - break; - - case WAN_BROADCAST_IP: - addr = ifaddr->ifa_broadcast; - break; - default: - break; - } - -out: - rcu_read_unlock(); - return addr; -} - -void add_gateway(sdla_t *card, struct net_device *dev) -{ - mm_segment_t oldfs; - struct rtentry route; - int res; - - memset((char*)&route,0,sizeof(struct rtentry)); - - ((struct sockaddr_in *) - &(route.rt_dst))->sin_addr.s_addr = 0; - ((struct sockaddr_in *) - &(route.rt_dst))->sin_family = AF_INET; - - ((struct sockaddr_in *) - &(route.rt_genmask))->sin_addr.s_addr = 0; - ((struct sockaddr_in *) - &(route.rt_genmask)) ->sin_family = AF_INET; - - - route.rt_flags = 0; - route.rt_dev = dev->name; - - oldfs = get_fs(); - set_fs(get_ds()); - res = ip_rt_ioctl(SIOCADDRT,&route); - set_fs(oldfs); - - if (res == 0){ - printk(KERN_INFO "%s: Gateway added for %s\n", - card->devname,dev->name); - } - - return; -} - -MODULE_LICENSE("GPL"); - -/****** End *********************************************************/ diff --git a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c deleted file mode 100644 index 812a1183c502..000000000000 --- a/drivers/net/wan/wanpipe_multppp.c +++ /dev/null @@ -1,2358 +0,0 @@ -/***************************************************************************** -* wanpipe_multppp.c Multi-Port PPP driver module. -* -* Authors: Nenad Corbic -* -* Copyright: (c) 1995-2001 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. -* ============================================================================ -* Dec 15 2000 Updated for 2.4.X kernel -* Nov 15 2000 Fixed the SyncPPP support for kernels 2.2.16 and higher. -* The pppstruct has changed. -* Jul 13 2000 Using the kernel Syncppp module on top of RAW Wanpipe CHDLC -* module. -*****************************************************************************/ - -#include -#include /* printk(), and other useful stuff */ -#include /* offsetof(), etc. */ -#include /* return codes */ -#include /* inline memset(), etc. */ -#include /* kmalloc(), kfree() */ -#include /* WAN router definitions */ -#include /* WANPIPE common user API definitions */ -#include /* ARPHRD_* defines */ -#include /* time_after() macro */ - -#include /* sockaddr_in */ -#include -#include -#include /* htons(), etc. */ -#include -#include - -#include /* CHDLC firmware API definitions */ -#include /* CHDLC (async) API definitions */ - -#include /* Socket Driver common area */ -#include - - -#include -#include - -#include - - -/****** Defines & Macros ****************************************************/ - -#ifdef _DEBUG_ -#define STATIC -#else -#define STATIC static -#endif - -/* reasons for enabling the timer interrupt on the adapter */ -#define TMR_INT_ENABLED_UDP 0x01 -#define TMR_INT_ENABLED_UPDATE 0x02 -#define TMR_INT_ENABLED_CONFIG 0x04 - -#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */ -#define CHDLC_HDR_LEN 1 - -#define IFF_POINTTOPOINT 0x10 - -#define CHDLC_API 0x01 - -#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" ) -#define MAX_BH_BUFF 10 - -#define CRC_LENGTH 2 -#define PPP_HEADER_LEN 4 - -/******Data Structures*****************************************************/ - -/* This structure is placed in the private data area of the device structure. - * The card structure used to occupy the private area but now the following - * structure will incorporate the card structure along with CHDLC specific data - */ - -typedef struct chdlc_private_area -{ - void *if_ptr; /* General Pointer used by SPPP */ - wanpipe_common_t common; - sdla_t *card; - int TracingEnabled; /* For enabling Tracing */ - unsigned long curr_trace_addr; /* Used for Tracing */ - unsigned long start_trace_addr; - unsigned long end_trace_addr; - unsigned long base_addr_trace_buffer; - unsigned long end_addr_trace_buffer; - unsigned short number_trace_elements; - unsigned available_buffer_space; - unsigned long router_start_time; - unsigned char route_status; - unsigned char route_removed; - unsigned long tick_counter; /* For 5s timeout counter */ - unsigned long router_up_time; - u32 IP_address; /* IP addressing */ - u32 IP_netmask; - unsigned char mc; /* Mulitcast support on/off */ - unsigned short udp_pkt_lgth; /* udp packet processing */ - char udp_pkt_src; - char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; - unsigned short timer_int_enabled; - char update_comms_stats; /* updating comms stats */ - - //FIXME: add driver stats as per frame relay! - -} chdlc_private_area_t; - -/* Route Status options */ -#define NO_ROUTE 0x00 -#define ADD_ROUTE 0x01 -#define ROUTE_ADDED 0x02 -#define REMOVE_ROUTE 0x03 - - -/* variable for keeping track of enabling/disabling FT1 monitor status */ -static int rCount = 0; - -/* variable for tracking how many interfaces to open for WANPIPE on the - two ports */ - -extern void disable_irq(unsigned int); -extern void enable_irq(unsigned int); - -/****** Function Prototypes *************************************************/ -/* WAN link driver entry points. These are called by the WAN router module. */ -static int update(struct wan_device* wandev); -static int new_if(struct wan_device* wandev, struct net_device* dev, - wanif_conf_t* conf); -static int del_if(struct wan_device* wandev, struct net_device* dev); - -/* Network device interface */ -static int if_init(struct net_device* dev); -static int if_open(struct net_device* dev); -static int if_close(struct net_device* dev); -static int if_send(struct sk_buff* skb, struct net_device* dev); -static struct net_device_stats* if_stats(struct net_device* dev); - -static void if_tx_timeout(struct net_device *dev); - -/* CHDLC Firmware interface functions */ -static int chdlc_configure (sdla_t* card, void* data); -static int chdlc_comm_enable (sdla_t* card); -static int chdlc_comm_disable (sdla_t* card); -static int chdlc_read_version (sdla_t* card, char* str); -static int chdlc_set_intr_mode (sdla_t* card, unsigned mode); -static int chdlc_send (sdla_t* card, void* data, unsigned len); -static int chdlc_read_comm_err_stats (sdla_t* card); -static int chdlc_read_op_stats (sdla_t* card); -static int config_chdlc (sdla_t *card); - - -/* Miscellaneous CHDLC Functions */ -static int set_chdlc_config (sdla_t* card); -static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev); -static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb); -static int process_chdlc_exception(sdla_t *card); -static int process_global_exception(sdla_t *card); -static int update_comms_stats(sdla_t* card, - chdlc_private_area_t* chdlc_priv_area); -static void port_set_state (sdla_t *card, int); - -/* Interrupt handlers */ -static void wsppp_isr (sdla_t* card); -static void rx_intr (sdla_t* card); -static void timer_intr(sdla_t *); - -/* Miscellaneous functions */ -static int reply_udp( unsigned char *data, unsigned int mbox_len ); -static int intr_test( sdla_t* card); -static int udp_pkt_type( struct sk_buff *skb , sdla_t* card); -static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, struct net_device* dev, - chdlc_private_area_t* chdlc_priv_area); -static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, - chdlc_private_area_t* chdlc_priv_area); -static unsigned short calc_checksum (char *, int); -static void s508_lock (sdla_t *card, unsigned long *smp_flags); -static void s508_unlock (sdla_t *card, unsigned long *smp_flags); -static void send_ppp_term_request(struct net_device *dev); - - -static int Intr_test_counter; -/****** Public Functions ****************************************************/ - -/*============================================================================ - * Cisco HDLC 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 wsppp_init (sdla_t* card, wandev_conf_t* conf) -{ - unsigned char port_num; - int err; - unsigned long max_permitted_baud = 0; - SHARED_MEMORY_INFO_STRUCT *flags; - - union - { - char str[80]; - } u; - volatile CHDLC_MAILBOX_STRUCT* mb; - CHDLC_MAILBOX_STRUCT* mb1; - unsigned long timeout; - - /* Verify configuration ID */ - if (conf->config_id != WANCONFIG_MPPP) { - printk(KERN_INFO "%s: invalid configuration ID %u!\n", - card->devname, conf->config_id); - return -EINVAL; - } - - /* Find out which Port to use */ - if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){ - if (card->next){ - - if (conf->comm_port != card->next->u.c.comm_port){ - card->u.c.comm_port = conf->comm_port; - }else{ - printk(KERN_ERR "%s: ERROR - %s port used!\n", - card->wandev.name, PORT(conf->comm_port)); - return -EINVAL; - } - }else{ - card->u.c.comm_port = conf->comm_port; - } - }else{ - printk(KERN_ERR "%s: ERROR - Invalid Port Selected!\n", - card->wandev.name); - return -EINVAL; - } - - - /* Initialize protocol-specific fields */ - if(card->hw.type != SDLA_S514){ - - if (card->u.c.comm_port == WANOPT_PRI){ - card->mbox = (void *) card->hw.dpmbase; - }else{ - card->mbox = (void *) card->hw.dpmbase + - SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT; - } - }else{ - /* for a S514 adapter, set a pointer to the actual mailbox in the */ - /* allocated virtual memory area */ - if (card->u.c.comm_port == WANOPT_PRI){ - card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT; - }else{ - card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT; - } - } - - mb = mb1 = card->mbox; - - if (!card->configured){ - - /* The board will place an 'I' in the return code to indicate that it is - ready to accept commands. We expect this to be completed in less - than 1 second. */ - - timeout = jiffies + 1 * HZ; - while (mb->return_code != 'I') /* Wait 1s for board to initialize */ - if (time_after(jiffies, timeout)) break; - - if (mb->return_code != 'I') { - printk(KERN_INFO - "%s: Initialization not completed by adapter\n", - card->devname); - printk(KERN_INFO "Please contact Sangoma representative.\n"); - return -EIO; - } - } - - /* 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 (chdlc_read_version(card, u.str)) - return -EIO; - - printk(KERN_INFO "%s: Running Raw CHDLC firmware v%s\n" - "%s: for Multi-Port PPP protocol.\n", - card->devname,u.str,card->devname); - - card->isr = &wsppp_isr; - card->poll = NULL; - card->exec = NULL; - card->wandev.update = &update; - card->wandev.new_if = &new_if; - card->wandev.del_if = &del_if; - card->wandev.udp_port = conf->udp_port; - - card->wandev.new_if_cnt = 0; - - /* reset the number of times the 'update()' proc has been called */ - card->u.c.update_call_count = 0; - - card->wandev.ttl = conf->ttl; - card->wandev.interface = conf->interface; - - if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&& - card->hw.type != SDLA_S514){ - printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n", - card->devname, PORT(card->u.c.comm_port)); - return -EIO; - } - - - card->wandev.clocking = conf->clocking; - - port_num = card->u.c.comm_port; - - /* Setup Port Bps */ - - if(card->wandev.clocking) { - if((port_num == WANOPT_PRI) || card->u.c.receive_only) { - /* For Primary Port 0 */ - 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; - } - - /* Add on a PPP Header */ - card->wandev.mtu += PPP_HEADER_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) { - clear_bit(1, (void*)&card->wandev.critical); - - 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){ - err = intr_test(card); - - if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { - printk(KERN_ERR "%s: Interrupt test failed (%i)\n", - card->devname, Intr_test_counter); - printk(KERN_ERR "%s: Please choose another interrupt\n", - card->devname); - return -EIO; - } - - printk(KERN_INFO "%s: Interrupt test passed (%i)\n", - card->devname, Intr_test_counter); - } - - - 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; - - 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((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 + 1 * HZ; - for(;;) { - if(chdlc_priv_area->update_comms_stats == 0) - break; - if (time_after(jiffies, timeout)){ - 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* pdev, - wanif_conf_t* conf) -{ - - struct ppp_device *pppdev = (struct ppp_device *)pdev; - struct net_device *dev = NULL; - struct sppp *sp; - sdla_t* card = wandev->private; - chdlc_private_area_t* chdlc_priv_area; - - 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; - - /* 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; - - //We don't need this any more - chdlc_priv_area->route_status = NO_ROUTE; - chdlc_priv_area->route_removed = 0; - - printk(KERN_INFO "%s: Firmware running in HDLC STREAMING Mode\n", - wandev->name); - - /* Setup wanpipe as a router (WANPIPE) or as an API */ - if( strcmp(conf->usedby, "WANPIPE") == 0) { - printk(KERN_INFO "%s: Driver running in WANPIPE mode!\n", - wandev->name); - card->u.c.usedby = WANPIPE; - } else { - printk(KERN_INFO - "%s: API Mode is not supported for SyncPPP!\n", - wandev->name); - kfree(chdlc_priv_area); - return -EINVAL; - } - - /* Get Multicast Information */ - chdlc_priv_area->mc = conf->mc; - - - chdlc_priv_area->if_ptr = pppdev; - - /* prepare network device data space for registration */ - - strcpy(dev->name,card->u.c.if_name); - - /* Attach PPP protocol layer to pppdev - * The sppp_attach() will initilize the dev structure - * and setup ppp layer protocols. - * All we have to do is to bind in: - * if_open(), if_close(), if_send() and get_stats() functions. - */ - sppp_attach(pppdev); - dev = pppdev->dev; - sp = &pppdev->sppp; - - /* Enable PPP Debugging */ - // FIXME Fix this up somehow - //sp->pp_flags |= PP_DEBUG; - sp->pp_flags &= ~PP_CISCO; - - dev->init = &if_init; - dev->priv = chdlc_priv_area; - - return 0; -} - - - - -/*============================================================================ - * Delete logical channel. - */ -static int del_if(struct wan_device* wandev, struct net_device* dev) -{ - chdlc_private_area_t *chdlc_priv_area = dev->priv; - sdla_t *card = chdlc_priv_area->card; - unsigned long smp_lock; - - /* Detach the PPP layer */ - printk(KERN_INFO "%s: Detaching SyncPPP Module from %s\n", - wandev->name,dev->name); - - lock_adapter_irq(&wandev->lock,&smp_lock); - - sppp_detach(dev); - chdlc_priv_area->if_ptr=NULL; - - chdlc_set_intr_mode(card, 0); - if (card->u.c.comm_enabled) - chdlc_comm_disable(card); - unlock_adapter_irq(&wandev->lock,&smp_lock); - - port_set_state(card, WAN_DISCONNECTED); - - 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; - - /* NOTE: Most of the dev initialization was - * done in sppp_attach(), called by new_if() - * function. All we have to do here is - * to link four major routines below. - */ - - /* Initialize device driver entry points */ - dev->open = &if_open; - dev->stop = &if_close; - dev->hard_start_xmit = &if_send; - dev->get_stats = &if_stats; - dev->tx_timeout = &if_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; - - - /* Initialize hardware parameters */ - dev->irq = wandev->irq; - dev->dma = wandev->dma; - dev->base_addr = wandev->ioport; - dev->mem_start = wandev->maddr; - dev->mem_end = wandev->maddr + wandev->msize - 1; - - /* Set transmit buffer queue length - * If we over fill this queue the packets will - * be droped by the kernel. - * sppp_attach() sets this to 10, but - * 100 will give us more room at low speeds. - */ - dev->tx_queue_len = 100; - - return 0; -} - - -/*============================================================================ - * Handle transmit timeout event from netif watchdog - */ -static void if_tx_timeout(struct net_device *dev) -{ - chdlc_private_area_t* chan = dev->priv; - sdla_t *card = chan->card; - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - - ++card->wandev.stats.collisions; - - printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); - netif_wake_queue (dev); -} - - -/*============================================================================ - * Open network interface. - * o enable communications and interrupts. - * o prevent module from unloading by incrementing use count - * - * Return 0 if O.k. or errno. - */ -static int if_open(struct net_device* dev) -{ - chdlc_private_area_t* chdlc_priv_area = dev->priv; - sdla_t* card = chdlc_priv_area->card; - struct timeval tv; - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - - /* Only one open per interface is allowed */ - if (netif_running(dev)) - return -EBUSY; - - /* Start PPP Layer */ - if (sppp_open(dev)){ - return -EIO; - } - - do_gettimeofday(&tv); - chdlc_priv_area->router_start_time = tv.tv_sec; - - netif_start_queue(dev); - - wanpipe_open(card); - - chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG; - flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER; - return 0; -} - -/*============================================================================ - * Close network interface. - * o if this is the last close, then disable communications and interrupts. - * o reset flags. - */ -static int if_close(struct net_device* dev) -{ - chdlc_private_area_t* chdlc_priv_area = dev->priv; - sdla_t* card = chdlc_priv_area->card; - - /* Stop the PPP Layer */ - sppp_close(dev); - netif_stop_queue(dev); - - wanpipe_close(card); - - return 0; -} - -/*============================================================================ - * Send a packet on a network interface. - * o set tbusy flag (marks start of the transmission) to block a timer-based - * transmit from overlapping. - * o check link state. If link is not up, then drop the packet. - * o execute adapter send command. - * o free socket buffer - * - * Return: 0 complete (socket buffer must be freed) - * non-0 packet may be re-transmitted (tbusy must be set) - * - * Notes: - * 1. This routine is called either by the protocol stack or by the "net - * bottom half" (with interrupts enabled). - * 2. Setting tbusy flag will inhibit further transmit requests from the - * protocol stack and can be used for flow control with protocol layer. - */ -static int if_send(struct sk_buff* skb, struct net_device* dev) -{ - chdlc_private_area_t *chdlc_priv_area = dev->priv; - sdla_t *card = chdlc_priv_area->card; - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct; - int udp_type = 0; - unsigned long smp_flags; - int err=0; - - netif_stop_queue(dev); - - - if (skb == NULL){ - /* If we get here, some higher layer thinks we've missed an - * tx-done interrupt. - */ - printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n", - card->devname, dev->name); - - netif_wake_queue(dev); - return 0; - } - - if (ntohs(skb->protocol) != htons(PVC_PROT)){ - /* check the udp packet type */ - - udp_type = udp_pkt_type(skb, card); - if (udp_type == UDP_CPIPE_TYPE){ - if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, - chdlc_priv_area)){ - chdlc_int->interrupt_permission |= - APP_INT_ON_TIMER; - } - netif_start_queue(dev); - return 0; - } - } - - /* Lock the 508 Card: SMP is supported */ - if(card->hw.type != SDLA_S514){ - s508_lock(card,&smp_flags); - } - - if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){ - - printk(KERN_INFO "%s: Critical in if_send: %lx\n", - card->wandev.name,card->wandev.critical); - ++card->wandev.stats.tx_dropped; - netif_start_queue(dev); - goto if_send_crit_exit; - } - - if (card->wandev.state != WAN_CONNECTED){ - ++card->wandev.stats.tx_dropped; - netif_start_queue(dev); - goto if_send_crit_exit; - } - - if (chdlc_send(card, skb->data, skb->len)){ - netif_stop_queue(dev); - - }else{ - ++card->wandev.stats.tx_packets; - card->wandev.stats.tx_bytes += skb->len; - dev->trans_start = jiffies; - netif_start_queue(dev); - } - -if_send_crit_exit: - if (!(err=netif_queue_stopped(dev))){ - dev_kfree_skb_any(skb); - }else{ - chdlc_priv_area->tick_counter = jiffies; - chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; - } - - clear_bit(SEND_CRIT, (void*)&card->wandev.critical); - if(card->hw.type != SDLA_S514){ - s508_unlock(card,&smp_flags); - } - - return err; -} - - -/*============================================================================ - * Reply to UDP Management system. - * Return length of reply. - */ -static int reply_udp( unsigned char *data, unsigned int mbox_len ) -{ - - unsigned short len, udp_length, temp, ip_length; - unsigned long ip_temp; - int even_bound = 0; - chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data; - - /* Set length of packet */ - len = sizeof(ip_pkt_t)+ - sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - sizeof(trace_info_t)+ - mbox_len; - - /* fill in UDP reply */ - c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; - - /* fill in UDP length */ - udp_length = sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - sizeof(trace_info_t)+ - mbox_len; - - /* put it on an even boundary */ - if ( udp_length & 0x0001 ) { - udp_length += 1; - len += 1; - even_bound = 1; - } - - temp = (udp_length<<8)|(udp_length>>8); - c_udp_pkt->udp_pkt.udp_length = temp; - - /* swap UDP ports */ - temp = c_udp_pkt->udp_pkt.udp_src_port; - c_udp_pkt->udp_pkt.udp_src_port = - c_udp_pkt->udp_pkt.udp_dst_port; - c_udp_pkt->udp_pkt.udp_dst_port = temp; - - /* add UDP pseudo header */ - temp = 0x1100; - *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp; - temp = (udp_length<<8)|(udp_length>>8); - *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp; - - - /* calculate UDP checksum */ - c_udp_pkt->udp_pkt.udp_checksum = 0; - c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET); - - /* fill in IP length */ - ip_length = len; - temp = (ip_length<<8)|(ip_length>>8); - c_udp_pkt->ip_pkt.total_length = temp; - - /* swap IP addresses */ - ip_temp = c_udp_pkt->ip_pkt.ip_src_address; - c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address; - c_udp_pkt->ip_pkt.ip_dst_address = ip_temp; - - /* fill in IP checksum */ - c_udp_pkt->ip_pkt.hdr_checksum = 0; - c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t)); - - return len; - -} /* reply_udp */ - -unsigned short calc_checksum (char *data, int len) -{ - unsigned short temp; - unsigned long sum=0; - int i; - - for( i = 0; i > 16 ) { - sum = (sum & 0xffffUL) + (sum >> 16); - } - - temp = (unsigned short)sum; - temp = ~temp; - - if( temp == 0 ) - temp = 0xffff; - - return temp; -} - - -/*============================================================================ - * Get ethernet-style interface statistics. - * Return a pointer to struct enet_statistics. - */ -static struct net_device_stats* if_stats(struct net_device* dev) -{ - sdla_t *my_card; - chdlc_private_area_t* chdlc_priv_area; - - /* Shutdown bug fix. In del_if() we kill - * dev->priv pointer. This function, gets - * called after del_if(), thus check - * if pointer has been deleted */ - if ((chdlc_priv_area=dev->priv) == NULL) - return NULL; - - my_card = chdlc_priv_area->card; - return &my_card->wandev.stats; -} - - -/****** Cisco HDLC Firmware Interface Functions *******************************/ - -/*============================================================================ - * Read firmware code version. - * Put code version as ASCII string in str. - */ -static int chdlc_read_version (sdla_t* card, char* str) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - int len; - char err; - mb->buffer_length = 0; - mb->command = READ_CHDLC_CODE_VERSION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - if(err != COMMAND_OK) { - chdlc_error(card,err,mb); - } - else if (str) { /* is not null */ - len = mb->buffer_length; - memcpy(str, mb->data, len); - str[len] = '\0'; - } - return (err); -} - -/*----------------------------------------------------------------------------- - * Configure CHDLC firmware. - */ -static int chdlc_configure (sdla_t* card, void* data) -{ - int err; - CHDLC_MAILBOX_STRUCT *mailbox = card->mbox; - int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT); - - mailbox->buffer_length = data_length; - memcpy(mailbox->data, data, data_length); - mailbox->command = SET_CHDLC_CONFIGURATION; - err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT; - - if (err != COMMAND_OK) chdlc_error (card, err, mailbox); - - return err; -} - - -/*============================================================================ - * Set interrupt mode -- HDLC Version. - */ - -static int chdlc_set_intr_mode (sdla_t* card, unsigned mode) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - CHDLC_INT_TRIGGERS_STRUCT* int_data = - (CHDLC_INT_TRIGGERS_STRUCT *)mb->data; - int err; - - int_data->CHDLC_interrupt_triggers = mode; - int_data->IRQ = card->hw.irq; - int_data->interrupt_timer = 1; - - mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT); - mb->command = SET_CHDLC_INTERRUPT_TRIGGERS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error (card, err, mb); - return err; -} - - -/*============================================================================ - * Enable communications. - */ - -static int chdlc_comm_enable (sdla_t* card) -{ - int err; - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - - mb->buffer_length = 0; - mb->command = ENABLE_CHDLC_COMMUNICATIONS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error(card, err, mb); - else - card->u.c.comm_enabled=1; - - return err; -} - -/*============================================================================ - * Disable communications and Drop the Modem lines (DCD and RTS). - */ -static int chdlc_comm_disable (sdla_t* card) -{ - int err; - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - - mb->buffer_length = 0; - mb->command = DISABLE_CHDLC_COMMUNICATIONS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error(card,err,mb); - - return err; -} - -/*============================================================================ - * Read communication error statistics. - */ -static int chdlc_read_comm_err_stats (sdla_t* card) -{ - int err; - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - - mb->buffer_length = 0; - mb->command = READ_COMMS_ERROR_STATS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error(card,err,mb); - return err; -} - - -/*============================================================================ - * Read CHDLC operational statistics. - */ -static int chdlc_read_op_stats (sdla_t* card) -{ - int err; - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - - mb->buffer_length = 0; - mb->command = READ_CHDLC_OPERATIONAL_STATS; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) - chdlc_error(card,err,mb); - return err; -} - - -/*============================================================================ - * Update communications error and general packet statistics. - */ -static int update_comms_stats(sdla_t* card, - chdlc_private_area_t* chdlc_priv_area) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - COMMS_ERROR_STATS_STRUCT* err_stats; - CHDLC_OPERATIONAL_STATS_STRUCT *op_stats; - - /* on the first timer interrupt, read the comms error statistics */ - if(chdlc_priv_area->update_comms_stats == 2) { - if(chdlc_read_comm_err_stats(card)) - return 1; - err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data; - card->wandev.stats.rx_over_errors = - err_stats->Rx_overrun_err_count; - card->wandev.stats.rx_crc_errors = - err_stats->CRC_err_count; - card->wandev.stats.rx_frame_errors = - err_stats->Rx_abort_count; - card->wandev.stats.rx_fifo_errors = - err_stats->Rx_dis_pri_bfrs_full_count; - card->wandev.stats.rx_missed_errors = - card->wandev.stats.rx_fifo_errors; - card->wandev.stats.tx_aborted_errors = - err_stats->sec_Tx_abort_count; - } - - /* on the second timer interrupt, read the operational statistics */ - else { - if(chdlc_read_op_stats(card)) - return 1; - op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data; - card->wandev.stats.rx_length_errors = - (op_stats->Rx_Data_discard_short_count + - op_stats->Rx_Data_discard_long_count); - } - - return 0; -} - -/*============================================================================ - * Send packet. - * Return: 0 - o.k. - * 1 - no transmit buffers available - */ -static int chdlc_send (sdla_t* card, void* data, unsigned len) -{ - CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf; - - if (txbuf->opp_flag) - return 1; - - sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len); - - txbuf->frame_length = len; - txbuf->opp_flag = 1; /* start transmission */ - - /* Update transmit buffer control fields */ - card->u.c.txbuf = ++txbuf; - - if ((void*)txbuf > card->u.c.txbuf_last) - card->u.c.txbuf = card->u.c.txbuf_base; - - return 0; -} - -/****** Firmware Error Handler **********************************************/ - -/*============================================================================ - * Firmware error handler. - * This routine is called whenever firmware command returns non-zero - * return code. - * - * Return zero if previous command has to be cancelled. - */ -static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb) -{ - unsigned cmd = mb->command; - - switch (err) { - - case CMD_TIMEOUT: - printk(KERN_ERR "%s: command 0x%02X timed out!\n", - card->devname, cmd); - break; - - case S514_BOTH_PORTS_SAME_CLK_MODE: - if(cmd == SET_CHDLC_CONFIGURATION) { - printk(KERN_INFO - "%s: Configure both ports for the same clock source\n", - card->devname); - break; - } - - default: - printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n", - card->devname, cmd, err); - } - - return 0; -} - -/****** Interrupt Handlers **************************************************/ - -/*============================================================================ - * Cisco HDLC interrupt service routine. - */ -STATIC void wsppp_isr (sdla_t* card) -{ - struct net_device* dev; - SHARED_MEMORY_INFO_STRUCT* flags = NULL; - int i; - sdla_t *my_card; - - - /* Check for which port the interrupt has been generated - * Since Secondary Port is piggybacking on the Primary - * the check must be done here. - */ - - flags = card->u.c.flags; - if (!flags->interrupt_info_struct.interrupt_type){ - /* Check for a second port (piggybacking) */ - if((my_card = card->next)){ - flags = my_card->u.c.flags; - if (flags->interrupt_info_struct.interrupt_type){ - card = my_card; - card->isr(card); - return; - } - } - } - - dev = card->wandev.dev; - card->in_isr = 1; - flags = card->u.c.flags; - - /* If we get an interrupt with no network device, stop the interrupts - * and issue an error */ - if ((!dev || !dev->priv) && flags->interrupt_info_struct.interrupt_type != - COMMAND_COMPLETE_APP_INT_PEND){ - goto isr_done; - } - - - /* if critical due to peripheral operations - * ie. update() or getstats() then reset the interrupt and - * wait for the board to retrigger. - */ - if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { - flags->interrupt_info_struct. - interrupt_type = 0; - goto isr_done; - } - - - /* On a 508 Card, if critical due to if_send - * Major Error !!! - */ - if(card->hw.type != SDLA_S514) { - if(test_bit(0, (void*)&card->wandev.critical)) { - printk(KERN_INFO "%s: Critical while in ISR: %lx\n", - card->devname, card->wandev.critical); - goto isr_done; - } - } - - switch(flags->interrupt_info_struct.interrupt_type) { - - case RX_APP_INT_PEND: /* 0x01: receive interrupt */ - rx_intr(card); - break; - - case TX_APP_INT_PEND: /* 0x02: transmit interrupt */ - flags->interrupt_info_struct.interrupt_permission &= - ~APP_INT_ON_TX_FRAME; - - netif_wake_queue(dev); - break; - - case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */ - ++ Intr_test_counter; - break; - - case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */ - process_chdlc_exception(card); - break; - - case GLOBAL_EXCEP_COND_APP_INT_PEND: - process_global_exception(card); - break; - - case TIMER_APP_INT_PEND: - timer_intr(card); - break; - - default: - printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", - card->devname, - flags->interrupt_info_struct.interrupt_type); - printk(KERN_INFO "Code name: "); - for(i = 0; i < 4; i ++) - printk(KERN_INFO "%c", - flags->global_info_struct.codename[i]); - printk(KERN_INFO "\nCode version: "); - for(i = 0; i < 4; i ++) - printk(KERN_INFO "%c", - flags->global_info_struct.codeversion[i]); - printk(KERN_INFO "\n"); - break; - } - -isr_done: - card->in_isr = 0; - flags->interrupt_info_struct.interrupt_type = 0; -} - -/*============================================================================ - * Receive interrupt handler. - */ -static void rx_intr (sdla_t* card) -{ - struct net_device *dev; - chdlc_private_area_t *chdlc_priv_area; - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb; - struct sk_buff *skb; - unsigned len; - unsigned addr = rxbuf->ptr_data_bfr; - void *buf; - int i,udp_type; - - if (rxbuf->opp_flag != 0x01) { - printk(KERN_INFO - "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", - card->devname, (unsigned)rxbuf, rxbuf->opp_flag); - printk(KERN_INFO "Code name: "); - for(i = 0; i < 4; i ++) - printk(KERN_INFO "%c", - flags->global_info_struct.codename[i]); - printk(KERN_INFO "\nCode version: "); - for(i = 0; i < 4; i ++) - printk(KERN_INFO "%c", - flags->global_info_struct.codeversion[i]); - printk(KERN_INFO "\n"); - - - /* Bug Fix: Mar 6 2000 - * If we get a corrupted mailbox, it measn that driver - * is out of sync with the firmware. There is no recovery. - * If we don't turn off all interrupts for this card - * the machine will crash. - */ - printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); - printk(KERN_INFO "Please contact Sangoma Technologies !\n"); - chdlc_set_intr_mode(card,0); - return; - } - - dev = card->wandev.dev; - - if (!dev){ - goto rx_exit; - } - - if (!netif_running(dev)){ - goto rx_exit; - } - - chdlc_priv_area = dev->priv; - - if (rxbuf->error_flag){ - goto rx_exit; - } - /* Take off two CRC bytes */ - - if (rxbuf->frame_length < 7 || rxbuf->frame_length > 1506 ){ - goto rx_exit; - } - - len = rxbuf->frame_length - CRC_LENGTH; - - /* Allocate socket buffer */ - skb = dev_alloc_skb(len); - - if (skb == NULL) { - if (net_ratelimit()){ - printk(KERN_INFO "%s: no socket buffers available!\n", - card->devname); - } - ++card->wandev.stats.rx_dropped; - goto rx_exit; - } - - /* Copy data to the socket buffer */ - if((addr + len) > card->u.c.rx_top + 1) { - unsigned tmp = card->u.c.rx_top - addr + 1; - buf = skb_put(skb, tmp); - sdla_peek(&card->hw, addr, buf, tmp); - addr = card->u.c.rx_base; - len -= tmp; - } - - buf = skb_put(skb, len); - sdla_peek(&card->hw, addr, buf, len); - - skb->protocol = htons(ETH_P_WAN_PPP); - - card->wandev.stats.rx_packets ++; - card->wandev.stats.rx_bytes += skb->len; - udp_type = udp_pkt_type( skb, card ); - - if(udp_type == UDP_CPIPE_TYPE) { - if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, - card, skb, dev, chdlc_priv_area)) { - flags->interrupt_info_struct. - interrupt_permission |= - APP_INT_ON_TIMER; - } - }else{ - /* Pass it up the protocol stack */ - skb->dev = dev; - skb->mac.raw = skb->data; - netif_rx(skb); - dev->last_rx = jiffies; - } - -rx_exit: - /* Release buffer element and calculate a pointer to the next one */ - rxbuf->opp_flag = 0x00; - card->u.c.rxmb = ++ rxbuf; - if((void*)rxbuf > card->u.c.rxbuf_last){ - card->u.c.rxmb = card->u.c.rxbuf_base; - } -} - -/*============================================================================ - * Timer interrupt handler. - * The timer interrupt is used for two purposes: - * 1) Processing udp calls from 'cpipemon'. - * 2) Reading board-level statistics for updating the proc file system. - */ -void timer_intr(sdla_t *card) -{ - struct net_device* dev; - chdlc_private_area_t* chdlc_priv_area = NULL; - SHARED_MEMORY_INFO_STRUCT* flags = NULL; - - dev = card->wandev.dev; - chdlc_priv_area = dev->priv; - - if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) { - if (!config_chdlc(card)){ - chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG; - } - } - - /* process a udp call if pending */ - if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) { - process_udp_mgmt_pkt(card, dev, - chdlc_priv_area); - chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP; - } - - - /* read the communications statistics if required */ - if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) { - update_comms_stats(card, chdlc_priv_area); - if(!(-- chdlc_priv_area->update_comms_stats)) { - chdlc_priv_area->timer_int_enabled &= - ~TMR_INT_ENABLED_UPDATE; - } - } - - /* only disable the timer interrupt if there are no udp or statistic */ - /* updates pending */ - if(!chdlc_priv_area->timer_int_enabled) { - flags = card->u.c.flags; - flags->interrupt_info_struct.interrupt_permission &= - ~APP_INT_ON_TIMER; - } -} - -/*------------------------------------------------------------------------------ - Miscellaneous Functions - - set_chdlc_config() used to set configuration options on the board -------------------------------------------------------------------------------*/ - -static int set_chdlc_config(sdla_t* card) -{ - - CHDLC_CONFIGURATION_STRUCT cfg; - - memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT)); - - if(card->wandev.clocking) - cfg.baud_rate = card->wandev.bps; - - cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ? - INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35; - - cfg.modem_config_options = 0; - //API OPTIONS - cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES; - cfg.modem_status_timer = 100; - cfg.CHDLC_protocol_options = HDLC_STREAMING_MODE; - cfg.percent_data_buffer_for_Tx = 50; - cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT | - CHDLC_RX_DATA_BYTE_COUNT_STAT); - cfg.max_CHDLC_data_field_length = card->wandev.mtu; - - cfg.transmit_keepalive_timer = 0; - cfg.receive_keepalive_timer = 0; - cfg.keepalive_error_tolerance = 0; - cfg.SLARP_request_timer = 0; - - cfg.IP_address = 0; - cfg.IP_netmask = 0; - - return chdlc_configure(card, &cfg); -} - -/*============================================================================ - * Process global exception condition - */ -static int process_global_exception(sdla_t *card) -{ - CHDLC_MAILBOX_STRUCT* mbox = card->mbox; - int err; - - mbox->buffer_length = 0; - mbox->command = READ_GLOBAL_EXCEPTION_CONDITION; - err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT; - - if(err != CMD_TIMEOUT ){ - - switch(mbox->return_code) { - - case EXCEP_MODEM_STATUS_CHANGE: - - printk(KERN_INFO "%s: Modem status change\n", - card->devname); - - switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) { - case (DCD_HIGH): - printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname); - break; - case (CTS_HIGH): - printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname); - break; - case ((DCD_HIGH | CTS_HIGH)): - printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname); - break; - default: - printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname); - break; - } - - if (!(mbox->data[0] & DCD_HIGH) || !(mbox->data[0] & DCD_HIGH)){ - //printk(KERN_INFO "Sending TERM Request Manually !\n"); - send_ppp_term_request(card->wandev.dev); - } - break; - - case EXCEP_TRC_DISABLED: - printk(KERN_INFO "%s: Line trace disabled\n", - card->devname); - break; - - case EXCEP_IRQ_TIMEOUT: - printk(KERN_INFO "%s: IRQ timeout occurred\n", - card->devname); - break; - - default: - printk(KERN_INFO "%s: Global exception %x\n", - card->devname, mbox->return_code); - break; - } - } - return 0; -} - - -/*============================================================================ - * Process chdlc exception condition - */ -static int process_chdlc_exception(sdla_t *card) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - int err; - - mb->buffer_length = 0; - mb->command = READ_CHDLC_EXCEPTION_CONDITION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if(err != CMD_TIMEOUT) { - - switch (err) { - - case EXCEP_LINK_ACTIVE: - port_set_state(card, WAN_CONNECTED); - break; - - case EXCEP_LINK_INACTIVE_MODEM: - port_set_state(card, WAN_DISCONNECTED); - break; - - case EXCEP_LOOPBACK_CONDITION: - printk(KERN_INFO "%s: Loopback Condition Detected.\n", - card->devname); - break; - - case NO_CHDLC_EXCEP_COND_TO_REPORT: - printk(KERN_INFO "%s: No exceptions reported.\n", - card->devname); - break; - default: - printk(KERN_INFO "%s: Exception Condition %x!\n", - card->devname,err); - break; - } - - } - return 0; -} - - -/*============================================================================= - * Store a UDP management packet for later processing. - */ - -static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, struct net_device* dev, - chdlc_private_area_t* chdlc_priv_area ) -{ - int udp_pkt_stored = 0; - - if(!chdlc_priv_area->udp_pkt_lgth && - (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) { - chdlc_priv_area->udp_pkt_lgth = skb->len; - chdlc_priv_area->udp_pkt_src = udp_pkt_src; - memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len); - chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP; - udp_pkt_stored = 1; - } - - if(udp_pkt_src == UDP_PKT_FRM_STACK) - dev_kfree_skb_any(skb); - else - dev_kfree_skb_any(skb); - - return(udp_pkt_stored); -} - - -/*============================================================================= - * Process UDP management packet. - */ - -static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, - chdlc_private_area_t* chdlc_priv_area ) -{ - unsigned char *buf; - unsigned int frames, len; - struct sk_buff *new_skb; - unsigned short buffer_length, real_len; - unsigned long data_ptr; - unsigned data_length; - int udp_mgmt_req_valid = 1; - CHDLC_MAILBOX_STRUCT *mb = card->mbox; - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - chdlc_udp_pkt_t *chdlc_udp_pkt; - struct timeval tv; - int err; - char ut_char; - - chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data; - - if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { - - switch(chdlc_udp_pkt->cblock.command) { - case READ_GLOBAL_STATISTICS: - case READ_MODEM_STATUS: - case READ_CHDLC_LINK_STATUS: - case CPIPE_ROUTER_UP_TIME: - case READ_COMMS_ERROR_STATS: - case READ_CHDLC_OPERATIONAL_STATS: - - /* These two commands are executed for - * each request */ - case READ_CHDLC_CONFIGURATION: - case READ_CHDLC_CODE_VERSION: - udp_mgmt_req_valid = 1; - break; - default: - udp_mgmt_req_valid = 0; - break; - } - } - - if(!udp_mgmt_req_valid) { - - /* set length to 0 */ - chdlc_udp_pkt->cblock.buffer_length = 0; - - /* set return code */ - chdlc_udp_pkt->cblock.return_code = 0xCD; - - if (net_ratelimit()){ - printk(KERN_INFO - "%s: Warning, Illegal UDP command attempted from network: %x\n", - card->devname,chdlc_udp_pkt->cblock.command); - } - - } else { - unsigned long trace_status_cfg_addr = 0; - TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct; - TRACE_STATUS_ELEMENT_STRUCT trace_element_struct; - - switch(chdlc_udp_pkt->cblock.command) { - - case CPIPE_ENABLE_TRACING: - if (!chdlc_priv_area->TracingEnabled) { - - /* OPERATE_DATALINE_MONITOR */ - - mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT); - mb->command = SET_TRACE_CONFIGURATION; - - ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> - trace_config = TRACE_ACTIVE; - /* Trace delay mode is not used because it slows - down transfer and results in a standoff situation - when there is a lot of data */ - - /* Configure the Trace based on user inputs */ - ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |= - chdlc_udp_pkt->data[0]; - - ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> - trace_deactivation_timer = 4000; - - - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) { - chdlc_error(card,err,mb); - card->TracingEnabled = 0; - chdlc_udp_pkt->cblock.return_code = err; - mb->buffer_length = 0; - break; - } - - /* Get the base address of the trace element list */ - mb->buffer_length = 0; - mb->command = READ_TRACE_CONFIGURATION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - if (err != COMMAND_OK) { - chdlc_error(card,err,mb); - chdlc_priv_area->TracingEnabled = 0; - chdlc_udp_pkt->cblock.return_code = err; - mb->buffer_length = 0; - break; - } - - trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *) - mb->data) -> ptr_trace_stat_el_cfg_struct; - - sdla_peek(&card->hw, trace_status_cfg_addr, - &trace_cfg_struct, sizeof(trace_cfg_struct)); - - chdlc_priv_area->start_trace_addr = trace_cfg_struct. - base_addr_trace_status_elements; - - chdlc_priv_area->number_trace_elements = - trace_cfg_struct.number_trace_status_elements; - - chdlc_priv_area->end_trace_addr = (unsigned long) - ((TRACE_STATUS_ELEMENT_STRUCT *) - chdlc_priv_area->start_trace_addr + - (chdlc_priv_area->number_trace_elements - 1)); - - chdlc_priv_area->base_addr_trace_buffer = - trace_cfg_struct.base_addr_trace_buffer; - - chdlc_priv_area->end_addr_trace_buffer = - trace_cfg_struct.end_addr_trace_buffer; - - chdlc_priv_area->curr_trace_addr = - trace_cfg_struct.next_trace_element_to_use; - - chdlc_priv_area->available_buffer_space = 2000 - - sizeof(ip_pkt_t) - - sizeof(udp_pkt_t) - - sizeof(wp_mgmt_t) - - sizeof(cblock_t) - - sizeof(trace_info_t); - } - chdlc_udp_pkt->cblock.return_code = COMMAND_OK; - mb->buffer_length = 0; - chdlc_priv_area->TracingEnabled = 1; - break; - - - case CPIPE_DISABLE_TRACING: - if (chdlc_priv_area->TracingEnabled) { - - /* OPERATE_DATALINE_MONITOR */ - mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT); - mb->command = SET_TRACE_CONFIGURATION; - ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> - trace_config = TRACE_INACTIVE; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - } - - chdlc_priv_area->TracingEnabled = 0; - chdlc_udp_pkt->cblock.return_code = COMMAND_OK; - mb->buffer_length = 0; - break; - - - case CPIPE_GET_TRACE_INFO: - - if (!chdlc_priv_area->TracingEnabled) { - chdlc_udp_pkt->cblock.return_code = 1; - mb->buffer_length = 0; - break; - } - - chdlc_udp_pkt->trace_info.ismoredata = 0x00; - buffer_length = 0; /* offset of packet already occupied */ - - for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){ - - trace_pkt_t *trace_pkt = (trace_pkt_t *) - &chdlc_udp_pkt->data[buffer_length]; - - sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr, - (unsigned char *)&trace_element_struct, - sizeof(TRACE_STATUS_ELEMENT_STRUCT)); - - if (trace_element_struct.opp_flag == 0x00) { - break; - } - - /* get pointer to real data */ - data_ptr = trace_element_struct.ptr_data_bfr; - - /* See if there is actual data on the trace buffer */ - if (data_ptr){ - data_length = trace_element_struct.trace_length; - }else{ - data_length = 0; - chdlc_udp_pkt->trace_info.ismoredata = 0x01; - } - - if( (chdlc_priv_area->available_buffer_space - buffer_length) - < ( sizeof(trace_pkt_t) + data_length) ) { - - /* indicate there are more frames on board & exit */ - chdlc_udp_pkt->trace_info.ismoredata = 0x01; - break; - } - - trace_pkt->status = trace_element_struct.trace_type; - - trace_pkt->time_stamp = - trace_element_struct.trace_time_stamp; - - trace_pkt->real_length = - trace_element_struct.trace_length; - - /* see if we can fit the frame into the user buffer */ - real_len = trace_pkt->real_length; - - if (data_ptr == 0) { - trace_pkt->data_avail = 0x00; - } else { - unsigned tmp = 0; - - /* get the data from circular buffer - must check for end of buffer */ - trace_pkt->data_avail = 0x01; - - if ((data_ptr + real_len) > - chdlc_priv_area->end_addr_trace_buffer + 1){ - - tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1; - sdla_peek(&card->hw, data_ptr, - trace_pkt->data,tmp); - data_ptr = chdlc_priv_area->base_addr_trace_buffer; - } - - sdla_peek(&card->hw, data_ptr, - &trace_pkt->data[tmp], real_len - tmp); - } - - /* zero the opp flag to show we got the frame */ - ut_char = 0x00; - sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1); - - /* now move onto the next frame */ - chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT); - - /* check if we went over the last address */ - if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) { - chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr; - } - - if(trace_pkt->data_avail == 0x01) { - buffer_length += real_len - 1; - } - - /* for the header */ - buffer_length += sizeof(trace_pkt_t); - - } /* For Loop */ - - if (frames == chdlc_priv_area->number_trace_elements){ - chdlc_udp_pkt->trace_info.ismoredata = 0x01; - } - chdlc_udp_pkt->trace_info.num_frames = frames; - - mb->buffer_length = buffer_length; - chdlc_udp_pkt->cblock.buffer_length = buffer_length; - - chdlc_udp_pkt->cblock.return_code = COMMAND_OK; - - break; - - - case CPIPE_FT1_READ_STATUS: - ((unsigned char *)chdlc_udp_pkt->data )[0] = - flags->FT1_info_struct.parallel_port_A_input; - - ((unsigned char *)chdlc_udp_pkt->data )[1] = - flags->FT1_info_struct.parallel_port_B_input; - - chdlc_udp_pkt->cblock.return_code = COMMAND_OK; - mb->buffer_length = 2; - break; - - case CPIPE_ROUTER_UP_TIME: - do_gettimeofday( &tv ); - chdlc_priv_area->router_up_time = tv.tv_sec - - chdlc_priv_area->router_start_time; - *(unsigned long *)&chdlc_udp_pkt->data = - chdlc_priv_area->router_up_time; - mb->buffer_length = sizeof(unsigned long); - break; - - case FT1_MONITOR_STATUS_CTRL: - /* Enable FT1 MONITOR STATUS */ - if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) || - (chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) { - - if( rCount++ != 0 ) { - chdlc_udp_pkt->cblock. - return_code = COMMAND_OK; - mb->buffer_length = 1; - break; - } - } - - /* Disable FT1 MONITOR STATUS */ - if( chdlc_udp_pkt->data[0] == 0) { - - if( --rCount != 0) { - chdlc_udp_pkt->cblock. - return_code = COMMAND_OK; - mb->buffer_length = 1; - break; - } - } - - default: - /* it's a board command */ - mb->command = chdlc_udp_pkt->cblock.command; - mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length; - if (mb->buffer_length) { - memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt-> - data, mb->buffer_length); - } - /* run the command on the board */ - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - if (err != COMMAND_OK) { - break; - } - - /* copy the result back to our buffer */ - memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t)); - - if (mb->buffer_length) { - memcpy(&chdlc_udp_pkt->data, &mb->data, - mb->buffer_length); - } - - } /* end of switch */ - } /* end of else */ - - /* Fill UDP TTL */ - chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl; - - len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length); - - if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { - if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) { - ++ card->wandev.stats.tx_packets; - card->wandev.stats.tx_bytes += len; - } - } else { - - /* Pass it up the stack - Allocate socket buffer */ - if ((new_skb = dev_alloc_skb(len)) != NULL) { - /* copy data into new_skb */ - - buf = skb_put(new_skb, len); - memcpy(buf, chdlc_priv_area->udp_pkt_data, len); - - /* Decapsulate pkt and pass it up the protocol stack */ - new_skb->protocol = htons(ETH_P_IP); - new_skb->dev = dev; - new_skb->mac.raw = new_skb->data; - - netif_rx(new_skb); - dev->last_rx = jiffies; - } else { - - printk(KERN_INFO "%s: no socket buffers available!\n", - card->devname); - } - } - - chdlc_priv_area->udp_pkt_lgth = 0; - - return 0; -} - -/*============================================================================ - * Initialize Receive and Transmit Buffers. - */ - -static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config; - CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config; - char err; - - mb->buffer_length = 0; - mb->command = READ_CHDLC_CONFIGURATION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - - if(err != COMMAND_OK) { - chdlc_error(card,err,mb); - return; - } - - if(card->hw.type == SDLA_S514) { - tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + - (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> - ptr_CHDLC_Tx_stat_el_cfg_struct)); - rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + - (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> - ptr_CHDLC_Rx_stat_el_cfg_struct)); - - /* Setup Head and Tails for buffers */ - card->u.c.txbuf_base = (void *)(card->hw.dpmbase + - tx_config->base_addr_Tx_status_elements); - card->u.c.txbuf_last = - (CHDLC_DATA_TX_STATUS_EL_STRUCT *) - card->u.c.txbuf_base + - (tx_config->number_Tx_status_elements - 1); - - card->u.c.rxbuf_base = (void *)(card->hw.dpmbase + - rx_config->base_addr_Rx_status_elements); - card->u.c.rxbuf_last = - (CHDLC_DATA_RX_STATUS_EL_STRUCT *) - card->u.c.rxbuf_base + - (rx_config->number_Rx_status_elements - 1); - - /* Set up next pointer to be used */ - card->u.c.txbuf = (void *)(card->hw.dpmbase + - tx_config->next_Tx_status_element_to_use); - card->u.c.rxmb = (void *)(card->hw.dpmbase + - rx_config->next_Rx_status_element_to_use); - } - else { - tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + - (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> - ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE)); - - rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + - (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> - ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE)); - - /* Setup Head and Tails for buffers */ - card->u.c.txbuf_base = (void *)(card->hw.dpmbase + - (tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE)); - card->u.c.txbuf_last = - (CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base - + (tx_config->number_Tx_status_elements - 1); - card->u.c.rxbuf_base = (void *)(card->hw.dpmbase + - (rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE)); - card->u.c.rxbuf_last = - (CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base - + (rx_config->number_Rx_status_elements - 1); - - /* Set up next pointer to be used */ - card->u.c.txbuf = (void *)(card->hw.dpmbase + - (tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE)); - card->u.c.rxmb = (void *)(card->hw.dpmbase + - (rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE)); - } - - /* Setup Actual Buffer Start and end addresses */ - card->u.c.rx_base = rx_config->base_addr_Rx_buffer; - card->u.c.rx_top = rx_config->end_addr_Rx_buffer; - -} - -/*============================================================================= - * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR - * _TEST_COUNTER times. - */ -static int intr_test( sdla_t* card) -{ - CHDLC_MAILBOX_STRUCT* mb = card->mbox; - int err,i; - - Intr_test_counter = 0; - - /* The critical flag is unset because during initialization (if_open) - * we want the interrupts to be enabled so that when the wpc_isr is - * called it does not exit due to critical flag set. - */ - - err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE); - - if (err == CMD_OK) { - for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) { - mb->buffer_length = 0; - mb->command = READ_CHDLC_CODE_VERSION; - err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; - } - } - else { - return err; - } - - err = chdlc_set_intr_mode(card, 0); - - if (err != CMD_OK) - return err; - - return 0; -} - -/*============================================================================== - * Determine what type of UDP call it is. CPIPEAB ? - */ -static int udp_pkt_type(struct sk_buff *skb, sdla_t* card) -{ - chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data; - - if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) && - (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) && - (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) && - (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) { - return UDP_CPIPE_TYPE; - } - else return UDP_INVALID_TYPE; -} - -/*============================================================================ - * Set PORT state. - */ -static void port_set_state (sdla_t *card, int state) -{ - struct net_device *dev = card->wandev.dev; - chdlc_private_area_t *chdlc_priv_area = dev->priv; - - if (card->u.c.state != state) - { - switch (state) - { - case WAN_CONNECTED: - printk (KERN_INFO "%s: HDLC link connected!\n", - card->devname); - break; - - case WAN_CONNECTING: - printk (KERN_INFO "%s: HDLC link connecting...\n", - card->devname); - break; - - case WAN_DISCONNECTED: - printk (KERN_INFO "%s: HDLC link disconnected!\n", - card->devname); - break; - } - - card->wandev.state = card->u.c.state = state; - chdlc_priv_area->common.state = state; - } -} - -void s508_lock (sdla_t *card, unsigned long *smp_flags) -{ - spin_lock_irqsave(&card->wandev.lock, *smp_flags); - if (card->next){ - /* It is ok to use spin_lock here, since we - * already turned off interrupts */ - spin_lock(&card->next->wandev.lock); - } -} - -void s508_unlock (sdla_t *card, unsigned long *smp_flags) -{ - if (card->next){ - spin_unlock(&card->next->wandev.lock); - } - spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -} - - - -/*=========================================================================== - * config_chdlc - * - * Configure the chdlc protocol and enable communications. - * - * The if_open() function binds this function to the poll routine. - * Therefore, this function will run every time the chdlc interface - * is brought up. We cannot run this function from the if_open - * because if_open does not have access to the remote IP address. - * - * If the communications are not enabled, proceed to configure - * the card and enable communications. - * - * If the communications are enabled, it means that the interface - * was shutdown by ether the user or driver. In this case, we - * have to check that the IP addresses have not changed. If - * the IP addresses have changed, we have to reconfigure the firmware - * and update the changed IP addresses. Otherwise, just exit. - * - */ - -static int config_chdlc (sdla_t *card) -{ - struct net_device *dev = card->wandev.dev; - SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; - - if (card->u.c.comm_enabled){ - chdlc_comm_disable(card); - port_set_state(card, WAN_DISCONNECTED); - } - - if (set_chdlc_config(card)) { - printk(KERN_INFO "%s: CHDLC Configuration Failed!\n", - card->devname); - return 0; - } - init_chdlc_tx_rx_buff(card, dev); - - /* Set interrupt mode and mask */ - if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME | - APP_INT_ON_GLOBAL_EXCEP_COND | - APP_INT_ON_TX_FRAME | - APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){ - printk (KERN_INFO "%s: Failed to set interrupt triggers!\n", - card->devname); - return 0; - } - - - /* Mask the Transmit and Timer interrupt */ - flags->interrupt_info_struct.interrupt_permission &= - ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER); - - - if (chdlc_comm_enable(card) != 0) { - printk(KERN_INFO "%s: Failed to enable chdlc communications!\n", - card->devname); - flags->interrupt_info_struct.interrupt_permission = 0; - card->u.c.comm_enabled=0; - chdlc_set_intr_mode(card,0); - return 0; - } - - /* Initialize Rx/Tx buffer control fields */ - port_set_state(card, WAN_CONNECTING); - return 0; -} - - -static void send_ppp_term_request(struct net_device *dev) -{ - struct sk_buff *new_skb; - unsigned char *buf; - - if ((new_skb = dev_alloc_skb(8)) != NULL) { - /* copy data into new_skb */ - - buf = skb_put(new_skb, 8); - sprintf(buf,"%c%c%c%c%c%c%c%c", 0xFF,0x03,0xC0,0x21,0x05,0x98,0x00,0x07); - - /* Decapsulate pkt and pass it up the protocol stack */ - new_skb->protocol = htons(ETH_P_WAN_PPP); - new_skb->dev = dev; - new_skb->mac.raw = new_skb->data; - - netif_rx(new_skb); - dev->last_rx = jiffies; - } -} - - -MODULE_LICENSE("GPL"); - -/****** End ****************************************************************/ diff --git a/include/linux/sdla_asy.h b/include/linux/sdla_asy.h deleted file mode 100644 index f62242537c86..000000000000 --- a/include/linux/sdla_asy.h +++ /dev/null @@ -1,226 +0,0 @@ -/***************************************************************************** -* sdla_asy.h Header file for the Sangoma S508/S514 asynchronous code API -* -* Author: Gideon Hack -* -* Copyright: (c) 2000 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. -* ============================================================================ -* -* Jan 28, 2000 Gideon Hack Initial Version -* -*****************************************************************************/ - - -#ifndef _WANPIPE_ASYNC_H -#define _WANPIPE_ASYNC_H - -/* ---------------------------------------------------------------------------- - * Interface commands - * --------------------------------------------------------------------------*/ - -#define SET_ASY_CONFIGURATION 0xE2 /* set the asychronous operational configuration */ -#define READ_ASY_CONFIGURATION 0xE3 /* read the current asychronous operational configuration */ -#define ENABLE_ASY_COMMUNICATIONS 0xE4 /* enable asychronous communications */ -#define DISABLE_ASY_COMMUNICATIONS 0xE5 /* disable asychronous communications */ -#define READ_ASY_OPERATIONAL_STATS 0xE7 /* retrieve the asychronous operational statistics */ -#define FLUSH_ASY_OPERATIONAL_STATS 0xE8 /* flush the asychronous operational statistics */ -#define TRANSMIT_ASY_BREAK_SIGNAL 0xEC /* transmit an asychronous break signal */ - - - -/* ---------------------------------------------------------------------------- - * Return codes from interface commands - * --------------------------------------------------------------------------*/ - -#define COMMAND_INVALID_FOR_PORT 0x50 /* the command is invalid for the selected port */ -#define DISABLE_ASY_COMMS_BEFORE_CFG 0xE1 /* communications must be disabled before setting the configuration */ -#define ASY_COMMS_ENABLED 0xE1 /* communications are currently enabled */ -#define ASY_COMMS_DISABLED 0xE1 /* communications are currently disabled */ -#define ASY_CFG_BEFORE_COMMS_ENABLED 0xE2 /* perform a SET_ASY_CONFIGURATION before enabling comms */ -#define LGTH_ASY_CFG_DATA_INVALID 0xE2 /* the length of the passed configuration data is invalid */ -#define INVALID_ASY_CFG_DATA 0xE3 /* the passed configuration data is invalid */ -#define ASY_BREAK_SIGNAL_BUSY 0xEC /* a break signal is being transmitted */ - - - -/* ---------------------------------------------------------------------------- - * Constants for the SET_ASY_CONFIGURATION/READ_ASY_CONFIGURATION command - * --------------------------------------------------------------------------*/ - -/* the asynchronous configuration structure */ -typedef struct { - unsigned long baud_rate PACKED; /* the baud rate */ - unsigned short line_config_options PACKED; /* line configuration options */ - unsigned short modem_config_options PACKED; /* modem configuration options */ - unsigned short asy_API_options PACKED; /* asynchronous API options */ - unsigned short asy_protocol_options PACKED; /* asynchronous protocol options */ - unsigned short Tx_bits_per_char PACKED; /* number of bits per tx character */ - unsigned short Rx_bits_per_char PACKED; /* number of bits per received character */ - unsigned short stop_bits PACKED; /* number of stop bits per character */ - unsigned short parity PACKED; /* parity definition */ - unsigned short break_timer PACKED; /* the break signal timer */ - unsigned short asy_Rx_inter_char_timer PACKED; /* the receive inter-character timer */ - unsigned short asy_Rx_complete_length PACKED; /* the receive 'buffer complete' length */ - unsigned short XON_char PACKED; /* the XON character */ - unsigned short XOFF_char PACKED; /* the XOFF character */ - unsigned short asy_statistics_options PACKED; /* async operational stat options */ - unsigned long ptr_shared_mem_info_struct PACKED;/* ptr to the shared memory area information structure */ - unsigned long ptr_asy_Tx_stat_el_cfg_struct PACKED;/* ptr to the transmit status element configuration structure */ - unsigned long ptr_asy_Rx_stat_el_cfg_struct PACKED;/* ptr to the receive status element configuration structure */ -} ASY_CONFIGURATION_STRUCT; - -/* permitted minimum and maximum values for setting the asynchronous configuration */ -#define MIN_ASY_BAUD_RATE 50 /* maximum baud rate */ -#define MAX_ASY_BAUD_RATE 250000 /* minimum baud rate */ -#define MIN_ASY_BITS_PER_CHAR 5 /* minimum number of bits per character */ -#define MAX_ASY_BITS_PER_CHAR 8 /* maximum number of bits per character */ -#define MIN_BREAK_TMR_VAL 0 /* minimum break signal timer */ -#define MAX_BREAK_TMR_VAL 5000 /* maximum break signal timer */ -#define MIN_ASY_RX_INTER_CHAR_TMR 0 /* minimum receive inter-character timer */ -#define MAX_ASY_RX_INTER_CHAR_TMR 30000 /* maximum receive inter-character timer */ -#define MIN_ASY_RX_CPLT_LENGTH 0 /* minimum receive 'length complete' value */ -#define MAX_ASY_RX_CPLT_LENGTH 2000 /* maximum receive 'length complete' value */ - -/* bit settings for the 'asy_API_options' */ -#define ASY_RX_DATA_TRANSPARENT 0x0001 /* do not strip parity and unused bits from received characters */ - -/* bit settings for the 'asy_protocol_options' */ -#define ASY_RTS_HS_FOR_RX 0x0001 /* RTS handshaking is used for reception control */ -#define ASY_XON_XOFF_HS_FOR_RX 0x0002 /* XON/XOFF handshaking is used for reception control */ -#define ASY_XON_XOFF_HS_FOR_TX 0x0004 /* XON/XOFF handshaking is used for transmission control */ -#define ASY_DCD_HS_FOR_TX 0x0008 /* DCD handshaking is used for transmission control */ -#define ASY_CTS_HS_FOR_TX 0x0020 /* CTS handshaking is used for transmission control */ - -/* bit settings for the 'stop_bits' definition */ -#define ONE_STOP_BIT 1 /* representation for 1 stop bit */ -#define TWO_STOP_BITS 2 /* representation for 2 stop bits */ -#define ONE_AND_A_HALF_STOP_BITS 3 /* representation for 1.5 stop bits */ - -/* bit settings for the 'parity' definition */ -#define NO_PARITY 0 /* representation for no parity */ -#define ODD_PARITY 1 /* representation for odd parity */ -#define EVEN_PARITY 2 /* representation for even parity */ - - - -/* ---------------------------------------------------------------------------- - * Constants for the READ_COMMS_ERROR_STATS command (asynchronous mode) - * --------------------------------------------------------------------------*/ - -/* the communications error statistics structure */ -typedef struct { - unsigned short Rx_overrun_err_count PACKED; /* receiver overrun error count */ - unsigned short Rx_parity_err_count PACKED; /* parity errors received count */ - unsigned short Rx_framing_err_count PACKED; /* framing errors received count */ - unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later use */ - unsigned short comms_err_stat_reserved_2 PACKED;/* reserved for later use */ - unsigned short comms_err_stat_reserved_3 PACKED;/* reserved for later use */ - unsigned short comms_err_stat_reserved_4 PACKED;/* reserved for later use */ - unsigned short comms_err_stat_reserved_5 PACKED;/* reserved for later use */ - unsigned short DCD_state_change_count PACKED; /* DCD state change count */ - unsigned short CTS_state_change_count PACKED; /* CTS state change count */ -} ASY_COMMS_ERROR_STATS_STRUCT; - - - -/* ---------------------------------------------------------------------------- - * Constants for the READ_ASY_OPERATIONAL_STATS command - * --------------------------------------------------------------------------*/ - -/* the asynchronous operational statistics structure */ -typedef struct { - - /* Data transmission statistics */ - unsigned long Data_blocks_Tx_count PACKED;/* number of blocks transmitted */ - unsigned long Data_bytes_Tx_count PACKED;/* number of bytes transmitted */ - unsigned long Data_Tx_throughput PACKED;/* transmit throughput */ - unsigned long no_ms_for_Data_Tx_thruput_comp PACKED;/* millisecond time used for the Tx throughput computation */ - unsigned long Tx_Data_discard_lgth_err_count PACKED;/* number of Data blocks discarded (length error) */ - unsigned long reserved_Data_frm_Tx_stat1 PACKED;/* reserved for later use */ - unsigned long reserved_Data_frm_Tx_stat2 PACKED;/* reserved for later use */ - unsigned long reserved_Data_frm_Tx_stat3 PACKED;/* reserved for later use */ - - /* Data reception statistics */ - unsigned long Data_blocks_Rx_count PACKED;/* number of blocks received */ - unsigned long Data_bytes_Rx_count PACKED;/* number of bytes received */ - unsigned long Data_Rx_throughput PACKED;/* receive throughput */ - unsigned long no_ms_for_Data_Rx_thruput_comp PACKED;/* millisecond time used for the Rx throughput computation */ - unsigned long Rx_Data_bytes_discard_count PACKED;/* received Data bytes discarded */ - unsigned long reserved_Data_frm_Rx_stat1 PACKED;/* reserved for later use */ - - /* handshaking protocol statistics */ - unsigned short XON_chars_Tx_count PACKED; /* number of XON characters transmitted */ - unsigned short XOFF_chars_Tx_count PACKED; /* number of XOFF characters transmitted */ - unsigned short XON_chars_Rx_count PACKED; /* number of XON characters received */ - unsigned short XOFF_chars_Rx_count PACKED; /* number of XOFF characters received */ - unsigned short Tx_halt_modem_low_count PACKED; /* number of times Tx halted (modem line low) */ - unsigned short Rx_halt_RTS_low_count PACKED; /* number of times Rx halted by setting RTS low */ - unsigned long reserved_handshaking_stat1 PACKED;/* reserved for later use */ - - /* break statistics */ - unsigned short break_Tx_count PACKED; /* number of break sequences transmitted */ - unsigned short break_Rx_count PACKED; /* number of break sequences received */ - unsigned long reserved_break_stat1 PACKED;/* reserved for later use */ - - /* miscellaneous statistics */ - unsigned long reserved_misc_stat1 PACKED; /* reserved for later use */ - unsigned long reserved_misc_stat2 PACKED; /* reserved for later use */ - -} ASY_OPERATIONAL_STATS_STRUCT; - - - -/* ---------------------------------------------------------------------------- - * Constants for Data transmission - * --------------------------------------------------------------------------*/ - -/* the Data block transmit status element configuration structure */ -typedef struct { - unsigned short number_Tx_status_elements PACKED; /* number of transmit status elements */ - unsigned long base_addr_Tx_status_elements PACKED; /* base address of the transmit element list */ - unsigned long next_Tx_status_element_to_use PACKED; /* pointer to the next transmit element to be used */ -} ASY_TX_STATUS_EL_CFG_STRUCT; - - -/* the Data block transmit status element structure */ -typedef struct { - unsigned char opp_flag PACKED; /* opp flag */ - unsigned short data_length PACKED; /* length of the block to be transmitted */ - unsigned char reserved_1 PACKED; /* reserved for internal use */ - unsigned long reserved_2 PACKED; /* reserved for internal use */ - unsigned long reserved_3 PACKED; /* reserved for internal use */ - unsigned long ptr_data_bfr PACKED; /* pointer to the data area */ -} ASY_DATA_TX_STATUS_EL_STRUCT; - - - -/* ---------------------------------------------------------------------------- - * Constants for Data reception - * --------------------------------------------------------------------------*/ - -/* the Data block receive status element configuration structure */ -typedef struct { - unsigned short number_Rx_status_elements PACKED;/* number of receive status elements */ - unsigned long base_addr_Rx_status_elements PACKED;/* base address of the receive element list */ - unsigned long next_Rx_status_element_to_use PACKED;/* pointer to the next receive element to be used */ - unsigned long base_addr_Rx_buffer PACKED;/* base address of the receive data buffer */ - unsigned long end_addr_Rx_buffer PACKED;/* end address of the receive data buffer */ -} ASY_RX_STATUS_EL_CFG_STRUCT; - -/* the Data block receive status element structure */ -typedef struct { - unsigned char opp_flag PACKED; /* opp flag */ - unsigned short data_length PACKED; /* length of the received data block */ - unsigned char reserved_1 PACKED; /* reserved for internal use */ - unsigned short time_stamp PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */ - unsigned short data_buffered PACKED; /* the number of data bytes still buffered */ - unsigned long reserved_2 PACKED; /* reserved for internal use */ - unsigned long ptr_data_bfr PACKED; /* pointer to the data area */ -} ASY_DATA_RX_STATUS_EL_STRUCT; - -#endif diff --git a/include/linux/sdla_chdlc.h b/include/linux/sdla_chdlc.h deleted file mode 100644 index d2e35a299034..000000000000 --- a/include/linux/sdla_chdlc.h +++ /dev/null @@ -1,813 +0,0 @@ -/************************************************************************* - sdla_chdlc.h Sangoma Cisco HDLC firmware API definitions - - Author: Gideon Hack - Nenad Corbic - - Copyright: (c) 1995-2000 Sangoma Technologies Inc. - - This program is free software; you can redistribute it and/or - modify it under the term 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. - -=========================================================================== - Oct 04, 1999 Nenad Corbic Updated API support - Jun 02, 1999 Gideon Hack Changes for S514 usage. - Oct 28, 1998 Jaspreet Singh Made changes for Dual Port CHDLC. - Jun 11, 1998 David Fong Initial version. -=========================================================================== - - Organization - - Compatibility notes - - Constants defining the shared memory control block (mailbox) - - Interface commands - - Return code from interface commands - - Constants for the commands (structures for casting data) - - UDP Management constants and structures - -*************************************************************************/ - -#ifndef _SDLA_CHDLC_H -# define _SDLC_CHDLC_H - -/*------------------------------------------------------------------------ - Notes: - - All structres defined in this file are byte-aligned. - - Compiler Platform - ------------------------ - GNU C Linux - -------------------------------------------------------------------------*/ - -#ifndef PACKED -#define PACKED __attribute__((packed)) -#endif /* PACKED */ - - -/* ---------------------------------------------------------------------------- - * Constants defining the shared memory control block (mailbox) - * --------------------------------------------------------------------------*/ - -#define PRI_BASE_ADDR_MB_STRUCT 0xE000 /* the base address of the mailbox structure on the adapter */ -#define SEC_BASE_ADDR_MB_STRUCT 0xE800 /* the base address of the mailbox structure on the adapter */ -#define SIZEOF_MB_DATA_BFR 2032 /* the size of the actual mailbox data area */ -#define NUMBER_MB_RESERVED_BYTES 0x0B /* the number of reserved bytes in the mailbox header area */ - - -#define MIN_LGTH_CHDLC_DATA_CFG 300 /* min length of the CHDLC data field (for configuration purposes) */ -#define PRI_MAX_NO_DATA_BYTES_IN_FRAME 15354 /* PRIMARY - max length of the CHDLC data field */ - -typedef struct { - unsigned char opp_flag PACKED; /* the opp flag */ - unsigned char command PACKED; /* the user command */ - unsigned short buffer_length PACKED; /* the data length */ - unsigned char return_code PACKED; /* the return code */ - unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED; /* reserved for later */ - unsigned char data[SIZEOF_MB_DATA_BFR] PACKED; /* the data area */ -} CHDLC_MAILBOX_STRUCT; - -typedef struct { - pid_t pid_num PACKED; - CHDLC_MAILBOX_STRUCT cmdarea PACKED; - -} CMDBLOCK_STRUCT; - - - - -/* ---------------------------------------------------------------------------- - * Interface commands - * --------------------------------------------------------------------------*/ - -/* global interface commands */ -#define READ_GLOBAL_EXCEPTION_CONDITION 0x01 -#define SET_GLOBAL_CONFIGURATION 0x02 -#define READ_GLOBAL_CONFIGURATION 0x03 -#define READ_GLOBAL_STATISTICS 0x04 -#define FLUSH_GLOBAL_STATISTICS 0x05 -#define SET_MODEM_STATUS 0x06 /* set status of DTR or RTS */ -#define READ_MODEM_STATUS 0x07 /* read status of CTS and DCD */ -#define READ_COMMS_ERROR_STATS 0x08 -#define FLUSH_COMMS_ERROR_STATS 0x09 -#define SET_TRACE_CONFIGURATION 0x0A /* set the line trace config */ -#define READ_TRACE_CONFIGURATION 0x0B /* read the line trace config */ -#define READ_TRACE_STATISTICS 0x0C /* read the trace statistics */ -#define FLUSH_TRACE_STATISTICS 0x0D /* flush the trace statistics */ -#define FT1_MONITOR_STATUS_CTRL 0x1C /* set the status of the S508/FT1 monitoring */ -#define SET_FT1_CONFIGURATION 0x18 /* set the FT1 configuration */ -#define READ_FT1_CONFIGURATION 0x19 /* read the FT1 configuration */ -#define TRANSMIT_ASYNC_DATA_TO_FT1 0x1A /* output asynchronous data to the FT1 */ -#define RECEIVE_ASYNC_DATA_FROM_FT1 0x1B /* receive asynchronous data from the FT1 */ -#define FT1_MONITOR_STATUS_CTRL 0x1C /* set the status of the FT1 monitoring */ - -#define READ_FT1_OPERATIONAL_STATS 0x1D /* read the S508/FT1 operational statistics */ -#define SET_FT1_MODE 0x1E /* set the operational mode of the S508/FT1 module */ - -/* CHDLC-level interface commands */ -#define READ_CHDLC_CODE_VERSION 0x20 -#define READ_CHDLC_EXCEPTION_CONDITION 0x21 /* read exception condition from the adapter */ -#define SET_CHDLC_CONFIGURATION 0x22 -#define READ_CHDLC_CONFIGURATION 0x23 -#define ENABLE_CHDLC_COMMUNICATIONS 0x24 -#define DISABLE_CHDLC_COMMUNICATIONS 0x25 -#define READ_CHDLC_LINK_STATUS 0x26 -#define READ_CHDLC_OPERATIONAL_STATS 0x27 -#define FLUSH_CHDLC_OPERATIONAL_STATS 0x28 -#define SET_CHDLC_INTERRUPT_TRIGGERS 0x30 /* set application interrupt triggers */ -#define READ_CHDLC_INTERRUPT_TRIGGERS 0x31 /* read application interrupt trigger configuration */ - -/* Special UDP drivers management commands */ -#define CPIPE_ENABLE_TRACING 0x50 -#define CPIPE_DISABLE_TRACING 0x51 -#define CPIPE_GET_TRACE_INFO 0x52 -#define CPIPE_GET_IBA_DATA 0x53 -#define CPIPE_FT1_READ_STATUS 0x54 -#define CPIPE_DRIVER_STAT_IFSEND 0x55 -#define CPIPE_DRIVER_STAT_INTR 0x56 -#define CPIPE_DRIVER_STAT_GEN 0x57 -#define CPIPE_FLUSH_DRIVER_STATS 0x58 -#define CPIPE_ROUTER_UP_TIME 0x59 - -/* Driver specific commands for API */ -#define CHDLC_READ_TRACE_DATA 0xE4 /* read trace data */ -#define TRACE_ALL 0x00 -#define TRACE_PROT 0x01 -#define TRACE_DATA 0x02 - -#define DISCARD_RX_ERROR_FRAMES 0x0001 - -/* ---------------------------------------------------------------------------- - * Return codes from interface commands - * --------------------------------------------------------------------------*/ - -#define COMMAND_OK 0x00 - -/* return codes from global interface commands */ -#define NO_GLOBAL_EXCEP_COND_TO_REPORT 0x01 /* there is no CHDLC exception condition to report */ -#define LGTH_GLOBAL_CFG_DATA_INVALID 0x01 /* the length of the passed global configuration data is invalid */ -#define LGTH_TRACE_CFG_DATA_INVALID 0x01 /* the length of the passed trace configuration data is invalid */ -#define IRQ_TIMEOUT_VALUE_INVALID 0x02 /* an invalid application IRQ timeout value was selected */ -#define TRACE_CONFIG_INVALID 0x02 /* the passed line trace configuration is invalid */ -#define ADAPTER_OPERATING_FREQ_INVALID 0x03 /* an invalid adapter operating frequency was selected */ -#define TRC_DEAC_TMR_INVALID 0x03 /* the trace deactivation timer is invalid */ -#define S508_FT1_ADPTR_NOT_PRESENT 0x0C /* the S508/FT1 adapter is not present */ -#define INVALID_FT1_STATUS_SELECTION 0x0D /* the S508/FT1 status selection is invalid */ -#define FT1_OP_STATS_NOT_ENABLED 0x0D /* the FT1 operational statistics have not been enabled */ -#define FT1_OP_STATS_NOT_AVAILABLE 0x0E /* the FT1 operational statistics are not currently available */ -#define S508_FT1_MODE_SELECTION_BUSY 0x0E /* the S508/FT1 adapter is busy selecting the operational mode */ - -/* return codes from command READ_GLOBAL_EXCEPTION_CONDITION */ -#define EXCEP_MODEM_STATUS_CHANGE 0x10 /* a modem status change occurred */ -#define EXCEP_TRC_DISABLED 0x11 /* the trace has been disabled */ -#define EXCEP_IRQ_TIMEOUT 0x12 /* IRQ timeout */ - -/* return codes from CHDLC-level interface commands */ -#define NO_CHDLC_EXCEP_COND_TO_REPORT 0x21 /* there is no CHDLC exception condition to report */ -#define CHDLC_COMMS_DISABLED 0x21 /* communications are not currently enabled */ -#define CHDLC_COMMS_ENABLED 0x21 /* communications are currently enabled */ -#define DISABLE_CHDLC_COMMS_BEFORE_CFG 0x21 /* CHDLC communications must be disabled before setting the configuration */ -#define ENABLE_CHDLC_COMMS_BEFORE_CONN 0x21 /* communications must be enabled before using the CHDLC_CONNECT conmmand */ -#define CHDLC_CFG_BEFORE_COMMS_ENABLED 0x22 /* perform a SET_CHDLC_CONFIGURATION before enabling comms */ -#define LGTH_CHDLC_CFG_DATA_INVALID 0x22 /* the length of the passed CHDLC configuration data is invalid */ -#define LGTH_INT_TRIGGERS_DATA_INVALID 0x22 /* the length of the passed interrupt trigger data is invalid */ -#define INVALID_IRQ_SELECTED 0x23 /* in invalid IRQ was selected in the SET_CHDLC_INTERRUPT_TRIGGERS */ -#define INVALID_CHDLC_CFG_DATA 0x23 /* the passed CHDLC configuration data is invalid */ -#define IRQ_TMR_VALUE_INVALID 0x24 /* an invalid application IRQ timer value was selected */ -#define LARGER_PERCENT_TX_BFR_REQUIRED 0x24 /* a larger Tx buffer percentage is required */ -#define LARGER_PERCENT_RX_BFR_REQUIRED 0x25 /* a larger Rx buffer percentage is required */ -#define S514_BOTH_PORTS_SAME_CLK_MODE 0x26 /* S514 - both ports must have same clock mode */ -#define INVALID_CMND_HDLC_STREAM_MODE 0x4E /* the CHDLC interface command is invalid for HDLC streaming mode */ -#define INVALID_CHDLC_COMMAND 0x4F /* the defined CHDLC interface command is invalid */ - -/* return codes from command READ_CHDLC_EXCEPTION_CONDITION */ -#define EXCEP_LINK_ACTIVE 0x30 /* the CHDLC link has become active */ -#define EXCEP_LINK_INACTIVE_MODEM 0x31 /* the CHDLC link has become inactive (modem status) */ -#define EXCEP_LINK_INACTIVE_KPALV 0x32 /* the CHDLC link has become inactive (keepalive status) */ -#define EXCEP_IP_ADDRESS_DISCOVERED 0x33 /* the IP address has been discovered */ -#define EXCEP_LOOPBACK_CONDITION 0x34 /* a loopback condition has occurred */ - - -/* return code from command CHDLC_SEND_WAIT and CHDLC_SEND_NO_WAIT */ -#define LINK_DISCONNECTED 0x21 -#define NO_TX_BFRS_AVAIL 0x24 - - -/* ---------------------------------------------------------------------------- - * Constants for the SET_GLOBAL_CONFIGURATION/READ_GLOBAL_CONFIGURATION commands - * --------------------------------------------------------------------------*/ - -/* the global configuration structure */ -typedef struct { - unsigned short adapter_config_options PACKED; /* adapter config options */ - unsigned short app_IRQ_timeout PACKED; /* application IRQ timeout */ - unsigned long adapter_operating_frequency PACKED; /* adapter operating frequency */ -} GLOBAL_CONFIGURATION_STRUCT; - -/* settings for the 'app_IRQ_timeout' */ -#define MAX_APP_IRQ_TIMEOUT_VALUE 5000 /* the maximum permitted IRQ timeout */ - - - -/* ---------------------------------------------------------------------------- - * Constants for the READ_GLOBAL_STATISTICS command - * --------------------------------------------------------------------------*/ - -/* the global statistics structure */ -typedef struct { - unsigned short app_IRQ_timeout_count PACKED; -} GLOBAL_STATS_STRUCT; - - - -/* ---------------------------------------------------------------------------- - * Constants for the READ_COMMS_ERROR_STATS command - * --------------------------------------------------------------------------*/ - -/* the communications error statistics structure */ -typedef struct { - unsigned short Rx_overrun_err_count PACKED; - unsigned short CRC_err_count PACKED; /* receiver CRC error count */ - unsigned short Rx_abort_count PACKED; /* abort frames recvd count */ - unsigned short Rx_dis_pri_bfrs_full_count PACKED;/* receiver disabled */ - unsigned short comms_err_stat_reserved_1 PACKED;/* reserved for later */ - unsigned short sec_Tx_abort_msd_Tx_int_count PACKED; /* secondary - abort frames transmitted count (missed Tx interrupt) */ - unsigned short missed_Tx_und_int_count PACKED; /* missed tx underrun interrupt count */ - unsigned short sec_Tx_abort_count PACKED; /*secondary-abort frames tx count */ - unsigned short DCD_state_change_count PACKED; /* DCD state change */ - unsigned short CTS_state_change_count PACKED; /* CTS state change */ -} COMMS_ERROR_STATS_STRUCT; - - - -/* ---------------------------------------------------------------------------- - * Constants used for line tracing - * --------------------------------------------------------------------------*/ - -/* the trace configuration structure (SET_TRACE_CONFIGURATION/READ_TRACE_CONFIGURATION commands) */ -typedef struct { - unsigned char trace_config PACKED; /* trace configuration */ - unsigned short trace_deactivation_timer PACKED; /* trace deactivation timer */ - unsigned long ptr_trace_stat_el_cfg_struct PACKED; /* a pointer to the line trace element configuration structure */ -} LINE_TRACE_CONFIG_STRUCT; - -/* 'trace_config' bit settings */ -#define TRACE_INACTIVE 0x00 /* trace is inactive */ -#define TRACE_ACTIVE 0x01 /* trace is active */ -#define TRACE_DELAY_MODE 0x04 /* operate the trace in delay mode */ -#define TRACE_DATA_FRAMES 0x08 /* trace Data frames */ -#define TRACE_SLARP_FRAMES 0x10 /* trace SLARP frames */ -#define TRACE_CDP_FRAMES 0x20 /* trace CDP frames */ - -/* the line trace status element configuration structure */ -typedef struct { - unsigned short number_trace_status_elements PACKED; /* number of line trace elements */ - unsigned long base_addr_trace_status_elements PACKED; /* base address of the trace element list */ - unsigned long next_trace_element_to_use PACKED; /* pointer to the next trace element to be used */ - unsigned long base_addr_trace_buffer PACKED; /* base address of the trace data buffer */ - unsigned long end_addr_trace_buffer PACKED; /* end address of the trace data buffer */ -} TRACE_STATUS_EL_CFG_STRUCT; - -/* the line trace status element structure */ -typedef struct { - unsigned char opp_flag PACKED; /* opp flag */ - unsigned short trace_length PACKED; /* trace length */ - unsigned char trace_type PACKED; /* trace type */ - unsigned short trace_time_stamp PACKED; /* time stamp */ - unsigned short trace_reserved_1 PACKED; /* reserved for later use */ - unsigned long trace_reserved_2 PACKED; /* reserved for later use */ - unsigned long ptr_data_bfr PACKED; /* ptr to the trace data buffer */ -} TRACE_STATUS_ELEMENT_STRUCT; - -/* "trace_type" bit settings */ -#define TRACE_INCOMING 0x00 -#define TRACE_OUTGOINGING 0x01 -#define TRACE_INCOMING_ABORTED 0x10 -#define TRACE_INCOMING_CRC_ERROR 0x20 -#define TRACE_INCOMING_OVERRUN_ERROR 0x40 - - - -/* the line trace statistics structure */ -typedef struct { - unsigned long frames_traced_count PACKED; /* number of frames traced */ - unsigned long trc_frms_not_recorded_count PACKED; /* number of trace frames discarded */ -} LINE_TRACE_STATS_STRUCT; - - -/* ---------------------------------------------------------------------------- - * Constants for the FT1_MONITOR_STATUS_CTRL command - * --------------------------------------------------------------------------*/ - -#define DISABLE_FT1_STATUS_STATISTICS 0x00 /* disable the FT1 status and statistics monitoring */ -#define ENABLE_READ_FT1_STATUS 0x01 /* read the FT1 operational status */ -#define ENABLE_READ_FT1_OP_STATS 0x02 /* read the FT1 operational statistics */ -#define FLUSH_FT1_OP_STATS 0x04 /* flush the FT1 operational statistics */ - - - - -/* ---------------------------------------------------------------------------- - * Constants for the SET_CHDLC_CONFIGURATION command - * --------------------------------------------------------------------------*/ - -/* the CHDLC configuration structure */ -typedef struct { - unsigned long baud_rate PACKED; /* the baud rate */ - unsigned short line_config_options PACKED; /* line configuration options */ - unsigned short modem_config_options PACKED; /* modem configration options */ - unsigned short modem_status_timer PACKED; /* timer for monitoring modem status changes */ - unsigned short CHDLC_API_options PACKED; /* CHDLC API options */ - unsigned short CHDLC_protocol_options PACKED; /* CHDLC protocol options */ - unsigned short percent_data_buffer_for_Tx PACKED; /* percentage data buffering used for Tx */ - unsigned short CHDLC_statistics_options PACKED; /* CHDLC operational statistics options */ - unsigned short max_CHDLC_data_field_length PACKED; /* the maximum length of the CHDLC Data field */ - unsigned short transmit_keepalive_timer PACKED; /* the transmit keepalive timer */ - unsigned short receive_keepalive_timer PACKED; /* the receive keepalive timer */ - unsigned short keepalive_error_tolerance PACKED; /* the receive keepalive error tolerance */ - unsigned short SLARP_request_timer PACKED; /* the SLARP request timer */ - unsigned long IP_address PACKED; /* the IP address */ - unsigned long IP_netmask PACKED; /* the IP netmask */ - unsigned long ptr_shared_mem_info_struct PACKED; /* a pointer to the shared memory area information structure */ - unsigned long ptr_CHDLC_Tx_stat_el_cfg_struct PACKED; /* a pointer to the transmit status element configuration structure */ - unsigned long ptr_CHDLC_Rx_stat_el_cfg_struct PACKED; /* a pointer to the receive status element configuration structure */ -} CHDLC_CONFIGURATION_STRUCT; - -/* settings for the 'line_config_options' */ -#define INTERFACE_LEVEL_V35 0x0000 /* V.35 interface level */ -#define INTERFACE_LEVEL_RS232 0x0001 /* RS-232 interface level */ - -/* settings for the 'modem_config_options' */ - -#define DONT_RAISE_DTR_RTS_ON_EN_COMMS 0x0001 -/* don't automatically raise DTR and RTS when performing an - ENABLE_CHDLC_COMMUNICATIONS command */ - -#define DONT_REPORT_CHG_IN_MODEM_STAT 0x0002 -/* don't report changes in modem status to the application */ - - -/* bit settings for the 'CHDLC_protocol_options' byte */ - -#define IGNORE_DCD_FOR_LINK_STAT 0x0001 -/* ignore DCD in determining the CHDLC link status */ - -#define IGNORE_CTS_FOR_LINK_STAT 0x0002 -/* ignore CTS in determining the CHDLC link status */ - -#define IGNORE_KPALV_FOR_LINK_STAT 0x0004 -/* ignore keepalive frames in determining the CHDLC link status */ - -#define SINGLE_TX_BUFFER 0x4000 -/* configure a single transmit buffer */ - -#define HDLC_STREAMING_MODE 0x8000 - -/* settings for the 'CHDLC_statistics_options' */ - -#define CHDLC_TX_DATA_BYTE_COUNT_STAT 0x0001 -/* record the number of Data bytes transmitted */ - -#define CHDLC_RX_DATA_BYTE_COUNT_STAT 0x0002 -/* record the number of Data bytes received */ - -#define CHDLC_TX_THROUGHPUT_STAT 0x0004 -/* compute the Data frame transmit throughput */ - -#define CHDLC_RX_THROUGHPUT_STAT 0x0008 -/* compute the Data frame receive throughput */ - - -/* permitted minimum and maximum values for setting the CHDLC configuration */ -#define PRI_MAX_BAUD_RATE_S508 2666666 /* PRIMARY - maximum baud rate (S508) */ -#define SEC_MAX_BAUD_RATE_S508 258064 /* SECONDARY - maximum baud rate (S508) */ -#define PRI_MAX_BAUD_RATE_S514 2750000 /* PRIMARY - maximum baud rate (S508) */ -#define SEC_MAX_BAUD_RATE_S514 515625 /* SECONDARY - maximum baud rate (S508) */ - -#define MIN_MODEM_TIMER 0 /* minimum modem status timer */ -#define MAX_MODEM_TIMER 5000 /* maximum modem status timer */ - -#define SEC_MAX_NO_DATA_BYTES_IN_FRAME 2048 /* SECONDARY - max length of the CHDLC data field */ - -#define MIN_Tx_KPALV_TIMER 0 /* minimum transmit keepalive timer */ -#define MAX_Tx_KPALV_TIMER 60000 /* maximum transmit keepalive timer */ -#define DEFAULT_Tx_KPALV_TIMER 10000 /* default transmit keepalive timer */ - -#define MIN_Rx_KPALV_TIMER 10 /* minimum receive keepalive timer */ -#define MAX_Rx_KPALV_TIMER 60000 /* maximum receive keepalive timer */ -#define DEFAULT_Rx_KPALV_TIMER 10000 /* default receive keepalive timer */ - -#define MIN_KPALV_ERR_TOL 1 /* min kpalv error tolerance count */ -#define MAX_KPALV_ERR_TOL 20 /* max kpalv error tolerance count */ -#define DEFAULT_KPALV_ERR_TOL 3 /* default value */ - -#define MIN_SLARP_REQ_TIMER 0 /* min transmit SLARP Request timer */ -#define MAX_SLARP_REQ_TIMER 60000 /* max transmit SLARP Request timer */ -#define DEFAULT_SLARP_REQ_TIMER 0 /* default value -- no SLARP */ - - - -/* ---------------------------------------------------------------------------- - * Constants for the READ_CHDLC_LINK_STATUS command - * --------------------------------------------------------------------------*/ - -/* the CHDLC status structure */ -typedef struct { - unsigned char CHDLC_link_status PACKED; /* CHDLC link status */ - unsigned char no_Data_frms_for_app PACKED; /* number of Data frames available for the application */ - unsigned char receiver_status PACKED; /* enabled/disabled */ - unsigned char SLARP_state PACKED; /* internal SLARP state */ -} CHDLC_LINK_STATUS_STRUCT; - -/* settings for the 'CHDLC_link_status' variable */ -#define CHDLC_LINK_INACTIVE 0x00 /* the CHDLC link is inactive */ -#define CHDLC_LINK_ACTIVE 0x01 /* the CHDLC link is active */ - - - -/* ---------------------------------------------------------------------------- - * Constants for the READ_CHDLC_OPERATIONAL_STATS command - * --------------------------------------------------------------------------*/ - -/* the CHDLC operational statistics structure */ -typedef struct { - - /* Data frame transmission statistics */ - unsigned long Data_frames_Tx_count PACKED; /* # of frames transmitted */ - unsigned long Data_bytes_Tx_count PACKED; /* # of bytes transmitted */ - unsigned long Data_Tx_throughput PACKED; /* transmit throughput */ - unsigned long no_ms_for_Data_Tx_thruput_comp PACKED; /* millisecond time used for the Tx throughput computation */ - unsigned long Tx_Data_discard_lgth_err_count PACKED; /* number of Data frames discarded (length error) */ - unsigned long reserved_Data_frm_Tx_stat1 PACKED; /* reserved for later */ - unsigned long reserved_Data_frm_Tx_stat2 PACKED; /* reserved for later */ - unsigned long reserved_Data_frm_Tx_stat3 PACKED; /* reserved for later */ - - /* Data frame reception statistics */ - unsigned long Data_frames_Rx_count PACKED; /* number of frames received */ - unsigned long Data_bytes_Rx_count PACKED; /* number of bytes received */ - unsigned long Data_Rx_throughput PACKED; /* receive throughput */ - unsigned long no_ms_for_Data_Rx_thruput_comp PACKED; /* millisecond time used for the Rx throughput computation */ - unsigned long Rx_Data_discard_short_count PACKED; /* received Data frames discarded (too short) */ - unsigned long Rx_Data_discard_long_count PACKED; /* received Data frames discarded (too long) */ - unsigned long Rx_Data_discard_inactive_count PACKED; /* received Data frames discarded (link inactive) */ - unsigned long reserved_Data_frm_Rx_stat1 PACKED; /* reserved for later */ - - /* SLARP frame transmission/reception statistics */ - unsigned long CHDLC_SLARP_REQ_Tx_count PACKED; /* number of SLARP Request frames transmitted */ - unsigned long CHDLC_SLARP_REQ_Rx_count PACKED; /* number of SLARP Request frames received */ - unsigned long CHDLC_SLARP_REPLY_Tx_count PACKED; /* number of SLARP Reply frames transmitted */ - unsigned long CHDLC_SLARP_REPLY_Rx_count PACKED; /* number of SLARP Reply frames received */ - unsigned long CHDLC_SLARP_KPALV_Tx_count PACKED; /* number of SLARP keepalive frames transmitted */ - unsigned long CHDLC_SLARP_KPALV_Rx_count PACKED; /* number of SLARP keepalive frames received */ - unsigned long reserved_SLARP_stat1 PACKED; /* reserved for later */ - unsigned long reserved_SLARP_stat2 PACKED; /* reserved for later */ - - /* CDP frame transmission/reception statistics */ - unsigned long CHDLC_CDP_Tx_count PACKED; /* number of CDP frames transmitted */ - unsigned long CHDLC_CDP_Rx_count PACKED; /* number of CDP frames received */ - unsigned long reserved_CDP_stat1 PACKED; /* reserved for later */ - unsigned long reserved_CDP_stat2 PACKED; /* reserved for later */ - unsigned long reserved_CDP_stat3 PACKED; /* reserved for later */ - unsigned long reserved_CDP_stat4 PACKED; /* reserved for later */ - unsigned long reserved_CDP_stat5 PACKED; /* reserved for later */ - unsigned long reserved_CDP_stat6 PACKED; /* reserved for later */ - - /* Incoming frames with a format error statistics */ - unsigned short Rx_frm_incomp_CHDLC_hdr_count PACKED; /* frames received of with incomplete Cisco HDLC header */ - unsigned short Rx_frms_too_long_count PACKED; /* frames received of excessive length count */ - unsigned short Rx_invalid_CHDLC_addr_count PACKED; /* frames received with an invalid CHDLC address count */ - unsigned short Rx_invalid_CHDLC_ctrl_count PACKED; /* frames received with an invalid CHDLC control field count */ - unsigned short Rx_invalid_CHDLC_type_count PACKED; /* frames received of an invalid CHDLC frame type count */ - unsigned short Rx_SLARP_invalid_code_count PACKED; /* SLARP frame received with an invalid packet code */ - unsigned short Rx_SLARP_Reply_bad_IP_addr PACKED; /* SLARP Reply received - bad IP address */ - unsigned short Rx_SLARP_Reply_bad_netmask PACKED; /* SLARP Reply received - bad netmask */ - unsigned long reserved_frm_format_err1 PACKED; /* reserved for later */ - unsigned long reserved_frm_format_err2 PACKED; /* reserved for later */ - unsigned long reserved_frm_format_err3 PACKED; /* reserved for later */ - unsigned long reserved_frm_format_err4 PACKED; /* reserved for later */ - - /* CHDLC timeout/retry statistics */ - unsigned short SLARP_Rx_keepalive_TO_count PACKED; /* timeout count for incoming SLARP frames */ - unsigned short SLARP_Request_TO_count PACKED; /* timeout count for SLARP Request frames */ - unsigned long To_retry_reserved_stat1 PACKED; /* reserved for later */ - unsigned long To_retry_reserved_stat2 PACKED; /* reserved for later */ - unsigned long To_retry_reserved_stat3 PACKED; /* reserved for later */ - - /* CHDLC link active/inactive and loopback statistics */ - unsigned short link_active_count PACKED; /* number of times that the link went active */ - unsigned short link_inactive_modem_count PACKED; /* number of times that the link went inactive (modem failure) */ - unsigned short link_inactive_keepalive_count PACKED; /* number of times that the link went inactive (keepalive failure) */ - unsigned short link_looped_count PACKED; /* link looped count */ - unsigned long link_status_reserved_stat1 PACKED; /* reserved for later use */ - unsigned long link_status_reserved_stat2 PACKED; /* reserved for later use */ - - /* miscellaneous statistics */ - unsigned long reserved_misc_stat1 PACKED; /* reserved for later */ - unsigned long reserved_misc_stat2 PACKED; /* reserved for later */ - unsigned long reserved_misc_stat3 PACKED; /* reserved for later */ - unsigned long reserved_misc_stat4 PACKED; /* reserved for later */ - -} CHDLC_OPERATIONAL_STATS_STRUCT; - - - -/* ---------------------------------------------------------------------------- - * Constants for using application interrupts - * --------------------------------------------------------------------------*/ - -/* the structure used for the SET_CHDLC_INTERRUPT_TRIGGERS/READ_CHDLC_INTERRUPT_TRIGGERS command */ -typedef struct { - unsigned char CHDLC_interrupt_triggers PACKED; /* CHDLC interrupt trigger configuration */ - unsigned char IRQ PACKED; /* IRQ to be used */ - unsigned short interrupt_timer PACKED; /* interrupt timer */ - unsigned short misc_interrupt_bits PACKED; /* miscellaneous bits */ -} CHDLC_INT_TRIGGERS_STRUCT; - -/* 'CHDLC_interrupt_triggers' bit settings */ -#define APP_INT_ON_RX_FRAME 0x01 /* interrupt on Data frame reception */ -#define APP_INT_ON_TX_FRAME 0x02 /* interrupt when an Data frame may be transmitted */ -#define APP_INT_ON_COMMAND_COMPLETE 0x04 /* interrupt when an interface command is complete */ -#define APP_INT_ON_TIMER 0x08 /* interrupt on a defined millisecond timeout */ -#define APP_INT_ON_GLOBAL_EXCEP_COND 0x10 /* interrupt on a global exception condition */ -#define APP_INT_ON_CHDLC_EXCEP_COND 0x20 /* interrupt on an CHDLC exception condition */ -#define APP_INT_ON_TRACE_DATA_AVAIL 0x80 /* interrupt when trace data is available */ - -/* interrupt types indicated at 'interrupt_type' byte of the INTERRUPT_INFORMATION_STRUCT */ -#define NO_APP_INTS_PEND 0x00 /* no interrups are pending */ -#define RX_APP_INT_PEND 0x01 /* a receive interrupt is pending */ -#define TX_APP_INT_PEND 0x02 /* a transmit interrupt is pending */ -#define COMMAND_COMPLETE_APP_INT_PEND 0x04 /* a 'command complete' interrupt is pending */ -#define TIMER_APP_INT_PEND 0x08 /* a timer interrupt is pending */ -#define GLOBAL_EXCEP_COND_APP_INT_PEND 0x10 /* a global exception condition interrupt is pending */ -#define CHDLC_EXCEP_COND_APP_INT_PEND 0x20 /* an CHDLC exception condition interrupt is pending */ -#define TRACE_DATA_AVAIL_APP_INT_PEND 0x80 /* a trace data available interrupt is pending */ - - -/* modem status changes */ -#define DCD_HIGH 0x08 -#define CTS_HIGH 0x20 - - -/* ---------------------------------------------------------------------------- - * Constants for Data frame transmission - * --------------------------------------------------------------------------*/ - -/* the Data frame transmit status element configuration structure */ -typedef struct { - unsigned short number_Tx_status_elements PACKED; /* number of transmit status elements */ - unsigned long base_addr_Tx_status_elements PACKED; /* base address of the transmit element list */ - unsigned long next_Tx_status_element_to_use PACKED; /* pointer to the next transmit element to be used */ -} CHDLC_TX_STATUS_EL_CFG_STRUCT; - -/* the Data frame transmit status element structure */ -typedef struct { - unsigned char opp_flag PACKED; /* opp flag */ - unsigned short frame_length PACKED; /* length of the frame to be transmitted */ - unsigned char reserved_1 PACKED; /* reserved for internal use */ - unsigned long reserved_2 PACKED; /* reserved for internal use */ - unsigned long reserved_3 PACKED; /* reserved for internal use */ - unsigned long ptr_data_bfr PACKED; /* pointer to the data area */ -} CHDLC_DATA_TX_STATUS_EL_STRUCT; - - - -/* ---------------------------------------------------------------------------- - * Constants for Data frame reception - * --------------------------------------------------------------------------*/ - -/* the Data frame receive status element configuration structure */ -typedef struct { - unsigned short number_Rx_status_elements PACKED; /* number of receive status elements */ - unsigned long base_addr_Rx_status_elements PACKED; /* base address of the receive element list */ - unsigned long next_Rx_status_element_to_use PACKED; /* pointer to the next receive element to be used */ - unsigned long base_addr_Rx_buffer PACKED; /* base address of the receive data buffer */ - unsigned long end_addr_Rx_buffer PACKED; /* end address of the receive data buffer */ -} CHDLC_RX_STATUS_EL_CFG_STRUCT; - -/* the Data frame receive status element structure */ -typedef struct { - unsigned char opp_flag PACKED; /* opp flag */ - unsigned short frame_length PACKED; /* length of the received frame */ - unsigned char error_flag PACKED; /* frame errors (HDLC_STREAMING_MODE)*/ - unsigned short time_stamp PACKED; /* receive time stamp (HDLC_STREAMING_MODE) */ - unsigned long reserved_1 PACKED; /* reserved for internal use */ - unsigned short reserved_2 PACKED; /* reserved for internal use */ - unsigned long ptr_data_bfr PACKED; /* pointer to the data area */ -} CHDLC_DATA_RX_STATUS_EL_STRUCT; - - - -/* ---------------------------------------------------------------------------- - * Constants defining the shared memory information area - * --------------------------------------------------------------------------*/ - -/* the global information structure */ -typedef struct { - unsigned char global_status PACKED; /* global status */ - unsigned char modem_status PACKED; /* current modem status */ - unsigned char global_excep_conditions PACKED; /* global exception conditions */ - unsigned char glob_info_reserved[5] PACKED; /* reserved */ - unsigned char codename[4] PACKED; /* Firmware name */ - unsigned char codeversion[4] PACKED; /* Firmware version */ -} GLOBAL_INFORMATION_STRUCT; - -/* the CHDLC information structure */ -typedef struct { - unsigned char CHDLC_status PACKED; /* CHDLC status */ - unsigned char CHDLC_excep_conditions PACKED; /* CHDLC exception conditions */ - unsigned char CHDLC_info_reserved[14] PACKED; /* reserved */ -} CHDLC_INFORMATION_STRUCT; - -/* the interrupt information structure */ -typedef struct { - unsigned char interrupt_type PACKED; /* type of interrupt triggered */ - unsigned char interrupt_permission PACKED; /* interrupt permission mask */ - unsigned char int_info_reserved[14] PACKED; /* reserved */ -} INTERRUPT_INFORMATION_STRUCT; - -/* the S508/FT1 information structure */ -typedef struct { - unsigned char parallel_port_A_input PACKED; /* input - parallel port A */ - unsigned char parallel_port_B_input PACKED; /* input - parallel port B */ - unsigned char FT1_info_reserved[14] PACKED; /* reserved */ -} FT1_INFORMATION_STRUCT; - -/* the shared memory area information structure */ -typedef struct { - GLOBAL_INFORMATION_STRUCT global_info_struct PACKED; /* the global information structure */ - CHDLC_INFORMATION_STRUCT CHDLC_info_struct PACKED; /* the CHDLC information structure */ - INTERRUPT_INFORMATION_STRUCT interrupt_info_struct PACKED; /* the interrupt information structure */ - FT1_INFORMATION_STRUCT FT1_info_struct PACKED; /* the S508/FT1 information structure */ -} SHARED_MEMORY_INFO_STRUCT; - -/* ---------------------------------------------------------------------------- - * UDP Management constants and structures - * --------------------------------------------------------------------------*/ - -/* The embedded control block for UDP mgmt - This is essentially a mailbox structure, without the large data field */ - -typedef struct { - unsigned char opp_flag PACKED; /* the opp flag */ - unsigned char command PACKED; /* the user command */ - unsigned short buffer_length PACKED; /* the data length */ - unsigned char return_code PACKED; /* the return code */ - unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED; /* reserved for later */ -} cblock_t; - - -/* UDP management packet layout (data area of ip packet) */ -/* -typedef struct { - unsigned char signature[8] PACKED; - unsigned char request_reply PACKED; - unsigned char id PACKED; - unsigned char reserved[6] PACKED; - cblock_t cblock PACKED; - unsigned char num_frames PACKED; - unsigned char ismoredata PACKED; - unsigned char data[SIZEOF_MB_DATA_BFR] PACKED; -} udp_management_packet_t; - -*/ - -typedef struct { - unsigned char num_frames PACKED; - unsigned char ismoredata PACKED; -} trace_info_t; - -typedef struct { - ip_pkt_t ip_pkt PACKED; - udp_pkt_t udp_pkt PACKED; - wp_mgmt_t wp_mgmt PACKED; - cblock_t cblock PACKED; - trace_info_t trace_info PACKED; - unsigned char data[SIZEOF_MB_DATA_BFR] PACKED; -} chdlc_udp_pkt_t; - -typedef struct ft1_exec_cmd{ - unsigned char command PACKED; /* the user command */ - unsigned short buffer_length PACKED; /* the data length */ - unsigned char return_code PACKED; /* the return code */ - unsigned char MB_reserved[NUMBER_MB_RESERVED_BYTES] PACKED; -} ft1_exec_cmd_t; - -typedef struct { - unsigned char opp_flag PACKED; - ft1_exec_cmd_t cmd PACKED; - unsigned char data[SIZEOF_MB_DATA_BFR] PACKED; -} ft1_exec_t; - -#define UDPMGMT_SIGNATURE "CTPIPEAB" - - -/* UDP/IP packet (for UDP management) layout */ -/* -typedef struct { - unsigned char reserved[2] PACKED; - unsigned short ip_length PACKED; - unsigned char reserved2[4] PACKED; - unsigned char ip_ttl PACKED; - unsigned char ip_protocol PACKED; - unsigned short ip_checksum PACKED; - unsigned long ip_src_address PACKED; - unsigned long ip_dst_address PACKED; - unsigned short udp_src_port PACKED; - unsigned short udp_dst_port PACKED; - unsigned short udp_length PACKED; - unsigned short udp_checksum PACKED; - udp_management_packet_t um_packet PACKED; -} ip_packet_t; -*/ - -/* valid ip_protocol for UDP management */ -#define UDPMGMT_UDP_PROTOCOL 0x11 - - -typedef struct { - unsigned char status PACKED; - unsigned char data_avail PACKED; - unsigned short real_length PACKED; - unsigned short time_stamp PACKED; - unsigned char data[1] PACKED; -} trace_pkt_t; - -typedef struct { - unsigned char error_flag PACKED; - unsigned short time_stamp PACKED; - unsigned char reserved[13] PACKED; -} api_rx_hdr_t; - -typedef struct { - api_rx_hdr_t api_rx_hdr PACKED; - void * data PACKED; -} api_rx_element_t; - -typedef struct { - unsigned char attr PACKED; - unsigned char reserved[15] PACKED; -} api_tx_hdr_t; - -typedef struct { - api_tx_hdr_t api_tx_hdr PACKED; - void * data PACKED; -} api_tx_element_t; - -/* ---------------------------------------------------------------------------- - * Constants for the SET_FT1_CONFIGURATION/READ_FT1_CONFIGURATION command - * --------------------------------------------------------------------------*/ - -/* the FT1 configuration structure */ -typedef struct { - unsigned short framing_mode; - unsigned short encoding_mode; - unsigned short line_build_out; - unsigned short channel_base; - unsigned short baud_rate_kbps; /* the baud rate (in kbps) */ - unsigned short clock_mode; -} ft1_config_t; - -/* settings for the 'framing_mode' */ -#define ESF_FRAMING 0x00 /* ESF framing */ -#define D4_FRAMING 0x01 /* D4 framing */ - -/* settings for the 'encoding_mode' */ -#define B8ZS_ENCODING 0x00 /* B8ZS encoding */ -#define AMI_ENCODING 0x01 /* AMI encoding */ - -/* settings for the 'line_build_out' */ -#define LN_BLD_CSU_0dB_DSX1_0_to_133 0x00 /* set build out to CSU (0db) or DSX-1 (0-133ft) */ -#define LN_BLD_DSX1_133_to_266 0x01 /* set build out DSX-1 (133-266ft) */ -#define LN_BLD_DSX1_266_to_399 0x02 /* set build out DSX-1 (266-399ft) */ -#define LN_BLD_DSX1_399_to_533 0x03 /* set build out DSX-1 (399-533ft) */ -#define LN_BLD_DSX1_533_to_655 0x04 /* set build out DSX-1 (533-655ft) */ -#define LN_BLD_CSU_NEG_7dB 0x05 /* set build out to CSU (-7.5db) */ -#define LN_BLD_CSU_NEG_15dB 0x06 /* set build out to CSU (-15db) */ -#define LN_BLD_CSU_NEG_22dB 0x07 /* set build out to CSU (-22.5db) */ - -/* settings for the 'channel_base' */ -#define MIN_CHANNEL_BASE_VALUE 1 /* the minimum permitted channel base value */ -#define MAX_CHANNEL_BASE_VALUE 24 /* the maximum permitted channel base value */ - -/* settings for the 'baud_rate_kbps' */ -#define MIN_BAUD_RATE_KBPS 0 /* the minimum permitted baud rate (kbps) */ -#define MAX_BAUD_RATE_KBPS 1536 /* the maximum permitted baud rate (kbps) */ -#define BAUD_RATE_FT1_AUTO_CONFIG 0xFFFF /* the baud rate used to trigger an automatic FT1 configuration */ - -/* settings for the 'clock_mode' */ -#define CLOCK_MODE_NORMAL 0x00 /* clock mode set to normal (slave) */ -#define CLOCK_MODE_MASTER 0x01 /* clock mode set to master */ - - -#define BAUD_RATE_FT1_AUTO_CONFIG 0xFFFF -#define AUTO_FT1_CONFIG_NOT_COMPLETE 0x08 -#define AUTO_FT1_CFG_FAIL_OP_MODE 0x0C -#define AUTO_FT1_CFG_FAIL_INVALID_LINE 0x0D - - -#ifdef _MSC_ -# pragma pack() -#endif -#endif /* _SDLA_CHDLC_H */ diff --git a/include/linux/sdla_ppp.h b/include/linux/sdla_ppp.h deleted file mode 100644 index 6f3923179c29..000000000000 --- a/include/linux/sdla_ppp.h +++ /dev/null @@ -1,575 +0,0 @@ -/***************************************************************************** -* sdla_ppp.h Sangoma PPP firmware API definitions. -* -* Author: Nenad Corbic -* -* 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. -* ============================================================================ -* Feb 24, 2000 Nenad Corbic v2.1.2 -* Jan 06, 1997 Gene Kozin v2.0 -* Apr 11, 1996 Gene Kozin Initial version. -*****************************************************************************/ -#ifndef _SDLA_PPP_H -#define _SDLA_PPP_H - -/*---------------------------------------------------------------------------- - * Notes: - * ------ - * 1. All structures defined in this file are byte-alined. - * - * Compiler Platform - * -------- -------- - * GNU C Linux - */ - -#ifndef PACKED -# define PACKED __attribute__((packed)) -#endif /* PACKED */ - -/* Adapter memory layout and important constants */ -#define PPP508_MB_VECT 0xE000 /* mailbox window vector */ -#define PPP508_MB_OFFS 0 /* mailbox offset */ -#define PPP508_FLG_OFFS 0x1000 /* status flags offset */ -#define PPP508_BUF_OFFS 0x1100 /* buffer info block offset */ -#define PPP514_MB_OFFS 0xE000 /* mailbox offset */ -#define PPP514_FLG_OFFS 0xF000 /* status flags offset */ -#define PPP514_BUF_OFFS 0xF100 /* buffer info block offset */ - -#define PPP_MAX_DATA 1008 /* command block data buffer length */ - -/****** Data Structures *****************************************************/ - -/*---------------------------------------------------------------------------- - * PPP Command Block. - */ -typedef struct ppp_cmd{ - unsigned char command PACKED; /* command code */ - unsigned short length PACKED; /* length of data buffer */ - unsigned char result PACKED; /* return code */ - unsigned char rsrv[11] PACKED; /* reserved for future use */ -} ppp_cmd_t; - -typedef struct cblock{ - unsigned char opp_flag PACKED; - unsigned char command PACKED; /* command code */ - unsigned short length PACKED; /* length of data buffer */ - unsigned char result PACKED; /* return code */ - unsigned char rsrv[11] PACKED; /* reserved for future use */ -} cblock_t; - -typedef struct ppp_udp_pkt{ - ip_pkt_t ip_pkt PACKED; - udp_pkt_t udp_pkt PACKED; - wp_mgmt_t wp_mgmt PACKED; - cblock_t cblock PACKED; - unsigned char data[MAX_LGTH_UDP_MGNT_PKT] PACKED; -} ppp_udp_pkt_t; - -typedef struct { - unsigned char status PACKED; - unsigned char data_avail PACKED; - unsigned short real_length PACKED; - unsigned short time_stamp PACKED; - unsigned char data[1] PACKED; -} trace_pkt_t; - - -typedef struct { - unsigned char opp_flag PACKED; - unsigned char trace_type PACKED; - unsigned short trace_length PACKED; - unsigned short trace_data_ptr PACKED; - unsigned short trace_time_stamp PACKED; -} trace_element_t; - -/* 'command' field defines */ -#define PPP_READ_CODE_VERSION 0x10 /* configuration commands */ -#define PPP_SET_CONFIG 0x05 -#define PPP_READ_CONFIG 0x06 -#define PPP_SET_INTR_FLAGS 0x20 -#define PPP_READ_INTR_FLAGS 0x21 -#define PPP_SET_INBOUND_AUTH 0x30 -#define PPP_SET_OUTBOUND_AUTH 0x31 -#define PPP_GET_CONNECTION_INFO 0x32 - -#define PPP_COMM_ENABLE 0x03 /* operational commands */ -#define PPP_COMM_DISABLE 0x04 -#define PPP_SEND_SIGN_FRAME 0x23 -#define PPP_READ_SIGN_RESPONSE 0x24 -#define PPP_DATALINE_MONITOR 0x33 - -#define PPP_READ_STATISTICS 0x07 /* statistics commands */ -#define PPP_FLUSH_STATISTICS 0x08 -#define PPP_READ_ERROR_STATS 0x09 -#define PPP_FLUSH_ERROR_STATS 0x0A -#define PPP_READ_PACKET_STATS 0x12 -#define PPP_FLUSH_PACKET_STATS 0x13 -#define PPP_READ_LCP_STATS 0x14 -#define PPP_FLUSH_LCP_STATS 0x15 -#define PPP_READ_LPBK_STATS 0x16 -#define PPP_FLUSH_LPBK_STATS 0x17 -#define PPP_READ_IPCP_STATS 0x18 -#define PPP_FLUSH_IPCP_STATS 0x19 -#define PPP_READ_IPXCP_STATS 0x1A -#define PPP_FLUSH_IPXCP_STATS 0x1B -#define PPP_READ_PAP_STATS 0x1C -#define PPP_FLUSH_PAP_STATS 0x1D -#define PPP_READ_CHAP_STATS 0x1E -#define PPP_FLUSH_CHAP_STATS 0x1F - -/* 'result' field defines */ -#define PPPRES_OK 0x00 /* command executed successfully */ -#define PPPRES_INVALID_STATE 0x09 /* invalid command in this context */ - -/*---------------------------------------------------------------------------- - * PPP Mailbox. - * This structure is located at offset PPP???_MB_OFFS into PPP???_MB_VECT - */ -typedef struct ppp_mbox -{ - unsigned char flag PACKED; /* 00h: command execution flag */ - ppp_cmd_t cmd PACKED; /* 01h: command block */ - unsigned char data[1] PACKED; /* 10h: variable length data buffer */ -} ppp_mbox_t; - -/*---------------------------------------------------------------------------- - * PPP Status Flags. - * This structure is located at offset PPP???_FLG_OFFS into - * PPP???_MB_VECT. - */ -typedef struct ppp_flags -{ - unsigned char iflag PACKED; /* 00: interrupt flag */ - unsigned char imask PACKED; /* 01: interrupt mask */ - unsigned char resrv PACKED; - unsigned char mstatus PACKED; /* 03: modem status */ - unsigned char lcp_state PACKED; /* 04: LCP state */ - unsigned char ppp_phase PACKED; /* 05: PPP phase */ - unsigned char ip_state PACKED; /* 06: IPCP state */ - unsigned char ipx_state PACKED; /* 07: IPXCP state */ - unsigned char pap_state PACKED; /* 08: PAP state */ - unsigned char chap_state PACKED; /* 09: CHAP state */ - unsigned short disc_cause PACKED; /* 0A: disconnection cause */ -} ppp_flags_t; - -/* 'iflag' defines */ -#define PPP_INTR_RXRDY 0x01 /* Rx ready */ -#define PPP_INTR_TXRDY 0x02 /* Tx ready */ -#define PPP_INTR_MODEM 0x04 /* modem status change (DCD, CTS) */ -#define PPP_INTR_CMD 0x08 /* interface command completed */ -#define PPP_INTR_DISC 0x10 /* data link disconnected */ -#define PPP_INTR_OPEN 0x20 /* data link open */ -#define PPP_INTR_DROP_DTR 0x40 /* DTR drop timeout expired */ -#define PPP_INTR_TIMER 0x80 /* timer interrupt */ - - -/* 'mstatus' defines */ -#define PPP_MDM_DCD 0x08 /* mdm_status: DCD */ -#define PPP_MDM_CTS 0x20 /* mdm_status: CTS */ - -/* 'disc_cause' defines */ -#define PPP_LOCAL_TERMINATION 0x0001 /* Local Request by PPP termination phase */ -#define PPP_DCD_CTS_DROP 0x0002 /* DCD and/or CTS dropped. Link down */ -#define PPP_REMOTE_TERMINATION 0x0800 /* Remote Request by PPP termination phase */ - -/* 'misc_config_bits' defines */ -#define DONT_RE_TX_ABORTED_I_FRAMES 0x01 -#define TX_FRM_BYTE_COUNT_STATS 0x02 -#define RX_FRM_BYTE_COUNT_STATS 0x04 -#define TIME_STAMP_IN_RX_FRAMES 0x08 -#define NON_STD_ADPTR_FREQ 0x10 -#define INTERFACE_LEVEL_RS232 0x20 -#define AUTO_LINK_RECOVERY 0x100 -#define DONT_TERMINATE_LNK_MAX_CONFIG 0x200 - -/* 'authentication options' defines */ -#define NO_AUTHENTICATION 0x00 -#define INBOUND_AUTH 0x80 -#define PAP_AUTH 0x01 -#define CHAP_AUTH 0x02 - -/* 'ip options' defines */ -#define L_AND_R_IP_NO_ASSIG 0x00 -#define L_IP_LOCAL_ASSIG 0x01 -#define L_IP_REMOTE_ASSIG 0x02 -#define R_IP_LOCAL_ASSIG 0x04 -#define R_IP_REMOTE_ASSIG 0x08 -#define ENABLE_IP 0x80 - -/* 'ipx options' defines */ -#define ROUTING_PROT_DEFAULT 0x20 -#define ENABLE_IPX 0x80 -#define DISABLE_IPX 0x00 - -/*---------------------------------------------------------------------------- - * PPP Buffer Info. - * This structure is located at offset PPP508_BUF_OFFS into - * PPP508_MB_VECT. - */ -typedef struct ppp508_buf_info -{ - unsigned short txb_num PACKED; /* 00: number of transmit buffers */ - unsigned long txb_ptr PACKED; /* 02: pointer to the buffer ctl. */ - unsigned long txb_nxt PACKED; - unsigned char rsrv1[22] PACKED; - unsigned short rxb_num PACKED; /* 20: number of receive buffers */ - unsigned long rxb_ptr PACKED; /* 22: pointer to the buffer ctl. */ - unsigned long rxb1_ptr PACKED; /* 26: pointer to the first buf.ctl. */ - unsigned long rxb_base PACKED; /* 2A: pointer to the buffer base */ - unsigned char rsrv2[2] PACKED; - unsigned long rxb_end PACKED; /* 30: pointer to the buffer end */ -} ppp508_buf_info_t; - -/*---------------------------------------------------------------------------- - * Transmit/Receive Buffer Control Block. - */ -typedef struct ppp_buf_ctl -{ - unsigned char flag PACKED; /* 00: 'buffer ready' flag */ - unsigned short length PACKED; /* 01: length of data */ - unsigned char reserved1[1] PACKED; /* 03: */ - unsigned char proto PACKED; /* 04: protocol */ - unsigned short timestamp PACKED; /* 05: time stamp (Rx only) */ - unsigned char reserved2[5] PACKED; /* 07: */ - union - { - unsigned short o_p[2]; /* 1C: buffer offset & page (S502) */ - unsigned long ptr; /* 1C: buffer pointer (S508) */ - } buf PACKED; -} ppp_buf_ctl_t; - -/*---------------------------------------------------------------------------- - * S508 Adapter Configuration Block (passed to the PPP_SET_CONFIG command). - */ -typedef struct ppp508_conf -{ - unsigned long line_speed PACKED; /* 00: baud rate, bps */ - unsigned short txbuf_percent PACKED; /* 04: % of Tx buffer */ - unsigned short conf_flags PACKED; /* 06: configuration bits */ - unsigned short mtu_local PACKED; /* 08: local MTU */ - unsigned short mtu_remote PACKED; /* 0A: remote MTU */ - unsigned short restart_tmr PACKED; /* 0C: restart timer */ - unsigned short auth_rsrt_tmr PACKED; /* 0E: authentication timer */ - unsigned short auth_wait_tmr PACKED; /* 10: authentication timer */ - unsigned short mdm_fail_tmr PACKED; /* 12: modem failure timer */ - unsigned short dtr_drop_tmr PACKED; /* 14: DTR drop timer */ - unsigned short connect_tmout PACKED; /* 16: connection timeout */ - unsigned short conf_retry PACKED; /* 18: max. retry */ - unsigned short term_retry PACKED; /* 1A: max. retry */ - unsigned short fail_retry PACKED; /* 1C: max. retry */ - unsigned short auth_retry PACKED; /* 1E: max. retry */ - unsigned char auth_options PACKED; /* 20: authentication opt. */ - unsigned char ip_options PACKED; /* 21: IP options */ - unsigned long ip_local PACKED; /* 22: local IP address */ - unsigned long ip_remote PACKED; /* 26: remote IP address */ - unsigned char ipx_options PACKED; /* 2A: IPX options */ - unsigned char ipx_netno[4] PACKED; /* 2B: IPX net number */ - unsigned char ipx_local[6] PACKED; /* 2F: local IPX node number*/ - unsigned char ipx_remote[6] PACKED; /* 35: remote IPX node num.*/ - unsigned char ipx_router[48] PACKED; /* 3B: IPX router name*/ - unsigned long alt_cpu_clock PACKED; /* 6B: */ -} ppp508_conf_t; - -/*---------------------------------------------------------------------------- - * S508 Adapter Read Connection Information Block - * Returned by the PPP_GET_CONNECTION_INFO command - */ -typedef struct ppp508_connect_info -{ - unsigned short mru PACKED; /* 00-01 Remote Max Rec' Unit */ - unsigned char ip_options PACKED; /* 02: Negotiated ip options */ - unsigned long ip_local PACKED; /* 03-06: local IP address */ - unsigned long ip_remote PACKED; /* 07-0A: remote IP address */ - unsigned char ipx_options PACKED; /* 0B: Negotiated ipx options */ - unsigned char ipx_netno[4] PACKED; /* 0C-0F: IPX net number */ - unsigned char ipx_local[6] PACKED; /* 10-1F: local IPX node # */ - unsigned char ipx_remote[6] PACKED; /* 16-1B: remote IPX node # */ - unsigned char ipx_router[48] PACKED; /* 1C-4B: IPX router name */ - unsigned char auth_status PACKED; /* 4C: Authentication Status */ - unsigned char inbd_auth_peerID[1] PACKED; /* 4D: variable length inbound authenticated peer ID */ -} ppp508_connect_info_t; - -/* 'line_speed' field */ -#define PPP_BITRATE_1200 0x01 -#define PPP_BITRATE_2400 0x02 -#define PPP_BITRATE_4800 0x03 -#define PPP_BITRATE_9600 0x04 -#define PPP_BITRATE_19200 0x05 -#define PPP_BITRATE_38400 0x06 -#define PPP_BITRATE_45000 0x07 -#define PPP_BITRATE_56000 0x08 -#define PPP_BITRATE_64000 0x09 -#define PPP_BITRATE_74000 0x0A -#define PPP_BITRATE_112000 0x0B -#define PPP_BITRATE_128000 0x0C -#define PPP_BITRATE_156000 0x0D - -/* Defines for the 'conf_flags' field */ -#define PPP_IGNORE_TX_ABORT 0x01 /* don't re-transmit aborted frames */ -#define PPP_ENABLE_TX_STATS 0x02 /* enable Tx statistics */ -#define PPP_ENABLE_RX_STATS 0x04 /* enable Rx statistics */ -#define PPP_ENABLE_TIMESTAMP 0x08 /* enable timestamp */ - -/* 'ip_options' defines */ -#define PPP_LOCAL_IP_LOCAL 0x01 -#define PPP_LOCAL_IP_REMOTE 0x02 -#define PPP_REMOTE_IP_LOCAL 0x04 -#define PPP_REMOTE_IP_REMOTE 0x08 - -/* 'ipx_options' defines */ -#define PPP_REMOTE_IPX_NETNO 0x01 -#define PPP_REMOTE_IPX_LOCAL 0x02 -#define PPP_REMOTE_IPX_REMOTE 0x04 -#define PPP_IPX_ROUTE_RIP_SAP 0x08 -#define PPP_IPX_ROUTE_NLSP 0x10 -#define PPP_IPX_ROUTE_DEFAULT 0x20 -#define PPP_IPX_CONF_COMPLETE 0x40 -#define PPP_IPX_ENABLE 0x80 - -/*---------------------------------------------------------------------------- - * S508 Adapter Configuration Block (returned by the PPP_READ_CONFIG command). - */ -typedef struct ppp508_get_conf -{ - unsigned long bps PACKED; /* 00: baud rate, bps */ - ppp508_conf_t conf PACKED; /* 04: requested config. */ - unsigned short txb_num PACKED; /* 6F: number of Tx buffers */ - unsigned short rxb_num PACKED; /* 71: number of Rx buffers */ -} ppp508_get_conf_t; - -/*---------------------------------------------------------------------------- - * S508 Operational Statistics (returned by the PPP_READ_STATISTIC command). - */ -typedef struct ppp508_stats -{ - unsigned short reserved1 PACKED; /* 00: */ - unsigned short rx_bad_len PACKED; /* 02: */ - unsigned short reserved2 PACKED; /* 04: */ - unsigned long tx_frames PACKED; /* 06: */ - unsigned long tx_bytes PACKED; /* 0A: */ - unsigned long rx_frames PACKED; /* 0E: */ - unsigned long rx_bytes PACKED; /* 12: */ -} ppp508_stats_t; - -/*---------------------------------------------------------------------------- - * Adapter Error Statistics (returned by the PPP_READ_ERROR_STATS command). - */ -typedef struct ppp_err_stats -{ - unsigned char rx_overrun PACKED; /* 00: Rx overrun errors */ - unsigned char rx_bad_crc PACKED; /* 01: Rx CRC errors */ - unsigned char rx_abort PACKED; /* 02: Rx aborted frames */ - unsigned char rx_lost PACKED; /* 03: Rx frames lost */ - unsigned char tx_abort PACKED; /* 04: Tx aborted frames */ - unsigned char tx_underrun PACKED; /* 05: Tx underrun errors */ - unsigned char tx_missed_intr PACKED; /* 06: Tx underruns missed */ - unsigned char reserved PACKED; /* 07: Tx underruns missed */ - unsigned char dcd_trans PACKED; /* 08: DCD transitions */ - unsigned char cts_trans PACKED; /* 09: CTS transitions */ -} ppp_err_stats_t; - -/*---------------------------------------------------------------------------- - * Packet Statistics (returned by the PPP_READ_PACKET_STATS command). - */ -typedef struct ppp_pkt_stats -{ - unsigned short rx_bad_header PACKED; /* 00: */ - unsigned short rx_prot_unknwn PACKED; /* 02: */ - unsigned short rx_too_large PACKED; /* 04: */ - unsigned short rx_lcp PACKED; /* 06: */ - unsigned short tx_lcp PACKED; /* 08: */ - unsigned short rx_ipcp PACKED; /* 0A: */ - unsigned short tx_ipcp PACKED; /* 0C: */ - unsigned short rx_ipxcp PACKED; /* 0E: */ - unsigned short tx_ipxcp PACKED; /* 10: */ - unsigned short rx_pap PACKED; /* 12: */ - unsigned short tx_pap PACKED; /* 14: */ - unsigned short rx_chap PACKED; /* 16: */ - unsigned short tx_chap PACKED; /* 18: */ - unsigned short rx_lqr PACKED; /* 1A: */ - unsigned short tx_lqr PACKED; /* 1C: */ - unsigned short rx_ip PACKED; /* 1E: */ - unsigned short tx_ip PACKED; /* 20: */ - unsigned short rx_ipx PACKED; /* 22: */ - unsigned short tx_ipx PACKED; /* 24: */ -} ppp_pkt_stats_t; - -/*---------------------------------------------------------------------------- - * LCP Statistics (returned by the PPP_READ_LCP_STATS command). - */ -typedef struct ppp_lcp_stats -{ - unsigned short rx_unknown PACKED; /* 00: unknown LCP type */ - unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */ - unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */ - unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */ - unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */ - unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */ - unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */ - unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */ - unsigned short rx_proto_rej PACKED; /* 10: Protocol-Reject */ - unsigned short rx_echo_rqst PACKED; /* 12: Echo-Request */ - unsigned short rx_echo_reply PACKED; /* 14: Echo-Reply */ - unsigned short rx_disc_rqst PACKED; /* 16: Discard-Request */ - unsigned short tx_conf_rqst PACKED; /* 18: Configure-Request */ - unsigned short tx_conf_ack PACKED; /* 1A: Configure-Ack */ - unsigned short tx_conf_nak PACKED; /* 1C: Configure-Nak */ - unsigned short tx_conf_rej PACKED; /* 1E: Configure-Reject */ - unsigned short tx_term_rqst PACKED; /* 20: Terminate-Request */ - unsigned short tx_term_ack PACKED; /* 22: Terminate-Ack */ - unsigned short tx_code_rej PACKED; /* 24: Code-Reject */ - unsigned short tx_proto_rej PACKED; /* 26: Protocol-Reject */ - unsigned short tx_echo_rqst PACKED; /* 28: Echo-Request */ - unsigned short tx_echo_reply PACKED; /* 2A: Echo-Reply */ - unsigned short tx_disc_rqst PACKED; /* 2E: Discard-Request */ - unsigned short rx_too_large PACKED; /* 30: packets too large */ - unsigned short rx_ack_inval PACKED; /* 32: invalid Conf-Ack */ - unsigned short rx_rej_inval PACKED; /* 34: invalid Conf-Reject */ - unsigned short rx_rej_badid PACKED; /* 36: Conf-Reject w/bad ID */ -} ppp_lcp_stats_t; - -/*---------------------------------------------------------------------------- - * Loopback Error Statistics (returned by the PPP_READ_LPBK_STATS command). - */ -typedef struct ppp_lpbk_stats -{ - unsigned short conf_magic PACKED; /* 00: */ - unsigned short loc_echo_rqst PACKED; /* 02: */ - unsigned short rem_echo_rqst PACKED; /* 04: */ - unsigned short loc_echo_reply PACKED; /* 06: */ - unsigned short rem_echo_reply PACKED; /* 08: */ - unsigned short loc_disc_rqst PACKED; /* 0A: */ - unsigned short rem_disc_rqst PACKED; /* 0C: */ - unsigned short echo_tx_collsn PACKED; /* 0E: */ - unsigned short echo_rx_collsn PACKED; /* 10: */ -} ppp_lpbk_stats_t; - -/*---------------------------------------------------------------------------- - * Protocol Statistics (returned by the PPP_READ_IPCP_STATS and - * PPP_READ_IPXCP_STATS commands). - */ -typedef struct ppp_prot_stats -{ - unsigned short rx_unknown PACKED; /* 00: unknown type */ - unsigned short rx_conf_rqst PACKED; /* 02: Configure-Request */ - unsigned short rx_conf_ack PACKED; /* 04: Configure-Ack */ - unsigned short rx_conf_nak PACKED; /* 06: Configure-Nak */ - unsigned short rx_conf_rej PACKED; /* 08: Configure-Reject */ - unsigned short rx_term_rqst PACKED; /* 0A: Terminate-Request */ - unsigned short rx_term_ack PACKED; /* 0C: Terminate-Ack */ - unsigned short rx_code_rej PACKED; /* 0E: Code-Reject */ - unsigned short reserved PACKED; /* 10: */ - unsigned short tx_conf_rqst PACKED; /* 12: Configure-Request */ - unsigned short tx_conf_ack PACKED; /* 14: Configure-Ack */ - unsigned short tx_conf_nak PACKED; /* 16: Configure-Nak */ - unsigned short tx_conf_rej PACKED; /* 18: Configure-Reject */ - unsigned short tx_term_rqst PACKED; /* 1A: Terminate-Request */ - unsigned short tx_term_ack PACKED; /* 1C: Terminate-Ack */ - unsigned short tx_code_rej PACKED; /* 1E: Code-Reject */ - unsigned short rx_too_large PACKED; /* 20: packets too large */ - unsigned short rx_ack_inval PACKED; /* 22: invalid Conf-Ack */ - unsigned short rx_rej_inval PACKED; /* 24: invalid Conf-Reject */ - unsigned short rx_rej_badid PACKED; /* 26: Conf-Reject w/bad ID */ -} ppp_prot_stats_t; - -/*---------------------------------------------------------------------------- - * PAP Statistics (returned by the PPP_READ_PAP_STATS command). - */ -typedef struct ppp_pap_stats -{ - unsigned short rx_unknown PACKED; /* 00: unknown type */ - unsigned short rx_auth_rqst PACKED; /* 02: Authenticate-Request */ - unsigned short rx_auth_ack PACKED; /* 04: Authenticate-Ack */ - unsigned short rx_auth_nak PACKED; /* 06: Authenticate-Nak */ - unsigned short reserved PACKED; /* 08: */ - unsigned short tx_auth_rqst PACKED; /* 0A: Authenticate-Request */ - unsigned short tx_auth_ack PACKED; /* 0C: Authenticate-Ack */ - unsigned short tx_auth_nak PACKED; /* 0E: Authenticate-Nak */ - unsigned short rx_too_large PACKED; /* 10: packets too large */ - unsigned short rx_bad_peerid PACKED; /* 12: invalid peer ID */ - unsigned short rx_bad_passwd PACKED; /* 14: invalid password */ -} ppp_pap_stats_t; - -/*---------------------------------------------------------------------------- - * CHAP Statistics (returned by the PPP_READ_CHAP_STATS command). - */ -typedef struct ppp_chap_stats -{ - unsigned short rx_unknown PACKED; /* 00: unknown type */ - unsigned short rx_challenge PACKED; /* 02: Authenticate-Request */ - unsigned short rx_response PACKED; /* 04: Authenticate-Ack */ - unsigned short rx_success PACKED; /* 06: Authenticate-Nak */ - unsigned short rx_failure PACKED; /* 08: Authenticate-Nak */ - unsigned short reserved PACKED; /* 0A: */ - unsigned short tx_challenge PACKED; /* 0C: Authenticate-Request */ - unsigned short tx_response PACKED; /* 0E: Authenticate-Ack */ - unsigned short tx_success PACKED; /* 10: Authenticate-Nak */ - unsigned short tx_failure PACKED; /* 12: Authenticate-Nak */ - unsigned short rx_too_large PACKED; /* 14: packets too large */ - unsigned short rx_bad_peerid PACKED; /* 16: invalid peer ID */ - unsigned short rx_bad_passwd PACKED; /* 18: invalid password */ - unsigned short rx_bad_md5 PACKED; /* 1A: invalid MD5 format */ - unsigned short rx_bad_resp PACKED; /* 1C: invalid response */ -} ppp_chap_stats_t; - -/*---------------------------------------------------------------------------- - * Connection Information (returned by the PPP_GET_CONNECTION_INFO command). - */ -typedef struct ppp_conn_info -{ - unsigned short remote_mru PACKED; /* 00: */ - unsigned char ip_options PACKED; /* 02: */ - unsigned char ip_local[4] PACKED; /* 03: */ - unsigned char ip_remote[4] PACKED; /* 07: */ - unsigned char ipx_options PACKED; /* 0B: */ - unsigned char ipx_network[4] PACKED; /* 0C: */ - unsigned char ipx_local[6] PACKED; /* 10: */ - unsigned char ipx_remote[6] PACKED; /* 16: */ - unsigned char ipx_router[48] PACKED; /* 1C: */ - unsigned char auth_status PACKED; /* 4C: */ - unsigned char peer_id[0] PACKED; /* 4D: */ -} ppp_conn_info_t; - -/* Data structure for SET_TRIGGER_INTR command - */ - -typedef struct ppp_intr_info{ - unsigned char i_enable PACKED; /* 0 Interrupt enable bits */ - unsigned char irq PACKED; /* 1 Irq number */ - unsigned short timer_len PACKED; /* 2 Timer delay */ -} ppp_intr_info_t; - - -#define FT1_MONITOR_STATUS_CTRL 0x80 -#define SET_FT1_MODE 0x81 - - - -/* Special UDP drivers management commands */ -#define PPIPE_ENABLE_TRACING 0x20 -#define PPIPE_DISABLE_TRACING 0x21 -#define PPIPE_GET_TRACE_INFO 0x22 -#define PPIPE_GET_IBA_DATA 0x23 -#define PPIPE_KILL_BOARD 0x24 -#define PPIPE_FT1_READ_STATUS 0x25 -#define PPIPE_DRIVER_STAT_IFSEND 0x26 -#define PPIPE_DRIVER_STAT_INTR 0x27 -#define PPIPE_DRIVER_STAT_GEN 0x28 -#define PPIPE_FLUSH_DRIVER_STATS 0x29 -#define PPIPE_ROUTER_UP_TIME 0x30 - -#define DISABLE_TRACING 0x00 -#define TRACE_SIGNALLING_FRAMES 0x01 -#define TRACE_DATA_FRAMES 0x02 - - - -#ifdef _MSC_ -# pragma pack() -#endif -#endif /* _SDLA_PPP_H */ diff --git a/include/linux/sdla_x25.h b/include/linux/sdla_x25.h deleted file mode 100644 index 57db980e27ad..000000000000 --- a/include/linux/sdla_x25.h +++ /dev/null @@ -1,772 +0,0 @@ -/***************************************************************************** -* sdla_x25.h Sangoma X.25 firmware API definitions. -* -* Author: Nenad Corbic -* -* Copyright: (c) 1995-2000 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. -* ============================================================================ -* Feb 28, 2000 Nenad Corbic Updated for socket based x25api -* Dec 13, 1996 Gene Kozin Initial version -*****************************************************************************/ -#ifndef _SDLA_X25_H -#define _SDLA_X25_H - -/*---------------------------------------------------------------------------- - * Notes: - * ------ - * 1. All structures defined in this file are byte-alined. - * Compiler Platform - * -------- -------- - * GNU C Linux - * - */ - -#ifndef PACKED -# define PACKED __attribute__((packed)) -#endif /* PACKED */ - -/****** CONSTANTS DEFINITIONS ***********************************************/ - -#define X25_MAX_CHAN 255 /* max number of open X.25 circuits */ -#define X25_MAX_DATA 1024 /* max length of X.25 data buffer */ -/* - * X.25 shared memory layout. - */ -#define X25_MBOX_OFFS 0x16B0 /* general mailbox block */ -#define X25_RXMBOX_OFFS 0x1AD0 /* receive mailbox */ -#define X25_STATUS_OFFS 0x1EF0 /* X.25 status structure */ -#define X25_MB_VECTOR 0xE000 /* S514 mailbox window vecotr */ -#define X25_MISC_HDLC_BITS 0x1F00 /*X.25 miscallaneous HDLC bits */ - -/* code levels */ -#define HDLC_LEVEL 0x01 -#define X25_LEVEL 0x02 -#define X25_AND_HDLC_LEVEL 0x03 -#define DO_HDLC_LEVEL_ERROR_CHECKING 0x04 - -/****** DATA STRUCTURES *****************************************************/ - -/*---------------------------------------------------------------------------- - * X.25 Command Block. - */ -typedef struct X25Cmd -{ - unsigned char command PACKED; /* command code */ - unsigned short length PACKED; /* transfer data length */ - unsigned char result PACKED; /* return code */ - unsigned char pf PACKED; /* P/F bit */ - unsigned short lcn PACKED; /* logical channel */ - unsigned char qdm PACKED; /* Q/D/M bits */ - unsigned char cause PACKED; /* cause field */ - unsigned char diagn PACKED; /* diagnostics */ - unsigned char pktType PACKED; /* packet type */ - unsigned char resrv[4] PACKED; /* reserved */ -} TX25Cmd; - -/* - * Defines for the 'command' field. - */ -/*----- General commands --------------*/ -#define X25_SET_GLOBAL_VARS 0x0B /* set global variables */ -#define X25_READ_MODEM_STATUS 0x0C /* read modem status */ -#define X25_READ_CODE_VERSION 0x15 /* read firmware version number */ -#define X25_TRACE_CONFIGURE 0x14 /* configure trace facility */ -#define X25_READ_TRACE_DATA 0x16 /* read trace data */ -#define X25_SET_INTERRUPT_MODE 0x17 /* set interrupt generation mode */ -#define X25_READ_INTERRUPT_MODE 0x18 /* read interrupt generation mode */ -/*----- HDLC-level commands -----------*/ -#define X25_HDLC_LINK_CONFIGURE 0x01 /* configure HDLC link level */ -#define X25_HDLC_LINK_OPEN 0x02 /* open HDLC link */ -#define X25_HDLC_LINK_CLOSE 0x03 /* close HDLC link */ -#define X25_HDLC_LINK_SETUP 0x04 /* set up HDLC link */ -#define X25_HDLC_LINK_DISC 0x05 /* disconnect DHLC link */ -#define X25_HDLC_LINK_STATUS 0x06 /* read DHLC link status */ -#define X25_HDLC_READ_STATS 0x07 /* read operational statistics */ -#define X25_HDLC_FLUSH_STATS 0x08 /* flush operational statistics */ -#define X25_HDLC_READ_COMM_ERR 0x09 /* read error statistics */ -#define X25_HDLC_FLUSH_COMM_ERR 0x0A /* flush error statistics */ -#define X25_HDLC_FLUSH_BUFFERS 0x0D /* flush HDLC-level data buffers */ -#define X25_HDLC_SPRVS_CNT_STAT 0x0F /* read surervisory count status */ -#define X25_HDLC_SEND_UI_FRAME 0x10 /* send unnumbered information frame */ -#define X25_HDLC_WRITE 0x11 /* send HDLC information frame */ -#define X25_HDLC_READ 0x21 /* read HDLC information frame */ -#define X25_HDLC_READ_CONFIG 0x12 /* read HDLC configuration */ -#define X25_HDLC_SET_CONFIG 0x13 /* set HDLC configuration */ -#define SET_PROTOCOL_LEVEL 0x1F /* set protocol level */ -/*----- X.25-level commands -----------*/ -#define X25_READ 0x22 /* read X.25 packet */ -#define X25_WRITE 0x23 /* send X.25 packet */ -#define X25_PLACE_CALL 0x30 /* place a call on SVC */ -#define X25_ACCEPT_CALL 0x31 /* accept incomming call */ -#define X25_CLEAR_CALL 0x32 /* clear call */ -#define X25_CLEAR_CONFRM 0x33 /* send clear confirmation packet */ -#define X25_RESET 0x34 /* send reset request packet */ -#define X25_RESET_CONFRM 0x35 /* send reset confirmation packet */ -#define X25_RESTART 0x36 /* send restart request packet */ -#define X25_RESTART_CONFRM 0x37 /* send restart confirmation packet */ -#define X25_INTERRUPT 0x38 /* send interrupt request packet */ -#define X25_INTERRUPT_CONFRM 0x39 /* send interrupt confirmation pkt */ -#define X25_REGISTRATION_RQST 0x3A /* send registration request packet */ -#define X25_REGISTRATION_CONFRM 0x3B /* send registration confirmation */ -#define X25_IS_DATA_AVAILABLE 0x40 /* querry receive queue */ -#define X25_INCOMMING_CALL_CTL 0x41 /* select incomming call options */ -#define X25_CONFIGURE_PVC 0x42 /* configure PVC */ -#define X25_GET_ACTIVE_CHANNELS 0x43 /* get a list of active circuits */ -#define X25_READ_CHANNEL_CONFIG 0x44 /* read virt. circuit configuration */ -#define X25_FLUSH_DATA_BUFFERS 0x45 /* flush X.25-level data buffers */ -#define X25_READ_HISTORY_TABLE 0x46 /* read asynchronous event log */ -#define X25_HISTORY_TABLE_CTL 0x47 /* control asynchronous event log */ -#define X25_GET_TX_D_BIT_STATUS 0x48 /* is packet with D-bit acknowleged */ -#define X25_READ_STATISTICS 0x49 /* read X.25-level statistics */ -#define X25_FLUSH_STATISTICS 0x4A /* flush X.25-level statistics */ -#define X25_READ_CONFIGURATION 0x50 /* read HDLC & X.25 configuration */ -#define X25_SET_CONFIGURATION 0x51 /* set HDLC & X.25 configuration */ - -/* - * Defines for the 'result' field. - */ -/*----- General results ---------------*/ -#define X25RES_OK 0x00 -#define X25RES_ERROR 0x01 -#define X25RES_LINK_NOT_IN_ABM 0x02 /* link is not in ABM mode */ -#define X25RES_LINK_CLOSED 0x03 -#define X25RES_INVAL_LENGTH 0x04 -#define X25RES_INVAL_CMD 0x05 -#define X25RES_UNNUMBERED_FRAME 0x06 /* unnunbered frame received */ -#define X25RES_FRM_REJECT_MODE 0x07 /* link is in Frame Reject mode */ -#define X25RES_MODEM_FAILURE 0x08 /* DCD and/or CTS dropped */ -#define X25RES_N2_RETRY_LIMIT 0x09 /* N2 retry limit has been exceeded */ -#define X25RES_INVAL_LCN 0x30 /* invalid logical channel number */ -#define X25RES_INVAL_STATE 0x31 /* channel is not in data xfer mode */ -#define X25RES_INVAL_DATA_LEN 0x32 /* invalid data length */ -#define X25RES_NOT_READY 0x33 /* no data available / buffers full */ -#define X25RES_NETWORK_DOWN 0x34 -#define X25RES_CHANNEL_IN_USE 0x35 /* there is data queued on this LCN */ -#define X25RES_REGST_NOT_SUPPRT 0x36 /* registration not supported */ -#define X25RES_INVAL_FORMAT 0x37 /* invalid packet format */ -#define X25RES_D_BIT_NOT_SUPPRT 0x38 /* D-bit pragmatics not supported */ -#define X25RES_FACIL_NOT_SUPPRT 0x39 /* Call facility not supported */ -#define X25RES_INVAL_CALL_ARG 0x3A /* errorneous call arguments */ -#define X25RES_INVAL_CALL_DATA 0x3B /* errorneous call user data */ -#define X25RES_ASYNC_PACKET 0x40 /* asynchronous packet received */ -#define X25RES_PROTO_VIOLATION 0x41 /* protocol violation occurred */ -#define X25RES_PKT_TIMEOUT 0x42 /* X.25 packet time out */ -#define X25RES_PKT_RETRY_LIMIT 0x43 /* X.25 packet retry limit exceeded */ -/*----- Command-dependent results -----*/ -#define X25RES_LINK_DISC 0x00 /* HDLC_LINK_STATUS */ -#define X25RES_LINK_IN_ABM 0x01 /* HDLC_LINK_STATUS */ -#define X25RES_NO_DATA 0x01 /* HDLC_READ/READ_TRACE_DATA*/ -#define X25RES_TRACE_INACTIVE 0x02 /* READ_TRACE_DATA */ -#define X25RES_LINK_IS_OPEN 0x01 /* HDLC_LINK_OPEN */ -#define X25RES_LINK_IS_DISC 0x02 /* HDLC_LINK_DISC */ -#define X25RES_LINK_IS_CLOSED 0x03 /* HDLC_LINK_CLOSE */ -#define X25RES_INVAL_PARAM 0x31 /* INCOMMING_CALL_CTL */ -#define X25RES_INVAL_CONFIG 0x35 /* REGISTR_RQST/CONFRM */ - -/* - * Defines for the 'qdm_bits' field. - */ -#define X25CMD_Q_BIT_MASK 0x04 -#define X25CMD_D_BIT_MASK 0x02 -#define X25CMD_M_BIT_MASK 0x01 - -/* - * Defines for the 'pkt_type' field. - */ -/*----- Asynchronous events ------*/ -#define ASE_CLEAR_RQST 0x02 -#define ASE_RESET_RQST 0x04 -#define ASE_RESTART_RQST 0x08 -#define ASE_INTERRUPT 0x10 -#define ASE_DTE_REGISTR_RQST 0x20 -#define ASE_CALL_RQST 0x30 -#define ASE_CALL_ACCEPTED 0x31 -#define ASE_CLEAR_CONFRM 0x32 -#define ASE_RESET_CONFRM 0x33 -#define ASE_RESTART_CONFRM 0x34 -#define ASE_INTERRUPT_CONFRM 0x35 -#define ASE_DCE_REGISTR_CONFRM 0x36 -#define ASE_DIAGNOSTIC 0x37 -#define ASE_CALL_AUTO_CLEAR 0x38 -#define AUTO_RESPONSE_FLAG 0x80 -/*----- Time-Out events ----------*/ -#define TOE_RESTART_RQST 0x03 -#define TOE_CALL_RQST 0x05 -#define TOE_CLEAR_RQST 0x08 -#define TOE_RESET_RQST 0x0A -/*----- Protocol Violation events */ -#define PVE_CLEAR_RQST 0x32 -#define PVE_RESET_RQST 0x33 -#define PVE_RESTART_RQST 0x34 -#define PVE_DIAGNOSTIC 0x37 - -#define INTR_ON_RX_FRAME 0x01 -#define INTR_ON_TX_FRAME 0x02 -#define INTR_ON_MODEM_STATUS_CHANGE 0x04 -#define INTR_ON_COMMAND_COMPLETE 0x08 -#define INTR_ON_X25_ASY_TRANSACTION 0x10 -#define INTR_ON_TIMER 0x40 -#define DIRECT_RX_INTR_USAGE 0x80 - -#define NO_INTR_PENDING 0x00 -#define RX_INTR_PENDING 0x01 -#define TX_INTR_PENDING 0x02 -#define MODEM_INTR_PENDING 0x04 -#define COMMAND_COMPLETE_INTR_PENDING 0x08 -#define X25_ASY_TRANS_INTR_PENDING 0x10 -#define TIMER_INTR_PENDING 0x40 - -/*---------------------------------------------------------------------------- - * X.25 Mailbox. - * This structure is located at offsets X25_MBOX_OFFS and X25_RXMBOX_OFFS - * into shared memory window. - */ -typedef struct X25Mbox -{ - unsigned char opflag PACKED; /* 00h: execution flag */ - TX25Cmd cmd PACKED; /* 01h: command block */ - unsigned char data[1] PACKED; /* 10h: data buffer */ -} TX25Mbox; - -/*---------------------------------------------------------------------------- - * X.25 Time Stamp Structure. - */ -typedef struct X25TimeStamp -{ - unsigned char month PACKED; - unsigned char date PACKED; - unsigned char sec PACKED; - unsigned char min PACKED; - unsigned char hour PACKED; -} TX25TimeStamp; - -/*---------------------------------------------------------------------------- - * X.25 Status Block. - * This structure is located at offset X25_STATUS_OFF into shared memory - * window. - */ -typedef struct X25Status -{ - unsigned short pvc_map PACKED; /* 00h: PVC map */ - unsigned short icc_map PACKED; /* 02h: Incomming Chan. map */ - unsigned short twc_map PACKED; /* 04h: Two-way Cnan. map */ - unsigned short ogc_map PACKED; /* 06h: Outgoing Chan. map */ - TX25TimeStamp tstamp PACKED; /* 08h: timestamp (BCD) */ - unsigned char iflags PACKED; /* 0Dh: interrupt flags */ - unsigned char imask PACKED; /* 0Eh: interrupt mask */ - unsigned char resrv PACKED; /* 0Eh: */ - unsigned char gflags PACKED; /* 10h: misc. HDLC/X25 flags */ - unsigned char cflags[X25_MAX_CHAN] PACKED; /* channel status bytes */ -} TX25Status; - -/* - * Bitmasks for the 'iflags' field. - */ -#define X25_RX_INTR 0x01 /* receive interrupt */ -#define X25_TX_INTR 0x02 /* transmit interrupt */ -#define X25_MODEM_INTR 0x04 /* modem status interrupt (CTS/DCD) */ -#define X25_EVENT_INTR 0x10 /* asyncronous event encountered */ -#define X25_CMD_INTR 0x08 /* interface command complete */ - -/* - * Bitmasks for the 'gflags' field. - */ -#define X25_HDLC_ABM 0x01 /* HDLC is in ABM mode */ -#define X25_RX_READY 0x02 /* X.25 data available */ -#define X25_TRACE_READY 0x08 /* trace data available */ -#define X25_EVENT_IND 0x20 /* asynchronous event indicator */ -#define X25_TX_READY 0x40 /* space is available in Tx buf.*/ - -/* - * Bitmasks for the 'cflags' field. - */ -#define X25_XFER_MODE 0x80 /* channel is in data transfer mode */ -#define X25_TXWIN_OPEN 0x40 /* transmit window open */ -#define X25_RXBUF_MASK 0x3F /* number of data buffers available */ - -/***************************************************************************** - * Following definitions structurize contents of the TX25Mbox.data field for - * different X.25 interface commands. - ****************************************************************************/ - -/* --------------------------------------------------------------------------- - * X25_SET_GLOBAL_VARS Command. - */ -typedef struct X25GlobalVars -{ - unsigned char resrv PACKED; /* 00h: reserved */ - unsigned char dtrCtl PACKED; /* 01h: DTR control code */ - unsigned char resErr PACKED; /* 01h: '1' - reset modem error */ -} TX25GlobalVars; - -/* - * Defines for the 'dtrCtl' field. - */ -#define X25_RAISE_DTR 0x01 -#define X25_DROP_DTR 0x02 - -/* --------------------------------------------------------------------------- - * X25_READ_MODEM_STATUS Command. - */ -typedef struct X25ModemStatus -{ - unsigned char status PACKED; /* 00h: modem status */ -} TX25ModemStatus; - -/* - * Defines for the 'status' field. - */ -#define X25_CTS_MASK 0x20 -#define X25_DCD_MASK 0x08 - -/* --------------------------------------------------------------------------- - * X25_HDLC_LINK_STATUS Command. - */ -typedef struct X25LinkStatus -{ - unsigned char txQueued PACKED; /* 00h: queued Tx I-frames*/ - unsigned char rxQueued PACKED; /* 01h: queued Rx I-frames*/ - unsigned char station PACKED; /* 02h: DTE/DCE config. */ - unsigned char reserved PACKED; /* 03h: reserved */ - unsigned char sfTally PACKED; /* 04h: supervisory frame tally */ -} TX25LinkStatus; - -/* - * Defines for the 'station' field. - */ -#define X25_STATION_DTE 0x01 /* station configured as DTE */ -#define X25_STATION_DCE 0x02 /* station configured as DCE */ - -/* --------------------------------------------------------------------------- - * X25_HDLC_READ_STATS Command. - */ -typedef struct HdlcStats -{ /* a number of ... */ - unsigned short rxIFrames PACKED; /* 00h: ready Rx I-frames */ - unsigned short rxNoseq PACKED; /* 02h: frms out-of-sequence */ - unsigned short rxNodata PACKED; /* 04h: I-frms without data */ - unsigned short rxDiscarded PACKED; /* 06h: discarded frames */ - unsigned short rxTooLong PACKED; /* 08h: frames too long */ - unsigned short rxBadAddr PACKED; /* 0Ah: frms with inval.addr*/ - unsigned short txAcked PACKED; /* 0Ch: acknowledged I-frms */ - unsigned short txRetransm PACKED; /* 0Eh: re-transmit. I-frms */ - unsigned short t1Timeout PACKED; /* 10h: T1 timeouts */ - unsigned short rxSABM PACKED; /* 12h: received SABM frames */ - unsigned short rxDISC PACKED; /* 14h: received DISC frames */ - unsigned short rxDM PACKED; /* 16h: received DM frames */ - unsigned short rxFRMR PACKED; /* 18h: FRMR frames received */ - unsigned short txSABM PACKED; /* 1Ah: transm. SABM frames*/ - unsigned short txDISC PACKED; /* 1Ch: transm. DISC frames*/ - unsigned short txDM PACKED; /* 1Eh: transm. DM frames */ - unsigned short txFRMR PACKED; /* 20h: transm. FRMR frames*/ -} THdlcStats; - -/* --------------------------------------------------------------------------- - * X25_HDLC_READ_COMM_ERR Command. - */ -typedef struct HdlcCommErr -{ /* a number of ... */ - unsigned char rxOverrun PACKED; /* 00h: Rx overrun errors */ - unsigned char rxBadCrc PACKED; /* 01h: Rx CRC errors */ - unsigned char rxAborted PACKED; /* 02h: Rx aborted frames */ - unsigned char rxDropped PACKED; /* 03h: frames lost */ - unsigned char txAborted PACKED; /* 04h: Tx aborted frames */ - unsigned char txUnderrun PACKED; /* 05h: Tx underrun errors */ - unsigned char txMissIntr PACKED; /* 06h: missed underrun ints */ - unsigned char reserved PACKED; /* 07h: reserved */ - unsigned char droppedDCD PACKED; /* 08h: times DCD dropped */ - unsigned char droppedCTS PACKED; /* 09h: times CTS dropped */ -} THdlcCommErr; - -/* --------------------------------------------------------------------------- - * X25_SET_CONFIGURATION & X25_READ_CONFIGURATION Commands. - */ -typedef struct X25Config -{ -unsigned char baudRate PACKED; /* 00h: */ - unsigned char t1 PACKED; /* 01h: */ - unsigned char t2 PACKED; /* 02h: */ - unsigned char n2 PACKED; /* 03h: */ - unsigned short hdlcMTU PACKED; /* 04h: */ - unsigned char hdlcWindow PACKED; /* 06h: */ - unsigned char t4 PACKED; /* 07h: */ - unsigned char autoModem PACKED; /* 08h: */ - unsigned char autoHdlc PACKED; /* 09h: */ - unsigned char hdlcOptions PACKED; /* 0Ah: */ - unsigned char station PACKED; /* 0Bh: */ - unsigned char pktWindow PACKED; /* 0Ch: */ - unsigned short defPktSize PACKED; /* 0Dh: */ - unsigned short pktMTU PACKED; /* 0Fh: */ - unsigned short loPVC PACKED; /* 11h: */ - unsigned short hiPVC PACKED; /* 13h: */ - unsigned short loIncommingSVC PACKED; /* 15h: */ - unsigned short hiIncommingSVC PACKED; /* 17h: */ - unsigned short loTwoWaySVC PACKED; /* 19h: */ - unsigned short hiTwoWaySVC PACKED; /* 1Bh: */ - unsigned short loOutgoingSVC PACKED; /* 1Dh: */ - unsigned short hiOutgoingSVC PACKED; /* 1Fh: */ - unsigned short options PACKED; /* 21h: */ - unsigned char responseOpt PACKED; /* 23h: */ - unsigned short facil1 PACKED; /* 24h: */ - unsigned short facil2 PACKED; /* 26h: */ - unsigned short ccittFacil PACKED; /* 28h: */ - unsigned short otherFacil PACKED; /* 2Ah: */ - unsigned short ccittCompat PACKED; /* 2Ch: */ - unsigned char t10t20 PACKED; /* 2Eh: */ - unsigned char t11t21 PACKED; /* 2Fh: */ - unsigned char t12t22 PACKED; /* 30h: */ - unsigned char t13t23 PACKED; /* 31h: */ - unsigned char t16t26 PACKED; /* 32H: */ - unsigned char t28 PACKED; /* 33h: */ - unsigned char r10r20 PACKED; /* 34h: */ - unsigned char r12r22 PACKED; /* 35h: */ - unsigned char r13r23 PACKED; /* 36h: */ -} TX25Config; - -/* --------------------------------------------------------------------------- - * X25_READ_CHANNEL_CONFIG Command. - */ -typedef struct X25ChanAlloc /*----- Channel allocation -*/ -{ - unsigned short loPVC PACKED; /* 00h: lowest PVC number */ - unsigned short hiPVC PACKED; /* 02h: highest PVC number */ - unsigned short loIncommingSVC PACKED; /* 04h: lowest incoming SVC */ - unsigned short hiIncommingSVC PACKED; /* 06h: highest incoming SVC */ - unsigned short loTwoWaySVC PACKED; /* 08h: lowest two-way SVC */ - unsigned short hiTwoWaySVC PACKED; /* 0Ah: highest two-way SVC */ - unsigned short loOutgoingSVC PACKED; /* 0Ch: lowest outgoing SVC */ - unsigned short hiOutgoingSVC PACKED; /* 0Eh: highest outgoing SVC */ -} TX25ChanAlloc; - -typedef struct X25ChanCfg /*------ Channel configuration -----*/ -{ - unsigned char type PACKED; /* 00h: channel type */ - unsigned char txConf PACKED; /* 01h: Tx packet and window sizes */ - unsigned char rxConf PACKED; /* 01h: Rx packet and window sizes */ -} TX25ChanCfg; - -/* - * Defines for the 'type' field. - */ -#define X25_PVC 0x01 /* PVC */ -#define X25_SVC_IN 0x03 /* Incoming SVC */ -#define X25_SVC_TWOWAY 0x07 /* Two-way SVC */ -#define X25_SVC_OUT 0x0B /* Outgoing SVC */ - -/*---------------------------------------------------------------------------- - * X25_READ_STATISTICS Command. - */ -typedef struct X25Stats -{ /* number of packets Tx/Rx'ed */ - unsigned short txRestartRqst PACKED; /* 00h: Restart Request */ - unsigned short rxRestartRqst PACKED; /* 02h: Restart Request */ - unsigned short txRestartConf PACKED; /* 04h: Restart Confirmation */ - unsigned short rxRestartConf PACKED; /* 06h: Restart Confirmation */ - unsigned short txResetRqst PACKED; /* 08h: Reset Request */ - unsigned short rxResetRqst PACKED; /* 0Ah: Reset Request */ - unsigned short txResetConf PACKED; /* 0Ch: Reset Confirmation */ - unsigned short rxResetConf PACKED; /* 0Eh: Reset Confirmation */ - unsigned short txCallRequest PACKED; /* 10h: Call Request */ - unsigned short rxCallRequest PACKED; /* 12h: Call Request */ - unsigned short txCallAccept PACKED; /* 14h: Call Accept */ - unsigned short rxCallAccept PACKED; /* 16h: Call Accept */ - unsigned short txClearRqst PACKED; /* 18h: Clear Request */ - unsigned short rxClearRqst PACKED; /* 1Ah: Clear Request */ - unsigned short txClearConf PACKED; /* 1Ch: Clear Confirmation */ - unsigned short rxClearConf PACKED; /* 1Eh: Clear Confirmation */ - unsigned short txDiagnostic PACKED; /* 20h: Diagnostic */ - unsigned short rxDiagnostic PACKED; /* 22h: Diagnostic */ - unsigned short txRegRqst PACKED; /* 24h: Registration Request */ - unsigned short rxRegRqst PACKED; /* 26h: Registration Request */ - unsigned short txRegConf PACKED; /* 28h: Registration Confirm.*/ - unsigned short rxRegConf PACKED; /* 2Ah: Registration Confirm.*/ - unsigned short txInterrupt PACKED; /* 2Ch: Interrupt */ - unsigned short rxInterrupt PACKED; /* 2Eh: Interrupt */ - unsigned short txIntrConf PACKED; /* 30h: Interrupt Confirm. */ - unsigned short rxIntrConf PACKED; /* 32h: Interrupt Confirm. */ - unsigned short txData PACKED; /* 34h: Data */ - unsigned short rxData PACKED; /* 36h: Data */ - unsigned short txRR PACKED; /* 38h: RR */ - unsigned short rxRR PACKED; /* 3Ah: RR */ - unsigned short txRNR PACKED; /* 3Ch: RNR */ - unsigned short rxRNR PACKED; /* 3Eh: RNR */ -} TX25Stats; - -/*---------------------------------------------------------------------------- - * X25_READ_HISTORY_TABLE Command. - */ -typedef struct X25EventLog -{ - unsigned char type PACKED; /* 00h: transaction type */ - unsigned short lcn PACKED; /* 01h: logical channel num */ - unsigned char packet PACKED; /* 03h: async packet type */ - unsigned char cause PACKED; /* 04h: X.25 cause field */ - unsigned char diag PACKED; /* 05h: X.25 diag field */ - TX25TimeStamp ts PACKED; /* 06h: time stamp */ -} TX25EventLog; - -/* - * Defines for the 'type' field. - */ -#define X25LOG_INCOMMING 0x00 -#define X25LOG_APPLICATION 0x01 -#define X25LOG_AUTOMATIC 0x02 -#define X25LOG_ERROR 0x04 -#define X25LOG_TIMEOUT 0x08 -#define X25LOG_RECOVERY 0x10 - -/* - * Defines for the 'packet' field. - */ -#define X25LOG_CALL_RQST 0x0B -#define X25LOG_CALL_ACCEPTED 0x0F -#define X25LOG_CLEAR_RQST 0x13 -#define X25LOG_CLEAR_CONFRM 0x17 -#define X25LOG_RESET_RQST 0x1B -#define X25LOG_RESET_CONFRM 0x1F -#define X25LOG_RESTART_RQST 0xFB -#define X25LOG_RESTART_COMFRM 0xFF -#define X25LOG_DIAGNOSTIC 0xF1 -#define X25LOG_DTE_REG_RQST 0xF3 -#define X25LOG_DTE_REG_COMFRM 0xF7 - -/* --------------------------------------------------------------------------- - * X25_TRACE_CONFIGURE Command. - */ -typedef struct X25TraceCfg -{ - unsigned char flags PACKED; /* 00h: trace configuration flags */ - unsigned char timeout PACKED; /* 01h: timeout for trace delay mode*/ -} TX25TraceCfg; - -/* - * Defines for the 'flags' field. - */ -#define X25_TRC_ENABLE 0x01 /* bit0: '1' - trace enabled */ -#define X25_TRC_TIMESTAMP 0x02 /* bit1: '1' - time stamping enabled*/ -#define X25_TRC_DELAY 0x04 /* bit2: '1' - trace delay enabled */ -#define X25_TRC_DATA 0x08 /* bit3: '1' - trace data packets */ -#define X25_TRC_SUPERVISORY 0x10 /* bit4: '1' - trace suprvisory pkts*/ -#define X25_TRC_ASYNCHRONOUS 0x20 /* bit5: '1' - trace asynch. packets*/ -#define X25_TRC_HDLC 0x40 /* bit6: '1' - trace all packets */ -#define X25_TRC_READ 0x80 /* bit7: '1' - get current config. */ - -/* --------------------------------------------------------------------------- - * X25_READ_TRACE_DATA Command. - */ -typedef struct X25Trace /*----- Trace data structure -------*/ -{ - unsigned short length PACKED; /* 00h: trace data length */ - unsigned char type PACKED; /* 02h: trace type */ - unsigned char lost_cnt PACKED; /* 03h: N of traces lost */ - TX25TimeStamp tstamp PACKED; /* 04h: mon/date/sec/min/hour */ - unsigned short millisec PACKED; /* 09h: ms time stamp */ - unsigned char data[0] PACKED; /* 0Bh: traced frame */ -} TX25Trace; - -/* - * Defines for the 'type' field. - */ -#define X25_TRC_TYPE_MASK 0x0F /* bits 0..3: trace type */ -#define X25_TRC_TYPE_RX_FRAME 0x00 /* received frame trace */ -#define X25_TRC_TYPE_TX_FRAME 0x01 /* transmitted frame */ -#define X25_TRC_TYPE_ERR_FRAME 0x02 /* error frame */ - -#define X25_TRC_ERROR_MASK 0xF0 /* bits 4..7: error code */ -#define X25_TRCERR_RX_ABORT 0x10 /* receive abort error */ -#define X25_TRCERR_RX_BADCRC 0x20 /* receive CRC error */ -#define X25_TRCERR_RX_OVERRUN 0x30 /* receiver overrun error */ -#define X25_TRCERR_RX_TOO_LONG 0x40 /* excessive frame length error */ -#define X25_TRCERR_TX_ABORT 0x70 /* aborted frame transmittion error */ -#define X25_TRCERR_TX_UNDERRUN 0x80 /* transmit underrun error */ - -/***************************************************************************** - * Following definitions describe HDLC frame and X.25 packet formats. - ****************************************************************************/ - -typedef struct HDLCFrame /*----- DHLC Frame Format ----------*/ -{ - unsigned char addr PACKED; /* address field */ - unsigned char cntl PACKED; /* control field */ - unsigned char data[0] PACKED; -} THDLCFrame; - -typedef struct X25Pkt /*----- X.25 Paket Format ----------*/ -{ - unsigned char lcn_hi PACKED; /* 4 MSB of Logical Channel Number */ - unsigned char lcn_lo PACKED; /* 8 LSB of Logical Channel Number */ - unsigned char type PACKED; - unsigned char data[0] PACKED; -} TX25Pkt; - -/* - * Defines for the 'lcn_hi' field. - */ -#define X25_Q_BIT_MASK 0x80 /* Data Qualifier Bit mask */ -#define X25_D_BIT_MASK 0x40 /* Delivery Confirmation Bit mask */ -#define X25_M_BITS_MASK 0x30 /* Modulo Bits mask */ -#define X25_LCN_MSB_MASK 0x0F /* LCN most significant bits mask */ - -/* - * Defines for the 'type' field. - */ -#define X25PKT_DATA 0x01 /* Data packet mask */ -#define X25PKT_SUPERVISORY 0x02 /* Supervisory packet mask */ -#define X25PKT_CALL_RQST 0x0B /* Call Request/Incoming */ -#define X25PKT_CALL_ACCEPTED 0x0F /* Call Accepted/Connected */ -#define X25PKT_CLEAR_RQST 0x13 /* Clear Request/Indication */ -#define X25PKT_CLEAR_CONFRM 0x17 /* Clear Confirmation */ -#define X25PKT_RESET_RQST 0x1B /* Reset Request/Indication */ -#define X25PKT_RESET_CONFRM 0x1F /* Reset Confirmation */ -#define X25PKT_RESTART_RQST 0xFB /* Restart Request/Indication */ -#define X25PKT_RESTART_CONFRM 0xFF /* Restart Confirmation */ -#define X25PKT_INTERRUPT 0x23 /* Interrupt */ -#define X25PKT_INTERRUPT_CONFRM 0x27 /* Interrupt Confirmation */ -#define X25PKT_DIAGNOSTIC 0xF1 /* Diagnostic */ -#define X25PKT_REGISTR_RQST 0xF3 /* Registration Request */ -#define X25PKT_REGISTR_CONFRM 0xF7 /* Registration Confirmation */ -#define X25PKT_RR_MASKED 0x01 /* Receive Ready packet after masking */ -#define X25PKT_RNR_MASKED 0x05 /* Receive Not Ready after masking */ - - -typedef struct { - TX25Cmd cmd PACKED; - char data[X25_MAX_DATA] PACKED; -} mbox_cmd_t; - - -typedef struct { - unsigned char qdm PACKED; /* Q/D/M bits */ - unsigned char cause PACKED; /* cause field */ - unsigned char diagn PACKED; /* diagnostics */ - unsigned char pktType PACKED; - unsigned short length PACKED; - unsigned char result PACKED; - unsigned short lcn PACKED; - char reserved[7] PACKED; -}x25api_hdr_t; - - -typedef struct { - x25api_hdr_t hdr PACKED; - char data[X25_MAX_DATA] PACKED; -}x25api_t; - - -/* - * XPIPEMON Definitions - */ - -/* valid ip_protocol for UDP management */ -#define UDPMGMT_UDP_PROTOCOL 0x11 -#define UDPMGMT_XPIPE_SIGNATURE "XLINK8ND" -#define UDPMGMT_DRVRSTATS_SIGNATURE "DRVSTATS" - -/* values for request/reply byte */ -#define UDPMGMT_REQUEST 0x01 -#define UDPMGMT_REPLY 0x02 -#define UDP_OFFSET 12 - - -typedef struct { - unsigned char opp_flag PACKED; /* the opp flag */ - unsigned char command PACKED; /* command code */ - unsigned short length PACKED; /* transfer data length */ - unsigned char result PACKED; /* return code */ - unsigned char pf PACKED; /* P/F bit */ - unsigned short lcn PACKED; /* logical channel */ - unsigned char qdm PACKED; /* Q/D/M bits */ - unsigned char cause PACKED; /* cause field */ - unsigned char diagn PACKED; /* diagnostics */ - unsigned char pktType PACKED; /* packet type */ - unsigned char resrv[4] PACKED; /* reserved */ -} cblock_t; - -typedef struct { - ip_pkt_t ip_pkt PACKED; - udp_pkt_t udp_pkt PACKED; - wp_mgmt_t wp_mgmt PACKED; - cblock_t cblock PACKED; - unsigned char data[4080] PACKED; -} x25_udp_pkt_t; - - -typedef struct read_hdlc_stat { - unsigned short inf_frames_rx_ok PACKED; - unsigned short inf_frames_rx_out_of_seq PACKED; - unsigned short inf_frames_rx_no_data PACKED; - unsigned short inf_frames_rx_dropped PACKED; - unsigned short inf_frames_rx_data_too_long PACKED; - unsigned short inf_frames_rx_invalid_addr PACKED; - unsigned short inf_frames_tx_ok PACKED; - unsigned short inf_frames_tx_retransmit PACKED; - unsigned short T1_timeouts PACKED; - unsigned short SABM_frames_rx PACKED; - unsigned short DISC_frames_rx PACKED; - unsigned short DM_frames_rx PACKED; - unsigned short FRMR_frames_rx PACKED; - unsigned short SABM_frames_tx PACKED; - unsigned short DISC_frames_tx PACKED; - unsigned short DM_frames_tx PACKED; - unsigned short FRMR_frames_tx PACKED; -} read_hdlc_stat_t; - -typedef struct read_comms_err_stats{ - unsigned char overrun_err_rx PACKED; - unsigned char CRC_err PACKED; - unsigned char abort_frames_rx PACKED; - unsigned char frames_dropped_buf_full PACKED; - unsigned char abort_frames_tx PACKED; - unsigned char transmit_underruns PACKED; - unsigned char missed_tx_underruns_intr PACKED; - unsigned char reserved PACKED; - unsigned char DCD_drop PACKED; - unsigned char CTS_drop PACKED; -} read_comms_err_stats_t; - -typedef struct trace_data { - unsigned short length PACKED; - unsigned char type PACKED; - unsigned char trace_dropped PACKED; - unsigned char reserved[5] PACKED; - unsigned short timestamp PACKED; - unsigned char data PACKED; -} trace_data_t; - -enum {UDP_XPIPE_TYPE}; - -#define XPIPE_ENABLE_TRACING 0x14 -#define XPIPE_DISABLE_TRACING 0x14 -#define XPIPE_GET_TRACE_INFO 0x16 -#define XPIPE_FT1_READ_STATUS 0x74 -#define XPIPE_DRIVER_STAT_IFSEND 0x75 -#define XPIPE_DRIVER_STAT_INTR 0x76 -#define XPIPE_DRIVER_STAT_GEN 0x77 -#define XPIPE_FLUSH_DRIVER_STATS 0x78 -#define XPIPE_ROUTER_UP_TIME 0x79 -#define XPIPE_SET_FT1_MODE 0x81 -#define XPIPE_FT1_STATUS_CTRL 0x80 - - -/* error messages */ -#define NO_BUFFS_OR_CLOSED_WIN 0x33 -#define DATA_LENGTH_TOO_BIG 0x32 -#define NO_DATA_AVAILABLE 0x33 -#define Z80_TIMEOUT_ERROR 0x0a -#define NO_BUFFS 0x08 - - -/* Trace options */ -#define TRACE_DEFAULT 0x03 -#define TRACE_SUPERVISOR_FRMS 0x10 -#define TRACE_ASYNC_FRMS 0x20 -#define TRACE_ALL_HDLC_FRMS 0x40 -#define TRACE_DATA_FRMS 0x08 - - -#endif /* _SDLA_X25_H */ diff --git a/include/linux/sdladrv.h b/include/linux/sdladrv.h deleted file mode 100644 index c85e103d5e7b..000000000000 --- a/include/linux/sdladrv.h +++ /dev/null @@ -1,66 +0,0 @@ -/***************************************************************************** -* sdladrv.h SDLA Support Module. Kernel API Definitions. -* -* Author: Gideon Hack -* -* Copyright: (c) 1995-2000 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. -* ============================================================================ -* Jun 02, 1999 Gideon Hack Added support for the S514 PCI adapter. -* Dec 11, 1996 Gene Kozin Complete overhaul. -* Oct 17, 1996 Gene Kozin Minor bug fixes. -* Jun 12, 1996 Gene Kozin Added support for S503 card. -* Dec 06, 1995 Gene Kozin Initial version. -*****************************************************************************/ -#ifndef _SDLADRV_H -#define _SDLADRV_H - - -#define SDLA_MAXIORANGE 4 /* maximum I/O port range */ -#define SDLA_WINDOWSIZE 0x2000 /* default dual-port memory window size */ -/****** Data Structures *****************************************************/ - -/*---------------------------------------------------------------------------- - * Adapter hardware configuration. Pointer to this structure is passed to all - * APIs. - */ -typedef struct sdlahw -{ - unsigned type; /* adapter type */ - unsigned fwid; /* firmware ID */ - unsigned port; /* adapter I/O port base */ - int irq; /* interrupt request level */ - char S514_cpu_no[1]; /* PCI CPU Number */ - unsigned char S514_slot_no; /* PCI Slot Number */ - char auto_pci_cfg; /* Autodetect PCI Slot */ - struct pci_dev *pci_dev; /* PCI device */ - void * dpmbase; /* dual-port memory base */ - unsigned dpmsize; /* dual-port memory size */ - unsigned pclk; /* CPU clock rate, kHz */ - unsigned long memory; /* memory size */ - unsigned long vector; /* local offset of the DPM window */ - unsigned io_range; /* I/O port range */ - unsigned char regs[SDLA_MAXIORANGE]; /* was written to registers */ - unsigned reserved[5]; -} sdlahw_t; - -/****** Function Prototypes *************************************************/ - -extern int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len); -extern int sdla_down (sdlahw_t* hw); -extern void S514_intack (sdlahw_t* hw, u32 int_status); -extern void read_S514_int_stat (sdlahw_t* hw, u32* int_status); -extern int sdla_mapmem (sdlahw_t* hw, unsigned long addr); -extern int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, - unsigned len); -extern int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, - unsigned len); -extern int sdla_exec (void* opflag); - -extern unsigned wanpipe_hw_probe(void); - -#endif /* _SDLADRV_H */ diff --git a/include/linux/sdlapci.h b/include/linux/sdlapci.h deleted file mode 100644 index 6f7c904f188d..000000000000 --- a/include/linux/sdlapci.h +++ /dev/null @@ -1,72 +0,0 @@ -/***************************************************************************** -* sdlapci.h WANPIPE(tm) Multiprotocol WAN Link Driver. -* Definitions for the SDLA PCI adapter. -* -* Author: Gideon Hack -* -* Copyright: (c) 1999-2000 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. -* ============================================================================ -* Jun 02, 1999 Gideon Hack Initial version. -*****************************************************************************/ -#ifndef _SDLAPCI_H -#define _SDLAPCI_H - -/****** Defines *************************************************************/ - -/* Definitions for identifying and finding S514 PCI adapters */ -#define V3_VENDOR_ID 0x11B0 /* V3 vendor ID number */ -#define V3_DEVICE_ID 0x0002 /* V3 device ID number */ -#define SANGOMA_SUBSYS_VENDOR 0x4753 /* ID for Sangoma */ -#define PCI_DEV_SLOT_MASK 0x1F /* mask for slot numbering */ -#define PCI_IRQ_NOT_ALLOCATED 0xFF /* interrupt line for no IRQ */ - -/* Local PCI register offsets */ -#define PCI_VENDOR_ID_WORD 0x00 /* vendor ID */ -#define PCI_IO_BASE_DWORD 0x10 /* IO base */ -#define PCI_MEM_BASE0_DWORD 0x14 /* memory base - apperture 0 */ -#define PCI_MEM_BASE1_DWORD 0x18 /* memory base - apperture 1 */ -#define PCI_SUBSYS_VENDOR_WORD 0x2C /* subsystem vendor ID */ -#define PCI_INT_LINE_BYTE 0x3C /* interrupt line */ -#define PCI_INT_PIN_BYTE 0x3D /* interrupt pin */ -#define PCI_MAP0_DWORD 0x40 /* PCI to local bus address 0 */ -#define PCI_MAP1_DWORD 0x44 /* PCI to local bus address 1 */ -#define PCI_INT_STATUS 0x48 /* interrupt status */ -#define PCI_INT_CONFIG 0x4C /* interrupt configuration */ - -/* Local PCI register usage */ -#define PCI_MEMORY_ENABLE 0x00000003 /* enable PCI memory */ -#define PCI_CPU_A_MEM_DISABLE 0x00000002 /* disable CPU A memory */ -#define PCI_CPU_B_MEM_DISABLE 0x00100002 /* disable CPU B memory */ -#define PCI_ENABLE_IRQ_CPU_A 0x005A0004 /* enable IRQ for CPU A */ -#define PCI_ENABLE_IRQ_CPU_B 0x005A0008 /* enable IRQ for CPU B */ -#define PCI_DISABLE_IRQ_CPU_A 0x00000004 /* disable IRQ for CPU A */ -#define PCI_DISABLE_IRQ_CPU_B 0x00000008 /* disable IRQ for CPU B */ - -/* Setting for the Interrupt Status register */ -#define IRQ_CPU_A 0x04 /* IRQ for CPU A */ -#define IRQ_CPU_B 0x08 /* IRQ for CPU B */ - -/* The maximum size of the S514 memory */ -#define MAX_SIZEOF_S514_MEMORY (256 * 1024) - -/* S514 control register offsets within the memory address space */ -#define S514_CTRL_REG_BYTE 0x80000 - -/* S514 adapter control bytes */ -#define S514_CPU_HALT 0x00 -#define S514_CPU_START 0x01 - -/* The maximum number of S514 adapters supported */ -#define MAX_S514_CARDS 20 - -#define PCI_CARD_TYPE 0x2E -#define S514_DUAL_CPU 0x12 -#define S514_SINGLE_CPU 0x11 - -#endif /* _SDLAPCI_H */ - diff --git a/include/linux/sdlasfm.h b/include/linux/sdlasfm.h deleted file mode 100644 index 94aaa8ada667..000000000000 --- a/include/linux/sdlasfm.h +++ /dev/null @@ -1,104 +0,0 @@ -/***************************************************************************** -* sdlasfm.h WANPIPE(tm) Multiprotocol WAN Link Driver. -* Definitions for the SDLA Firmware Module (SFM). -* -* Author: Gideon Hack -* -* Copyright: (c) 1995-1999 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. -* ============================================================================ -* Jun 02, 1999 Gideon Hack Added support for the S514 adapter. -* Dec 11, 1996 Gene Kozin Cosmetic changes -* Apr 16, 1996 Gene Kozin Changed adapter & firmware IDs. Version 2 -* Dec 15, 1995 Gene Kozin Structures chaned -* Nov 09, 1995 Gene Kozin Initial version. -*****************************************************************************/ -#ifndef _SDLASFM_H -#define _SDLASFM_H - -/****** Defines *************************************************************/ - -#define SFM_VERSION 2 -#define SFM_SIGNATURE "SFM - Sangoma SDLA Firmware Module" - -/* min/max */ -#define SFM_IMAGE_SIZE 0x8000 /* max size of SDLA code image file */ -#define SFM_DESCR_LEN 256 /* max length of description string */ -#define SFM_MAX_SDLA 16 /* max number of compatible adapters */ - -/* Adapter types */ -#define SDLA_S502A 5020 -#define SDLA_S502E 5021 -#define SDLA_S503 5030 -#define SDLA_S508 5080 -#define SDLA_S507 5070 -#define SDLA_S509 5090 -#define SDLA_S514 5140 - -/* S514 PCI adapter CPU numbers */ -#define S514_CPU_A 'A' -#define S514_CPU_B 'B' - - -/* Firmware identification numbers: - * 0 .. 999 Test & Diagnostics - * 1000 .. 1999 Streaming HDLC - * 2000 .. 2999 Bisync - * 3000 .. 3999 SDLC - * 4000 .. 4999 HDLC - * 5000 .. 5999 X.25 - * 6000 .. 6999 Frame Relay - * 7000 .. 7999 PPP - * 8000 .. 8999 Cisco HDLC - */ -#define SFID_CALIB502 200 -#define SFID_STRM502 1200 -#define SFID_STRM508 1800 -#define SFID_BSC502 2200 -#define SFID_SDLC502 3200 -#define SFID_HDLC502 4200 -#define SFID_HDLC508 4800 -#define SFID_X25_502 5200 -#define SFID_X25_508 5800 -#define SFID_FR502 6200 -#define SFID_FR508 6800 -#define SFID_PPP502 7200 -#define SFID_PPP508 7800 -#define SFID_PPP514 7140 -#define SFID_CHDLC508 8800 -#define SFID_CHDLC514 8140 - -/****** Data Types **********************************************************/ - -typedef struct sfm_info /* firmware module information */ -{ - unsigned short codeid; /* firmware ID */ - unsigned short version; /* firmaware version number */ - unsigned short adapter[SFM_MAX_SDLA]; /* compatible adapter types */ - unsigned long memsize; /* minimum memory size */ - unsigned short reserved[2]; /* reserved */ - unsigned short startoffs; /* entry point offset */ - unsigned short winoffs; /* dual-port memory window offset */ - unsigned short codeoffs; /* code load offset */ - unsigned short codesize; /* code size */ - unsigned short dataoffs; /* configuration data load offset */ - unsigned short datasize; /* configuration data size */ -} sfm_info_t; - -typedef struct sfm /* SDLA firmware file structire */ -{ - char signature[80]; /* SFM file signature */ - unsigned short version; /* file format version */ - unsigned short checksum; /* info + image */ - unsigned short reserved[6]; /* reserved */ - char descr[SFM_DESCR_LEN]; /* description string */ - sfm_info_t info; /* firmware module info */ - unsigned char image[1]; /* code image (variable size) */ -} sfm_t; - -#endif /* _SDLASFM_H */ - diff --git a/include/linux/wanpipe.h b/include/linux/wanpipe.h deleted file mode 100644 index dae9860091dd..000000000000 --- a/include/linux/wanpipe.h +++ /dev/null @@ -1,483 +0,0 @@ -/***************************************************************************** -* wanpipe.h WANPIPE(tm) Multiprotocol WAN Link Driver. -* User-level API definitions. -* -* Author: Nenad Corbic -* Gideon Hack -* -* Copyright: (c) 1995-2000 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 3, 2000 Nenad Corbic Added config_id to sdla_t structure. -* Used to determine the protocol running. -* Jul 13, 2000 Nenad Corbic Added SyncPPP Support -* Feb 24, 2000 Nenad Corbic Added support for x25api driver -* Oct 04, 1999 Nenad Corbic New CHDLC and FRAME RELAY code, SMP support -* Jun 02, 1999 Gideon Hack Added 'update_call_count' for Cisco HDLC -* support -* Jun 26, 1998 David Fong Added 'ip_mode' in sdla_t.u.p for dynamic IP -* routing mode configuration -* Jun 12, 1998 David Fong Added Cisco HDLC union member in sdla_t -* Dec 08, 1997 Jaspreet Singh Added 'authenticator' in union of 'sdla_t' -* Nov 26, 1997 Jaspreet Singh Added 'load_sharing' structure. Also added -* 'devs_struct','dev_to_devtint_next' to 'sdla_t' -* Nov 24, 1997 Jaspreet Singh Added 'irq_dis_if_send_count', -* 'irq_dis_poll_count' to 'sdla_t'. -* Nov 06, 1997 Jaspreet Singh Added a define called 'INTR_TEST_MODE' -* Oct 20, 1997 Jaspreet Singh Added 'buff_intr_mode_unbusy' and -* 'dlci_intr_mode_unbusy' to 'sdla_t' -* Oct 18, 1997 Jaspreet Singh Added structure to maintain global driver -* statistics. -* Jan 15, 1997 Gene Kozin Version 3.1.0 -* o added UDP management stuff -* Jan 02, 1997 Gene Kozin Version 3.0.0 -*****************************************************************************/ -#ifndef _WANPIPE_H -#define _WANPIPE_H - -#include - -/* Defines */ - -#ifndef PACKED -#define PACKED __attribute__((packed)) -#endif - -#define WANPIPE_MAGIC 0x414C4453L /* signature: 'SDLA' reversed */ - -/* IOCTL numbers (up to 16) */ -#define WANPIPE_DUMP (ROUTER_USER+0) /* dump adapter's memory */ -#define WANPIPE_EXEC (ROUTER_USER+1) /* execute firmware command */ - -#define TRACE_ALL 0x00 -#define TRACE_PROT 0x01 -#define TRACE_DATA 0x02 - -/* values for request/reply byte */ -#define UDPMGMT_REQUEST 0x01 -#define UDPMGMT_REPLY 0x02 -#define UDP_OFFSET 12 - -#define MAX_CMD_BUFF 10 -#define MAX_X25_LCN 255 /* Maximum number of x25 channels */ -#define MAX_LCN_NUM 4095 /* Maximum lcn number */ -#define MAX_FT1_RETRY 100 - -#ifndef AF_WANPIPE - #define AF_WANPIPE 25 - #ifndef PF_WANPIPE - #define PF_WANPIPE AF_WANPIPE - #endif -#endif - - -#define TX_TIMEOUT 5*HZ - -/* General Critical Flags */ -#define SEND_CRIT 0x00 -#define PERI_CRIT 0x01 - -/* Chdlc and PPP polling critical flag */ -#define POLL_CRIT 0x03 - -/* Frame Relay Tx IRQ send critical flag */ -#define SEND_TXIRQ_CRIT 0x02 - -/* Frame Relay ARP critical flag */ -#define ARP_CRIT 0x03 - -/* Bit maps for dynamic interface configuration - * DYN_OPT_ON : turns this option on/off - * DEV_DOWN : device was shutdown by the driver not - * by user - */ -#define DYN_OPT_ON 0x00 -#define DEV_DOWN 0x01 - -/* - * Data structures for IOCTL calls. - */ - -typedef struct sdla_dump /* WANPIPE_DUMP */ -{ - unsigned long magic; /* for verification */ - unsigned long offset; /* absolute adapter memory address */ - unsigned long length; /* block length */ - void* ptr; /* -> buffer */ -} sdla_dump_t; - -typedef struct sdla_exec /* WANPIPE_EXEC */ -{ - unsigned long magic; /* for verification */ - void* cmd; /* -> command structure */ - void* data; /* -> data buffer */ -} sdla_exec_t; - -/* UDP management stuff */ - -typedef struct wum_header -{ - unsigned char signature[8]; /* 00h: signature */ - unsigned char type; /* 08h: request/reply */ - unsigned char command; /* 09h: commnand */ - unsigned char reserved[6]; /* 0Ah: reserved */ -} wum_header_t; - -/************************************************************************* - Data Structure for global statistics -*************************************************************************/ - -typedef struct global_stats -{ - unsigned long isr_entry; - unsigned long isr_already_critical; - unsigned long isr_rx; - unsigned long isr_tx; - unsigned long isr_intr_test; - unsigned long isr_spurious; - unsigned long isr_enable_tx_int; - unsigned long rx_intr_corrupt_rx_bfr; - unsigned long rx_intr_on_orphaned_DLCI; - unsigned long rx_intr_dev_not_started; - unsigned long tx_intr_dev_not_started; - unsigned long poll_entry; - unsigned long poll_already_critical; - unsigned long poll_processed; - unsigned long poll_tbusy_bad_status; - unsigned long poll_host_disable_irq; - unsigned long poll_host_enable_irq; - -} global_stats_t; - - -typedef struct{ - unsigned short udp_src_port PACKED; - unsigned short udp_dst_port PACKED; - unsigned short udp_length PACKED; - unsigned short udp_checksum PACKED; -} udp_pkt_t; - - -typedef struct { - unsigned char ver_inet_hdr_length PACKED; - unsigned char service_type PACKED; - unsigned short total_length PACKED; - unsigned short identifier PACKED; - unsigned short flags_frag_offset PACKED; - unsigned char ttl PACKED; - unsigned char protocol PACKED; - unsigned short hdr_checksum PACKED; - unsigned long ip_src_address PACKED; - unsigned long ip_dst_address PACKED; -} ip_pkt_t; - - -typedef struct { - unsigned char signature[8] PACKED; - unsigned char request_reply PACKED; - unsigned char id PACKED; - unsigned char reserved[6] PACKED; -} wp_mgmt_t; - -/************************************************************************* - Data Structure for if_send statistics -*************************************************************************/ -typedef struct if_send_stat{ - 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_tbusy; - unsigned long if_send_tbusy_timeout; - unsigned long if_send_PIPE_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_bfr_passed_to_adptr; - unsigned long if_send_protocol_error; - unsigned long if_send_bfr_not_passed_to_adptr; - unsigned long if_send_tx_int_enabled; - unsigned long if_send_consec_send_fail; -} if_send_stat_t; - -typedef struct rx_intr_stat{ - unsigned long rx_intr_no_socket; - unsigned long rx_intr_dev_not_started; - unsigned long rx_intr_PIPE_request; - unsigned long rx_intr_bfr_not_passed_to_stack; - unsigned long rx_intr_bfr_passed_to_stack; -} rx_intr_stat_t; - -typedef struct pipe_mgmt_stat{ - unsigned long UDP_PIPE_mgmt_kmalloc_err; - unsigned long UDP_PIPE_mgmt_direction_err; - unsigned long UDP_PIPE_mgmt_adptr_type_err; - unsigned long UDP_PIPE_mgmt_adptr_cmnd_OK; - unsigned long UDP_PIPE_mgmt_adptr_cmnd_timeout; - unsigned long UDP_PIPE_mgmt_adptr_send_passed; - unsigned long UDP_PIPE_mgmt_adptr_send_failed; - unsigned long UDP_PIPE_mgmt_not_passed_to_stack; - unsigned long UDP_PIPE_mgmt_passed_to_stack; - unsigned long UDP_PIPE_mgmt_no_socket; - unsigned long UDP_PIPE_mgmt_passed_to_adptr; -} pipe_mgmt_stat_t; - - -typedef struct { - struct sk_buff *skb; -} bh_data_t, cmd_data_t; - -#define MAX_LGTH_UDP_MGNT_PKT 2000 - - -/* This is used for interrupt testing */ -#define INTR_TEST_MODE 0x02 - -#define WUM_SIGNATURE_L 0x50495046 -#define WUM_SIGNATURE_H 0x444E3845 - -#define WUM_KILL 0x50 -#define WUM_EXEC 0x51 - -#define WANPIPE 0x00 -#define API 0x01 -#define BRIDGE 0x02 -#define BRIDGE_NODE 0x03 - -#ifdef __KERNEL__ -/****** Kernel Interface ****************************************************/ - -#include /* SDLA support module API definitions */ -#include /* SDLA firmware module definitions */ -#include -#include -#include -#include -#include -#include -#include -#include - -/****** Data Structures *****************************************************/ - -/* Adapter Data Space. - * This structure is needed because we handle multiple cards, otherwise - * static data would do it. - */ -typedef struct sdla -{ - char devname[WAN_DRVNAME_SZ+1]; /* card name */ - sdlahw_t hw; /* hardware configuration */ - struct wan_device wandev; /* WAN device data space */ - - unsigned open_cnt; /* number of open interfaces */ - unsigned long state_tick; /* link state timestamp */ - unsigned intr_mode; /* Type of Interrupt Mode */ - char in_isr; /* interrupt-in-service flag */ - char buff_int_mode_unbusy; /* flag for carrying out dev_tint */ - char dlci_int_mode_unbusy; /* flag for carrying out dev_tint */ - long configured; /* flag for previous configurations */ - - unsigned short irq_dis_if_send_count; /* Disabling irqs in if_send*/ - unsigned short irq_dis_poll_count; /* Disabling irqs in poll routine*/ - unsigned short force_enable_irq; - char TracingEnabled; /* flag for enabling trace */ - global_stats_t statistics; /* global statistics */ - void* mbox; /* -> mailbox */ - void* rxmb; /* -> receive mailbox */ - void* flags; /* -> adapter status flags */ - void (*isr)(struct sdla* card); /* interrupt service routine */ - void (*poll)(struct sdla* card); /* polling routine */ - int (*exec)(struct sdla* card, void* u_cmd, void* u_data); - /* Used by the listen() system call */ - /* Wanpipe Socket Interface */ - int (*func) (struct sk_buff *, struct sock *); - struct sock *sk; - - /* Shutdown function */ - void (*disable_comm) (struct sdla *card); - - /* Secondary Port Device: Piggibacking */ - struct sdla *next; - - /* TTY driver variables */ - unsigned char tty_opt; - struct tty_struct *tty; - unsigned int tty_minor; - unsigned int tty_open; - unsigned char *tty_buf; - unsigned char *tty_rx; - struct work_struct tty_work; - - union - { - struct - { /****** X.25 specific data **********/ - u32 lo_pvc; - u32 hi_pvc; - u32 lo_svc; - u32 hi_svc; - struct net_device *svc_to_dev_map[MAX_X25_LCN]; - struct net_device *pvc_to_dev_map[MAX_X25_LCN]; - struct net_device *tx_dev; - struct net_device *cmd_dev; - u32 no_dev; - volatile u8 *hdlc_buf_status; - u32 tx_interrupts_pending; - u16 timer_int_enabled; - struct net_device *poll_device; - atomic_t command_busy; - - u16 udp_pkt_lgth; - u32 udp_type; - u8 udp_pkt_src; - u32 udp_lcn; - struct net_device *udp_dev; - s8 udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; - - u8 LAPB_hdlc; /* Option to turn off X25 and run only LAPB */ - u8 logging; /* Option to log call messages */ - u8 oob_on_modem; /* Option to send modem status to the api */ - u16 num_of_ch; /* Number of channels configured by the user */ - - struct work_struct x25_poll_work; - struct timer_list x25_timer; - } x; - struct - { /****** frame relay specific data ***/ - void* rxmb_base; /* -> first Rx buffer */ - void* rxmb_last; /* -> last Rx buffer */ - unsigned rx_base; /* S508 receive buffer base */ - unsigned rx_top; /* S508 receive buffer end */ - unsigned short node_dlci[100]; - unsigned short dlci_num; - struct net_device *dlci_to_dev_map[991 + 1]; - unsigned tx_interrupts_pending; - unsigned short timer_int_enabled; - unsigned short udp_pkt_lgth; - int udp_type; - char udp_pkt_src; - unsigned udp_dlci; - char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; - void* trc_el_base; /* first trace element */ - void* trc_el_last; /* last trace element */ - void *curr_trc_el; /* current trace element */ - unsigned short trc_bfr_space; /* trace buffer space */ - unsigned char update_comms_stats; - struct net_device *arp_dev; - spinlock_t if_send_lock; - } f; - struct /****** PPP-specific data ***********/ - { - char if_name[WAN_IFNAME_SZ+1]; /* interface name */ - void* txbuf; /* -> current Tx buffer */ - void* txbuf_base; /* -> first Tx buffer */ - void* txbuf_last; /* -> last Tx buffer */ - void* rxbuf_base; /* -> first Rx buffer */ - void* rxbuf_last; /* -> last Rx buffer */ - unsigned rx_base; /* S508 receive buffer base */ - unsigned rx_top; /* S508 receive buffer end */ - char ip_mode; /* STATIC/HOST/PEER IP Mode */ - char authenticator; /* Authenticator for PAP/CHAP */ - unsigned char comm_enabled; /* Is comm enabled or not */ - unsigned char peer_route; /* Process Peer Route */ - unsigned long *txbuf_next; /* Next Tx buffer to use */ - unsigned long *rxbuf_next; /* Next Rx buffer to use */ - } p; - struct /* Cisco HDLC-specific data */ - { - char if_name[WAN_IFNAME_SZ+1]; /* interface name */ - unsigned char comm_port;/* Communication Port O or 1 */ - unsigned char usedby; /* Used by WANPIPE or API */ - void* rxmb; /* Receive mail box */ - void* flags; /* flags */ - void* tx_status; /* Tx status element */ - void* rx_status; /* Rx status element */ - void* txbuf; /* -> current Tx buffer */ - void* txbuf_base; /* -> first Tx buffer */ - void* txbuf_last; /* -> last Tx buffer */ - void* rxbuf_base; /* -> first Rx buffer */ - void* rxbuf_last; /* -> last Rx buffer */ - unsigned rx_base; /* S508 receive buffer base */ - unsigned rx_top; /* S508 receive buffer end */ - unsigned char receive_only; /* high speed receivers */ - unsigned short protocol_options; - unsigned short kpalv_tx; /* Tx kpalv timer */ - unsigned short kpalv_rx; /* Rx kpalv timer */ - unsigned short kpalv_err; /* Error tolerance */ - unsigned short slarp_timer; /* SLARP req timer */ - unsigned state; /* state of the link */ - unsigned char api_status; - unsigned char update_call_count; - unsigned short api_options; /* for async config */ - unsigned char async_mode; - unsigned short tx_bits_per_char; - unsigned short rx_bits_per_char; - unsigned short stop_bits; - unsigned short parity; - unsigned short break_timer; - unsigned short inter_char_timer; - unsigned short rx_complete_length; - unsigned short xon_char; - unsigned short xoff_char; - unsigned char comm_enabled; /* Is comm enabled or not */ - unsigned char backup; - } c; - struct - { - void* tx_status; /* Tx status element */ - void* rx_status; /* Rx status element */ - void* trace_status; /* Trace status element */ - void* txbuf; /* -> current Tx buffer */ - void* txbuf_base; /* -> first Tx buffer */ - void* txbuf_last; /* -> last Tx buffer */ - void* rxbuf_base; /* -> first Rx buffer */ - void* rxbuf_last; /* -> last Rx buffer */ - void* tracebuf; /* -> current Trace buffer */ - void* tracebuf_base; /* -> current Trace buffer */ - void* tracebuf_last; /* -> current Trace buffer */ - unsigned rx_base; /* receive buffer base */ - unsigned rx_end; /* receive buffer end */ - unsigned trace_base; /* trace buffer base */ - unsigned trace_end; /* trace buffer end */ - - } h; - } u; -} sdla_t; - -/****** Public Functions ****************************************************/ - -void wanpipe_open (sdla_t* card); /* wpmain.c */ -void wanpipe_close (sdla_t* card); /* wpmain.c */ -void wanpipe_set_state (sdla_t* card, int state); /* wpmain.c */ - -int wpx_init (sdla_t* card, wandev_conf_t* conf); /* wpx.c */ -int wpf_init (sdla_t* card, wandev_conf_t* conf); /* wpf.c */ -int wpp_init (sdla_t* card, wandev_conf_t* conf); /* wpp.c */ -int wpc_init (sdla_t* card, wandev_conf_t* conf); /* Cisco HDLC */ -int bsc_init (sdla_t* card, wandev_conf_t* conf); /* BSC streaming */ -int hdlc_init(sdla_t* card, wandev_conf_t* conf); /* HDLC support */ -int wpft1_init (sdla_t* card, wandev_conf_t* conf); /* FT1 Config support */ -int wsppp_init (sdla_t* card, wandev_conf_t* conf); /* Sync PPP on top of RAW CHDLC */ - -extern sdla_t * wanpipe_find_card(char *); -extern sdla_t * wanpipe_find_card_num (int); - -extern void wanpipe_queue_work (struct work_struct *); -extern void wanpipe_mark_bh (void); -extern void wakeup_sk_bh(struct net_device *dev); -extern int change_dev_flags(struct net_device *dev, unsigned flags); -extern unsigned long get_ip_address(struct net_device *dev, int option); -extern void add_gateway(sdla_t *card, struct net_device *dev); - - -#endif /* __KERNEL__ */ -#endif /* _WANPIPE_H */ - diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c index 8b9bf4a763b5..b1265187b4a8 100644 --- a/net/wanrouter/af_wanpipe.c +++ b/net/wanrouter/af_wanpipe.c @@ -55,12 +55,10 @@ #include #include #include -#include #include #include #include #include -#include #ifdef CONFIG_INET #include -- cgit v1.2.3 From 21b2f0c803adaf00fce1b606c50b49ae8b106773 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 22 Mar 2006 17:52:04 +0100 Subject: [SCSI] unify SCSI_IOCTL_SEND_COMMAND implementations We currently have two implementations of this obsolete ioctl, one in the block layer and one in the scsi code. Both of them have drawbacks. This patch kills the scsi layer version after updating the block version with the missing bits: - argument checking - use scatterlist I/O - set number of retries based on the submitted command This is the last user of non-S/G I/O except for the gdth driver, so getting this in ASAP and through the scsi tree would be nie to kill the non-S/G I/O path. Jens, what do you think about adding a check for non-S/G I/O in the midlayer? Thanks to Or Gerlitz for testing this patch. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- block/scsi_ioctl.c | 101 ++++++++++++++++++-------- drivers/scsi/scsi_ioctl.c | 176 +--------------------------------------------- drivers/scsi/sg.c | 2 +- include/linux/blkdev.h | 4 ++ include/scsi/scsi_ioctl.h | 2 - 5 files changed, 78 insertions(+), 207 deletions(-) (limited to 'include/linux') diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 24f7af9d0abc..b33eda26e205 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -350,16 +350,51 @@ out: return ret; } +/** + * sg_scsi_ioctl -- handle deprecated SCSI_IOCTL_SEND_COMMAND ioctl + * @file: file this ioctl operates on (optional) + * @q: request queue to send scsi commands down + * @disk: gendisk to operate on (option) + * @sic: userspace structure describing the command to perform + * + * Send down the scsi command described by @sic to the device below + * the request queue @q. If @file is non-NULL it's used to perform + * fine-grained permission checks that allow users to send down + * non-destructive SCSI commands. If the caller has a struct gendisk + * available it should be passed in as @disk to allow the low level + * driver to use the information contained in it. A non-NULL @disk + * is only allowed if the caller knows that the low level driver doesn't + * need it (e.g. in the scsi subsystem). + * + * Notes: + * - This interface is deprecated - users should use the SG_IO + * interface instead, as this is a more flexible approach to + * performing SCSI commands on a device. + * - The SCSI command length is determined by examining the 1st byte + * of the given command. There is no way to override this. + * - Data transfers are limited to PAGE_SIZE + * - The length (x + y) must be at least OMAX_SB_LEN bytes long to + * accommodate the sense buffer when an error occurs. + * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that + * old code will not be surprised. + * - If a Unix error occurs (e.g. ENOMEM) then the user will receive + * a negative return and the Unix error code in 'errno'. + * If the SCSI command succeeds then 0 is returned. + * Positive numbers returned are the compacted SCSI error codes (4 + * bytes in one int) where the lowest byte is the SCSI status. + */ #define OMAX_SB_LEN 16 /* For backward compatibility */ - -static int sg_scsi_ioctl(struct file *file, request_queue_t *q, - struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic) +int sg_scsi_ioctl(struct file *file, struct request_queue *q, + struct gendisk *disk, struct scsi_ioctl_command __user *sic) { struct request *rq; int err; unsigned int in_len, out_len, bytes, opcode, cmdlen; char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; + if (!sic) + return -EINVAL; + /* * get in an out lengths, verify they don't exceed a page worth of data */ @@ -393,45 +428,53 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q, if (copy_from_user(rq->cmd, sic->data, cmdlen)) goto error; - if (copy_from_user(buffer, sic->data + cmdlen, in_len)) + if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) goto error; err = verify_command(file, rq->cmd); if (err) goto error; + /* default. possible overriden later */ + rq->retries = 5; + switch (opcode) { - case SEND_DIAGNOSTIC: - case FORMAT_UNIT: - rq->timeout = FORMAT_UNIT_TIMEOUT; - break; - case START_STOP: - rq->timeout = START_STOP_TIMEOUT; - break; - case MOVE_MEDIUM: - rq->timeout = MOVE_MEDIUM_TIMEOUT; - break; - case READ_ELEMENT_STATUS: - rq->timeout = READ_ELEMENT_STATUS_TIMEOUT; - break; - case READ_DEFECT_DATA: - rq->timeout = READ_DEFECT_DATA_TIMEOUT; - break; - default: - rq->timeout = BLK_DEFAULT_TIMEOUT; - break; + case SEND_DIAGNOSTIC: + case FORMAT_UNIT: + rq->timeout = FORMAT_UNIT_TIMEOUT; + rq->retries = 1; + break; + case START_STOP: + rq->timeout = START_STOP_TIMEOUT; + break; + case MOVE_MEDIUM: + rq->timeout = MOVE_MEDIUM_TIMEOUT; + break; + case READ_ELEMENT_STATUS: + rq->timeout = READ_ELEMENT_STATUS_TIMEOUT; + break; + case READ_DEFECT_DATA: + rq->timeout = READ_DEFECT_DATA_TIMEOUT; + rq->retries = 1; + break; + default: + rq->timeout = BLK_DEFAULT_TIMEOUT; + break; + } + + if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) { + err = DRIVER_ERROR << 24; + goto out; } memset(sense, 0, sizeof(sense)); rq->sense = sense; rq->sense_len = 0; - - rq->data = buffer; - rq->data_len = bytes; rq->flags |= REQ_BLOCK_PC; - rq->retries = 0; - blk_execute_rq(q, bd_disk, rq, 0); + blk_execute_rq(q, disk, rq, 0); + +out: err = rq->errors & 0xff; /* only 8 bit SCSI status */ if (err) { if (rq->sense_len && rq->sense) { @@ -450,7 +493,7 @@ error: blk_put_request(rq); return err; } - +EXPORT_SYMBOL_GPL(sg_scsi_ioctl); /* Send basic block requests */ static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data) diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 36e930066649..a89aff61d3d8 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -157,180 +157,6 @@ int scsi_set_medium_removal(struct scsi_device *sdev, char state) } EXPORT_SYMBOL(scsi_set_medium_removal); -/* - * This interface is deprecated - users should use the scsi generic (sg) - * interface instead, as this is a more flexible approach to performing - * generic SCSI commands on a device. - * - * The structure that we are passed should look like: - * - * struct sdata { - * unsigned int inlen; [i] Length of data to be written to device - * unsigned int outlen; [i] Length of data to be read from device - * unsigned char cmd[x]; [i] SCSI command (6 <= x <= 12). - * [o] Data read from device starts here. - * [o] On error, sense buffer starts here. - * unsigned char wdata[y]; [i] Data written to device starts here. - * }; - * Notes: - * - The SCSI command length is determined by examining the 1st byte - * of the given command. There is no way to override this. - * - Data transfers are limited to PAGE_SIZE (4K on i386, 8K on alpha). - * - The length (x + y) must be at least OMAX_SB_LEN bytes long to - * accommodate the sense buffer when an error occurs. - * The sense buffer is truncated to OMAX_SB_LEN (16) bytes so that - * old code will not be surprised. - * - If a Unix error occurs (e.g. ENOMEM) then the user will receive - * a negative return and the Unix error code in 'errno'. - * If the SCSI command succeeds then 0 is returned. - * Positive numbers returned are the compacted SCSI error codes (4 - * bytes in one int) where the lowest byte is the SCSI status. - * See the drivers/scsi/scsi.h file for more information on this. - * - */ -#define OMAX_SB_LEN 16 /* Old sense buffer length */ - -int scsi_ioctl_send_command(struct scsi_device *sdev, - struct scsi_ioctl_command __user *sic) -{ - char *buf; - unsigned char cmd[MAX_COMMAND_SIZE]; - unsigned char sense[SCSI_SENSE_BUFFERSIZE]; - char __user *cmd_in; - unsigned char opcode; - unsigned int inlen, outlen, cmdlen; - unsigned int needed, buf_needed; - int timeout, retries, result; - int data_direction; - gfp_t gfp_mask = GFP_KERNEL; - - if (!sic) - return -EINVAL; - - if (sdev->host->unchecked_isa_dma) - gfp_mask |= GFP_DMA; - - /* - * Verify that we can read at least this much. - */ - if (!access_ok(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command))) - return -EFAULT; - - if(__get_user(inlen, &sic->inlen)) - return -EFAULT; - - if(__get_user(outlen, &sic->outlen)) - return -EFAULT; - - /* - * We do not transfer more than MAX_BUF with this interface. - * If the user needs to transfer more data than this, they - * should use scsi_generics (sg) instead. - */ - if (inlen > MAX_BUF) - return -EINVAL; - if (outlen > MAX_BUF) - return -EINVAL; - - cmd_in = sic->data; - if(get_user(opcode, cmd_in)) - return -EFAULT; - - needed = buf_needed = (inlen > outlen ? inlen : outlen); - if (buf_needed) { - buf_needed = (buf_needed + 511) & ~511; - if (buf_needed > MAX_BUF) - buf_needed = MAX_BUF; - buf = kzalloc(buf_needed, gfp_mask); - if (!buf) - return -ENOMEM; - if (inlen == 0) { - data_direction = DMA_FROM_DEVICE; - } else if (outlen == 0 ) { - data_direction = DMA_TO_DEVICE; - } else { - /* - * Can this ever happen? - */ - data_direction = DMA_BIDIRECTIONAL; - } - - } else { - buf = NULL; - data_direction = DMA_NONE; - } - - /* - * Obtain the command from the user's address space. - */ - cmdlen = COMMAND_SIZE(opcode); - - result = -EFAULT; - - if (!access_ok(VERIFY_READ, cmd_in, cmdlen + inlen)) - goto error; - - if(__copy_from_user(cmd, cmd_in, cmdlen)) - goto error; - - /* - * Obtain the data to be sent to the device (if any). - */ - - if(inlen && copy_from_user(buf, cmd_in + cmdlen, inlen)) - goto error; - - switch (opcode) { - case SEND_DIAGNOSTIC: - case FORMAT_UNIT: - timeout = FORMAT_UNIT_TIMEOUT; - retries = 1; - break; - case START_STOP: - timeout = START_STOP_TIMEOUT; - retries = NORMAL_RETRIES; - break; - case MOVE_MEDIUM: - timeout = MOVE_MEDIUM_TIMEOUT; - retries = NORMAL_RETRIES; - break; - case READ_ELEMENT_STATUS: - timeout = READ_ELEMENT_STATUS_TIMEOUT; - retries = NORMAL_RETRIES; - break; - case READ_DEFECT_DATA: - timeout = READ_DEFECT_DATA_TIMEOUT; - retries = 1; - break; - default: - timeout = IOCTL_NORMAL_TIMEOUT; - retries = NORMAL_RETRIES; - break; - } - - result = scsi_execute(sdev, cmd, data_direction, buf, needed, - sense, timeout, retries, 0); - - /* - * If there was an error condition, pass the info back to the user. - */ - if (result) { - int sb_len = sizeof(*sense); - - sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; - if (copy_to_user(cmd_in, sense, sb_len)) - result = -EFAULT; - } else { - if (outlen && copy_to_user(cmd_in, buf, outlen)) - result = -EFAULT; - } - -error: - kfree(buf); - return result; -} -EXPORT_SYMBOL(scsi_ioctl_send_command); - /* * The scsi_ioctl_get_pci() function places into arg the value * pci_dev::slot_name (8 characters) for the PCI device (if any). @@ -409,7 +235,7 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) case SCSI_IOCTL_SEND_COMMAND: if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - return scsi_ioctl_send_command(sdev, arg); + return sg_scsi_ioctl(NULL, sdev->request_queue, NULL, arg); case SCSI_IOCTL_DOORLOCK: return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); case SCSI_IOCTL_DOORUNLOCK: diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 7405d0df95db..fcf9243dfa7d 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1044,7 +1044,7 @@ sg_ioctl(struct inode *inode, struct file *filp, if (!sg_allow_access(opcode, sdp->device->type)) return -EPERM; } - return scsi_ioctl_send_command(sdp->device, p); + return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p); case SG_SET_DEBUG: result = get_user(val, ip); if (result) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d0cac8b58de7..59e1259b1c40 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -17,6 +17,8 @@ #include +struct scsi_ioctl_command; + struct request_queue; typedef struct request_queue request_queue_t; struct elevator_queue; @@ -611,6 +613,8 @@ extern void blk_plug_device(request_queue_t *); extern int blk_remove_plug(request_queue_t *); extern void blk_recount_segments(request_queue_t *, struct bio *); extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *); +extern int sg_scsi_ioctl(struct file *, struct request_queue *, + struct gendisk *, struct scsi_ioctl_command __user *); extern void blk_start_queue(request_queue_t *q); extern void blk_stop_queue(request_queue_t *q); extern void blk_sync_queue(struct request_queue *q); diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h index d4be4d92d586..edb9525386da 100644 --- a/include/scsi/scsi_ioctl.h +++ b/include/scsi/scsi_ioctl.h @@ -41,8 +41,6 @@ typedef struct scsi_fctargaddress { } Scsi_FCTargAddress; extern int scsi_ioctl(struct scsi_device *, int, void __user *); -extern int scsi_ioctl_send_command(struct scsi_device *, - struct scsi_ioctl_command __user *); extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, void __user *arg, struct file *filp); -- cgit v1.2.3 From 9fc4831cc3e063019079581ff5062f9790d9b0c7 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Sun, 2 Apr 2006 10:21:26 -0800 Subject: [PATCH] USB: linux/usb/net2280.h common definitions Move common definitions for NET2280 to , so that I can use them in prism54usb (it is not merged yet, but I plan to do it soon). Signed-off-by: Pete Zaitcev Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/net2280.h | 417 +--------------------------------------- include/linux/usb/net2280.h | 444 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 445 insertions(+), 416 deletions(-) create mode 100644 include/linux/usb/net2280.h (limited to 'include/linux') diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h index e195abec8d7f..957d6df34015 100644 --- a/drivers/usb/gadget/net2280.h +++ b/drivers/usb/gadget/net2280.h @@ -22,422 +22,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/*-------------------------------------------------------------------------*/ - -/* NET2280 MEMORY MAPPED REGISTERS - * - * The register layout came from the chip documentation, and the bit - * number definitions were extracted from chip specification. - * - * Use the shift operator ('<<') to build bit masks, with readl/writel - * to access the registers through PCI. - */ - -/* main registers, BAR0 + 0x0000 */ -struct net2280_regs { - // offset 0x0000 - u32 devinit; -#define LOCAL_CLOCK_FREQUENCY 8 -#define FORCE_PCI_RESET 7 -#define PCI_ID 6 -#define PCI_ENABLE 5 -#define FIFO_SOFT_RESET 4 -#define CFG_SOFT_RESET 3 -#define PCI_SOFT_RESET 2 -#define USB_SOFT_RESET 1 -#define M8051_RESET 0 - u32 eectl; -#define EEPROM_ADDRESS_WIDTH 23 -#define EEPROM_CHIP_SELECT_ACTIVE 22 -#define EEPROM_PRESENT 21 -#define EEPROM_VALID 20 -#define EEPROM_BUSY 19 -#define EEPROM_CHIP_SELECT_ENABLE 18 -#define EEPROM_BYTE_READ_START 17 -#define EEPROM_BYTE_WRITE_START 16 -#define EEPROM_READ_DATA 8 -#define EEPROM_WRITE_DATA 0 - u32 eeclkfreq; - u32 _unused0; - // offset 0x0010 - - u32 pciirqenb0; /* interrupt PCI master ... */ -#define SETUP_PACKET_INTERRUPT_ENABLE 7 -#define ENDPOINT_F_INTERRUPT_ENABLE 6 -#define ENDPOINT_E_INTERRUPT_ENABLE 5 -#define ENDPOINT_D_INTERRUPT_ENABLE 4 -#define ENDPOINT_C_INTERRUPT_ENABLE 3 -#define ENDPOINT_B_INTERRUPT_ENABLE 2 -#define ENDPOINT_A_INTERRUPT_ENABLE 1 -#define ENDPOINT_0_INTERRUPT_ENABLE 0 - u32 pciirqenb1; -#define PCI_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - u32 cpu_irqenb0; /* ... or onboard 8051 */ -#define SETUP_PACKET_INTERRUPT_ENABLE 7 -#define ENDPOINT_F_INTERRUPT_ENABLE 6 -#define ENDPOINT_E_INTERRUPT_ENABLE 5 -#define ENDPOINT_D_INTERRUPT_ENABLE 4 -#define ENDPOINT_C_INTERRUPT_ENABLE 3 -#define ENDPOINT_B_INTERRUPT_ENABLE 2 -#define ENDPOINT_A_INTERRUPT_ENABLE 1 -#define ENDPOINT_0_INTERRUPT_ENABLE 0 - u32 cpu_irqenb1; -#define CPU_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_INTA_INTERRUPT_ENABLE 24 -#define PCI_PME_INTERRUPT_ENABLE 23 -#define PCI_SERR_INTERRUPT_ENABLE 22 -#define PCI_PERR_INTERRUPT_ENABLE 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - - // offset 0x0020 - u32 _unused1; - u32 usbirqenb1; -#define USB_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_INTA_INTERRUPT_ENABLE 24 -#define PCI_PME_INTERRUPT_ENABLE 23 -#define PCI_SERR_INTERRUPT_ENABLE 22 -#define PCI_PERR_INTERRUPT_ENABLE 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - u32 irqstat0; -#define INTA_ASSERTED 12 -#define SETUP_PACKET_INTERRUPT 7 -#define ENDPOINT_F_INTERRUPT 6 -#define ENDPOINT_E_INTERRUPT 5 -#define ENDPOINT_D_INTERRUPT 4 -#define ENDPOINT_C_INTERRUPT 3 -#define ENDPOINT_B_INTERRUPT 2 -#define ENDPOINT_A_INTERRUPT 1 -#define ENDPOINT_0_INTERRUPT 0 - u32 irqstat1; -#define POWER_STATE_CHANGE_INTERRUPT 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT 26 -#define PCI_PARITY_ERROR_INTERRUPT 25 -#define PCI_INTA_INTERRUPT 24 -#define PCI_PME_INTERRUPT 23 -#define PCI_SERR_INTERRUPT 22 -#define PCI_PERR_INTERRUPT 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19 -#define PCI_RETRY_ABORT_INTERRUPT 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16 -#define SOF_DOWN_INTERRUPT 14 -#define GPIO_INTERRUPT 13 -#define DMA_D_INTERRUPT 12 -#define DMA_C_INTERRUPT 11 -#define DMA_B_INTERRUPT 10 -#define DMA_A_INTERRUPT 9 -#define EEPROM_DONE_INTERRUPT 8 -#define VBUS_INTERRUPT 7 -#define CONTROL_STATUS_INTERRUPT 6 -#define ROOT_PORT_RESET_INTERRUPT 4 -#define SUSPEND_REQUEST_INTERRUPT 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2 -#define RESUME_INTERRUPT 1 -#define SOF_INTERRUPT 0 - // offset 0x0030 - u32 idxaddr; - u32 idxdata; - u32 fifoctl; -#define PCI_BASE2_RANGE 16 -#define IGNORE_FIFO_AVAILABILITY 3 -#define PCI_BASE2_SELECT 2 -#define FIFO_CONFIGURATION_SELECT 0 - u32 _unused2; - // offset 0x0040 - u32 memaddr; -#define START 28 -#define DIRECTION 27 -#define FIFO_DIAGNOSTIC_SELECT 24 -#define MEMORY_ADDRESS 0 - u32 memdata0; - u32 memdata1; - u32 _unused3; - // offset 0x0050 - u32 gpioctl; -#define GPIO3_LED_SELECT 12 -#define GPIO3_INTERRUPT_ENABLE 11 -#define GPIO2_INTERRUPT_ENABLE 10 -#define GPIO1_INTERRUPT_ENABLE 9 -#define GPIO0_INTERRUPT_ENABLE 8 -#define GPIO3_OUTPUT_ENABLE 7 -#define GPIO2_OUTPUT_ENABLE 6 -#define GPIO1_OUTPUT_ENABLE 5 -#define GPIO0_OUTPUT_ENABLE 4 -#define GPIO3_DATA 3 -#define GPIO2_DATA 2 -#define GPIO1_DATA 1 -#define GPIO0_DATA 0 - u32 gpiostat; -#define GPIO3_INTERRUPT 3 -#define GPIO2_INTERRUPT 2 -#define GPIO1_INTERRUPT 1 -#define GPIO0_INTERRUPT 0 -} __attribute__ ((packed)); - -/* usb control, BAR0 + 0x0080 */ -struct net2280_usb_regs { - // offset 0x0080 - u32 stdrsp; -#define STALL_UNSUPPORTED_REQUESTS 31 -#define SET_TEST_MODE 16 -#define GET_OTHER_SPEED_CONFIGURATION 15 -#define GET_DEVICE_QUALIFIER 14 -#define SET_ADDRESS 13 -#define ENDPOINT_SET_CLEAR_HALT 12 -#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11 -#define GET_STRING_DESCRIPTOR_2 10 -#define GET_STRING_DESCRIPTOR_1 9 -#define GET_STRING_DESCRIPTOR_0 8 -#define GET_SET_INTERFACE 6 -#define GET_SET_CONFIGURATION 5 -#define GET_CONFIGURATION_DESCRIPTOR 4 -#define GET_DEVICE_DESCRIPTOR 3 -#define GET_ENDPOINT_STATUS 2 -#define GET_INTERFACE_STATUS 1 -#define GET_DEVICE_STATUS 0 - u32 prodvendid; -#define PRODUCT_ID 16 -#define VENDOR_ID 0 - u32 relnum; - u32 usbctl; -#define SERIAL_NUMBER_INDEX 16 -#define PRODUCT_ID_STRING_ENABLE 13 -#define VENDOR_ID_STRING_ENABLE 12 -#define USB_ROOT_PORT_WAKEUP_ENABLE 11 -#define VBUS_PIN 10 -#define TIMED_DISCONNECT 9 -#define SUSPEND_IMMEDIATELY 7 -#define SELF_POWERED_USB_DEVICE 6 -#define REMOTE_WAKEUP_SUPPORT 5 -#define PME_POLARITY 4 -#define USB_DETECT_ENABLE 3 -#define PME_WAKEUP_ENABLE 2 -#define DEVICE_REMOTE_WAKEUP_ENABLE 1 -#define SELF_POWERED_STATUS 0 - // offset 0x0090 - u32 usbstat; -#define HIGH_SPEED 7 -#define FULL_SPEED 6 -#define GENERATE_RESUME 5 -#define GENERATE_DEVICE_REMOTE_WAKEUP 4 - u32 xcvrdiag; -#define FORCE_HIGH_SPEED_MODE 31 -#define FORCE_FULL_SPEED_MODE 30 -#define USB_TEST_MODE 24 -#define LINE_STATE 16 -#define TRANSCEIVER_OPERATION_MODE 2 -#define TRANSCEIVER_SELECT 1 -#define TERMINATION_SELECT 0 - u32 setup0123; - u32 setup4567; - // offset 0x0090 - u32 _unused0; - u32 ouraddr; -#define FORCE_IMMEDIATE 7 -#define OUR_USB_ADDRESS 0 - u32 ourconfig; -} __attribute__ ((packed)); - -/* pci control, BAR0 + 0x0100 */ -struct net2280_pci_regs { - // offset 0x0100 - u32 pcimstctl; -#define PCI_ARBITER_PARK_SELECT 13 -#define PCI_MULTI LEVEL_ARBITER 12 -#define PCI_RETRY_ABORT_ENABLE 11 -#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10 -#define DMA_READ_MULTIPLE_ENABLE 9 -#define DMA_READ_LINE_ENABLE 8 -#define PCI_MASTER_COMMAND_SELECT 6 -#define MEM_READ_OR_WRITE 0 -#define IO_READ_OR_WRITE 1 -#define CFG_READ_OR_WRITE 2 -#define PCI_MASTER_START 5 -#define PCI_MASTER_READ_WRITE 4 -#define PCI_MASTER_WRITE 0 -#define PCI_MASTER_READ 1 -#define PCI_MASTER_BYTE_WRITE_ENABLES 0 - u32 pcimstaddr; - u32 pcimstdata; - u32 pcimststat; -#define PCI_ARBITER_CLEAR 2 -#define PCI_EXTERNAL_ARBITER 1 -#define PCI_HOST_MODE 0 -} __attribute__ ((packed)); - -/* dma control, BAR0 + 0x0180 ... array of four structs like this, - * for channels 0..3. see also struct net2280_dma: descriptor - * that can be loaded into some of these registers. - */ -struct net2280_dma_regs { /* [11.7] */ - // offset 0x0180, 0x01a0, 0x01c0, 0x01e0, - u32 dmactl; -#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25 -#define DMA_CLEAR_COUNT_ENABLE 21 -#define DESCRIPTOR_POLLING_RATE 19 -#define POLL_CONTINUOUS 0 -#define POLL_1_USEC 1 -#define POLL_100_USEC 2 -#define POLL_1_MSEC 3 -#define DMA_VALID_BIT_POLLING_ENABLE 18 -#define DMA_VALID_BIT_ENABLE 17 -#define DMA_SCATTER_GATHER_ENABLE 16 -#define DMA_OUT_AUTO_START_ENABLE 4 -#define DMA_PREEMPT_ENABLE 3 -#define DMA_FIFO_VALIDATE 2 -#define DMA_ENABLE 1 -#define DMA_ADDRESS_HOLD 0 - u32 dmastat; -#define DMA_ABORT_DONE_INTERRUPT 27 -#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25 -#define DMA_TRANSACTION_DONE_INTERRUPT 24 -#define DMA_ABORT 1 -#define DMA_START 0 - u32 _unused0 [2]; - // offset 0x0190, 0x01b0, 0x01d0, 0x01f0, - u32 dmacount; -#define VALID_BIT 31 -#define DMA_DIRECTION 30 -#define DMA_DONE_INTERRUPT_ENABLE 29 -#define END_OF_CHAIN 28 -#define DMA_BYTE_COUNT_MASK ((1<<24)-1) -#define DMA_BYTE_COUNT 0 - u32 dmaaddr; - u32 dmadesc; - u32 _unused1; -} __attribute__ ((packed)); - -/* dedicated endpoint registers, BAR0 + 0x0200 */ - -struct net2280_dep_regs { /* [11.8] */ - // offset 0x0200, 0x0210, 0x220, 0x230, 0x240 - u32 dep_cfg; - // offset 0x0204, 0x0214, 0x224, 0x234, 0x244 - u32 dep_rsp; - u32 _unused [2]; -} __attribute__ ((packed)); - -/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs - * like this, for ep0 then the configurable endpoints A..F - * ep0 reserved for control; E and F have only 64 bytes of fifo - */ -struct net2280_ep_regs { /* [11.9] */ - // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 - u32 ep_cfg; -#define ENDPOINT_BYTE_COUNT 16 -#define ENDPOINT_ENABLE 10 -#define ENDPOINT_TYPE 8 -#define ENDPOINT_DIRECTION 7 -#define ENDPOINT_NUMBER 0 - u32 ep_rsp; -#define SET_NAK_OUT_PACKETS 15 -#define SET_EP_HIDE_STATUS_PHASE 14 -#define SET_EP_FORCE_CRC_ERROR 13 -#define SET_INTERRUPT_MODE 12 -#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11 -#define SET_NAK_OUT_PACKETS_MODE 10 -#define SET_ENDPOINT_TOGGLE 9 -#define SET_ENDPOINT_HALT 8 -#define CLEAR_NAK_OUT_PACKETS 7 -#define CLEAR_EP_HIDE_STATUS_PHASE 6 -#define CLEAR_EP_FORCE_CRC_ERROR 5 -#define CLEAR_INTERRUPT_MODE 4 -#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3 -#define CLEAR_NAK_OUT_PACKETS_MODE 2 -#define CLEAR_ENDPOINT_TOGGLE 1 -#define CLEAR_ENDPOINT_HALT 0 - u32 ep_irqenb; -#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6 -#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5 -#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3 -#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2 -#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1 -#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0 - u32 ep_stat; -#define FIFO_VALID_COUNT 24 -#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22 -#define TIMEOUT 21 -#define USB_STALL_SENT 20 -#define USB_IN_NAK_SENT 19 -#define USB_IN_ACK_RCVD 18 -#define USB_OUT_PING_NAK_SENT 17 -#define USB_OUT_ACK_SENT 16 -#define FIFO_OVERFLOW 13 -#define FIFO_UNDERFLOW 12 -#define FIFO_FULL 11 -#define FIFO_EMPTY 10 -#define FIFO_FLUSH 9 -#define SHORT_PACKET_OUT_DONE_INTERRUPT 6 -#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5 -#define NAK_OUT_PACKETS 4 -#define DATA_PACKET_RECEIVED_INTERRUPT 3 -#define DATA_PACKET_TRANSMITTED_INTERRUPT 2 -#define DATA_OUT_PING_TOKEN_INTERRUPT 1 -#define DATA_IN_TOKEN_INTERRUPT 0 - // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 - u32 ep_avail; - u32 ep_data; - u32 _unused0 [2]; -} __attribute__ ((packed)); +#include /*-------------------------------------------------------------------------*/ diff --git a/include/linux/usb/net2280.h b/include/linux/usb/net2280.h new file mode 100644 index 000000000000..c602f884f182 --- /dev/null +++ b/include/linux/usb/net2280.h @@ -0,0 +1,444 @@ +/* + * NetChip 2280 high/full speed USB device controller. + * Unlike many such controllers, this one talks PCI. + */ +#ifndef __LINUX_USB_NET2280_H +#define __LINUX_USB_NET2280_H + +/* + * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com) + * Copyright (C) 2003 David Brownell + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*-------------------------------------------------------------------------*/ + +/* NET2280 MEMORY MAPPED REGISTERS + * + * The register layout came from the chip documentation, and the bit + * number definitions were extracted from chip specification. + * + * Use the shift operator ('<<') to build bit masks, with readl/writel + * to access the registers through PCI. + */ + +/* main registers, BAR0 + 0x0000 */ +struct net2280_regs { + // offset 0x0000 + u32 devinit; +#define LOCAL_CLOCK_FREQUENCY 8 +#define FORCE_PCI_RESET 7 +#define PCI_ID 6 +#define PCI_ENABLE 5 +#define FIFO_SOFT_RESET 4 +#define CFG_SOFT_RESET 3 +#define PCI_SOFT_RESET 2 +#define USB_SOFT_RESET 1 +#define M8051_RESET 0 + u32 eectl; +#define EEPROM_ADDRESS_WIDTH 23 +#define EEPROM_CHIP_SELECT_ACTIVE 22 +#define EEPROM_PRESENT 21 +#define EEPROM_VALID 20 +#define EEPROM_BUSY 19 +#define EEPROM_CHIP_SELECT_ENABLE 18 +#define EEPROM_BYTE_READ_START 17 +#define EEPROM_BYTE_WRITE_START 16 +#define EEPROM_READ_DATA 8 +#define EEPROM_WRITE_DATA 0 + u32 eeclkfreq; + u32 _unused0; + // offset 0x0010 + + u32 pciirqenb0; /* interrupt PCI master ... */ +#define SETUP_PACKET_INTERRUPT_ENABLE 7 +#define ENDPOINT_F_INTERRUPT_ENABLE 6 +#define ENDPOINT_E_INTERRUPT_ENABLE 5 +#define ENDPOINT_D_INTERRUPT_ENABLE 4 +#define ENDPOINT_C_INTERRUPT_ENABLE 3 +#define ENDPOINT_B_INTERRUPT_ENABLE 2 +#define ENDPOINT_A_INTERRUPT_ENABLE 1 +#define ENDPOINT_0_INTERRUPT_ENABLE 0 + u32 pciirqenb1; +#define PCI_INTERRUPT_ENABLE 31 +#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 +#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 +#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18 +#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 +#define GPIO_INTERRUPT_ENABLE 13 +#define DMA_D_INTERRUPT_ENABLE 12 +#define DMA_C_INTERRUPT_ENABLE 11 +#define DMA_B_INTERRUPT_ENABLE 10 +#define DMA_A_INTERRUPT_ENABLE 9 +#define EEPROM_DONE_INTERRUPT_ENABLE 8 +#define VBUS_INTERRUPT_ENABLE 7 +#define CONTROL_STATUS_INTERRUPT_ENABLE 6 +#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 +#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 +#define RESUME_INTERRUPT_ENABLE 1 +#define SOF_INTERRUPT_ENABLE 0 + u32 cpu_irqenb0; /* ... or onboard 8051 */ +#define SETUP_PACKET_INTERRUPT_ENABLE 7 +#define ENDPOINT_F_INTERRUPT_ENABLE 6 +#define ENDPOINT_E_INTERRUPT_ENABLE 5 +#define ENDPOINT_D_INTERRUPT_ENABLE 4 +#define ENDPOINT_C_INTERRUPT_ENABLE 3 +#define ENDPOINT_B_INTERRUPT_ENABLE 2 +#define ENDPOINT_A_INTERRUPT_ENABLE 1 +#define ENDPOINT_0_INTERRUPT_ENABLE 0 + u32 cpu_irqenb1; +#define CPU_INTERRUPT_ENABLE 31 +#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 +#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 +#define PCI_INTA_INTERRUPT_ENABLE 24 +#define PCI_PME_INTERRUPT_ENABLE 23 +#define PCI_SERR_INTERRUPT_ENABLE 22 +#define PCI_PERR_INTERRUPT_ENABLE 21 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 +#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 +#define GPIO_INTERRUPT_ENABLE 13 +#define DMA_D_INTERRUPT_ENABLE 12 +#define DMA_C_INTERRUPT_ENABLE 11 +#define DMA_B_INTERRUPT_ENABLE 10 +#define DMA_A_INTERRUPT_ENABLE 9 +#define EEPROM_DONE_INTERRUPT_ENABLE 8 +#define VBUS_INTERRUPT_ENABLE 7 +#define CONTROL_STATUS_INTERRUPT_ENABLE 6 +#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 +#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 +#define RESUME_INTERRUPT_ENABLE 1 +#define SOF_INTERRUPT_ENABLE 0 + + // offset 0x0020 + u32 _unused1; + u32 usbirqenb1; +#define USB_INTERRUPT_ENABLE 31 +#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 +#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 +#define PCI_INTA_INTERRUPT_ENABLE 24 +#define PCI_PME_INTERRUPT_ENABLE 23 +#define PCI_SERR_INTERRUPT_ENABLE 22 +#define PCI_PERR_INTERRUPT_ENABLE 21 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 +#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 +#define GPIO_INTERRUPT_ENABLE 13 +#define DMA_D_INTERRUPT_ENABLE 12 +#define DMA_C_INTERRUPT_ENABLE 11 +#define DMA_B_INTERRUPT_ENABLE 10 +#define DMA_A_INTERRUPT_ENABLE 9 +#define EEPROM_DONE_INTERRUPT_ENABLE 8 +#define VBUS_INTERRUPT_ENABLE 7 +#define CONTROL_STATUS_INTERRUPT_ENABLE 6 +#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 +#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 +#define RESUME_INTERRUPT_ENABLE 1 +#define SOF_INTERRUPT_ENABLE 0 + u32 irqstat0; +#define INTA_ASSERTED 12 +#define SETUP_PACKET_INTERRUPT 7 +#define ENDPOINT_F_INTERRUPT 6 +#define ENDPOINT_E_INTERRUPT 5 +#define ENDPOINT_D_INTERRUPT 4 +#define ENDPOINT_C_INTERRUPT 3 +#define ENDPOINT_B_INTERRUPT 2 +#define ENDPOINT_A_INTERRUPT 1 +#define ENDPOINT_0_INTERRUPT 0 + u32 irqstat1; +#define POWER_STATE_CHANGE_INTERRUPT 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT 26 +#define PCI_PARITY_ERROR_INTERRUPT 25 +#define PCI_INTA_INTERRUPT 24 +#define PCI_PME_INTERRUPT 23 +#define PCI_SERR_INTERRUPT 22 +#define PCI_PERR_INTERRUPT 21 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19 +#define PCI_RETRY_ABORT_INTERRUPT 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16 +#define SOF_DOWN_INTERRUPT 14 +#define GPIO_INTERRUPT 13 +#define DMA_D_INTERRUPT 12 +#define DMA_C_INTERRUPT 11 +#define DMA_B_INTERRUPT 10 +#define DMA_A_INTERRUPT 9 +#define EEPROM_DONE_INTERRUPT 8 +#define VBUS_INTERRUPT 7 +#define CONTROL_STATUS_INTERRUPT 6 +#define ROOT_PORT_RESET_INTERRUPT 4 +#define SUSPEND_REQUEST_INTERRUPT 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2 +#define RESUME_INTERRUPT 1 +#define SOF_INTERRUPT 0 + // offset 0x0030 + u32 idxaddr; + u32 idxdata; + u32 fifoctl; +#define PCI_BASE2_RANGE 16 +#define IGNORE_FIFO_AVAILABILITY 3 +#define PCI_BASE2_SELECT 2 +#define FIFO_CONFIGURATION_SELECT 0 + u32 _unused2; + // offset 0x0040 + u32 memaddr; +#define START 28 +#define DIRECTION 27 +#define FIFO_DIAGNOSTIC_SELECT 24 +#define MEMORY_ADDRESS 0 + u32 memdata0; + u32 memdata1; + u32 _unused3; + // offset 0x0050 + u32 gpioctl; +#define GPIO3_LED_SELECT 12 +#define GPIO3_INTERRUPT_ENABLE 11 +#define GPIO2_INTERRUPT_ENABLE 10 +#define GPIO1_INTERRUPT_ENABLE 9 +#define GPIO0_INTERRUPT_ENABLE 8 +#define GPIO3_OUTPUT_ENABLE 7 +#define GPIO2_OUTPUT_ENABLE 6 +#define GPIO1_OUTPUT_ENABLE 5 +#define GPIO0_OUTPUT_ENABLE 4 +#define GPIO3_DATA 3 +#define GPIO2_DATA 2 +#define GPIO1_DATA 1 +#define GPIO0_DATA 0 + u32 gpiostat; +#define GPIO3_INTERRUPT 3 +#define GPIO2_INTERRUPT 2 +#define GPIO1_INTERRUPT 1 +#define GPIO0_INTERRUPT 0 +} __attribute__ ((packed)); + +/* usb control, BAR0 + 0x0080 */ +struct net2280_usb_regs { + // offset 0x0080 + u32 stdrsp; +#define STALL_UNSUPPORTED_REQUESTS 31 +#define SET_TEST_MODE 16 +#define GET_OTHER_SPEED_CONFIGURATION 15 +#define GET_DEVICE_QUALIFIER 14 +#define SET_ADDRESS 13 +#define ENDPOINT_SET_CLEAR_HALT 12 +#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11 +#define GET_STRING_DESCRIPTOR_2 10 +#define GET_STRING_DESCRIPTOR_1 9 +#define GET_STRING_DESCRIPTOR_0 8 +#define GET_SET_INTERFACE 6 +#define GET_SET_CONFIGURATION 5 +#define GET_CONFIGURATION_DESCRIPTOR 4 +#define GET_DEVICE_DESCRIPTOR 3 +#define GET_ENDPOINT_STATUS 2 +#define GET_INTERFACE_STATUS 1 +#define GET_DEVICE_STATUS 0 + u32 prodvendid; +#define PRODUCT_ID 16 +#define VENDOR_ID 0 + u32 relnum; + u32 usbctl; +#define SERIAL_NUMBER_INDEX 16 +#define PRODUCT_ID_STRING_ENABLE 13 +#define VENDOR_ID_STRING_ENABLE 12 +#define USB_ROOT_PORT_WAKEUP_ENABLE 11 +#define VBUS_PIN 10 +#define TIMED_DISCONNECT 9 +#define SUSPEND_IMMEDIATELY 7 +#define SELF_POWERED_USB_DEVICE 6 +#define REMOTE_WAKEUP_SUPPORT 5 +#define PME_POLARITY 4 +#define USB_DETECT_ENABLE 3 +#define PME_WAKEUP_ENABLE 2 +#define DEVICE_REMOTE_WAKEUP_ENABLE 1 +#define SELF_POWERED_STATUS 0 + // offset 0x0090 + u32 usbstat; +#define HIGH_SPEED 7 +#define FULL_SPEED 6 +#define GENERATE_RESUME 5 +#define GENERATE_DEVICE_REMOTE_WAKEUP 4 + u32 xcvrdiag; +#define FORCE_HIGH_SPEED_MODE 31 +#define FORCE_FULL_SPEED_MODE 30 +#define USB_TEST_MODE 24 +#define LINE_STATE 16 +#define TRANSCEIVER_OPERATION_MODE 2 +#define TRANSCEIVER_SELECT 1 +#define TERMINATION_SELECT 0 + u32 setup0123; + u32 setup4567; + // offset 0x0090 + u32 _unused0; + u32 ouraddr; +#define FORCE_IMMEDIATE 7 +#define OUR_USB_ADDRESS 0 + u32 ourconfig; +} __attribute__ ((packed)); + +/* pci control, BAR0 + 0x0100 */ +struct net2280_pci_regs { + // offset 0x0100 + u32 pcimstctl; +#define PCI_ARBITER_PARK_SELECT 13 +#define PCI_MULTI LEVEL_ARBITER 12 +#define PCI_RETRY_ABORT_ENABLE 11 +#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10 +#define DMA_READ_MULTIPLE_ENABLE 9 +#define DMA_READ_LINE_ENABLE 8 +#define PCI_MASTER_COMMAND_SELECT 6 +#define MEM_READ_OR_WRITE 0 +#define IO_READ_OR_WRITE 1 +#define CFG_READ_OR_WRITE 2 +#define PCI_MASTER_START 5 +#define PCI_MASTER_READ_WRITE 4 +#define PCI_MASTER_WRITE 0 +#define PCI_MASTER_READ 1 +#define PCI_MASTER_BYTE_WRITE_ENABLES 0 + u32 pcimstaddr; + u32 pcimstdata; + u32 pcimststat; +#define PCI_ARBITER_CLEAR 2 +#define PCI_EXTERNAL_ARBITER 1 +#define PCI_HOST_MODE 0 +} __attribute__ ((packed)); + +/* dma control, BAR0 + 0x0180 ... array of four structs like this, + * for channels 0..3. see also struct net2280_dma: descriptor + * that can be loaded into some of these registers. + */ +struct net2280_dma_regs { /* [11.7] */ + // offset 0x0180, 0x01a0, 0x01c0, 0x01e0, + u32 dmactl; +#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25 +#define DMA_CLEAR_COUNT_ENABLE 21 +#define DESCRIPTOR_POLLING_RATE 19 +#define POLL_CONTINUOUS 0 +#define POLL_1_USEC 1 +#define POLL_100_USEC 2 +#define POLL_1_MSEC 3 +#define DMA_VALID_BIT_POLLING_ENABLE 18 +#define DMA_VALID_BIT_ENABLE 17 +#define DMA_SCATTER_GATHER_ENABLE 16 +#define DMA_OUT_AUTO_START_ENABLE 4 +#define DMA_PREEMPT_ENABLE 3 +#define DMA_FIFO_VALIDATE 2 +#define DMA_ENABLE 1 +#define DMA_ADDRESS_HOLD 0 + u32 dmastat; +#define DMA_ABORT_DONE_INTERRUPT 27 +#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25 +#define DMA_TRANSACTION_DONE_INTERRUPT 24 +#define DMA_ABORT 1 +#define DMA_START 0 + u32 _unused0 [2]; + // offset 0x0190, 0x01b0, 0x01d0, 0x01f0, + u32 dmacount; +#define VALID_BIT 31 +#define DMA_DIRECTION 30 +#define DMA_DONE_INTERRUPT_ENABLE 29 +#define END_OF_CHAIN 28 +#define DMA_BYTE_COUNT_MASK ((1<<24)-1) +#define DMA_BYTE_COUNT 0 + u32 dmaaddr; + u32 dmadesc; + u32 _unused1; +} __attribute__ ((packed)); + +/* dedicated endpoint registers, BAR0 + 0x0200 */ + +struct net2280_dep_regs { /* [11.8] */ + // offset 0x0200, 0x0210, 0x220, 0x230, 0x240 + u32 dep_cfg; + // offset 0x0204, 0x0214, 0x224, 0x234, 0x244 + u32 dep_rsp; + u32 _unused [2]; +} __attribute__ ((packed)); + +/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs + * like this, for ep0 then the configurable endpoints A..F + * ep0 reserved for control; E and F have only 64 bytes of fifo + */ +struct net2280_ep_regs { /* [11.9] */ + // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 + u32 ep_cfg; +#define ENDPOINT_BYTE_COUNT 16 +#define ENDPOINT_ENABLE 10 +#define ENDPOINT_TYPE 8 +#define ENDPOINT_DIRECTION 7 +#define ENDPOINT_NUMBER 0 + u32 ep_rsp; +#define SET_NAK_OUT_PACKETS 15 +#define SET_EP_HIDE_STATUS_PHASE 14 +#define SET_EP_FORCE_CRC_ERROR 13 +#define SET_INTERRUPT_MODE 12 +#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11 +#define SET_NAK_OUT_PACKETS_MODE 10 +#define SET_ENDPOINT_TOGGLE 9 +#define SET_ENDPOINT_HALT 8 +#define CLEAR_NAK_OUT_PACKETS 7 +#define CLEAR_EP_HIDE_STATUS_PHASE 6 +#define CLEAR_EP_FORCE_CRC_ERROR 5 +#define CLEAR_INTERRUPT_MODE 4 +#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3 +#define CLEAR_NAK_OUT_PACKETS_MODE 2 +#define CLEAR_ENDPOINT_TOGGLE 1 +#define CLEAR_ENDPOINT_HALT 0 + u32 ep_irqenb; +#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6 +#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5 +#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3 +#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2 +#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1 +#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0 + u32 ep_stat; +#define FIFO_VALID_COUNT 24 +#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22 +#define TIMEOUT 21 +#define USB_STALL_SENT 20 +#define USB_IN_NAK_SENT 19 +#define USB_IN_ACK_RCVD 18 +#define USB_OUT_PING_NAK_SENT 17 +#define USB_OUT_ACK_SENT 16 +#define FIFO_OVERFLOW 13 +#define FIFO_UNDERFLOW 12 +#define FIFO_FULL 11 +#define FIFO_EMPTY 10 +#define FIFO_FLUSH 9 +#define SHORT_PACKET_OUT_DONE_INTERRUPT 6 +#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5 +#define NAK_OUT_PACKETS 4 +#define DATA_PACKET_RECEIVED_INTERRUPT 3 +#define DATA_PACKET_TRANSMITTED_INTERRUPT 2 +#define DATA_OUT_PING_TOKEN_INTERRUPT 1 +#define DATA_IN_TOKEN_INTERRUPT 0 + // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 + u32 ep_avail; + u32 ep_data; + u32 _unused0 [2]; +} __attribute__ ((packed)); + +#endif /* __LINUX_USB_NET2280_H */ -- cgit v1.2.3 From 4508a7a734b111b8b7e39986237d84acb1168dd0 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 20 Mar 2006 17:53:53 +1100 Subject: [PATCH] sysfs: Allow sysfs attribute files to be pollable It works like this: Open the file Read all the contents. Call poll requesting POLLERR or POLLPRI (so select/exceptfds works) When poll returns, close the file and go to top of loop. or lseek to start of file and go back to the 'read'. Events are signaled by an object manager calling sysfs_notify(kobj, dir, attr); If the dir is non-NULL, it is used to find a subdirectory which contains the attribute (presumably created by sysfs_create_group). This has a cost of one int per attribute, one wait_queuehead per kobject, one int per open file. The name "sysfs_notify" may be confused with the inotify functionality. Maybe it would be nice to support inotify for sysfs attributes as well? This patch also uses sysfs_notify to allow /sys/block/md*/md/sync_action to be pollable Signed-off-by: Neil Brown Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 1 + fs/sysfs/dir.c | 1 + fs/sysfs/file.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/sysfs/sysfs.h | 1 + include/linux/kobject.h | 2 ++ include/linux/sysfs.h | 6 ++++ lib/kobject.c | 1 + 7 files changed, 88 insertions(+) (limited to 'include/linux') diff --git a/drivers/md/md.c b/drivers/md/md.c index 1ed5152db450..434ca39d19c1 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -163,6 +163,7 @@ void md_new_event(mddev_t *mddev) { atomic_inc(&md_event_count); wake_up(&md_event_waiters); + sysfs_notify(&mddev->kobj, NULL, "sync_action"); } EXPORT_SYMBOL_GPL(md_new_event); diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 6cfdc9a87772..610b5bdbe75b 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -43,6 +43,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd, memset(sd, 0, sizeof(*sd)); atomic_set(&sd->s_count, 1); + atomic_set(&sd->s_event, 0); INIT_LIST_HEAD(&sd->s_children); list_add(&sd->s_sibling, &parent_sd->s_children); sd->s_element = element; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index f1cb1ddde511..cf3786625bfa 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,7 @@ struct sysfs_buffer { struct sysfs_ops * ops; struct semaphore sem; int needs_read_fill; + int event; }; @@ -72,6 +74,7 @@ struct sysfs_buffer { */ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) { + struct sysfs_dirent * sd = dentry->d_fsdata; struct attribute * attr = to_attr(dentry); struct kobject * kobj = to_kobj(dentry->d_parent); struct sysfs_ops * ops = buffer->ops; @@ -83,6 +86,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer if (!buffer->page) return -ENOMEM; + buffer->event = atomic_read(&sd->s_event); count = ops->show(kobj,attr,buffer->page); buffer->needs_read_fill = 0; BUG_ON(count > (ssize_t)PAGE_SIZE); @@ -348,12 +352,84 @@ static int sysfs_release(struct inode * inode, struct file * filp) return 0; } +/* Sysfs attribute files are pollable. The idea is that you read + * the content and then you use 'poll' or 'select' to wait for + * the content to change. When the content changes (assuming the + * manager for the kobject supports notification), poll will + * return POLLERR|POLLPRI, and select will return the fd whether + * it is waiting for read, write, or exceptions. + * Once poll/select indicates that the value has changed, you + * need to close and re-open the file, as simply seeking and reading + * again will not get new data, or reset the state of 'poll'. + * Reminder: this only works for attributes which actively support + * it, and it is not possible to test an attribute from userspace + * to see if it supports poll (Nether 'poll' or 'select' return + * an appropriate error code). When in doubt, set a suitable timeout value. + */ +static unsigned int sysfs_poll(struct file *filp, poll_table *wait) +{ + struct sysfs_buffer * buffer = filp->private_data; + struct kobject * kobj = to_kobj(filp->f_dentry->d_parent); + struct sysfs_dirent * sd = filp->f_dentry->d_fsdata; + int res = 0; + + poll_wait(filp, &kobj->poll, wait); + + if (buffer->event != atomic_read(&sd->s_event)) { + res = POLLERR|POLLPRI; + buffer->needs_read_fill = 1; + } + + return res; +} + + +static struct dentry *step_down(struct dentry *dir, const char * name) +{ + struct dentry * de; + + if (dir == NULL || dir->d_inode == NULL) + return NULL; + + mutex_lock(&dir->d_inode->i_mutex); + de = lookup_one_len(name, dir, strlen(name)); + mutex_unlock(&dir->d_inode->i_mutex); + dput(dir); + if (IS_ERR(de)) + return NULL; + if (de->d_inode == NULL) { + dput(de); + return NULL; + } + return de; +} + +void sysfs_notify(struct kobject * k, char *dir, char *attr) +{ + struct dentry *de = k->dentry; + if (de) + dget(de); + if (de && dir) + de = step_down(de, dir); + if (de && attr) + de = step_down(de, attr); + if (de) { + struct sysfs_dirent * sd = de->d_fsdata; + if (sd) + atomic_inc(&sd->s_event); + wake_up_interruptible(&k->poll); + dput(de); + } +} +EXPORT_SYMBOL_GPL(sysfs_notify); + const struct file_operations sysfs_file_operations = { .read = sysfs_read_file, .write = sysfs_write_file, .llseek = generic_file_llseek, .open = sysfs_open_file, .release = sysfs_release, + .poll = sysfs_poll, }; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 32958a7c50e9..3651ffb5ec09 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -11,6 +11,7 @@ extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, extern int sysfs_add_file(struct dentry *, const struct attribute *, int); extern void sysfs_hash_and_remove(struct dentry * dir, const char * name); +extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name); extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); extern void sysfs_remove_subdir(struct dentry *); diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 4cb1214ec290..dcd0623be892 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #define KOBJ_NAME_LEN 20 @@ -56,6 +57,7 @@ struct kobject { struct kset * kset; struct kobj_type * ktype; struct dentry * dentry; + wait_queue_head_t poll; }; extern int kobject_set_name(struct kobject *, const char *, ...) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 392da5a6dacb..1ea5d3cda6ae 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -74,6 +74,7 @@ struct sysfs_dirent { umode_t s_mode; struct dentry * s_dentry; struct iattr * s_iattr; + atomic_t s_event; }; #define SYSFS_ROOT 0x0001 @@ -117,6 +118,7 @@ int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); int sysfs_create_group(struct kobject *, const struct attribute_group *); void sysfs_remove_group(struct kobject *, const struct attribute_group *); +void sysfs_notify(struct kobject * k, char *dir, char *attr); #else /* CONFIG_SYSFS */ @@ -185,6 +187,10 @@ static inline void sysfs_remove_group(struct kobject * k, const struct attribute ; } +static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) +{ +} + #endif /* CONFIG_SYSFS */ #endif /* _SYSFS_H_ */ diff --git a/lib/kobject.c b/lib/kobject.c index 25204a41a9b0..01d957513940 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -128,6 +128,7 @@ void kobject_init(struct kobject * kobj) { kref_init(&kobj->kref); INIT_LIST_HEAD(&kobj->entry); + init_waitqueue_head(&kobj->poll); kobj->kset = kset_get(kobj->kset); } -- cgit v1.2.3 From d4d7e5dffc4844ef51fe11f497bd774c04413a00 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Fri, 24 Mar 2006 20:45:35 +0100 Subject: [PATCH] BLOCK: delay all uevents until partition table is scanned [BLOCK] delay all uevents until partition table is scanned Here we delay the annoucement of all block device events until the disk's partition table is scanned and all partition devices are already created and sysfs is populated. We have a bunch of old bugs for removable storage handling where we probe successfully for a filesystem on the raw disk, but at the same time the kernel recognizes a partition table and creates partition devices. Currently there is no sane way to tell if partitions will show up or not at the time the disk device is announced to userspace. With the delayed events we can simply skip any probe for a filesystem on the raw disk when we find already present partitions. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- fs/partitions/check.c | 38 ++++++++++++++++++++++++++++++-------- include/linux/genhd.h | 1 + 2 files changed, 31 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/fs/partitions/check.c b/fs/partitions/check.c index af0cb4b9e784..f3b6af071722 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -331,7 +331,9 @@ void delete_partition(struct gendisk *disk, int part) devfs_remove("%s/part%d", disk->devfs_name, part); if (p->holder_dir) kobject_unregister(p->holder_dir); - kobject_unregister(&p->kobj); + kobject_uevent(&p->kobj, KOBJ_REMOVE); + kobject_del(&p->kobj); + kobject_put(&p->kobj); } void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) @@ -357,7 +359,10 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->kobj.name,part); p->kobj.parent = &disk->kobj; p->kobj.ktype = &ktype_part; - kobject_register(&p->kobj); + kobject_init(&p->kobj); + kobject_add(&p->kobj); + if (!disk->part_uevent_suppress) + kobject_uevent(&p->kobj, KOBJ_ADD); partition_sysfs_add_subdir(p); disk->part[part-1] = p; } @@ -395,6 +400,8 @@ void register_disk(struct gendisk *disk) { struct block_device *bdev; char *s; + int i; + struct hd_struct *p; int err; strlcpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN); @@ -406,13 +413,12 @@ void register_disk(struct gendisk *disk) return; disk_sysfs_symlinks(disk); disk_sysfs_add_subdirs(disk); - kobject_uevent(&disk->kobj, KOBJ_ADD); /* No minors to use for partitions */ if (disk->minors == 1) { if (disk->devfs_name[0] != '\0') devfs_add_disk(disk); - return; + goto exit; } /* always add handle for the whole disk */ @@ -420,16 +426,32 @@ void register_disk(struct gendisk *disk) /* No such device (e.g., media were just removed) */ if (!get_capacity(disk)) - return; + goto exit; bdev = bdget_disk(disk, 0); if (!bdev) - return; + goto exit; + /* scan partition table, but suppress uevents */ bdev->bd_invalidated = 1; - if (blkdev_get(bdev, FMODE_READ, 0) < 0) - return; + disk->part_uevent_suppress = 1; + err = blkdev_get(bdev, FMODE_READ, 0); + disk->part_uevent_suppress = 0; + if (err < 0) + goto exit; blkdev_put(bdev); + +exit: + /* announce disk after possible partitions are already created */ + kobject_uevent(&disk->kobj, KOBJ_ADD); + + /* announce possible partitions */ + for (i = 1; i < disk->minors; i++) { + p = disk->part[i-1]; + if (!p || !p->nr_sects) + continue; + kobject_uevent(&p->kobj, KOBJ_ADD); + } } int rescan_partitions(struct gendisk *disk, struct block_device *bdev) diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 10a27f29d692..2ef845b35175 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -105,6 +105,7 @@ struct gendisk { * disks that can't be partitioned. */ char disk_name[32]; /* name of major driver */ struct hd_struct **part; /* [indexed by minor] */ + int part_uevent_suppress; struct block_device_operations *fops; struct request_queue *queue; void *private_data; -- cgit v1.2.3 From 026694920579590c73b5c56705d543568ed5ad41 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 23 Mar 2006 01:38:34 -0800 Subject: [PATCH] pm: print name of failed suspend function Print more diagnostic info to help identify the source of power management suspend failures. Example: usb_hcd_pci_suspend(): pci_set_power_state+0x0/0x1af() returns -22 pci_device_suspend(): usb_hcd_pci_suspend+0x0/0x11b() returns -22 suspend_device(): pci_device_suspend+0x0/0x34() returns -22 Work-in-progress. It needs lots more suspend_report_result() calls sprinkled everywhere. Cc: Patrick Mochel Cc: Pavel Machek Cc: Nigel Cunningham Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/suspend.c | 12 ++++++++++++ drivers/pci/pci-driver.c | 6 ++++-- drivers/pci/pci.c | 6 ++++-- drivers/usb/core/hcd-pci.c | 7 +++---- include/linux/pm.h | 8 ++++++++ 5 files changed, 31 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index bdb60663f2ef..662209d3f42d 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c @@ -10,6 +10,8 @@ #include #include +#include +#include #include "../base.h" #include "power.h" @@ -58,6 +60,7 @@ int suspend_device(struct device * dev, pm_message_t state) if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) { dev_dbg(dev, "suspending\n"); error = dev->bus->suspend(dev, state); + suspend_report_result(dev->bus->suspend, error); } up(&dev->sem); return error; @@ -169,3 +172,12 @@ int device_power_down(pm_message_t state) EXPORT_SYMBOL_GPL(device_power_down); +void __suspend_report_result(const char *function, void *fn, int ret) +{ + if (ret) { + printk(KERN_ERR "%s(): ", function); + print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn); + printk("%d\n", ret); + } +} +EXPORT_SYMBOL_GPL(__suspend_report_result); diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index f22f69ac6445..1456759936c5 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -271,10 +271,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state) struct pci_driver * drv = pci_dev->driver; int i = 0; - if (drv && drv->suspend) + if (drv && drv->suspend) { i = drv->suspend(pci_dev, state); - else + suspend_report_result(drv->suspend, i); + } else { pci_save_state(pci_dev); + } return i; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bea1ad1ad5ba..042fa5265cf6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -307,9 +307,11 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) * Can enter D0 from any state, but if we can only go deeper * to sleep if we're already in a low power state */ - if (state != PCI_D0 && dev->current_state > state) + if (state != PCI_D0 && dev->current_state > state) { + printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n", + __FUNCTION__, pci_name(dev), state, dev->current_state); return -EINVAL; - else if (dev->current_state == state) + } else if (dev->current_state == state) return 0; /* we're already there */ /* find PCI PM capability in list */ diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 0d2193b69235..66b78404ab34 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -213,11 +213,9 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) if (hcd->driver->suspend) { retval = hcd->driver->suspend(hcd, message); - if (retval) { - dev_dbg (&dev->dev, "PCI pre-suspend fail, %d\n", - retval); + suspend_report_result(hcd->driver->suspend, retval); + if (retval) goto done; - } } synchronize_irq(dev->irq); @@ -263,6 +261,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) * some device state (e.g. as part of clock reinit). */ retval = pci_set_power_state (dev, PCI_D3hot); + suspend_report_result(pci_set_power_state, retval); if (retval == 0) { int wake = device_can_wakeup(&hcd->self.root_hub->dev); diff --git a/include/linux/pm.h b/include/linux/pm.h index 6df2585c0169..66be58902b17 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -199,6 +199,12 @@ extern int device_suspend(pm_message_t state); extern int dpm_runtime_suspend(struct device *, pm_message_t); extern void dpm_runtime_resume(struct device *); +extern void __suspend_report_result(const char *function, void *fn, int ret); + +#define suspend_report_result(fn, ret) \ + do { \ + __suspend_report_result(__FUNCTION__, fn, ret); \ + } while (0) #else /* !CONFIG_PM */ @@ -219,6 +225,8 @@ static inline void dpm_runtime_resume(struct device * dev) { } +#define suspend_report_result(fn, ret) do { } while (0) + #endif /* changes to device_may_wakeup take effect on the next pm state change. -- cgit v1.2.3 From 41017f0cac925e4a6bcf3359b75e5538112d4216 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 8 Feb 2006 17:11:38 +0800 Subject: [PATCH] PCI: MSI(X) save/restore for suspend/resume Add MSI(X) configure sapce save/restore in generic PCI helper. Signed-off-by: Shaohua Li Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 227 +++++++++++++++++++++++++++++++++++++++++++++------- drivers/pci/pci.c | 6 ++ drivers/pci/pci.h | 11 +++ include/linux/pci.h | 31 +++++++ 4 files changed, 246 insertions(+), 29 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a77e79c8c82e..2087a397ef16 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -504,6 +504,201 @@ void pci_scan_msi_device(struct pci_dev *dev) nr_reserved_vectors++; } +#ifdef CONFIG_PM +int pci_save_msi_state(struct pci_dev *dev) +{ + int pos, i = 0; + u16 control; + struct pci_cap_saved_state *save_state; + u32 *cap; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (pos <= 0 || dev->no_msi) + return 0; + + pci_read_config_word(dev, msi_control_reg(pos), &control); + if (!(control & PCI_MSI_FLAGS_ENABLE)) + return 0; + + save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5, + GFP_KERNEL); + if (!save_state) { + printk(KERN_ERR "Out of memory in pci_save_msi_state\n"); + return -ENOMEM; + } + cap = &save_state->data[0]; + + pci_read_config_dword(dev, pos, &cap[i++]); + control = cap[0] >> 16; + pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]); + if (control & PCI_MSI_FLAGS_64BIT) { + pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]); + pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]); + } else + pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); + if (control & PCI_MSI_FLAGS_MASKBIT) + pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); + disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); + save_state->cap_nr = PCI_CAP_ID_MSI; + pci_add_saved_cap(dev, save_state); + return 0; +} + +void pci_restore_msi_state(struct pci_dev *dev) +{ + int i = 0, pos; + u16 control; + struct pci_cap_saved_state *save_state; + u32 *cap; + + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI); + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (!save_state || pos <= 0) + return; + cap = &save_state->data[0]; + + control = cap[i++] >> 16; + pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]); + if (control & PCI_MSI_FLAGS_64BIT) { + pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]); + pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]); + } else + pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]); + if (control & PCI_MSI_FLAGS_MASKBIT) + pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]); + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); + pci_remove_saved_cap(save_state); + kfree(save_state); +} + +int pci_save_msix_state(struct pci_dev *dev) +{ + int pos; + u16 control; + struct pci_cap_saved_state *save_state; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos <= 0 || dev->no_msi) + return 0; + + pci_read_config_word(dev, msi_control_reg(pos), &control); + if (!(control & PCI_MSIX_FLAGS_ENABLE)) + return 0; + save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16), + GFP_KERNEL); + if (!save_state) { + printk(KERN_ERR "Out of memory in pci_save_msix_state\n"); + return -ENOMEM; + } + *((u16 *)&save_state->data[0]) = control; + + disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); + save_state->cap_nr = PCI_CAP_ID_MSIX; + pci_add_saved_cap(dev, save_state); + return 0; +} + +void pci_restore_msix_state(struct pci_dev *dev) +{ + u16 save; + int pos; + int vector, head, tail = 0; + void __iomem *base; + int j; + struct msg_address address; + struct msg_data data; + struct msi_desc *entry; + int temp; + struct pci_cap_saved_state *save_state; + + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); + if (!save_state) + return; + save = *((u16 *)&save_state->data[0]); + pci_remove_saved_cap(save_state); + kfree(save_state); + + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos <= 0) + return; + + /* route the table */ + temp = dev->irq; + if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) + return; + vector = head = dev->irq; + while (head != tail) { + entry = msi_desc[vector]; + base = entry->mask_base; + j = entry->msi_attrib.entry_nr; + + msi_address_init(&address); + msi_data_init(&data, vector); + + address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; + address.lo_address.value |= entry->msi_attrib.current_cpu << + MSI_TARGET_CPU_SHIFT; + + writel(address.lo_address.value, + base + j * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); + writel(address.hi_address, + base + j * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); + writel(*(u32*)&data, + base + j * PCI_MSIX_ENTRY_SIZE + + PCI_MSIX_ENTRY_DATA_OFFSET); + + tail = msi_desc[vector]->link.tail; + vector = tail; + } + dev->irq = temp; + + pci_write_config_word(dev, msi_control_reg(pos), save); + enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); +} +#endif + +static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry) +{ + struct msg_address address; + struct msg_data data; + int pos, vector = dev->irq; + u16 control; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + pci_read_config_word(dev, msi_control_reg(pos), &control); + /* Configure MSI capability structure */ + msi_address_init(&address); + msi_data_init(&data, vector); + entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >> + MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); + pci_write_config_dword(dev, msi_lower_address_reg(pos), + address.lo_address.value); + if (is_64bit_address(control)) { + pci_write_config_dword(dev, + msi_upper_address_reg(pos), address.hi_address); + pci_write_config_word(dev, + msi_data_reg(pos, 1), *((u32*)&data)); + } else + pci_write_config_word(dev, + msi_data_reg(pos, 0), *((u32*)&data)); + if (entry->msi_attrib.maskbit) { + unsigned int maskbits, temp; + /* All MSIs are unmasked by default, Mask them all */ + pci_read_config_dword(dev, + msi_mask_bits_reg(pos, is_64bit_address(control)), + &maskbits); + temp = (1 << multi_msi_capable(control)); + temp = ((temp - 1) & ~temp); + maskbits |= temp; + pci_write_config_dword(dev, + msi_mask_bits_reg(pos, is_64bit_address(control)), + maskbits); + } +} + /** * msi_capability_init - configure device's MSI capability structure * @dev: pointer to the pci_dev data structure of MSI device function @@ -516,8 +711,6 @@ void pci_scan_msi_device(struct pci_dev *dev) static int msi_capability_init(struct pci_dev *dev) { struct msi_desc *entry; - struct msg_address address; - struct msg_data data; int pos, vector; u16 control; @@ -549,33 +742,8 @@ static int msi_capability_init(struct pci_dev *dev) /* Replace with MSI handler */ irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit); /* Configure MSI capability structure */ - msi_address_init(&address); - msi_data_init(&data, vector); - entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >> - MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); - pci_write_config_dword(dev, msi_lower_address_reg(pos), - address.lo_address.value); - if (is_64bit_address(control)) { - pci_write_config_dword(dev, - msi_upper_address_reg(pos), address.hi_address); - pci_write_config_word(dev, - msi_data_reg(pos, 1), *((u32*)&data)); - } else - pci_write_config_word(dev, - msi_data_reg(pos, 0), *((u32*)&data)); - if (entry->msi_attrib.maskbit) { - unsigned int maskbits, temp; - /* All MSIs are unmasked by default, Mask them all */ - pci_read_config_dword(dev, - msi_mask_bits_reg(pos, is_64bit_address(control)), - &maskbits); - temp = (1 << multi_msi_capable(control)); - temp = ((temp - 1) & ~temp); - maskbits |= temp; - pci_write_config_dword(dev, - msi_mask_bits_reg(pos, is_64bit_address(control)), - maskbits); - } + msi_register_init(dev, entry); + attach_msi_entry(entry, vector); /* Set MSI enabled bits */ enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); @@ -731,6 +899,7 @@ int pci_enable_msi(struct pci_dev* dev) vector_irq[dev->irq] = -1; nr_released_vectors--; spin_unlock_irqrestore(&msi_lock, flags); + msi_register_init(dev, msi_desc[dev->irq]); enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); return 0; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bea1ad1ad5ba..69a617d21824 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -444,6 +444,10 @@ pci_save_state(struct pci_dev *dev) /* XXX: 100% dword access ok here? */ for (i = 0; i < 16; i++) pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); + if ((i = pci_save_msi_state(dev)) != 0) + return i; + if ((i = pci_save_msix_state(dev)) != 0) + return i; return 0; } @@ -458,6 +462,8 @@ pci_restore_state(struct pci_dev *dev) for (i = 0; i < 16; i++) pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]); + pci_restore_msi_state(dev); + pci_restore_msix_state(dev); return 0; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 8f3fb47ea671..30630cbe2fe3 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -55,6 +55,17 @@ void pci_no_msi(void); static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } static inline void pci_no_msi(void) { } #endif +#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM) +int pci_save_msi_state(struct pci_dev *dev); +int pci_save_msix_state(struct pci_dev *dev); +void pci_restore_msi_state(struct pci_dev *dev); +void pci_restore_msix_state(struct pci_dev *dev); +#else +static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; } +static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; } +static inline void pci_restore_msi_state(struct pci_dev *dev) {} +static inline void pci_restore_msix_state(struct pci_dev *dev) {} +#endif extern int pcie_mch_quirk; extern struct device_attribute pci_dev_attrs[]; diff --git a/include/linux/pci.h b/include/linux/pci.h index 0aad5a378e95..15e1675edef9 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -100,6 +100,12 @@ enum pci_bus_flags { PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1, }; +struct pci_cap_saved_state { + struct hlist_node next; + char cap_nr; + u32 data[0]; +}; + /* * The pci_dev structure is used to describe PCI devices. */ @@ -159,6 +165,7 @@ struct pci_dev { unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ u32 saved_config_space[16]; /* config space saved at suspend time */ + struct hlist_head saved_cap_space; struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ int rom_attr_enabled; /* has display of the rom attribute been enabled? */ struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ @@ -169,6 +176,30 @@ struct pci_dev { #define to_pci_dev(n) container_of(n, struct pci_dev, dev) #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) +static inline struct pci_cap_saved_state *pci_find_saved_cap( + struct pci_dev *pci_dev,char cap) +{ + struct pci_cap_saved_state *tmp; + struct hlist_node *pos; + + hlist_for_each_entry(tmp, pos, &pci_dev->saved_cap_space, next) { + if (tmp->cap_nr == cap) + return tmp; + } + return NULL; +} + +static inline void pci_add_saved_cap(struct pci_dev *pci_dev, + struct pci_cap_saved_state *new_cap) +{ + hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space); +} + +static inline void pci_remove_saved_cap(struct pci_cap_saved_state *cap) +{ + hlist_del(&cap->next); +} + /* * For PCI devices, the region numbers are assigned this way: * -- cgit v1.2.3 From 5da594b1c523dffa19ebe7630e1ca285f439bd03 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 20 Mar 2006 14:33:56 -0500 Subject: [PATCH] pci_ids.h: correct naming of 1022:7450 (AMD 8131 Bridge) The naming of the constant defined for PCI ID 1022:7450 does not seem to match the information at http://pciids.sourceforge.net/: http://pci-ids.ucw.cz/iii/?i=1022 There 1022:7450 is listed as "AMD-8131 PCI-X Bridge" while 1022:7451 is listed as "AMD-8131 PCI-X IOAPIC". Yet, the current definition for 0x7450 is PCI_DEVICE_ID_AMD_8131_APIC. It seems to me like that name should map to 0x7451, while a name like PCI_DEVICE_ID_AMD_8131_BRIDGE should map to 0x7450. Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 2 +- include/linux/pci_ids.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4970f47be72c..2158feffe24a 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -592,7 +592,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) pci_write_config_byte( dev, AMD8131_MISC, tmp); } } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); static void __init quirk_svw_msi(struct pci_dev *dev) { diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 870fe38378b1..8d03e10212f5 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -497,7 +497,8 @@ #define PCI_DEVICE_ID_AMD_8111_SMBUS 0x746b #define PCI_DEVICE_ID_AMD_8111_AUDIO 0x746d #define PCI_DEVICE_ID_AMD_8151_0 0x7454 -#define PCI_DEVICE_ID_AMD_8131_APIC 0x7450 +#define PCI_DEVICE_ID_AMD_8131_BRIDGE 0x7450 +#define PCI_DEVICE_ID_AMD_8131_APIC 0x7451 #define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090 #define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091 #define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093 -- cgit v1.2.3 From e778272dd547d53dedf92240e8b3dbdee44b87b6 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 30 Mar 2006 12:55:10 -0800 Subject: [PATCH] PCI: fix sparse warning about pci_bus_flags Sparse warns about casting to a __bitwise type. However, it's correct to do when defining the enum for pci_bus_flags_t, so add a __force to quiet the warnings. This will fix getting include/linux/pci.h:100:26: warning: cast to restricted type from sparse all over the build. Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- include/linux/pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/pci.h b/include/linux/pci.h index 15e1675edef9..3a6a4e37a482 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -97,7 +97,7 @@ enum pci_channel_state { typedef unsigned short __bitwise pci_bus_flags_t; enum pci_bus_flags { - PCI_BUS_FLAGS_NO_MSI = (pci_bus_flags_t) 1, + PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, }; struct pci_cap_saved_state { -- cgit v1.2.3 From 78a596b4490e17b9990d87b9d468ef5bb70daa10 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 31 Mar 2006 01:38:12 -0800 Subject: [PATCH] remove kernel/power/pm.c:pm_unregister() Since the last user is removed in -mm, we can now remove this long deprecated function. Signed-off-by: Adrian Bunk Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/pm_legacy.h | 7 ------- kernel/power/pm.c | 20 -------------------- 2 files changed, 27 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pm_legacy.h b/include/linux/pm_legacy.h index 1252b45face1..008932d73c35 100644 --- a/include/linux/pm_legacy.h +++ b/include/linux/pm_legacy.h @@ -15,11 +15,6 @@ extern int pm_active; struct pm_dev __deprecated * pm_register(pm_dev_t type, unsigned long id, pm_callback callback); -/* - * Unregister a device with power management - */ -void __deprecated pm_unregister(struct pm_dev *dev); - /* * Unregister all devices with matching callback */ @@ -41,8 +36,6 @@ static inline struct pm_dev *pm_register(pm_dev_t type, return NULL; } -static inline void pm_unregister(struct pm_dev *dev) {} - static inline void pm_unregister_all(pm_callback callback) {} static inline int pm_send_all(pm_request_t rqst, void *data) diff --git a/kernel/power/pm.c b/kernel/power/pm.c index 0f6908cce1dd..84063ac8fcfc 100644 --- a/kernel/power/pm.c +++ b/kernel/power/pm.c @@ -75,25 +75,6 @@ struct pm_dev *pm_register(pm_dev_t type, return dev; } -/** - * pm_unregister - unregister a device with power management - * @dev: device to unregister - * - * Remove a device from the power management notification lists. The - * dev passed must be a handle previously returned by pm_register. - */ - -void pm_unregister(struct pm_dev *dev) -{ - if (dev) { - mutex_lock(&pm_devs_lock); - list_del(&dev->entry); - mutex_unlock(&pm_devs_lock); - - kfree(dev); - } -} - static void __pm_unregister(struct pm_dev *dev) { if (dev) { @@ -258,7 +239,6 @@ int pm_send_all(pm_request_t rqst, void *data) } EXPORT_SYMBOL(pm_register); -EXPORT_SYMBOL(pm_unregister); EXPORT_SYMBOL(pm_unregister_all); EXPORT_SYMBOL(pm_send_all); EXPORT_SYMBOL(pm_active); -- cgit v1.2.3 From 64541d19702cfdb7ea946fdc20faee849f6874b1 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 14 Apr 2006 12:43:15 -0600 Subject: [PATCH] kill unushed __put_task_struct_cb Somehow in the midst of dotting i's and crossing t's during the merge up to rc1 we wound up keeping __put_task_struct_cb when it should have been killed as it no longer has any users. Sorry I probably should have caught this while it was still in the -mm tree. Having the old code there gets confusing when reading through the code and trying to understand what is happening. Signed-off-by: Eric W. Biederman Signed-off-by: Linus Torvalds --- include/linux/sched.h | 1 - kernel/fork.c | 6 ------ 2 files changed, 7 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sched.h b/include/linux/sched.h index e3539c14e47e..b7d31e2e1729 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -911,7 +911,6 @@ static inline int pid_alive(struct task_struct *p) extern void free_task(struct task_struct *tsk); #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0) -extern void __put_task_struct_cb(struct rcu_head *rhp); extern void __put_task_struct(struct task_struct *t); static inline void put_task_struct(struct task_struct *t) diff --git a/kernel/fork.c b/kernel/fork.c index 3384eb89cb1c..54b15f8cda53 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -124,12 +124,6 @@ void __put_task_struct(struct task_struct *tsk) free_task(tsk); } -void __put_task_struct_cb(struct rcu_head *rhp) -{ - struct task_struct *tsk = container_of(rhp, struct task_struct, rcu); - __put_task_struct(tsk); -} - void __init fork_init(unsigned long mempages) { #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR -- cgit v1.2.3 From 13626a887fad4220bc7ca85f4b42ca8cfb805e11 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 2 Apr 2006 13:17:58 +0100 Subject: [MIPS] MV6434x: The name of the CPP symbol is __mips__, not __MIPS__. Signed-off-by: Ralf Baechle --- include/linux/mv643xx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h index 955d3069d727..edfa012fad3a 100644 --- a/include/linux/mv643xx.h +++ b/include/linux/mv643xx.h @@ -13,7 +13,7 @@ #ifndef __ASM_MV643XX_H #define __ASM_MV643XX_H -#ifdef __MIPS__ +#ifdef __mips__ #include #include #endif -- cgit v1.2.3 From 5e85d4abe3f43bb5362f384bab0e20ef082ce0b5 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 18 Apr 2006 22:20:16 -0700 Subject: [PATCH] task: Make task list manipulations RCU safe While we can currently walk through thread groups, process groups, and sessions with just the rcu_read_lock, this opens the door to walking the entire task list. We already have all of the other RCU guarantees so there is no cost in doing this, this should be enough so that proc can stop taking the tasklist lock during readdir. prev_task was killed because it has no users, and using it will miss new tasks when doing an rcu traversal. Signed-off-by: Eric W. Biederman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- include/linux/sched.h | 3 +-- kernel/exit.c | 2 +- kernel/fork.c | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/fs/exec.c b/fs/exec.c index 4121bb559739..3a79d97ac234 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -712,7 +712,7 @@ static int de_thread(struct task_struct *tsk) attach_pid(current, PIDTYPE_PID, current->pid); attach_pid(current, PIDTYPE_PGID, current->signal->pgrp); attach_pid(current, PIDTYPE_SID, current->signal->session); - list_add_tail(¤t->tasks, &init_task.tasks); + list_add_tail_rcu(¤t->tasks, &init_task.tasks); current->group_leader = current; leader->group_leader = current; diff --git a/include/linux/sched.h b/include/linux/sched.h index b7d31e2e1729..29b7d4f87d20 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1192,8 +1192,7 @@ extern void wait_task_inactive(task_t * p); #define remove_parent(p) list_del_init(&(p)->sibling) #define add_parent(p) list_add_tail(&(p)->sibling,&(p)->parent->children) -#define next_task(p) list_entry((p)->tasks.next, struct task_struct, tasks) -#define prev_task(p) list_entry((p)->tasks.prev, struct task_struct, tasks) +#define next_task(p) list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks) #define for_each_process(p) \ for (p = &init_task ; (p = next_task(p)) != &init_task ; ) diff --git a/kernel/exit.c b/kernel/exit.c index 1a9787ac6173..f86434d7b3d1 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -56,7 +56,7 @@ static void __unhash_process(struct task_struct *p) detach_pid(p, PIDTYPE_PGID); detach_pid(p, PIDTYPE_SID); - list_del_init(&p->tasks); + list_del_rcu(&p->tasks); __get_cpu_var(process_counts)--; } list_del_rcu(&p->thread_group); diff --git a/kernel/fork.c b/kernel/fork.c index 54b15f8cda53..34515772611e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1204,7 +1204,7 @@ static task_t *copy_process(unsigned long clone_flags, attach_pid(p, PIDTYPE_PGID, process_group(p)); attach_pid(p, PIDTYPE_SID, p->signal->session); - list_add_tail(&p->tasks, &init_task.tasks); + list_add_tail_rcu(&p->tasks, &init_task.tasks); __get_cpu_var(process_counts)++; } attach_pid(p, PIDTYPE_PID, p->pid); -- cgit v1.2.3 From 6e89280184e4990f5ea80d2504af89b6099523c4 Mon Sep 17 00:00:00 2001 From: Anatoli Antonovitch Date: Tue, 18 Apr 2006 22:22:05 -0700 Subject: [PATCH] ide: ATI SB600 IDE support Add support for the IDE device on ATI SB600 Signed-off-by: Felix Kuehling Acked-by: Bartlomiej Zolnierkiewicz Cc: Alan Cox Acked-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/atiixp.c | 1 + include/linux/pci_ids.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'include/linux') diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index df9ee9a78435..900efd1da587 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -348,6 +348,7 @@ static struct pci_device_id atiixp_pci_tbl[] = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, }, }; MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 8d03e10212f5..d6fe048376ab 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -356,6 +356,10 @@ #define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e #define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376 #define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379 +#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a +#define PCI_DEVICE_ID_ATI_IXP600_SATA 0x4380 +#define PCI_DEVICE_ID_ATI_IXP600_SRAID 0x4381 +#define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c #define PCI_VENDOR_ID_VLSI 0x1004 #define PCI_DEVICE_ID_VLSI_82C592 0x0005 -- cgit v1.2.3 From d3a7b202995421631f486313aacf9ab2ad48b2c8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 18 Apr 2006 22:22:07 -0700 Subject: [PATCH] remove the obsolete IDEPCI_FLAG_FORCE_PDC Noted by Sergei Shtylylov Signed-off-by: Adrian Bunk Acked-by: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/pdc202xx_old.c | 2 -- drivers/ide/setup-pci.c | 13 ------------- include/linux/ide.h | 1 - 3 files changed, 16 deletions(-) (limited to 'include/linux') diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 6f8f8645b02c..7ce5bf783688 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -798,7 +798,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .flags = IDEPCI_FLAG_FORCE_PDC, },{ /* 2 */ .name = "PDC20263", .init_setup = init_setup_pdc202ata4, @@ -819,7 +818,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .flags = IDEPCI_FLAG_FORCE_PDC, },{ /* 4 */ .name = "PDC20267", .init_setup = init_setup_pdc202xx, diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 7ebf992e8c2f..462ed3006c30 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -580,7 +580,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a int port; int at_least_one_hwif_enabled = 0; ide_hwif_t *hwif, *mate = NULL; - static int secondpdc = 0; u8 tmp; index->all = 0xf0f0; @@ -592,21 +591,9 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a for (port = 0; port <= 1; ++port) { ide_pci_enablebit_t *e = &(d->enablebits[port]); - /* - * If this is a Promise FakeRaid controller, - * the 2nd controller will be marked as - * disabled while it is actually there and enabled - * by the bios for raid purposes. - * Skip the normal "is it enabled" test for those. - */ - if ((d->flags & IDEPCI_FLAG_FORCE_PDC) && - (secondpdc++==1) && (port==1)) - goto controller_ok; - if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) continue; /* port not enabled */ -controller_ok: if (d->channels <= port) break; diff --git a/include/linux/ide.h b/include/linux/ide.h index 8d2db412ba9c..a8bef1d1371c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1220,7 +1220,6 @@ typedef struct ide_pci_enablebit_s { enum { /* Uses ISA control ports not PCI ones. */ IDEPCI_FLAG_ISA_PORTS = (1 << 0), - IDEPCI_FLAG_FORCE_PDC = (1 << 1), }; typedef struct ide_pci_device_s { -- cgit v1.2.3 From 7866babad542bb5e1dc95deb5800b577abef58dd Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 18 Apr 2006 13:14:13 -0400 Subject: NFS: fix PROC_FS=n compile error fs/built-in.o: In function `nfs_show_stats':inode.c:(.text+0x15481a): undefined reference to `rpc_print_iostats' net/built-in.o: In function `rpc_destroy_client': undefined reference to `rpc_free_iostats' net/built-in.o: In function `rpc_clone_client': undefined reference to `rpc_alloc_iostats' net/built-in.o: In function `rpc_new_client': undefined reference to `rpc_alloc_iostats' net/built-in.o: In function `xprt_release': undefined reference to `rpc_count_iostats' make: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Adrian Bunk Cc: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Trond Myklebust --- include/linux/sunrpc/metrics.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include/linux') diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h index 8f96e9dc369a..77f78e56c481 100644 --- a/include/linux/sunrpc/metrics.h +++ b/include/linux/sunrpc/metrics.h @@ -69,9 +69,21 @@ struct rpc_clnt; /* * EXPORTed functions for managing rpc_iostats structures */ + +#ifdef CONFIG_PROC_FS + struct rpc_iostats * rpc_alloc_iostats(struct rpc_clnt *); void rpc_count_iostats(struct rpc_task *); void rpc_print_iostats(struct seq_file *, struct rpc_clnt *); void rpc_free_iostats(struct rpc_iostats *); +#else /* CONFIG_PROC_FS */ + +static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; } +static inline void rpc_count_iostats(struct rpc_task *task) {} +static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {} +static inline void rpc_free_iostats(struct rpc_iostats *stats) {} + +#endif /* CONFIG_PROC_FS */ + #endif /* _LINUX_SUNRPC_METRICS_H */ -- cgit v1.2.3 From e99170ff3b799a9fd43d538932a9231fac1de9d4 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 18 Apr 2006 13:21:42 -0400 Subject: NFS,SUNRPC: Fix compiler warnings if CONFIG_PROC_FS & CONFIG_SYSCTL are unset Signed-off-by: Trond Myklebust --- fs/nfs/direct.c | 8 +++----- fs/nfs/file.c | 5 ++--- include/linux/sunrpc/xprt.h | 1 + 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 0f583cb16ddb..3c72b0c07283 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -112,10 +112,9 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode */ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) { - struct dentry *dentry = iocb->ki_filp->f_dentry; - dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n", - dentry->d_name.name, (long long) pos, nr_segs); + iocb->ki_filp->f_dentry->d_name.name, + (long long) pos, nr_segs); return -EINVAL; } @@ -468,7 +467,6 @@ static const struct rpc_call_ops nfs_commit_direct_ops = { static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) { struct nfs_write_data *data = dreq->commit_data; - struct rpc_task *task = &data->task; data->inode = dreq->inode; data->cred = dreq->ctx->cred; @@ -489,7 +487,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ dreq->commit_data = NULL; - dprintk("NFS: %5u initiated commit call\n", task->tk_pid); + dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); lock_kernel(); rpc_execute(&data->task); diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f1df2c8d9259..fade02c15e6e 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -534,10 +534,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) */ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) { - struct inode * inode = filp->f_mapping->host; - dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n", - inode->i_sb->s_id, inode->i_ino, + filp->f_dentry->d_inode->i_sb->s_id, + filp->f_dentry->d_inode->i_ino, fl->fl_type, fl->fl_flags); /* diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 7eebbab7160b..e8bbe8118de8 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -53,6 +53,7 @@ struct rpc_timeout { struct rpc_task; struct rpc_xprt; +struct seq_file; /* * This describes a complete RPC request -- cgit v1.2.3 From dc6de33674608f978ec29f5c2f7e3af458c06f78 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 20 Apr 2006 00:10:50 -0700 Subject: [NET]: Add skb->truesize assertion checking. Add some sanity checking. truesize should be at least sizeof(struct sk_buff) plus the current packet length. If not, then truesize is seriously mangled and deserves a kernel log message. Currently we'll do the check for release of stream socket buffers. But we can add checks to more spots over time. Incorporating ideas from Herbert Xu. Signed-off-by: David S. Miller --- include/linux/skbuff.h | 7 +++++++ include/net/sock.h | 1 + net/core/skbuff.c | 8 ++++++++ net/core/stream.c | 1 + 4 files changed, 17 insertions(+) (limited to 'include/linux') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c4619a428d9b..f8f234708b98 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -344,6 +344,13 @@ extern void skb_over_panic(struct sk_buff *skb, int len, void *here); extern void skb_under_panic(struct sk_buff *skb, int len, void *here); +extern void skb_truesize_bug(struct sk_buff *skb); + +static inline void skb_truesize_check(struct sk_buff *skb) +{ + if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len)) + skb_truesize_bug(skb); +} extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, int getfrag(void *from, char *to, int offset, diff --git a/include/net/sock.h b/include/net/sock.h index af2b0544586e..ff8b0dad7b0f 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -454,6 +454,7 @@ static inline void sk_stream_set_owner_r(struct sk_buff *skb, struct sock *sk) static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb) { + skb_truesize_check(skb); sock_set_flag(sk, SOCK_QUEUE_SHRUNK); sk->sk_wmem_queued -= skb->truesize; sk->sk_forward_alloc += skb->truesize; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 09464fa8d72f..fb3770f9c094 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -112,6 +112,14 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) BUG(); } +void skb_truesize_bug(struct sk_buff *skb) +{ + printk(KERN_ERR "SKB BUG: Invalid truesize (%u) " + "len=%u, sizeof(sk_buff)=%Zd\n", + skb->truesize, skb->len, sizeof(struct sk_buff)); +} +EXPORT_SYMBOL(skb_truesize_bug); + /* Allocate a new skbuff. We do this ourselves so we can fill in a few * 'private' fields and also do memory statistics to find all the * [BEEP] leaks. diff --git a/net/core/stream.c b/net/core/stream.c index 35e25259fd95..e9489696f694 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -176,6 +176,7 @@ void sk_stream_rfree(struct sk_buff *skb) { struct sock *sk = skb->sk; + skb_truesize_check(skb); atomic_sub(skb->truesize, &sk->sk_rmem_alloc); sk->sk_forward_alloc += skb->truesize; } -- cgit v1.2.3 From 72b38d436e4cd18185de11f4b48a6e62eb104644 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 20 Apr 2006 02:43:23 -0700 Subject: [PATCH] memory_hotplug.h cleanup We don't have to #if guard prototypes. This also fixes a bug observed by Randy Dunlap due to a misspelled option in the #if. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/memory_hotplug.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 4ca3e6ad03ec..911206386171 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -99,10 +99,7 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, return -ENOSYS; } -#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \ - || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) extern int add_memory(u64 start, u64 size); extern int remove_memory(u64 start, u64 size); -#endif #endif /* __LINUX_MEMORY_HOTPLUG_H */ -- cgit v1.2.3