diff -u --recursive --new-file v2.2.9/linux/CREDITS linux/CREDITS --- v2.2.9/linux/CREDITS Tue May 11 13:10:26 1999 +++ linux/CREDITS Fri May 14 09:00:16 1999 @@ -656,7 +656,7 @@ E: rgooch@atnf.csiro.au D: parent process death signal to children D: prctl() syscall -D: /proc/mtrr support to manipulate MTRRs on Pentium Pro's +D: /proc/mtrr support to manipulate MTRRs on Intel P6 family S: CSIRO Australia Telescope National Facility S: P.O. Box 76, Epping S: New South Wales, 2121 @@ -753,6 +753,13 @@ S: 77 Clarence Mews S: London SE16 1GD S: United Kingdom + +N: Bart Hartgers +E: bart@etpmod.phys.tue.nl +D: MTRR emulation with Centaur MCRs +S: Gen Stedmanstraat 212 +S: 5623 HZ Eindhoven +S: The Netherlands N: Kai Harrekilde-Petersen E: khp@dolphinics.no diff -u --recursive --new-file v2.2.9/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.2.9/linux/Documentation/Configure.help Tue May 11 13:10:26 1999 +++ linux/Documentation/Configure.help Fri May 14 09:00:16 1999 @@ -8684,6 +8684,9 @@ The AMD K6-2 (stepping 8 and above) and K6-3 processors have two MTRRs. These are supported. + + The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These + are supported. Saying Y here also fixes a problem with buggy SMP BIOSes which only set the MTRRs for the boot CPU and not the secondary CPUs. This can diff -u --recursive --new-file v2.2.9/linux/Documentation/sound/CMI8330 linux/Documentation/sound/CMI8330 --- v2.2.9/linux/Documentation/sound/CMI8330 Wed Mar 10 15:29:44 1999 +++ linux/Documentation/sound/CMI8330 Wed May 26 09:29:42 1999 @@ -1,46 +1,48 @@ -How to enable CMI 8330 soundchip on Linux +How to enable CMI 8330 (SOUNDPRO) soundchip on Linux ------------------------------------------ Stefan Laudat -Hello folks, - - The CMI8330 soundchip is a very small chip found on many recent - motherboards. In order to use it you just have to use a proper - isapnp.conf and a little bit of patience. +[Note: The CMI 8338 is unrelated and right now unsupported] + - Of course you will have to compile kernel sound support as module, - as shown below: + In order to use CMI8330 under Linux you just have to use a proper isapnp.conf, a good isapnp and a little bit of patience. I use isapnp 1.17, but +you may get a better one I guess at http://www.roestock.demon.co.uk/isapnptools/. + + Of course you will have to compile kernel sound support as module, as shown below: CONFIG_SOUND=m CONFIG_SOUND_OSS=m CONFIG_SOUND_SB=m CONFIG_SOUND_ADLIB=m CONFIG_SOUND_MPU401=m -# Just for fun :) +# Mikro$chaft sound system (kinda useful here ;)) CONFIG_SOUND_MSS=m The /etc/isapnp.conf file will be: + (READPORT 0x0203) (ISOLATE PRESERVE) (IDENTIFY *) (VERBOSITY 2) (CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING (VERIFYLD N) + + # WSS (CONFIGURE CMI0001/16777472 (LD 0 (IO 0 (SIZE 8) (BASE 0x0530)) (IO 1 (SIZE 8) (BASE 0x0388)) -(INT 0 (IRQ 5 (MODE +E))) +(INT 0 (IRQ 7 (MODE +E))) (DMA 0 (CHANNEL 0)) (NAME "CMI0001/16777472[0]{CMI8330/C3D Audio Adapter}") (ACT Y) )) -# Control device ? +# MPU (CONFIGURE CMI0001/16777472 (LD 1 (IO 0 (SIZE 2) (BASE 0x0330)) @@ -57,10 +59,11 @@ (ACT Y) )) -# SB... +# SoundBlaster + (CONFIGURE CMI0001/16777472 (LD 3 (IO 0 (SIZE 16) (BASE 0x0220)) -(INT 0 (IRQ 7 (MODE +E))) +(INT 0 (IRQ 5 (MODE +E))) (DMA 0 (CHANNEL 1)) (DMA 1 (CHANNEL 5)) (NAME "CMI0001/16777472[3]{CMI8330/C3D Audio Adapter}") @@ -74,13 +77,22 @@ The module sequence is trivial: -/sbin/modprobe sound -# You need to load the ad1848 module first. That matters, otherwise the -# chip falls into soundblaster compatibility and you won't get it back out -/sbin/insmod ad1848 io=0x530 dma=0 irq=5 soundpro=1 +/sbin/insmod soundcore +/sbin/insmod sound /sbin/insmod uart401 -/sbin/insmod sb io=0x220 irq=5 dma=1 dma16=-1 -/sbin/insmod mpu401 io=0x330 -/sbin/insmod opl3 io=0x388 +# insert this first +/sbin/insmod ad1848 io=0x530 irq=7 dma=0 soundpro=1 +# The sb module is an alternative to the ad1848 (Microsoft Sound System) +# Anyhow, this is full duplex and has MIDI +/sbin/insmod sb io=0x220 dma=1 dma16=5 irq=5 mpu_io=0x330 + + - The soundchip is now fully initialized. Enjoy it. +Alma Chao suggests the following /etc/conf.modules: + +alias sound ad1848 +alias synth0 opl3 +options ad1848 io=0x530 irq=7 dma=0 soundpro=1 +options opl3 io=0x388 + + diff -u --recursive --new-file v2.2.9/linux/Documentation/svga.txt linux/Documentation/svga.txt --- v2.2.9/linux/Documentation/svga.txt Thu Jul 16 18:09:22 1998 +++ linux/Documentation/svga.txt Fri May 14 12:47:07 1999 @@ -1,5 +1,5 @@ - Video Mode Selection Support 2.11 - (c) 1995--1997 Martin Mares, + Video Mode Selection Support 2.13 + (c) 1995--1999 Martin Mares, -------------------------------------------------------------------------------- 1. Intro @@ -9,6 +9,11 @@ to usage of the BIOS, the selection is limited to boot time (before the kernel decompression starts) and works only on 80X86 machines. + ** Short intro for the impatient: Just use vga=ask for the first time, + ** enter `scan' on the video mode prompt, pick the mode you want to use, + ** remember its mode ID (the four-digit hexadecimal number) and then + ** set the vga parameter to this number (converted to decimal first). + The video mode to be used is selected by a kernel parameter which can be specified in the kernel Makefile (the SVGA_MODE=... line) or by the "vga=..." option of LILO (or some other boot loader you use) or by the "vidmode" utility @@ -268,3 +273,4 @@ - Removed the doc section describing adding of new probing functions as I try to get rid of _all_ hardware probing here. 2.12 (25-May-98)- Added support for VESA frame buffer graphics. +2.13 (14-May-99)- Minor documentation fixes. diff -u --recursive --new-file v2.2.9/linux/Makefile linux/Makefile --- v2.2.9/linux/Makefile Thu May 13 23:10:29 1999 +++ linux/Makefile Fri May 28 18:10:19 1999 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 2 -SUBLEVEL = 9 +SUBLEVEL = 10 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -u --recursive --new-file v2.2.9/linux/README linux/README --- v2.2.9/linux/README Fri Jan 8 22:36:00 1999 +++ linux/README Sun May 30 10:17:03 1999 @@ -32,11 +32,11 @@ - There is a lot of documentation available both in electronic form on the Internet and in books, both Linux-specific and pertaining to general UNIX questions. I'd recommend looking into the documentation - subdirectories on any Linux ftp site for the LDP (Linux Documentation + subdirectories on any Linux FTP site for the LDP (Linux Documentation Project) books. This README is not meant to be documentation on the system: there are much better sources available. - - There are various readme's in the kernel Documentation/ subdirectory: + - There are various README files in the Documentation/ subdirectory: these typically contain kernel-specific installation notes for some drivers for example. See ./Documentation/00-INDEX for a list of what is contained in each file. Please read the Changes file, as it @@ -219,7 +219,7 @@ isn't anyone listed there, then the second best thing is to mail them to me (torvalds@transmeta.com), and possibly to any other relevant mailing-list or to the newsgroup. The mailing-lists are - useful especially for SCSI and NETworking problems, as I can't test + useful especially for SCSI and networking problems, as I can't test either of those personally anyway. - In all bug-reports, *please* tell what kernel you are talking about, diff -u --recursive --new-file v2.2.9/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.2.9/linux/arch/alpha/config.in Tue May 11 13:10:27 1999 +++ linux/arch/alpha/config.in Sat May 22 13:41:37 1999 @@ -142,6 +142,7 @@ if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \ -o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_JENSEN" = "y" \ + -o "$CONFIG_ALPHA_TAKARA" = "y" -o "$CONFIG_ALPHA_EB164" = "y" \ -o "$CONFIG_ALPHA_MIKASA" = "y" -o "$CONFIG_ALPHA_ALCOR" = "y" \ -o "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_MIATA" = "y" \ -o "$CONFIG_ALPHA_NORITAKE" = "y" -o "$CONFIG_ALPHA_PC164" = "y" \ @@ -166,7 +167,11 @@ define_bool CONFIG_ALPHA_AVANTI y fi -bool 'Symmetric multi-processing support' CONFIG_SMP +if [ "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_RAWHIDE" = "y" \ + -o "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_GENERIC" = "y" ] +then + bool 'Symmetric multi-processing support' CONFIG_SMP +fi if [ "$CONFIG_PCI" = "y" ]; then bool 'PCI quirks' CONFIG_PCI_QUIRKS diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.2.9/linux/arch/alpha/kernel/alpha_ksyms.c Tue Jan 19 11:32:50 1999 +++ linux/arch/alpha/kernel/alpha_ksyms.c Sat May 22 13:41:43 1999 @@ -52,6 +52,7 @@ EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(disable_irq_nosync); EXPORT_SYMBOL(screen_info); EXPORT_SYMBOL(perf_irq); @@ -170,8 +171,8 @@ EXPORT_SYMBOL(__global_restore_flags); #if DEBUG_SPINLOCK EXPORT_SYMBOL(spin_unlock); -EXPORT_SYMBOL(spin_lock); -EXPORT_SYMBOL(spin_trylock); +EXPORT_SYMBOL(debug_spin_lock); +EXPORT_SYMBOL(debug_spin_trylock); #endif #if DEBUG_RWLOCK EXPORT_SYMBOL(write_lock); diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c --- v2.2.9/linux/arch/alpha/kernel/core_cia.c Wed Sep 9 14:51:03 1998 +++ linux/arch/alpha/kernel/core_cia.c Sat May 22 13:41:43 1999 @@ -598,7 +598,7 @@ { CIA_jd = *(vuip)CIA_IOC_CIA_ERR; DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd)); - *(vuip)CIA_IOC_CIA_ERR = 0x0180; + *(vuip)CIA_IOC_CIA_ERR = CIA_jd; mb(); return 0; } @@ -698,6 +698,10 @@ reason = buf; break; } + mb(); + mb(); /* magic */ + draina(); + cia_pci_clr_err(); wrmces(rdmces()); /* reset machine check pending flag */ mb(); diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/fpreg.c linux/arch/alpha/kernel/fpreg.c --- v2.2.9/linux/arch/alpha/kernel/fpreg.c Tue Aug 18 22:02:02 1998 +++ linux/arch/alpha/kernel/fpreg.c Sat May 22 13:41:47 1999 @@ -1,10 +1,10 @@ /* - * kernel/fpreg.c + * arch/alpha/kernel/fpreg.c * * (C) Copyright 1998 Linus Torvalds */ -#ifdef __alpha_cix__ +#if defined(__alpha_cix__) || defined(__alpha_fix__) #define STT(reg,val) asm volatile ("ftoit $f"#reg",%0" : "=r"(val)); #else #define STT(reg,val) asm volatile ("stt $f"#reg",%0" : "=m"(val)); @@ -52,7 +52,7 @@ return val; } -#ifdef __alpha_cix__ +#if defined(__alpha_cix__) || defined(__alpha_fix__) #define LDT(reg,val) asm volatile ("itoft %0,$f"#reg : : "r"(val)); #else #define LDT(reg,val) asm volatile ("ldt $f"#reg",%0" : : "m"(val)); diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/head.S linux/arch/alpha/kernel/head.S --- v2.2.9/linux/arch/alpha/kernel/head.S Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/kernel/head.S Sat May 22 13:41:51 1999 @@ -32,24 +32,26 @@ #ifdef __SMP__ .align 3 - .globl __start_cpu - .ent __start_cpu - /* On entry here from SRM console, the HWPCB of this processor - has been loaded, and $27 contains the task pointer */ -__start_cpu: - .prologue 0 - /* First order of business, load the GP */ - br $26,1f -1: ldgp $29,0($26) - /* We need to get current loaded up with our first task... */ - mov $27,$8 - /* Set FEN */ - lda $16,1($31) - call_pal PAL_wrfen - /* ... and then we can start the processor. */ - jsr $26,start_secondary + .globl __smp_callin + .ent __smp_callin + /* On entry here from SRM console, the HWPCB of the per-cpu + slot for this processor has been loaded. We've arranged + for the UNIQUE value for this process to contain the PCBB + of the target idle task. */ +__smp_callin: + .prologue 1 + ldgp $29,0($27) # First order of business, load the GP. + + call_pal PAL_rduniq # Grab the target PCBB. + mov $0,$16 # Install it. + call_pal PAL_swpctx + + lda $8,0x3fff # Find "current". + bic $30,$8,$8 + + jsr $26,smp_callin call_pal PAL_halt - .end __start_cpu + .end __smp_callin #endif /* __SMP__ */ .align 3 diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v2.2.9/linux/arch/alpha/kernel/irq.c Tue Jan 19 11:32:50 1999 +++ linux/arch/alpha/kernel/irq.c Sat May 22 13:42:26 1999 @@ -192,13 +192,21 @@ } void -disable_irq(unsigned int irq_nr) +disable_irq_nosync(unsigned int irq_nr) { unsigned long flags; save_and_cli(flags); mask_irq(irq_nr); restore_flags(flags); +} + +void +disable_irq(unsigned int irq_nr) +{ + /* This works non-SMP, and SMP until we write code to distribute + interrupts to more that cpu 0. */ + disable_irq_nosync(irq_nr); } void diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.2.9/linux/arch/alpha/kernel/process.c Tue May 11 13:10:27 1999 +++ linux/arch/alpha/kernel/process.c Sat May 22 13:42:29 1999 @@ -75,33 +75,46 @@ return 0; } -static void __attribute__((noreturn)) -do_cpu_idle(void) +#ifdef __SMP__ +void +cpu_idle(void *unused) { /* An endless idle loop with no priority at all. */ current->priority = 0; + current->counter = -100; + while (1) { - check_pgt_cache(); - run_task_queue(&tq_scheduler); - current->counter = 0; - schedule(); - } -} + /* FIXME -- EV6 and LCA45 know how to power down + the CPU. */ -#ifdef __SMP__ -void -cpu_idle(void *unused) -{ - do_cpu_idle(); + /* Although we are an idle CPU, we do not want to + get into the scheduler unnecessarily. */ + if (current->need_resched) { + schedule(); + check_pgt_cache(); + } + } } #endif asmlinkage int sys_idle(void) { - if (current->pid == 0) - do_cpu_idle(); - return -EPERM; + if (current->pid != 0) + return -EPERM; + + /* An endless idle loop with no priority at all. */ + current->priority = 0; + current->counter = -100; + init_idle(); + + while (1) { + /* FIXME -- EV6 and LCA45 know how to power down + the CPU. */ + + schedule(); + check_pgt_cache(); + } } void diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h --- v2.2.9/linux/arch/alpha/kernel/proto.h Tue Feb 23 15:21:32 1999 +++ linux/arch/alpha/kernel/proto.h Sat May 22 13:42:31 1999 @@ -151,6 +151,8 @@ extern void setup_smp(void); extern int smp_info(char *buffer); extern void handle_ipi(struct pt_regs *); +extern void smp_percpu_timer_interrupt(struct pt_regs *); +extern int smp_boot_cpuid; /* bios32.c */ extern void reset_for_srm(void); @@ -178,7 +180,7 @@ extern void wrmces(unsigned long mces); extern void cserve_ena(unsigned long); extern void cserve_dis(unsigned long); -extern void __start_cpu(unsigned long); +extern void __smp_callin(void); /* entry.S */ extern void entArith(void); diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v2.2.9/linux/arch/alpha/kernel/setup.c Wed Apr 28 11:37:29 1999 +++ linux/arch/alpha/kernel/setup.c Sat May 22 13:42:31 1999 @@ -106,6 +106,7 @@ WEAK(alphabook1_mv); WEAK(avanti_mv); WEAK(cabriolet_mv); +WEAK(clipper_mv); WEAK(dp264_mv); WEAK(eb164_mv); WEAK(eb64p_mv); @@ -330,6 +331,10 @@ /* Round it up to an even number of pages. */ high = (high + PAGE_SIZE) & (PAGE_MASK*2); + + /* Enforce maximum of 2GB even if there is more. Blah. */ + if (high > 0x80000000UL) + high = 0x80000000UL; return PAGE_OFFSET + high; } @@ -448,11 +453,11 @@ static struct alpha_machine_vector *tsunami_vecs[] __initlocaldata = { NULL, - &dp264_mv, /* dp164 */ + &dp264_mv, /* dp264 */ &dp264_mv, /* warhol */ &dp264_mv, /* windjammer */ &monet_mv, /* monet */ - &dp264_mv, /* clipper */ + &clipper_mv, /* clipper */ &dp264_mv, /* goldrush */ &webbrick_mv, /* webbrick */ &dp264_mv, /* catamaran */ @@ -537,6 +542,7 @@ &alphabook1_mv, &avanti_mv, &cabriolet_mv, + &clipper_mv, &dp264_mv, &eb164_mv, &eb64p_mv, diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c --- v2.2.9/linux/arch/alpha/kernel/signal.c Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/kernel/signal.c Sat May 22 13:42:36 1999 @@ -24,6 +24,12 @@ #include #include +#include "proto.h" + + +#include "proto.h" + + #define DEBUG_SIG 0 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c --- v2.2.9/linux/arch/alpha/kernel/smp.c Tue May 11 13:10:27 1999 +++ linux/arch/alpha/kernel/smp.c Sat May 22 13:42:40 1999 @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -29,6 +30,8 @@ #include #include "proto.h" +#include "irq.h" + #define DEBUG_SMP 0 #if DEBUG_SMP @@ -37,62 +40,44 @@ #define DBGS(args) #endif -struct ipi_msg_flush_tb_struct { - volatile unsigned int flush_tb_mask; - union { - struct mm_struct * flush_mm; - struct vm_area_struct * flush_vma; - } p; - unsigned long flush_addr; - unsigned long flush_end; -}; - -static struct ipi_msg_flush_tb_struct ipi_msg_flush_tb __cacheline_aligned; -static spinlock_t flush_tb_lock = SPIN_LOCK_UNLOCKED; - +/* A collection of per-processor data. */ struct cpuinfo_alpha cpu_data[NR_CPUS]; -spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED; -spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; - -unsigned int boot_cpu_id = 0; -static int smp_activated = 0; +/* A collection of single bit ipi messages. */ +static struct { + unsigned long bits __cacheline_aligned; +} ipi_data[NR_CPUS]; -int smp_found_config = 0; /* Have we found an SMP box */ -static int max_cpus = -1; +enum ipi_message_type { + IPI_RESCHEDULE, + IPI_CALL_FUNC, + IPI_CPU_STOP, +}; -unsigned int cpu_present_map = 0; +spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED; -int smp_num_cpus = 1; -int smp_num_probed = 0; /* Internal processor count */ +/* Set to a secondary's cpuid when it comes online. */ +static unsigned long smp_secondary_alive; -int smp_threads_ready = 0; -volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; -volatile unsigned long smp_spinning[NR_CPUS] = { 0, }; +unsigned long cpu_present_mask; /* Which cpus ids came online. */ +static int max_cpus = -1; /* Command-line limitation. */ +int smp_boot_cpuid; /* Which processor we booted from. */ +int smp_num_probed; /* Internal processor count */ +int smp_num_cpus = 1; /* Number that came online. */ +int smp_threads_ready; /* True once the per process idle is forked. */ cycles_t cacheflush_time; -unsigned int prof_multiplier[NR_CPUS]; -unsigned int prof_counter[NR_CPUS]; - -volatile int ipi_bits[NR_CPUS] __cacheline_aligned; - -unsigned long boot_cpu_palrev; - -volatile int smp_commenced = 0; -volatile int smp_processors_ready = 0; - -volatile int cpu_number_map[NR_CPUS]; -volatile int cpu_logical_map[NR_CPUS]; +int cpu_number_map[NR_CPUS]; +int __cpu_logical_map[NR_CPUS]; extern void calibrate_delay(void); -extern struct thread_struct * original_pcb_ptr; - -static void smp_setup_percpu_timer(void); -static void secondary_cpu_start(int, struct task_struct *); -static void send_cpu_msg(char *, int); +extern asmlinkage void entInt(void); -/* Process bootcommand SMP options, like "nosmp" and "maxcpus=" */ + +/* + * Process bootcommand SMP options, like "nosmp" and "maxcpus=". + */ void __init smp_setup(char *str, int *ints) { @@ -102,100 +87,87 @@ max_cpus = 0; } -static void __init -smp_store_cpu_info(int id) +/* + * Called by both boot and secondaries to move global data into + * per-processor storage. + */ +static inline void __init +smp_store_cpu_info(int cpuid) { - /* This is it on Alpha, so far. */ - cpu_data[id].loops_per_sec = loops_per_sec; + cpu_data[cpuid].loops_per_sec = loops_per_sec; } -void __init -smp_commence(void) +/* + * Ideally sets up per-cpu profiling hooks. Doesn't do much now... + */ +static inline void __init +smp_setup_percpu_timer(int cpuid) { - /* Lets the callin's below out of their loop. */ - mb(); - smp_commenced = 1; + cpu_data[cpuid].prof_counter = 1; + cpu_data[cpuid].prof_multiplier = 1; + +#ifdef NOT_YET_PROFILING + load_profile_irq(mid_xlate[cpu], lvl14_resolution); + if (cpu == smp_boot_cpuid) + enable_pil_irq(14); +#endif } +/* + * Where secondaries begin a life of C. + */ void __init smp_callin(void) { int cpuid = hard_smp_processor_id(); DBGS(("CALLIN %d state 0x%lx\n", cpuid, current->state)); -#ifdef HUH - local_flush_cache_all(); - local_flush_tlb_all(); -#endif -#if 0 - set_irq_udt(mid_xlate[boot_cpu_id]); -#endif + + /* Turn on machine checks. */ + wrmces(7); + + /* Set trap vectors. */ + trap_init(); + + /* Set interrupt vector. */ + wrent(entInt, 0); + + /* Setup the scheduler for this processor. */ + init_idle(); /* Get our local ticker going. */ - smp_setup_percpu_timer(); + smp_setup_percpu_timer(cpuid); -#if 0 + /* Must have completely accurate bogos. */ + __sti(); calibrate_delay(); -#endif smp_store_cpu_info(cpuid); -#ifdef HUH - local_flush_cache_all(); - local_flush_tlb_all(); -#endif /* Allow master to continue. */ - set_bit(cpuid, (unsigned long *)&cpu_callin_map[cpuid]); -#ifdef HUH - local_flush_cache_all(); - local_flush_tlb_all(); -#endif - -#ifdef NOT_YET - while(!task[cpuid] || current_set[cpuid] != task[cpuid]) - barrier(); -#endif + wmb(); + smp_secondary_alive = cpuid; -#ifdef HUH - local_flush_cache_all(); - local_flush_tlb_all(); -#endif -#if 0 - __sti(); -#endif -} - -asmlinkage int __init -start_secondary(void *unused) -{ - extern asmlinkage void entInt(void); - extern void paging_init_secondary(void); + /* Wait for the go code. */ + while (!smp_threads_ready) + barrier(); - wrmces(7); - paging_init_secondary(); - trap_init(); - wrent(entInt, 0); + printk(KERN_INFO "SMP: commencing CPU %d current %p\n", + cpuid, current); - smp_callin(); - while (!smp_commenced) - barrier(); -#if 1 - printk("start_secondary: commencing CPU %d current %p\n", - hard_smp_processor_id(), current); -#endif + /* Do nothing. */ cpu_idle(NULL); } + +/* + * Rough estimation for SMP scheduling, this is the number of cycles it + * takes for a fully memory-limited process to flush the SMP-local cache. + * + * We are not told how much cache there is, so we have to guess. + */ static void __init smp_tune_scheduling (void) { - /* - * Rough estimation for SMP scheduling, this is the number of - * cycles it takes for a fully memory-limited process to flush - * the SMP-local cache. - * - * We are not told how much cache there is, so we have to guess. - */ - struct percpu_struct *cpu; unsigned long on_chip_cache; unsigned long freq; @@ -231,259 +203,159 @@ cacheflush_time = freq / 1024 * on_chip_cache / 5000; } - /* - * Cycle through the processors sending START msgs to boot each. + * Send a message to a secondary's console. "START" is one such + * interesting message. ;-) */ -void __init -smp_boot_cpus(void) +static void +send_secondary_console_msg(char *str, int cpuid) { - int cpucount = 0; - int i, first, prev; - - printk("Entering SMP Mode.\n"); - -#if 0 - __sti(); -#endif - - for(i=0; i < NR_CPUS; i++) { - cpu_number_map[i] = -1; - cpu_logical_map[i] = -1; - prof_counter[i] = 1; - prof_multiplier[i] = 1; - ipi_bits[i] = 0; - } - - cpu_number_map[boot_cpu_id] = 0; - cpu_logical_map[0] = boot_cpu_id; - current->processor = boot_cpu_id; /* ??? */ + struct percpu_struct *cpu; + register char *cp1, *cp2; + unsigned long cpumask; + size_t len; + long timeout; - smp_store_cpu_info(boot_cpu_id); - smp_tune_scheduling(); -#ifdef NOT_YET - printk("CPU%d: ", boot_cpu_id); - print_cpu_info(&cpu_data[boot_cpu_id]); - set_irq_udt(mid_xlate[boot_cpu_id]); -#endif - smp_setup_percpu_timer(); -#ifdef HUH - local_flush_cache_all(); -#endif - if (smp_num_probed == 1) - return; /* Not an MP box. */ + cpu = (struct percpu_struct *) + ((char*)hwrpb + + hwrpb->processor_offset + + cpuid * hwrpb->processor_size); -#if NOT_YET - /* - * If SMP should be disabled, then really disable it! - */ - if (!max_cpus) - { - smp_found_config = 0; - printk(KERN_INFO "SMP mode deactivated.\n"); - } -#endif + cpumask = (1L << cpuid); + if (hwrpb->txrdy & cpumask) + goto delay1; + ready1: - for (i = 0; i < NR_CPUS; i++) { + cp2 = str; + len = strlen(cp2); + *(unsigned int *)&cpu->ipc_buffer[0] = len; + cp1 = (char *) &cpu->ipc_buffer[1]; + memcpy(cp1, cp2, len); - if (i == boot_cpu_id) - continue; + /* atomic test and set */ + wmb(); + set_bit(cpuid, &hwrpb->rxrdy); - if (cpu_present_map & (1 << i)) { - struct task_struct *idle; - int timeout; - - /* Cook up an idler for this guy. */ - kernel_thread(start_secondary, NULL, CLONE_PID); - idle = task[++cpucount]; - if (!idle) - panic("No idle process for CPU %d", i); - idle->processor = i; - - DBGS(("smp_boot_cpus: CPU %d state 0x%lx flags 0x%lx\n", - i, idle->state, idle->flags)); - - /* whirrr, whirrr, whirrrrrrrrr... */ -#ifdef HUH - local_flush_cache_all(); -#endif - secondary_cpu_start(i, idle); + if (hwrpb->txrdy & cpumask) + goto delay2; + ready2: + return; - /* wheee... it's going... wait for 5 secs...*/ - for (timeout = 0; timeout < 50000; timeout++) { - if (cpu_callin_map[i]) - break; - udelay(100); - } - if (cpu_callin_map[i]) { - /* Another "Red Snapper". */ - cpu_number_map[i] = cpucount; - cpu_logical_map[cpucount] = i; - } else { - cpucount--; - printk("smp_boot_cpus: Processor %d" - " is stuck 0x%lx.\n", i, idle->flags); - } - } - if (!(cpu_callin_map[i])) { - cpu_present_map &= ~(1 << i); - cpu_number_map[i] = -1; - } - } -#ifdef HUH - local_flush_cache_all(); -#endif - if (cpucount == 0) { - printk("smp_boot_cpus: ERROR - only one Processor found.\n"); - cpu_present_map = (1 << smp_processor_id()); - } else { - unsigned long bogosum = 0; - for (i = 0; i < NR_CPUS; i++) { - if (cpu_present_map & (1 << i)) - bogosum += cpu_data[i].loops_per_sec; - } - printk("smp_boot_cpus: Total of %d Processors activated" - " (%lu.%02lu BogoMIPS).\n", - cpucount + 1, - (bogosum + 2500)/500000, - ((bogosum + 2500)/5000)%100); - smp_activated = 1; - smp_num_cpus = cpucount + 1; +delay1: + /* Wait one second. Note that jiffies aren't ticking yet. */ + for (timeout = 100000; timeout > 0; --timeout) { + if (!(hwrpb->txrdy & cpumask)) + goto ready1; + udelay(10); + barrier(); } + goto timeout; - /* Setup CPU list for IRQ distribution scheme. */ - first = prev = -1; - for (i = 0; i < NR_CPUS; i++) { - if (cpu_present_map & (1 << i)) { - if (first == -1) - first = i; - if (prev != -1) - cpu_data[i].next = i; - prev = i; - } +delay2: + /* Wait one second. */ + for (timeout = 100000; timeout > 0; --timeout) { + if (!(hwrpb->txrdy & cpumask)) + goto ready2; + udelay(10); + barrier(); } - cpu_data[prev].next = first; + goto timeout; - /* Ok, they are spinning and ready to go. */ - smp_processors_ready = 1; +timeout: + printk("Processor %x not ready\n", cpuid); + return; } -static void __init -smp_setup_percpu_timer(void) +/* + * A secondary console wants to send a message. Receive it. + */ +static void +recv_secondary_console_msg(void) { - int cpu = smp_processor_id(); - - prof_counter[cpu] = prof_multiplier[cpu] = 1; -#ifdef NOT_YET - load_profile_irq(mid_xlate[cpu], lvl14_resolution); - if (cpu == boot_cpu_id) - enable_pil_irq(14); -#endif -} - -extern void update_one_process(struct task_struct *p, unsigned long ticks, - unsigned long user, unsigned long system, - int cpu); + int mycpu, i, cnt; + unsigned long txrdy = hwrpb->txrdy; + char *cp1, *cp2, buf[80]; + struct percpu_struct *cpu; -void -smp_percpu_timer_interrupt(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); + DBGS(("recv_secondary_console_msg: TXRDY 0x%lx.\n", txrdy)); -#ifdef NOT_YET - clear_profile_irq(mid_xlate[cpu]); - if(!user_mode(regs)) - alpha_do_profile(regs->pc); -#endif + mycpu = hard_smp_processor_id(); - if (!--prof_counter[cpu]) { - int user = user_mode(regs); - if (current->pid) { - update_one_process(current, 1, user, !user, cpu); + for (i = 0; i < NR_CPUS; i++) { + if (!(txrdy & (1L << i))) + continue; - if (--current->counter < 0) { - current->counter = 0; - current->need_resched = 1; - } + DBGS(("recv_secondary_console_msg: " + "TXRDY contains CPU %d.\n", i)); - spin_lock(&ticker_lock); - if (user) { - if (current->priority < DEF_PRIORITY) { - kstat.cpu_nice++; - kstat.per_cpu_nice[cpu]++; - } else { - kstat.cpu_user++; - kstat.per_cpu_user[cpu]++; - } - } else { - kstat.cpu_system++; - kstat.per_cpu_system[cpu]++; - } - spin_unlock(&ticker_lock); - } - prof_counter[cpu] = prof_multiplier[cpu]; - } -} + cpu = (struct percpu_struct *) + ((char*)hwrpb + + hwrpb->processor_offset + + i * hwrpb->processor_size); -int __init -setup_profiling_timer(unsigned int multiplier) -{ -#ifdef NOT_YET - int i; - unsigned long flags; + printk(KERN_INFO "recv_secondary_console_msg: on %d from %d" + " HALT_REASON 0x%lx FLAGS 0x%lx\n", + mycpu, i, cpu->halt_reason, cpu->flags); - /* Prevent level14 ticker IRQ flooding. */ - if((!multiplier) || (lvl14_resolution / multiplier) < 500) - return -EINVAL; + cnt = cpu->ipc_buffer[0] >> 32; + if (cnt <= 0 || cnt >= 80) + strcpy(buf, "<<< BOGUS MSG >>>"); + else { + cp1 = (char *) &cpu->ipc_buffer[11]; + cp2 = buf; + strcpy(cp2, cp1); + + while ((cp2 = strchr(cp2, '\r')) != 0) { + *cp2 = ' '; + if (cp2[1] == '\n') + cp2[1] = ' '; + } + } - save_and_cli(flags); - for(i = 0; i < NR_CPUS; i++) { - if(cpu_present_map & (1 << i)) { - load_profile_irq(mid_xlate[i], lvl14_resolution / multip -lier); - prof_multiplier[i] = multiplier; - } + printk(KERN_INFO "recv_secondary_console_msg: on %d " + "message is '%s'\n", mycpu, buf); } - restore_flags(flags); - return 0; - -#endif - return -EINVAL; -} - -/* Only broken Intel needs this, thus it should not even be - referenced globally. */ - -void __init -initialize_secondary(void) -{ + hwrpb->txrdy = 0; } -static void __init +/* + * Convince the console to have a secondary cpu begin execution. + */ +static int __init secondary_cpu_start(int cpuid, struct task_struct *idle) { struct percpu_struct *cpu; - int timeout; + struct pcb_struct *hwpcb; + long timeout; cpu = (struct percpu_struct *) ((char*)hwrpb + hwrpb->processor_offset + cpuid * hwrpb->processor_size); + hwpcb = (struct pcb_struct *) cpu->hwpcb; - /* Set context to idle thread this CPU will use when running - assumption is that the idle thread is all set to go... ??? */ - memcpy(&cpu->hwpcb[0], &idle->tss, sizeof(struct pcb_struct)); - cpu->hwpcb[4] = cpu->hwpcb[0]; /* UNIQUE set to KSP ??? */ + /* Initialize the CPU's HWPCB to something just good enough for + us to get started. Immediately after starting, we'll swpctx + to the target idle task's tss. Reuse the stack in the mean + time. Precalculate the target PCBB. */ + hwpcb->ksp = (unsigned long) idle + sizeof(union task_union) - 16; + hwpcb->usp = 0; + hwpcb->ptbr = idle->tss.ptbr; + hwpcb->pcc = 0; + hwpcb->asn = 0; + hwpcb->unique = virt_to_phys(&idle->tss); + hwpcb->flags = idle->tss.pal_flags; + hwpcb->res1 = hwpcb->res2 = 0; - DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx\n", - cpu->hwpcb[0], cpu->hwpcb[2], hwrpb->vptb)); + DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n", + hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwcpb->unique)); DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n", cpuid, idle->state, idle->tss.pal_flags)); /* Setup HWRPB fields that SRM uses to activate secondary CPU */ - hwrpb->CPU_restart = __start_cpu; - hwrpb->CPU_restart_data = (unsigned long) idle; + hwrpb->CPU_restart = __smp_callin; + hwrpb->CPU_restart_data = (unsigned long) __smp_callin; /* Recalculate and update the HWRPB checksum */ hwrpb_update_checksum(hwrpb); @@ -495,99 +367,97 @@ /* SRM III 3.4.1.3 */ cpu->flags |= 0x22; /* turn on Context Valid and Restart Capable */ cpu->flags &= ~1; /* turn off Bootstrap In Progress */ - mb(); + wmb(); - send_cpu_msg("START\r\n", cpuid); + send_secondary_console_msg("START\r\n", cpuid); - /* now, we wait... */ - for (timeout = 10000; !(cpu->flags & 1); timeout--) { - if (timeout <= 0) { - printk("Processor %d failed to start\n", cpuid); - /* needed for pset_info to work */ -#if 0 - ipc_processor_enable(cpu_to_processor(cpunum)); -#endif - return; - } - mdelay(1); + /* Wait 1 second for an ACK from the console. Note that jiffies + aren't ticking yet. */ + for (timeout = 100000; timeout > 0; timeout--) { + if (cpu->flags & 1) + goto started; + udelay(10); barrier(); } + printk(KERN_ERR "SMP: Processor %d failed to start.\n", cpuid); + return -1; + +started: DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid)); + return 0; } -static void -send_cpu_msg(char *str, int cpuid) +/* + * Bring one cpu online. + */ +static int __init +smp_boot_one_cpu(int cpuid, int cpunum) { - struct percpu_struct *cpu; - register char *cp1, *cp2; - unsigned long cpumask; - size_t len; - int timeout; - - cpu = (struct percpu_struct *) - ((char*)hwrpb - + hwrpb->processor_offset - + cpuid * hwrpb->processor_size); - - cpumask = (1L << cpuid); - if (hwrpb->txrdy & cpumask) - goto delay1; - ready1: - - cp2 = str; - len = strlen(cp2); - *(unsigned int *)&cpu->ipc_buffer[0] = len; - cp1 = (char *) &cpu->ipc_buffer[1]; - memcpy(cp1, cp2, len); - - /* atomic test and set */ - set_bit(cpuid, &hwrpb->rxrdy); + struct task_struct *idle; + long timeout; - if (hwrpb->txrdy & cpumask) - goto delay2; - ready2: - return; - -delay1: - for (timeout = 10000; timeout > 0; --timeout) { - if (!(hwrpb->txrdy & cpumask)) - goto ready1; - udelay(100); + /* Cook up an idler for this guy. Note that the address we give + to kernel_thread is irrelevant -- it's going to start where + HWRPB.CPU_restart says to start. But this gets all the other + task-y sort of data structures set up like we wish. */ + kernel_thread((void *)__smp_callin, NULL, CLONE_PID|CLONE_VM); + idle = task[cpunum]; + if (!idle) + panic("No idle process for CPU %d", cpuid); + idle->processor = cpuid; + + /* Schedule the first task manually. */ + /* ??? Ingo, what is this? */ + idle->has_cpu = 1; + + DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n", + cpuid, idle->state, idle->flags)); + + /* The secondary will change this once it is happy. Note that + secondary_cpu_start contains the necessary memory barrier. */ + smp_secondary_alive = -1; + + /* Whirrr, whirrr, whirrrrrrrrr... */ + if (secondary_cpu_start(cpuid, idle)) + return -1; + + /* We've been acked by the console; wait one second for the task + to start up for real. Note that jiffies aren't ticking yet. */ + for (timeout = 0; timeout < 100000; timeout++) { + if (smp_secondary_alive != -1) + goto alive; + udelay(10); barrier(); } - goto timeout; - -delay2: - for (timeout = 10000; timeout > 0; --timeout) { - if (!(hwrpb->txrdy & cpumask)) - goto ready2; - udelay(100); - barrier(); - } - goto timeout; -timeout: - printk("Processor %x not ready\n", cpuid); - return; + printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid); + return -1; + +alive: + /* Another "Red Snapper". */ + cpu_number_map[cpuid] = cpunum; + __cpu_logical_map[cpunum] = cpuid; + return 0; } /* - * setup_smp() - * - * called from arch/alpha/kernel/setup.c:setup_arch() when __SMP__ defined + * Called from setup_arch. Detect an SMP system and which processors + * are present. */ void __init setup_smp(void) { struct percpu_struct *cpubase, *cpu; int i; - - boot_cpu_id = hard_smp_processor_id(); - if (boot_cpu_id != 0) { - printk("setup_smp: boot_cpu_id != 0 (%d).\n", boot_cpu_id); + + smp_boot_cpuid = hard_smp_processor_id(); + if (smp_boot_cpuid != 0) { + printk(KERN_WARNING "SMP: Booting off cpu %d instead of 0?\n", + smp_boot_cpuid); } if (hwrpb->nr_processors > 1) { + int boot_cpu_palrev; DBGS(("setup_smp: nr_processors %ld\n", hwrpb->nr_processors)); @@ -601,10 +471,9 @@ ((char *)cpubase + i*hwrpb->processor_size); if ((cpu->flags & 0x1cc) == 0x1cc) { smp_num_probed++; - /* assume here that "whami" == index */ - cpu_present_map |= (1 << i); - if (i != boot_cpu_id) - cpu->pal_revision = boot_cpu_palrev; + /* Assume here that "whami" == index */ + cpu_present_mask |= (1L << i); + cpu->pal_revision = boot_cpu_palrev; } DBGS(("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n", @@ -614,76 +483,249 @@ } } else { smp_num_probed = 1; - cpu_present_map = (1 << boot_cpu_id); + cpu_present_mask = (1L << smp_boot_cpuid); } - printk("setup_smp: %d CPUs probed, cpu_present_map 0x%x," - " boot_cpu_id %d\n", - smp_num_probed, cpu_present_map, boot_cpu_id); + + printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n", + smp_num_probed, cpu_present_mask); } -static void -secondary_console_message(void) +/* + * Called by smp_init bring all the secondaries online and hold them. + */ +void __init +smp_boot_cpus(void) { - int mycpu, i, cnt; - unsigned long txrdy = hwrpb->txrdy; - char *cp1, *cp2, buf[80]; - struct percpu_struct *cpu; + int cpu_count, i; + unsigned long bogosum; - DBGS(("secondary_console_message: TXRDY 0x%lx.\n", txrdy)); + /* Take care of some initial bookkeeping. */ + memset(cpu_number_map, -1, sizeof(cpu_number_map)); + memset(__cpu_logical_map, -1, sizeof(__cpu_logical_map)); + memset(ipi_data, 0, sizeof(ipi_data)); + + cpu_number_map[smp_boot_cpuid] = 0; + __cpu_logical_map[0] = smp_boot_cpuid; + current->processor = smp_boot_cpuid; - mycpu = hard_smp_processor_id(); + smp_store_cpu_info(smp_boot_cpuid); + smp_tune_scheduling(); + smp_setup_percpu_timer(smp_boot_cpuid); + + init_idle(); + + /* Nothing to do on a UP box, or when told not to. */ + if (smp_num_probed == 1 || max_cpus == 0) { + printk(KERN_INFO "SMP mode deactivated.\n"); + return; + } + printk(KERN_INFO "SMP starting up secondaries.\n"); + + cpu_count = 1; for (i = 0; i < NR_CPUS; i++) { - if (!(txrdy & (1L << i))) + if (i == smp_boot_cpuid) continue; - DBGS(("secondary_console_message: " - "TXRDY contains CPU %d.\n", i)); + if (((cpu_present_mask >> i) & 1) == 0) + continue; - cpu = (struct percpu_struct *) - ((char*)hwrpb - + hwrpb->processor_offset - + i * hwrpb->processor_size); + if (smp_boot_one_cpu(i, cpu_count)) + continue; - printk("secondary_console_message: on %d from %d" - " HALT_REASON 0x%lx FLAGS 0x%lx\n", - mycpu, i, cpu->halt_reason, cpu->flags); + cpu_count++; + } - cnt = cpu->ipc_buffer[0] >> 32; - if (cnt <= 0 || cnt >= 80) - strcpy(buf, "<<< BOGUS MSG >>>"); - else { - cp1 = (char *) &cpu->ipc_buffer[11]; - cp2 = buf; - strcpy(cp2, cp1); - - while ((cp2 = strchr(cp2, '\r')) != 0) { - *cp2 = ' '; - if (cp2[1] == '\n') - cp2[1] = ' '; - } - } + if (cpu_count == 1) { + printk(KERN_ERR "SMP: Only one lonely processor alive.\n"); + return; + } + + bogosum = 0; + for (i = 0; i < NR_CPUS; i++) { + if (cpu_present_mask & (1L << i)) + bogosum += cpu_data[i].loops_per_sec; + } + printk(KERN_INFO "SMP: Total of %d processors activated " + "(%lu.%02lu BogoMIPS).\n", + cpu_count, (bogosum + 2500) / 500000, + ((bogosum + 2500) / 5000) % 100); + + smp_num_cpus = cpu_count; +} + +/* + * Called by smp_init to release the blocking online cpus once they + * are all started. + */ +void __init +smp_commence(void) +{ + /* smp_init sets smp_threads_ready -- that's enough. */ + mb(); +} + +/* + * Only broken Intel needs this, thus it should not even be + * referenced globally. + */ + +void __init +initialize_secondary(void) +{ +} + + +extern void update_one_process(struct task_struct *p, unsigned long ticks, + unsigned long user, unsigned long system, + int cpu); + +void +smp_percpu_timer_interrupt(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int user = user_mode(regs); + struct cpuinfo_alpha *data = &cpu_data[cpu]; + +#ifdef NOT_YET_PROFILING + clear_profile_irq(mid_xlate[cpu]); + if (!user) + alpha_do_profile(regs->pc); +#endif + + if (!--data->prof_counter) { + /* We need to make like a normal interrupt -- otherwise + timer interrupts ignore the global interrupt lock, + which would be a Bad Thing. */ + irq_enter(cpu, TIMER_IRQ); + + update_one_process(current, 1, user, !user, cpu); + if (current->pid) { + if (--current->counter < 0) { + current->counter = 0; + current->need_resched = 1; + } + + if (user) { + if (current->priority < DEF_PRIORITY) { + kstat.cpu_nice++; + kstat.per_cpu_nice[cpu]++; + } else { + kstat.cpu_user++; + kstat.per_cpu_user[cpu]++; + } + } else { + kstat.cpu_system++; + kstat.per_cpu_system[cpu]++; + } + } - printk("secondary_console_message: on %d message is '%s'\n", - mycpu, buf); + data->prof_counter = data->prof_multiplier; + irq_exit(cpu, TIMER_IRQ); } +} - hwrpb->txrdy = 0; +int __init +setup_profiling_timer(unsigned int multiplier) +{ +#ifdef NOT_YET_PROFILING + int i; + unsigned long flags; + + /* Prevent level14 ticker IRQ flooding. */ + if((!multiplier) || (lvl14_resolution / multiplier) < 500) + return -EINVAL; + + save_and_cli(flags); + for (i = 0; i < NR_CPUS; i++) { + if (cpu_present_mask & (1L << i)) { + load_profile_irq(mid_xlate[i], + lvl14_resolution / multiplier); + prof_multiplier[i] = multiplier; + } + } + restore_flags(flags); + + return 0; +#else + return -EINVAL; +#endif } -enum ipi_message_type { - IPI_TLB_ALL, - IPI_TLB_MM, - IPI_TLB_PAGE, - IPI_RESCHEDULE, - IPI_CPU_STOP + +static void +send_ipi_message(unsigned long to_whom, enum ipi_message_type operation) +{ + long i, j; + + /* Reduce the number of memory barriers by doing two loops, + one to set the bits, one to invoke the interrupts. */ + + mb(); /* Order out-of-band data and bit setting. */ + + for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) { + if (to_whom & j) + set_bit(operation, &ipi_data[i].bits); + } + + mb(); /* Order bit setting and interrupt. */ + + for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) { + if (to_whom & j) + wripir(i); + } +} + +/* Structure and data for smp_call_function. This is designed to + minimize static memory requirements. Plus it looks cleaner. */ + +struct smp_call_struct { + void (*func) (void *info); + void *info; + long wait; + atomic_t unstarted_count; + atomic_t unfinished_count; }; +static struct smp_call_struct *smp_call_function_data; + +/* Atomicly drop data into a shared pointer. The pointer is free if + it is initially locked. If retry, spin until free. */ + +static inline int +pointer_lock (void *lock, void *data, int retry) +{ + void *old, *tmp; + + mb(); +again: + /* Compare and swap with zero. */ + asm volatile ( + "1: ldq_l %0,%1\n" + " mov %3,%2\n" + " bne %0,2f\n" + " stq_c %2,%1\n" + " beq %2,1b\n" + "2:" + : "=&r"(old), "=m"(*(void **)lock), "=&r"(tmp) + : "r"(data) + : "memory"); + + if (old == 0) + return 0; + if (! retry) + return -EBUSY; + + while (*(void **)lock) + schedule(); + goto again; +} + void handle_ipi(struct pt_regs *regs) { int this_cpu = smp_processor_id(); - volatile int * pending_ipis = &ipi_bits[this_cpu]; + unsigned long *pending_ipis = &ipi_data[this_cpu].bits; unsigned long ops; DBGS(("handle_ipi: on CPU %d ops 0x%x PC 0x%lx\n", @@ -699,190 +741,189 @@ ops &= ~which; which = ffz(~which); - if (which < IPI_RESCHEDULE) { - if (which == IPI_TLB_ALL) - tbia(); - else if (which == IPI_TLB_MM) { - struct mm_struct * mm; - mm = ipi_msg_flush_tb.p.flush_mm; - if (mm == current->mm) - flush_tlb_current(mm); - } - else /* IPI_TLB_PAGE */ { - struct vm_area_struct * vma; - struct mm_struct * mm; - unsigned long addr; - - vma = ipi_msg_flush_tb.p.flush_vma; - mm = vma->vm_mm; - addr = ipi_msg_flush_tb.flush_addr; - - if (mm == current->mm) - flush_tlb_current_page(mm, vma, addr); - } - clear_bit(this_cpu, &ipi_msg_flush_tb.flush_tb_mask); - } - else if (which == IPI_RESCHEDULE) { + if (which == IPI_RESCHEDULE) { /* Reschedule callback. Everything to be done is done by the interrupt return path. */ } + else if (which == IPI_CALL_FUNC) { + struct smp_call_struct *data; + void (*func)(void *info); + void *info; + int wait; + + data = smp_call_function_data; + func = data->func; + info = data->info; + wait = data->wait; + + /* Notify the sending CPU that the data has been + received, and execution is about to begin. */ + mb(); + atomic_dec (&data->unstarted_count); + + /* At this point the structure may be gone unless + wait is true. */ + (*func)(info); + + /* Notify the sending CPU that the task is done. */ + mb(); + if (wait) atomic_dec (&data->unfinished_count); + } else if (which == IPI_CPU_STOP) { halt(); } else { - printk(KERN_CRIT "unknown_ipi() on CPU %d: %lu\n", + printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which); } } while (ops); + mb(); /* Order data access and bit testing. */ } cpu_data[this_cpu].ipi_count++; if (hwrpb->txrdy) - secondary_console_message(); + recv_secondary_console_msg(); } -static void -send_ipi_message(unsigned long to_whom, enum ipi_message_type operation) +void +smp_send_reschedule(int cpu) { - long i, j; - - /* Reduce the number of memory barriers by doing two loops, - one to set the bits, one to invoke the interrupts. */ - - mb(); /* Order out-of-band data and bit setting. */ - - for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) { - if (to_whom & j) - set_bit(operation, &ipi_bits[i]); - } - - mb(); /* Order bit setting and interrupt. */ + send_ipi_message(1L << cpu, IPI_RESCHEDULE); +} - for (i = 0, j = 1; i < NR_CPUS; ++i, j <<= 1) { - if (to_whom & j) - wripir(i); - } +void +smp_send_stop(void) +{ + unsigned long to_whom = cpu_present_mask ^ (1L << smp_processor_id()); + send_ipi_message(to_whom, IPI_CPU_STOP); } +/* + * Run a function on all other CPUs. + * The function to run. This must be fast and non-blocking. + * An arbitrary pointer to pass to the function. + * If true, keep retrying until ready. + * If true, wait until function has completed on other CPUs. + * [RETURNS] 0 on success, else a negative status code. + * + * Does not return until remote CPUs are nearly ready to execute + * or are or have executed. + */ + int -smp_info(char *buffer) +smp_call_function (void (*func) (void *info), void *info, int retry, int wait) { - long i; - unsigned long sum = 0; - for (i = 0; i < NR_CPUS; i++) - sum += cpu_data[i].ipi_count; + unsigned long to_whom = cpu_present_mask ^ (1L << smp_processor_id()); + struct smp_call_struct data; + long timeout; + + data.func = func; + data.info = info; + data.wait = wait; + atomic_set(&data.unstarted_count, smp_num_cpus - 1); + atomic_set(&data.unfinished_count, smp_num_cpus - 1); + + /* Aquire the smp_call_function_data mutex. */ + if (pointer_lock(&smp_call_function_data, &data, retry)) + return -EBUSY; + + /* Send a message to all other CPUs. */ + send_ipi_message(to_whom, IPI_CALL_FUNC); + + /* Wait for a minimal response. */ + timeout = jiffies + HZ; + while (atomic_read (&data.unstarted_count) > 0 + && time_before (jiffies, timeout)) + barrier(); - return sprintf(buffer, "CPUs probed %d active %d map 0x%x IPIs %ld\n", - smp_num_probed, smp_num_cpus, cpu_present_map, sum); -} + /* We either got one or timed out -- clear the lock. */ + mb(); + smp_call_function_data = 0; + if (atomic_read (&data.unstarted_count) > 0) + return -ETIMEDOUT; + + /* Wait for a complete response, if needed. */ + if (wait) { + while (atomic_read (&data.unfinished_count) > 0) + barrier(); + } -void -smp_send_reschedule(int cpu) -{ - send_ipi_message(1 << cpu, IPI_RESCHEDULE); + return 0; } -void -smp_send_stop(void) +static void +ipi_flush_tlb_all(void *ignored) { - unsigned long to_whom = cpu_present_map ^ (1 << smp_processor_id()); - send_ipi_message(to_whom, IPI_CPU_STOP); + tbia(); } void flush_tlb_all(void) { - unsigned long to_whom = cpu_present_map ^ (1 << smp_processor_id()); - long timeout = 1000000; - - spin_lock(&flush_tb_lock); - - ipi_msg_flush_tb.flush_tb_mask = to_whom; - send_ipi_message(to_whom, IPI_TLB_ALL); tbia(); - while (ipi_msg_flush_tb.flush_tb_mask && --timeout) { - udelay(1); - barrier(); - } - - if (timeout == 0) { - printk("flush_tlb_all: STUCK on CPU %d mask 0x%x\n", - smp_processor_id(), - ipi_msg_flush_tb.flush_tb_mask); - ipi_msg_flush_tb.flush_tb_mask = 0; + /* Although we don't have any data to pass, we do want to + synchronize with the other processors. */ + if (smp_call_function(ipi_flush_tlb_all, NULL, 1, 1)) { + printk(KERN_CRIT "flush_tlb_all: timed out\n"); } +} - spin_unlock(&flush_tb_lock); +static void +ipi_flush_tlb_mm(void *x) +{ + struct mm_struct *mm = (struct mm_struct *) x; + if (mm == current->mm) + flush_tlb_current(mm); } void flush_tlb_mm(struct mm_struct *mm) { - unsigned long to_whom = cpu_present_map ^ (1 << smp_processor_id()); - long timeout = 1000000; - - spin_lock(&flush_tb_lock); - - ipi_msg_flush_tb.flush_tb_mask = to_whom; - ipi_msg_flush_tb.p.flush_mm = mm; - send_ipi_message(to_whom, IPI_TLB_MM); - - if (mm != current->mm) - flush_tlb_other(mm); - else + if (mm == current->mm) flush_tlb_current(mm); + else + flush_tlb_other(mm); - while (ipi_msg_flush_tb.flush_tb_mask && --timeout) { - udelay(1); - barrier(); + if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) { + printk(KERN_CRIT "flush_tlb_mm: timed out\n"); } +} - if (timeout == 0) { - printk("flush_tlb_mm: STUCK on CPU %d mask 0x%x\n", - smp_processor_id(), - ipi_msg_flush_tb.flush_tb_mask); - ipi_msg_flush_tb.flush_tb_mask = 0; - } +struct flush_tlb_page_struct { + struct vm_area_struct *vma; + struct mm_struct *mm; + unsigned long addr; +}; - spin_unlock(&flush_tb_lock); +static void +ipi_flush_tlb_page(void *x) +{ + struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x; + if (data->mm == current->mm) + flush_tlb_current_page(data->mm, data->vma, data->addr); } void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) { - int cpu = smp_processor_id(); - unsigned long to_whom = cpu_present_map ^ (1 << cpu); - struct mm_struct * mm = vma->vm_mm; - int timeout = 1000000; - - spin_lock(&flush_tb_lock); - - ipi_msg_flush_tb.flush_tb_mask = to_whom; - ipi_msg_flush_tb.p.flush_vma = vma; - ipi_msg_flush_tb.flush_addr = addr; - send_ipi_message(to_whom, IPI_TLB_PAGE); - - if (mm != current->mm) - flush_tlb_other(mm); - else - flush_tlb_current_page(mm, vma, addr); + struct flush_tlb_page_struct data; + struct mm_struct *mm = vma->vm_mm; - while (ipi_msg_flush_tb.flush_tb_mask && --timeout) { - udelay(1); - barrier(); - } + data.vma = vma; + data.mm = mm; + data.addr = addr; - if (timeout == 0) { - printk("flush_tlb_page: STUCK on CPU %d mask 0x%x\n", - smp_processor_id(), - ipi_msg_flush_tb.flush_tb_mask); - ipi_msg_flush_tb.flush_tb_mask = 0; + if (mm == current->mm) + flush_tlb_current_page(mm, vma, addr); + else + flush_tlb_other(mm); + + if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) { + printk(KERN_CRIT "flush_tlb_page: timed out\n"); } - - spin_unlock(&flush_tb_lock); } void @@ -892,6 +933,20 @@ flush_tlb_mm(mm); } + +int +smp_info(char *buffer) +{ + long i; + unsigned long sum = 0; + for (i = 0; i < NR_CPUS; i++) + sum += cpu_data[i].ipi_count; + + return sprintf(buffer, "CPUs probed %d active %d map 0x%lx IPIs %ld\n", + smp_num_probed, smp_num_cpus, cpu_present_mask, sum); +} + + #if DEBUG_SPINLOCK #ifdef MANAGE_SPINLOCK_IPL @@ -932,17 +987,16 @@ spin_lock(spinlock_t * lock) { long tmp; - long stuck = 1<<27; + long stuck; void *inline_pc = __builtin_return_address(0); unsigned long started = jiffies; int printed = 0; int cpu = smp_processor_id(); long old_ipl = spinlock_raise_ipl(lock); + stuck = 1L << 28; try_again: - stuck = 0x10000000; /* was 4G, now 256M */ - /* Use sub-sections to put the actual loop at the end of this object file's text section so as to perfect branch prediction. */ @@ -961,19 +1015,16 @@ " blbs %0,2b\n" " br 1b\n" ".previous" - : "=r" (tmp), - "=m" (__dummy_lock(lock)), - "=r" (stuck) - : "2" (stuck)); + : "=r" (tmp), "=m" (__dummy_lock(lock)), "=r" (stuck) + : "1" (__dummy_lock(lock)), "2" (stuck)); if (stuck < 0) { - if (!printed) { - printk("spinlock stuck at %p(%d) owner %s at %p\n", - inline_pc, cpu, lock->task->comm, - lock->previous); - printed = 1; - } - stuck = 1<<30; + printk(KERN_WARNING + "spinlock stuck at %p(%d) owner %s at %p(%d) st %ld\n", + inline_pc, cpu, lock->task->comm, lock->previous, + lock->task->processor, lock->task->state); + stuck = 1L << 36; + printed = 1; goto try_again; } @@ -984,7 +1035,7 @@ lock->task = current; if (printed) { - printk("spinlock grabbed at %p(%d) %ld ticks\n", + printk(KERN_WARNING "spinlock grabbed at %p(%d) %ld ticks\n", inline_pc, cpu, jiffies - started); } } @@ -1006,7 +1057,7 @@ return ret; } #endif /* DEBUG_SPINLOCK */ - + #if DEBUG_RWLOCK void write_lock(rwlock_t * lock) { @@ -1038,18 +1089,17 @@ " blt %1,8b\n" " br 1b\n" ".previous" - : "=m" (__dummy_lock(lock)), "=&r" (regx), "=&r" (regy) - , "=&r" (stuck_lock), "=&r" (stuck_reader) - : "0" (__dummy_lock(lock)) - , "3" (stuck_lock), "4" (stuck_reader) - ); + : "=m" (__dummy_lock(lock)), "=&r" (regx), "=&r" (regy), + "=&r" (stuck_lock), "=&r" (stuck_reader) + : "0" (__dummy_lock(lock)), "3" (stuck_lock), "4" (stuck_reader)); if (stuck_lock < 0) { - printk("write_lock stuck at %p\n", inline_pc); + printk(KERN_WARNING "write_lock stuck at %p\n", inline_pc); goto try_again; } if (stuck_reader < 0) { - printk("write_lock stuck on readers at %p\n", inline_pc); + printk(KERN_WARNING "write_lock stuck on readers at %p\n", + inline_pc); goto try_again; } } @@ -1079,11 +1129,10 @@ " br 1b\n" ".previous" : "=m" (__dummy_lock(lock)), "=&r" (regx), "=&r" (stuck_lock) - : "0" (__dummy_lock(lock)), "2" (stuck_lock) - ); + : "0" (__dummy_lock(lock)), "2" (stuck_lock)); if (stuck_lock < 0) { - printk("read_lock stuck at %p\n", inline_pc); + printk(KERN_WARNING "read_lock stuck at %p\n", inline_pc); goto try_again; } } diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c --- v2.2.9/linux/arch/alpha/kernel/sys_dp264.c Tue Feb 23 15:21:32 1999 +++ linux/arch/alpha/kernel/sys_dp264.c Sat May 22 13:42:40 1999 @@ -66,6 +66,33 @@ } static void +clipper_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) { + volatile unsigned long *csr; + + if (TSUNAMI_bootcpu < 2) + if (!TSUNAMI_bootcpu) + csr = &TSUNAMI_cchip->dim0.csr; + else + csr = &TSUNAMI_cchip->dim1.csr; + else + if (TSUNAMI_bootcpu == 2) + csr = &TSUNAMI_cchip->dim2.csr; + else + csr = &TSUNAMI_cchip->dim3.csr; + + *csr = (~mask >> 16) | (1UL << 55); /* master ISA enable */ + mb(); + *csr; + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +} + +static void dp264_device_interrupt(unsigned long vector, struct pt_regs * regs) { #if 1 @@ -105,11 +132,16 @@ ack = irq = (vector - 0x800) >> 4; /* - * The DP264 SRM console reports PCI interrupts with a vector - * 0x100 *higher* than one might expect, as PCI IRQ 0 (ie bit 0) - * shows up as IRQ 16, etc, etc. We adjust it down by 16 to have - * it line up with the actual bit numbers from the DIM registers, - * which is how we manage the interrupts/mask. Sigh... + * The EV6 machines SRM console reports PCI interrupts with a vector + * calculated by: + * + * 0x900 + (0x10 * DRIR-bit) + * + * So bit 16 shows up as IRQ 32, etc, etc. + * + * On DP264/BRICK/MONET, we adjust it down by 16 because at least + * that many of the low order bits of the DRIR are not used, and + * so we don't count them. */ if (irq >= 32) ack = irq = irq - 16; @@ -117,11 +149,32 @@ handle_irq(irq, ack, regs); } +static void +clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) +{ + int irq, ack; + + ack = irq = (vector - 0x800) >> 4; + + /* + * The EV6 machines SRM console reports PCI interrupts with a vector + * calculated by: + * + * 0x900 + (0x10 * DRIR-bit) + * + * So bit 16 shows up as IRQ 32, etc, etc. + * + * CLIPPER uses bits 8-47 for PCI interrupts, so we do not need + * to scale down the vector reported, we just use it. + * + * Eg IRQ 24 is DRIR bit 8, etc, etc + */ + handle_irq(irq, ack, regs); +} + static void __init dp264_init_irq(void) { - volatile unsigned long *csr; - outb(0, DMA1_RESET_REG); outb(0, DMA2_RESET_REG); outb(DMA_MODE_CASCADE, DMA2_MODE_REG); @@ -130,23 +183,26 @@ if (alpha_using_srm) alpha_mv.device_interrupt = dp264_srm_device_interrupt; - if (TSUNAMI_bootcpu < 2) - if (!TSUNAMI_bootcpu) - csr = &TSUNAMI_cchip->dim0.csr; - else - csr = &TSUNAMI_cchip->dim1.csr; - else - if (TSUNAMI_bootcpu == 2) - csr = &TSUNAMI_cchip->dim2.csr; - else - csr = &TSUNAMI_cchip->dim3.csr; - - /* Note invert on MASK bits. */ - *csr = ~(alpha_irq_mask); - mb(); - *csr; + dp264_update_irq_hw(16, alpha_irq_mask, 0); + + enable_irq(55); /* Enable ISA interrupt controller. */ + enable_irq(2); +} + +static void __init +clipper_init_irq(void) +{ + outb(0, DMA1_RESET_REG); + outb(0, DMA2_RESET_REG); + outb(DMA_MODE_CASCADE, DMA2_MODE_REG); + outb(0, DMA2_MASK_REG); + + if (alpha_using_srm) + alpha_mv.device_interrupt = clipper_srm_device_interrupt; + + clipper_update_irq_hw(16, alpha_irq_mask, 0); - enable_irq(55); /* Enable CYPRESS interrupt controller (ISA). */ + enable_irq(55); /* Enable ISA interrupt controller. */ enable_irq(2); } @@ -221,7 +277,7 @@ const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5; int irq = COMMON_TABLE_LOOKUP; - if (irq >= 0) + if (irq > 0) irq += 16 * dev2hose(dev); return irq; @@ -300,10 +356,10 @@ { 30, 30, 30, 30, 30}, /* IdSel 11 21143 #2 */ { -1, -1, -1, -1, -1}, /* IdSel 12 unused */ { -1, -1, -1, -1, -1}, /* IdSel 13 unused */ - { 47, 47, 46, 45, 44}, /* IdSel 14 slot 0 */ + { 35, 35, 34, 33, 32}, /* IdSel 14 slot 0 */ { 39, 39, 38, 37, 36}, /* IdSel 15 slot 1 */ { 43, 43, 42, 41, 40}, /* IdSel 16 slot 2 */ - { 35, 35, 34, 33, 32}, /* IdSel 17 slot 3 */ + { 47, 47, 46, 45, 44}, /* IdSel 17 slot 3 */ }; const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5; int irq = COMMON_TABLE_LOOKUP; @@ -311,6 +367,28 @@ return irq; } +static int __init +clipper_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[7][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 1 slot 1 */ + { 16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 2 slot 2 */ + { 16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 3 slot 3 */ + { 16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 4 slot 4 */ + { 16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 5 slot 5 */ + { 16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 6 slot 6 */ + { -1, -1, -1, -1, -1} /* IdSel 7 ISA Bridge */ + }; + const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5; + int irq = COMMON_TABLE_LOOKUP; + + if (irq > 0) + irq += 16 * dev2hose(dev); + + return irq; +} + static void __init dp264_pci_fixup(void) { @@ -336,6 +414,13 @@ SMC669_Init(0); } +static void __init +clipper_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(clipper_map_irq, common_swizzle); +} + /* * The System Vectors @@ -407,5 +492,26 @@ pci_fixup: webbrick_pci_fixup, kill_arch: generic_kill_arch, }; -/* No alpha_mv alias for webbrick, since we compile it in unconditionally - with DP264; setup_arch knows how to cope. */ +struct alpha_machine_vector clipper_mv __initmv = { + vector_name: "Clipper", + DO_EV6_MMU, + DO_DEFAULT_RTC, + DO_TSUNAMI_IO, + DO_TSUNAMI_BUS, + machine_check: tsunami_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 64, + irq_probe_mask: _PROBE_MASK(64), + update_irq_hw: clipper_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: dp264_device_interrupt, + + init_arch: tsunami_init_arch, + init_irq: clipper_init_irq, + init_pit: generic_init_pit, + pci_fixup: clipper_pci_fixup, + kill_arch: generic_kill_arch, +}; +/* No alpha_mv alias for webbrick/monet/clipper, since we compile them + in unconditionally with DP264; setup_arch knows how to cope. */ diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c --- v2.2.9/linux/arch/alpha/kernel/time.c Wed Apr 28 11:37:29 1999 +++ linux/arch/alpha/kernel/time.c Sat May 22 13:42:49 1999 @@ -42,6 +42,12 @@ #include "proto.h" #include "irq.h" +extern rwlock_t xtime_lock; +extern volatile unsigned long lost_ticks; /*kernel/sched.c*/ + +extern rwlock_t xtime_lock; +extern volatile unsigned long lost_ticks; /*kernel/sched.c*/ + static int set_rtc_mmss(unsigned long); @@ -86,15 +92,15 @@ long nticks; #ifdef __SMP__ - extern void smp_percpu_timer_interrupt(struct pt_regs *); - extern unsigned int boot_cpu_id; - /* when SMP, do this for *all* CPUs, - but only do the rest for the boot CPU */ + /* When SMP, do this for *all* CPUs, but only do the rest for + the boot CPU. */ smp_percpu_timer_interrupt(regs); - if (smp_processor_id() != boot_cpu_id) - return; + if (smp_processor_id() != smp_boot_cpuid) + return; #endif + write_lock(&xtime_lock); + /* * Calculate how many ticks have passed since the last update, * including any previous partial leftover. Save any resulting @@ -124,6 +130,8 @@ int tmp = set_rtc_mmss(xtime.tv_sec); state.last_rtc_update = xtime.tv_sec - (tmp ? 600 : 0); } + + write_unlock(&xtime_lock); } /* @@ -226,7 +234,8 @@ { void (*irq_handler)(int, void *, struct pt_regs *); unsigned int year, mon, day, hour, min, sec, cc1, cc2; - unsigned long cycle_freq, diff, one_percent; + unsigned long cycle_freq, one_percent; + long diff; /* * The Linux interpretation of the CMOS clock register contents: @@ -242,7 +251,7 @@ if (!est_cycle_freq) { /* Sometimes the hwrpb->cycle_freq value is bogus. - Go another round to check up on it and see. */ + Go another round to check up on it and see. */ do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); cc2 = rpcc(); @@ -279,8 +288,7 @@ mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - { + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(sec); BCD_TO_BIN(min); BCD_TO_BIN(hour); @@ -328,18 +336,24 @@ void do_gettimeofday(struct timeval *tv) { - unsigned long flags, delta_cycles, delta_usec; - unsigned long sec, usec; - __u32 now; - extern volatile unsigned long lost_ticks; /*kernel/sched.c*/ + unsigned long sec, usec, lost, flags; + unsigned long delta_cycles, delta_usec, partial_tick; - now = rpcc(); - save_and_cli(flags); + read_lock_irqsave(&xtime_lock, flags); + + delta_cycles = rpcc() - state.last_time; sec = xtime.tv_sec; usec = xtime.tv_usec; - delta_cycles = now - state.last_time; - restore_flags(flags); + partial_tick = state.partial_tick; + lost = lost_ticks; + + read_unlock_irqrestore(&xtime_lock, flags); +#ifdef __SMP__ + /* Until and unless we figure out how to get cpu cycle counters + in sync and keep them there, we can't use the rpcc tricks. */ + delta_usec = lost * (1000000 / HZ); +#else /* * usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks) * = cycles * (s_t_p_c) * 1e6 / (2**48 * ticks) @@ -354,13 +368,10 @@ */ delta_usec = (delta_cycles * state.scaled_ticks_per_cycle - + state.partial_tick - + (lost_ticks << FIX_SHIFT) ) * 15625; + + partial_tick + + (lost << FIX_SHIFT)) * 15625; delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2; - - /* the 'lost_tics' term above implements this: - * delta_usec += lost_ticks * (1000000 / HZ); - */ +#endif usec += delta_usec; if (usec >= 1000000) { @@ -375,13 +386,41 @@ void do_settimeofday(struct timeval *tv) { - cli(); - xtime = *tv; + unsigned long delta_usec; + long sec, usec; + + write_lock_irq(&xtime_lock); + + /* The offset that is added into time in do_gettimeofday above + must be subtracted out here to keep a coherent view of the + time. Without this, a full-tick error is possible. */ + +#ifdef __SMP__ + delta_usec = lost_ticks * (1000000 / HZ); +#else + delta_usec = rpcc() - state.last_time; + delta_usec = (delta_usec * state.scaled_ticks_per_cycle + + state.partial_tick + + (lost_ticks << FIX_SHIFT)) * 15625; + delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2; +#endif + + sec = tv->tv_sec; + usec = tv->tv_usec; + usec -= delta_usec; + if (usec < 0) { + usec += 1000000; + sec -= 1; + } + + xtime.tv_sec = sec; + xtime.tv_usec = usec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - sti(); + + write_unlock_irq(&xtime_lock); } diff -u --recursive --new-file v2.2.9/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c --- v2.2.9/linux/arch/alpha/kernel/traps.c Tue May 11 13:10:27 1999 +++ linux/arch/alpha/kernel/traps.c Sat May 22 13:42:51 1999 @@ -1,5 +1,5 @@ /* - * kernel/traps.c + * arch/alpha/kernel/traps.c * * (C) Copyright 1994 Linus Torvalds */ @@ -95,6 +95,9 @@ { if (regs->ps & 8) return; +#ifdef __SMP__ + printk("CPU %d ", hard_smp_processor_id()); +#endif printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); dik_show_regs(regs, r9_15); dik_show_code((unsigned int *)regs->pc); @@ -128,8 +131,8 @@ if (summary & 1) { /* Software-completion summary bit is set, so try to emulate the instruction. */ - if (implver() == IMPLVER_EV6) { - /* Whee! EV6 has precice exceptions. */ + if (!amask(AMASK_PRECISE_TRAP)) { + /* 21264 (except pass 1) has precise exceptions. */ if (alpha_fp_emul(regs.pc - 4)) return; } else { @@ -138,14 +141,12 @@ } } - lock_kernel(); #if 0 printk("%s: arithmetic trap at %016lx: %02lx %016lx\n", current->comm, regs.pc, summary, write_mask); #endif die_if_kernel("Arithmetic fault", ®s, 0, 0); send_sig(SIGFPE, current, 1); - unlock_kernel(); } asmlinkage void @@ -235,10 +236,8 @@ unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs) { - lock_kernel(); die_if_kernel("Instruction fault", ®s, type, 0); force_sig(SIGILL, current); - unlock_kernel(); } @@ -453,10 +452,8 @@ unsigned long newpc; newpc = fixup_exception(una_reg, fixup, pc); - lock_kernel(); printk("Forwarding unaligned exception at %lx (%lx)\n", pc, newpc); - unlock_kernel(); (®s)->pc = newpc; return; @@ -610,11 +607,9 @@ cnt = 0; } if (++cnt < 5) { - lock_kernel(); printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n", current->comm, current->pid, regs->pc - 4, va, opcode, reg); - unlock_kernel(); } last_time = jiffies; } @@ -868,16 +863,12 @@ give_sigsegv: regs->pc -= 4; /* make pc point to faulting insn */ - lock_kernel(); send_sig(SIGSEGV, current, 1); - unlock_kernel(); return; give_sigbus: regs->pc -= 4; - lock_kernel(); send_sig(SIGBUS, current, 1); - unlock_kernel(); return; } diff -u --recursive --new-file v2.2.9/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v2.2.9/linux/arch/alpha/mm/init.c Fri Oct 23 22:01:19 1998 +++ linux/arch/alpha/mm/init.c Sat May 22 13:42:53 1999 @@ -256,26 +256,6 @@ return start_mem; } -#ifdef __SMP__ -/* - * paging_init_secondary(), called ONLY by secondary CPUs, - * sets up current->tss contents appropriately and does a load_PCB. - * note that current should be pointing at the idle thread task struct - * for this CPU. - */ -void -paging_init_secondary(void) -{ - current->tss.ptbr = init_task.tss.ptbr; - current->tss.pal_flags = 1; - current->tss.flags = 0; - load_PCB(¤t->tss); - tbia(); - - return; -} -#endif /* __SMP__ */ - #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM) void srm_paging_stop (void) diff -u --recursive --new-file v2.2.9/linux/arch/i386/boot/video.S linux/arch/i386/boot/video.S --- v2.2.9/linux/arch/i386/boot/video.S Mon Oct 5 13:13:35 1998 +++ linux/arch/i386/boot/video.S Fri May 14 12:47:07 1999 @@ -1,14 +1,19 @@ ! -! Display adapter & video mode setup, version 2.12 (25-May-98) +! Display adapter & video mode setup, version 2.13 (14-May-99) ! -! Copyright (C) 1995 -- 1998 Martin Mares +! Copyright (C) 1995 -- 1999 Martin Mares ! Based on the original setup.S code (C) Linus Torvalds and Mats Anderson ! +! For further information, look at Documentation/svga.txt. +! #include /* for CONFIG_VIDEO_* */ ! Enable autodetection of SVGA adapters and modes. If you really need this -! feature, drop me a mail as I think of removing it some day... +! feature, drop me a mail as I think of removing it some day. You can +! always enter `scan' to get the video mode table and then use the real +! video mode numbers (those 4-digit hexadecimal numbers, NOT the menu +! item numbers) which don't rely on any autodetection. #undef CONFIG_VIDEO_SVGA ! Enable autodetection of VESA modes @@ -1939,7 +1944,7 @@ badmdt: .ascii "You passed an undefined mode number." db 0x0d, 0x0a, 0 vesaer: .ascii "Error: Scanning of VESA modes failed. Please " - .ascii "report to ." + .ascii "report to ." db 0x0d, 0x0a, 0 old_name: .ascii "CGA/MDA/HGA" db 0 diff -u --recursive --new-file v2.2.9/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c --- v2.2.9/linux/arch/i386/kernel/mtrr.c Tue May 11 13:10:27 1999 +++ linux/arch/i386/kernel/mtrr.c Fri May 14 09:00:17 1999 @@ -1,6 +1,6 @@ /* Generic MTRR (Memory Type Range Register) driver. - Copyright (C) 1997-1998 Richard Gooch + Copyright (C) 1997-1999 Richard Gooch This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -196,6 +196,11 @@ 19990310 Richard Gooch Support K6-II/III based on Alan Cox's patches. v1.34 + 19990511 Bart Hartgers + Support Centaur C6 MCR's. + 19990512 Richard Gooch + Minor cleanups. + v1.35 */ #include #include @@ -232,7 +237,7 @@ #include #include "irq.h" -#define MTRR_VERSION "1.34 (19990310)" +#define MTRR_VERSION "1.35 (19990512)" #define TRUE 1 #define FALSE 0 @@ -313,8 +318,13 @@ /* Disable interrupts locally */ __save_flags (ctxt->flags); __cli (); - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) return; - + switch (boot_cpu_data.x86_vendor) + { + case X86_VENDOR_AMD: + case X86_VENDOR_CENTAUR: + return; + /*break;*/ + } /* Save value of CR4 and clear Page Global Enable (bit 7) */ if (boot_cpu_data.x86_capability & X86_FEATURE_PGE) asm volatile ("movl %%cr4, %0\n\t" @@ -352,12 +362,14 @@ { unsigned long tmp; - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_AMD: + case X86_VENDOR_CENTAUR: __restore_flags (ctxt->flags); return; + /*break;*/ } - /* Flush caches and TLBs */ asm volatile ("wbinvd" : : : "memory" ); @@ -399,7 +411,9 @@ return (config & 0xff); /*break;*/ case X86_VENDOR_CYRIX: - /* Cyrix have 8 ARRs */ + /* Cyrix have 8 ARRs */ + case X86_VENDOR_CENTAUR: + /* and Centaur has 8 MCR's */ return 8; /*break;*/ case X86_VENDOR_AMD: @@ -422,6 +436,7 @@ /*break;*/ case X86_VENDOR_CYRIX: case X86_VENDOR_AMD: + case X86_VENDOR_CENTAUR: return 1; /*break;*/ } @@ -450,7 +465,6 @@ /* Clean up mask_lo so it gives the real address mask. */ mask_lo = (mask_lo & 0xfffff000UL); - /* This works correctly if size is a power of two, i.e. a contiguous range. */ *size = ~(mask_lo - 1); @@ -480,7 +494,6 @@ /* Enable interrupts if it was enabled previously */ __restore_flags (flags); - shift = ((unsigned char *) base)[1] & 0x0f; *base &= 0xfffff000UL; @@ -550,6 +563,20 @@ return; } /* End Function amd_get_mtrr */ +static struct +{ + unsigned long high; + unsigned long low; +} centaur_mcr[8]; + +static void centaur_get_mcr (unsigned int reg, unsigned long *base, + unsigned long *size, mtrr_type *type) +{ + *base = centaur_mcr[reg].high & 0xfffff000; + *size = (~(centaur_mcr[reg].low & 0xfffff000))+1; + *type = MTRR_TYPE_WRCOMB; /* If it is there, it is write-combining */ +} /* End Function centaur_get_mcr */ + static void (*get_mtrr) (unsigned int reg, unsigned long *base, unsigned long *size, mtrr_type *type) = NULL; @@ -647,11 +674,10 @@ else /* Set the register to the base (already shifted for us), the type (off by one) and an inverted bitmask of the size - The size is the only odd bit. We are fed say 512K We invert this and we get 111 1111 1111 1011 but if you subtract one and invert you get the desired - 111 1111 1111 1100 mask + 111 1111 1111 1100 mask */ *(reg ? &high : &low)=(((~(size-1))>>15)&0x0001FFFC)|base|(type+1); /* @@ -663,10 +689,36 @@ if (do_safe) set_mtrr_done (&ctxt); } /* End Function amd_set_mtrr_up */ + +static void centaur_set_mcr_up (unsigned int reg, unsigned long base, + unsigned long size, mtrr_type type, + int do_safe) +{ + struct set_mtrr_context ctxt; + unsigned long low, high; + + if (do_safe) set_mtrr_prepare( &ctxt ); + if (size == 0) + { + /* Disable */ + high = low = 0; + } + else + { + high = base & 0xfffff000; /* base works on 4K pages... */ + low = ((~(size-1))&0xfffff000); + low |= 0x1f; /* only support write-combining... */ + } + centaur_mcr[reg].high = high; + centaur_mcr[reg].low = low; + wrmsr (0x110 + reg, low, high); + if (do_safe) set_mtrr_done( &ctxt ); +} /* End Function centaur_set_mtrr_up */ + static void (*set_mtrr_up) (unsigned int reg, unsigned long base, unsigned long size, mtrr_type type, int do_safe) = NULL; - + #ifdef __SMP__ struct mtrr_var_range @@ -694,23 +746,21 @@ { unsigned int lo, hi; int changed = FALSE; - - rdmsr(MTRRphysBase_MSR(index), lo, hi); + rdmsr(MTRRphysBase_MSR(index), lo, hi); if ((vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL) || (vr->base_hi & 0xfUL) != (hi & 0xfUL)) { - wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi); + wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi); changed = TRUE; } - rdmsr(MTRRphysMask_MSR(index), lo, hi); + rdmsr(MTRRphysMask_MSR(index), lo, hi); if ((vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL) || (vr->mask_hi & 0xfUL) != (hi & 0xfUL)) { - wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi); + wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi); changed = TRUE; } - return changed; } /* End Function set_mtrr_var_range_testing */ @@ -723,7 +773,6 @@ for (i = 0; i < 2; i++) rdmsr(MTRRfix16K_80000_MSR + i, p[2 + i*2], p[3 + i*2]); - for (i = 0; i < 8; i++) rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i*2], p[7 + i*2]); } /* End Function get_fixed_ranges */ @@ -777,14 +826,13 @@ unsigned long lo, dummy; nvrs = state->num_var_ranges = get_num_var_ranges(); - vrs = state->var_ranges + vrs = state->var_ranges = kmalloc (nvrs * sizeof (struct mtrr_var_range), GFP_KERNEL); if (vrs == NULL) nvrs = state->num_var_ranges = 0; for (i = 0; i < nvrs; i++) get_mtrr_var_range (i, &vrs[i]); - get_fixed_ranges (state->fixed_ranges); rdmsr (MTRRdefType_MSR, lo, dummy); @@ -818,7 +866,6 @@ if ( set_fixed_ranges_testing(state->fixed_ranges) ) change_mask |= MTRR_CHANGE_MASK_FIXED; - /* Set_mtrr_restore restores the old value of MTRRdefType, so to set it we fiddle with the saved value */ if ((ctxt->deftype_lo & 0xff) != state->def_type @@ -831,7 +878,7 @@ return change_mask; } /* End Function set_mtrr_state */ - + static atomic_t undone_count; static volatile int wait_barrier_execute = FALSE; static volatile int wait_barrier_cache_enable = FALSE; @@ -1025,13 +1072,22 @@ } /* Fall through */ case X86_VENDOR_CYRIX: + case X86_VENDOR_CENTAUR: if ( (base & 0xfff) || (size & 0xfff) ) { printk ("mtrr: size and base must be multiples of 4 kiB\n"); printk ("mtrr: size: %lx base: %lx\n", size, base); return -EINVAL; } - if (base + size < 0x100000) + if (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR) + { + if (type != MTRR_TYPE_WRCOMB) + { + printk ("mtrr: only write-combining is supported\n"); + return -EINVAL; + } + } + else if (base + size < 0x100000) { printk ("mtrr: cannot set region below 1 MiB (0x%lx,0x%lx)\n", base, size); @@ -1050,7 +1106,7 @@ } break; case X86_VENDOR_AMD: - /* Apply the K6 block alignment and size rules + /* Apply the K6 block alignment and size rules In order o Uncached or gathering only o 128K or bigger block @@ -1572,6 +1628,30 @@ if ( ccrc[6] ) printk ("mtrr: ARR3 was write protected, unprotected\n"); } /* End Function cyrix_arr_init */ +__initfunc(static void centaur_mcr_init (void)) +{ + unsigned i; + struct set_mtrr_context ctxt; + + set_mtrr_prepare (&ctxt); + /* Unfortunately, MCR's are read-only, so there is no way to + * find out what the bios might have done. + */ + /* Clear all MCR's. + * This way we are sure that the centaur_mcr array contains the actual + * values. The disadvantage is that any BIOS tweaks are thus undone. + */ + for (i = 0; i < 8; ++i) + { + centaur_mcr[i].high = 0; + centaur_mcr[i].low = 0; + wrmsr (0x110 + i , 0, 0); + } + /* Throw the main write-combining switch... */ + wrmsr (0x120, 0x01f0001f, 0); + set_mtrr_done (&ctxt); +} /* End Function centaur_mcr_init */ + __initfunc(static void mtrr_setup (void)) { printk ("mtrr: v%s Richard Gooch (rgooch@atnf.csiro.au)\n", MTRR_VERSION); @@ -1582,7 +1662,6 @@ set_mtrr_up = intel_set_mtrr_up; break; case X86_VENDOR_CYRIX: - printk ("mtrr: Using Cyrix style ARRs\n"); get_mtrr = cyrix_get_arr; set_mtrr_up = cyrix_set_arr_up; get_free_region = cyrix_get_free_region; @@ -1591,6 +1670,10 @@ get_mtrr = amd_get_mtrr; set_mtrr_up = amd_set_mtrr_up; break; + case X86_VENDOR_CENTAUR: + get_mtrr = centaur_get_mcr; + set_mtrr_up = centaur_set_mcr_up; + break; } } /* End Function mtrr_setup */ @@ -1611,6 +1694,9 @@ case X86_VENDOR_CYRIX: cyrix_arr_init (); break; + case X86_VENDOR_CENTAUR: + centaur_mcr_init (); + break; } } /* End Function mtrr_init_boot_cpu */ @@ -1675,6 +1761,9 @@ case X86_VENDOR_CYRIX: cyrix_arr_init (); break; + case X86_VENDOR_CENTAUR: + centaur_mcr_init (); + break; } # endif /* !__SMP__ */ diff -u --recursive --new-file v2.2.9/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.2.9/linux/arch/i386/kernel/setup.c Tue May 11 13:10:27 1999 +++ linux/arch/i386/kernel/setup.c Fri May 14 09:00:17 1999 @@ -9,6 +9,9 @@ * Force Cyrix 6x86(MX) and M II processors to report MTRR capability * and fix against Cyrix "coma bug" by * Zoltan Boszormenyi February 1999. + * + * Force Centaur C6 processors to report MTRR capability. + * Bart Hartgers , May 199. */ /* @@ -861,6 +864,8 @@ /* lv|=(1<<6); - may help too if the board can cope */ printk("now 0x%X", lv); wrmsr(0x107, lv, hv); + /* Emulate MTRRs using Centaur's MCR. */ + c->x86_capability |= X86_FEATURE_MTRR; } printk("\n"); } diff -u --recursive --new-file v2.2.9/linux/arch/i386/lib/checksum.S linux/arch/i386/lib/checksum.S --- v2.2.9/linux/arch/i386/lib/checksum.S Tue Jan 19 11:32:51 1999 +++ linux/arch/i386/lib/checksum.S Tue Jun 1 14:05:46 1999 @@ -369,7 +369,7 @@ #define ROUND1(x) \ SRC(movl x(%esi), %ebx ) ; \ - addl %ebx, %eax\n ; \ + addl %ebx, %eax ; \ DST(movl %ebx, x(%edi) ) ; #define ROUND(x) \ diff -u --recursive --new-file v2.2.9/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.2.9/linux/arch/sparc/kernel/sys_sunos.c Sun Nov 8 14:02:45 1998 +++ linux/arch/sparc/kernel/sys_sunos.c Mon May 24 13:03:56 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.94 1998/10/12 06:15:04 jj Exp $ +/* $Id: sys_sunos.c,v 1.97 1999/05/24 19:40:39 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1198,7 +1198,7 @@ lock_kernel(); ret = check_nonblock(sys_readv(fd,vector,count),fd); - lock_kernel(); + unlock_kernel(); return ret; } diff -u --recursive --new-file v2.2.9/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c --- v2.2.9/linux/arch/sparc64/kernel/setup.c Wed Apr 28 11:37:30 1999 +++ linux/arch/sparc64/kernel/setup.c Sat May 29 11:10:15 1999 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.43 1999/04/12 08:08:24 davem Exp $ +/* $Id: setup.c,v 1.43.2.1 1999/05/28 02:18:13 davem Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -550,7 +550,9 @@ ic_servaddr = sv; if (gw) ic_gateway = gw; +#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP) ic_proto_enabled = 0; +#endif } } #endif diff -u --recursive --new-file v2.2.9/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.2.9/linux/arch/sparc64/kernel/sys_sparc32.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/kernel/sys_sparc32.c Sun May 16 10:39:59 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.107 1999/03/05 13:21:02 davem Exp $ +/* $Id: sys_sparc32.c,v 1.108 1999/05/16 10:50:32 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -2363,6 +2363,94 @@ __scm_destroy(scm); } +/* In these cases we (currently) can just copy to data over verbatim + * because all CMSGs created by the kernel have well defined types which + * have the same layout in both the 32-bit and 64-bit API. One must add + * some special cased conversions here if we start sending control messages + * with incompatible types. + * + * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after + * we do our work. The remaining cases are: + * + * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean + * IP_TTL int 32-bit clean + * IP_TOS __u8 32-bit clean + * IP_RECVOPTS variable length 32-bit clean + * IP_RETOPTS variable length 32-bit clean + * (these last two are clean because the types are defined + * by the IPv4 protocol) + * IP_RECVERR struct sock_extended_err + + * struct sockaddr_in 32-bit clean + * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + + * struct sockaddr_in6 32-bit clean + * IPV6_PKTINFO struct in6_pktinfo 32-bit clean + * IPV6_HOPLIMIT int 32-bit clean + * IPV6_FLOWINFO u32 32-bit clean + * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean + * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) +{ + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; + struct cmsghdr *ucmsg; + + bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; + space_avail = kmsg->msg_controllen + bufsz; + wp = workbuf = kmalloc(bufsz, GFP_KERNEL); + if(workbuf == NULL) + goto fail; + + /* To make this more sane we assume the kernel sends back properly + * formatted control messages. Because of how the kernel will truncate + * the cmsg_len for MSG_TRUNC cases, we need not check that case either. + */ + ucmsg = (struct cmsghdr *) orig_cmsg_uptr; + while(((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) { + struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; + int clen64, clen32; + + /* UCMSG is the 64-bit format CMSG entry in user-space. + * KCMSG32 is within the kernel space temporary buffer + * we use to convert into a 32-bit style CMSG. + */ + __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); + __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + + CMSG32_ALIGN(sizeof(struct cmsghdr32))); + kcmsg32->cmsg_len = clen32; + + ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); + wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); + } + + /* Copy back fixed up data, and adjust pointers. */ + bufsz = (wp - workbuf); + copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); + + kmsg->msg_control = (struct cmsghdr *) + (((char *)orig_cmsg_uptr) + bufsz); + kmsg->msg_controllen = space_avail - bufsz; + + kfree(workbuf); + return; + +fail: + /* If we leave the 64-bit format CMSG chunks in there, + * the application could get confused and crash. So to + * ensure greater recovery, we report no CMSGs. + */ + kmsg->msg_controllen += bufsz; + kmsg->msg_control = (void *) orig_cmsg_uptr; +} + asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) { struct socket *sock; @@ -2455,6 +2543,14 @@ if(scm.fp) __scm_destroy(&scm); } else { + /* If recvmsg processing itself placed some + * control messages into user space, it's is + * using 64-bit CMSG processing, so we need + * to fix it up before we tack on more stuff. + */ + if((unsigned long) kern_msg.msg_control != cmsg_ptr) + cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); + /* Wheee... */ if(sock->passcred) put_cmsg32(&kern_msg, @@ -2471,9 +2567,9 @@ if(uaddr != NULL && err >= 0) err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); if(cmsg_ptr != 0 && err >= 0) { - u32 ucmsg_ptr = ((u32)(unsigned long)kern_msg.msg_control); - err = __put_user(ucmsg_ptr, &user_msg->msg_control); - err |= __put_user(kern_msg.msg_controllen, &user_msg->msg_controllen); + unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); + __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr); + err |= __put_user(uclen, &user_msg->msg_controllen); } if(err >= 0) err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); diff -u --recursive --new-file v2.2.9/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.2.9/linux/arch/sparc64/kernel/sys_sunos32.c Sun Nov 8 14:02:48 1998 +++ linux/arch/sparc64/kernel/sys_sunos32.c Mon May 24 13:03:56 1999 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.22 1998/10/26 20:01:13 davem Exp $ +/* $Id: sys_sunos32.c,v 1.25 1999/05/24 19:40:44 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -1347,7 +1347,7 @@ lock_kernel(); ret = check_nonblock(sys32_readv(fd, vector, count), fd); - lock_kernel(); + unlock_kernel(); return ret; } diff -u --recursive --new-file v2.2.9/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c --- v2.2.9/linux/arch/sparc64/solaris/fs.c Tue Mar 23 14:35:47 1999 +++ linux/arch/sparc64/solaris/fs.c Thu May 13 23:25:57 1999 @@ -410,7 +410,11 @@ mm_segment_t old_fs = get_fs(); int error; struct sol_statvfs *ss = (struct sol_statvfs *)A(buf); - + + if (!inode->i_sb) + return -ENODEV; + if (!inode->i_sb->s_op->statfs) + return -ENOSYS; set_fs (KERNEL_DS); error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs)); set_fs (old_fs); @@ -448,6 +452,10 @@ int error; struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf); + if (!inode->i_sb) + return -ENODEV; + if (!inode->i_sb->s_op->statfs) + return -ENOSYS; set_fs (KERNEL_DS); error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs)); set_fs (old_fs); @@ -489,9 +497,7 @@ if (!IS_ERR(dentry)) { struct inode * inode = dentry->d_inode; - error = -ENOSYS; - if (inode->i_sb->s_op->statfs) - error = report_statvfs(inode, buf); + error = report_statvfs(inode, buf); dput(dentry); } unlock_kernel(); @@ -515,10 +521,6 @@ error = -ENOENT; else if (!(inode = dentry->d_inode)) error = -ENOENT; - else if (!inode->i_sb) - error = -ENODEV; - else if (!inode->i_sb->s_op->statfs) - error = -ENOSYS; else error = report_statvfs(inode, buf); fput(file); @@ -538,9 +540,7 @@ if (!IS_ERR(dentry)) { struct inode * inode = dentry->d_inode; - error = -ENOSYS; - if (inode->i_sb->s_op->statfs) - error = report_statvfs64(inode, buf); + error = report_statvfs64(inode, buf); dput(dentry); } unlock_kernel(); @@ -564,10 +564,6 @@ error = -ENOENT; else if (!(inode = dentry->d_inode)) error = -ENOENT; - else if (!inode->i_sb) - error = -ENODEV; - else if (!inode->i_sb->s_op->statfs) - error = -ENOSYS; else error = report_statvfs64(inode, buf); fput(file); diff -u --recursive --new-file v2.2.9/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.2.9/linux/drivers/block/ide.c Thu May 13 23:10:29 1999 +++ linux/drivers/block/ide.c Sat May 22 14:20:54 1999 @@ -926,6 +926,7 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout) { byte stat; + int i; unsigned long flags; udelay(1); /* spec allows drive 400ns to assert "BUSY" */ @@ -942,9 +943,18 @@ } __restore_flags(flags); /* local CPU only */ } - udelay(1); /* allow status to settle, then read it again */ - if (OK_STAT((stat = GET_STAT()), good, bad)) - return 0; + /* + * Allow status to settle, then read it again. + * A few rare drives vastly violate the 400ns spec here, + * so we'll wait up to 10usec for a "good" status + * rather than expensively fail things immediately. + * This fix courtesy of Matthew Faupel & Niccolo Rigacci. + */ + for (i = 0; i < 10; i++) { + udelay(1); + if (OK_STAT((stat = GET_STAT()), good, bad)) + return 0; + } ide_error(drive, "status error", stat); return 1; } diff -u --recursive --new-file v2.2.9/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.2.9/linux/drivers/block/loop.c Tue Jan 19 11:32:51 1999 +++ linux/drivers/block/loop.c Sun May 30 10:17:03 1999 @@ -504,6 +504,8 @@ if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE) return -EINVAL; type = info.lo_encrypt_type; + if (info.lo_encrypt_key_size == 0 && type == LO_CRYPT_XOR) + return -EINVAL; if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL) return -EINVAL; err = loop_release_xfer(lo); diff -u --recursive --new-file v2.2.9/linux/drivers/block/ns87415.c linux/drivers/block/ns87415.c --- v2.2.9/linux/drivers/block/ns87415.c Tue Mar 23 14:35:47 1999 +++ linux/drivers/block/ns87415.c Sat May 29 11:10:15 1999 @@ -49,8 +49,25 @@ new = use_dma ? ((new & ~other) | bit) : (new & ~bit); if (new != *old) { + unsigned char stat; + + /* + * Don't change DMA engine settings while Write Buffers + * are busy. + */ + (void) pci_read_config_byte(dev, 0x43, &stat); + while (stat & 0x03) { + udelay(1); + (void) pci_read_config_byte(dev, 0x43, &stat); + } + *old = new; (void) pci_write_config_dword(dev, 0x40, new); + + /* + * And let things settle... + */ + udelay(10); } __restore_flags(flags); /* local CPU only */ diff -u --recursive --new-file v2.2.9/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.2.9/linux/drivers/char/bttv.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/char/bttv.c Sun May 30 10:17:03 1999 @@ -543,6 +543,8 @@ { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}}, /* Pixelview PlayTV (bt878) */ { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }}, + /* "Leadtek WinView 601", */ + { 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, {0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}}, }; #define TVCARDS (sizeof(tvcards)/sizeof(tvcard)) @@ -2036,6 +2038,41 @@ I2CWrite(&(btv->i2c), I2C_TDA9850, TDA9850_CON3, con3, 1); } + + /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */ + if (btv->type == BTTV_WINVIEW_601) { + int bits_out, loops, vol, data; + + /* 32 levels logarithmic */ + vol = 32 - ((v.volume>>11)); + /* units */ + bits_out = (PT2254_DBS_IN_2>>(vol%5)); + /* tens */ + bits_out |= (PT2254_DBS_IN_10>>(vol/5)); + bits_out |= PT2254_L_CHANEL | PT2254_R_CHANEL; + data = btread(BT848_GPIO_DATA); + data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA| + WINVIEW_PT2254_STROBE); + for (loops = 17; loops >= 0 ; loops--) { + if (bits_out & (1<have_msp3400) { i2c_control_device(&(btv->i2c), @@ -3033,6 +3070,9 @@ case BTTV_VHX: strcpy(btv->video_dev.name,"BT848(Aimslab-VHX)"); break; + case BTTV_WINVIEW_601: + strcpy(btv->video_dev.name,"BT848(Leadtek WinView 601)"); + break; } printk("%s\n",btv->video_dev.name); audio(btv, AUDIO_MUTE); diff -u --recursive --new-file v2.2.9/linux/drivers/char/bttv.h linux/drivers/char/bttv.h --- v2.2.9/linux/drivers/char/bttv.h Wed Apr 28 11:37:30 1999 +++ linux/drivers/char/bttv.h Sun May 30 10:17:03 1999 @@ -210,6 +210,7 @@ #define BTTV_VHX 0x0e #define BTTV_ZOLTRIX 0x0f #define BTTV_PIXVIEWPLAYTV 0x10 +#define BTTV_WINVIEW_601 0x11 #define AUDIO_TUNER 0x00 #define AUDIO_RADIO 0x01 @@ -259,5 +260,13 @@ #define TEA6300_TR 0x03 /* treble control */ #define TEA6300_FA 0x04 /* fader control */ #define TEA6300_SW 0x05 /* mute and source switch */ + +#define PT2254_L_CHANEL 0x10 +#define PT2254_R_CHANEL 0x08 +#define PT2254_DBS_IN_2 0x400 +#define PT2254_DBS_IN_10 0x20000 +#define WINVIEW_PT2254_CLK 0x40 +#define WINVIEW_PT2254_DATA 0x20 +#define WINVIEW_PT2254_STROBE 0x80 #endif diff -u --recursive --new-file v2.2.9/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.2.9/linux/drivers/char/cyclades.c Fri Apr 16 14:47:30 1999 +++ linux/drivers/char/cyclades.c Mon May 24 22:38:02 1999 @@ -1,7 +1,7 @@ #define BLOCKMOVE #define Z_WAKE static char rcsid[] = -"$Revision: 2.2.2.1 $$Date: 1999/04/08 16:17:43 $"; +"$Revision: 2.2.2.2 $$Date: 1999/05/21 17:18:15 $"; /* * linux/drivers/char/cyclades.c @@ -21,7 +21,7 @@ * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, * and then fixed as suggested by Michael K. Johnson 12/12/92. * - * This version does not support shared irq's. + * This version supports shared IRQ's (only for PCI boards). * * This module exports the following rs232 io functions: * int cy_init(void); @@ -31,6 +31,17 @@ * void cleanup_module(void); * * $Log: cyclades.c,v $ + * Revision 2.2.2.2 1999/05/14 17:18:15 ivan + * /proc entry location changed to /proc/tty/driver/cyclades; + * Added support to shared IRQ's (only for PCI boards); + * Added support for Cobalt Qube2 systems; + * IRQ [de]allocation scheme revisited; + * BREAK implementation changed in order to make use of the 'break_ctl' + * TTY facility; + * Fixed typo in TTY structure field 'driver_name'; + * Included a PCI bridge reset and EEPROM reload in the board + * initialization code (for both Y and Z series). + * * Revision 2.2.2.1 1999/04/08 16:17:43 ivan * Fixed a bug in cy_wait_until_sent that was preventing the port to be * closed properly after a SIGINT; @@ -536,7 +547,7 @@ #undef CY_16Y_HACK #undef CY_ENABLE_MONITORING #undef CY_PCI_DEBUG -#define CY_PROC +#undef CY_PROC #if 0 #define PAUSE __asm__("nop"); @@ -600,6 +611,14 @@ #include #include +#ifdef CONFIG_COBALT_27 +#include +#include + +#define CACHED_TO_UNCACHED(x) (((unsigned long)(x) & \ + (unsigned long)0x1fffffff) + KSEG1) +#endif + #define cy_put_user put_user static unsigned long cy_get_user(unsigned long *addr) @@ -638,6 +657,7 @@ static struct tty_driver cy_serial_driver, cy_callout_driver; static int serial_refcount; +#ifndef CONFIG_COBALT_27 static volatile int cy_irq_triggered; static volatile int cy_triggered; static int cy_wild_int_mask; @@ -665,6 +685,8 @@ }; #define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*)) +#endif /* CONFIG_COBALT_27 */ + /* This is the per-card data structure containing address, irq, number of channels, etc. This driver supports a maximum of NR_CARDS cards. */ @@ -681,11 +703,6 @@ static struct termios *serial_termios[NR_PORTS]; static struct termios *serial_termios_locked[NR_PORTS]; -/* This is the per-irq data structure, - it maps an irq to the corresponding card */ - -static struct cyclades_card *IRQ_cards[NR_IRQS]; - /* * tmp_buf is used as a temporary buffer by serial_write. We need to * lock it in case the copy_from_user blocks while swapping in a page, @@ -790,7 +807,9 @@ static void cy_start(struct tty_struct *); static void set_line_char(struct cyclades_port *); +#ifndef CONFIG_COBALT_27 static void cy_probe(int, void *, struct pt_regs *); +#endif /* CONFIG_COBALT_27 */ static void cyz_poll(unsigned long); #ifdef CYCLOM_SHOW_STATUS static void show_status(int); @@ -959,6 +978,8 @@ return(0); } /* cyy_issue_cmd */ +#ifndef CONFIG_COBALT_27 /* ISA interrupt detection code */ + static int probe_ready; /* @@ -1149,6 +1170,8 @@ return; } /* cy_probe */ +#endif /* CONFIG_COBALT_27 */ + /* The real interrupt service routine is called whenever the card wants its hand held--chars received, out buffer empty, modem change, etc. @@ -1172,9 +1195,9 @@ int mdm_change; int mdm_status; - if((cinfo = IRQ_cards[irq]) == 0){ + if((cinfo = (struct cyclades_card *)dev_id) == 0){ #ifdef CY_DEBUG_INTERRUPTS -printk("cy_interrupt: spurious interrupt %d\n\r", irq); + printk("cy_interrupt: spurious interrupt %d\n\r", irq); #endif return; /* spurious interrupt */ } @@ -1206,7 +1229,7 @@ } if (status & CySRReceive) { /* reception interrupt */ #ifdef CY_DEBUG_INTERRUPTS -printk("cy_interrupt: rcvd intr, chip %d\n\r", chip); + printk("cy_interrupt: rcvd intr, chip %d\n\r", chip); #endif /* determine the channel & change to that context */ save_xir = (u_char) cy_readb(base_addr+(CyRIR<x_char = 0; } - if (info->x_break){ - /* The Cirrus chip requires the "Embedded - Transmit Commands" of start break, delay, - and end break sequences to be sent. The - duration of the break is given in TICs, - which runs at HZ (typically 100) and the - PPR runs at 200 Hz, so the delay is - duration * 200/HZ, and thus a break can - run from 1/100 sec to about 5/4 sec. - For CD1400 J or later, replace the 200 Hz - by 500 Hz. - */ - /* start break */ - cy_writeb((u_long)base_addr + (CyTDR<chip_rev >= CD1400_REV_J ) { - /* It is a CD1400 rev. J or later */ - cy_writeb((u_long)base_addr + (CyTDR<x_break*500/HZ); - } else { - cy_writeb((u_long)base_addr + (CyTDR<x_break*200/HZ); + if (info->breakon || info->breakoff) { + if (info->breakon) { + cy_writeb((u_long)base_addr + (CyTDR<breakon = 0; + char_count -= 2; + } + if (info->breakoff) { + cy_writeb((u_long)base_addr + (CyTDR<breakoff = 0; + char_count -= 2; } - /* finish break */ - cy_writeb((u_long)base_addr + (CyTDR<x_break = 0; } while (char_count-- > 0){ @@ -1871,12 +1876,6 @@ info->last_active = jiffies; info->jiffies[2] = jiffies; } - if (info->x_break){ - printk("cyc cyz_poll shouldn't see x_break\n"); - info->x_break = 0; - info->last_active = jiffies; - info->jiffies[2] = jiffies; - } #ifdef BLOCKMOVE while(0 < (small_count = cy_min((tx_bufsize - tx_put), @@ -1946,26 +1945,35 @@ startup(struct cyclades_port * info) { unsigned long flags; + int retval = 0; unsigned char *base_addr; int card,chip,channel,index; + unsigned long page; + + page = get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + save_flags(flags); cli(); if (info->flags & ASYNC_INITIALIZED){ - return 0; + free_page(page); + goto errout; } if (!info->type){ if (info->tty){ set_bit(TTY_IO_ERROR, &info->tty->flags); } - return 0; - } - if (!info->xmit_buf){ - info->xmit_buf = (unsigned char *) get_free_page (GFP_KERNEL); - if (!info->xmit_buf){ - return -ENOMEM; - } + free_page(page); + goto errout; } + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *) page; + set_line_char(info); card = info->card; @@ -1982,39 +1990,40 @@ card, chip, channel, (long)base_addr);/**/ #endif - save_flags(flags); cli(); - cy_writeb((ulong)base_addr+(CyCAR<default_timeout - ? info->default_timeout - : 0x02)); /* 10ms rx timeout */ + cy_writeb((ulong)base_addr+(CyRTPR<default_timeout + ? info->default_timeout : 0x02)); /* 10ms rx timeout */ - cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index); + cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index); - cy_writeb((ulong)base_addr+(CyCAR<flags |= ASYNC_INITIALIZED; + cy_writeb((u_long)base_addr+(CySRER<flags |= ASYNC_INITIALIZED; + + if (info->tty){ + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + info->breakon = info->breakoff = 0; + memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); + info->idle_stats.in_use = + info->idle_stats.recv_idle = + info->idle_stats.xmit_idle = jiffies; - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); - info->idle_stats.in_use = - info->idle_stats.recv_idle = - info->idle_stats.xmit_idle = jiffies; restore_flags(flags); + } else { struct FIRM_ID *firm_id; struct ZFW_CTRL *zfw_ctrl; @@ -2022,6 +2031,8 @@ struct CH_CTRL *ch_ctrl; int retval; + restore_flags(flags); + base_addr = (unsigned char*) (cy_card[card].base_addr); firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); @@ -2074,7 +2085,7 @@ clear_bit(TTY_IO_ERROR, &info->tty->flags); } info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - + info->breakon = info->breakoff = 0; memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); info->idle_stats.in_use = info->idle_stats.recv_idle = @@ -2085,6 +2096,10 @@ printk(" cyc startup done\n"); #endif return 0; + +errout: + restore_flags(flags); + return retval; } /* startup */ @@ -3763,36 +3778,62 @@ return 0; } /* set_modem_info */ +/* + * cy_break() --- routine which turns the break handling on or off + */ static void -send_break( struct cyclades_port * info, int duration) +cy_break(struct tty_struct *tty, int break_state) { + struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + if (serial_paranoia_check(info, tty->device, "cy_break")) + return; + + save_flags(flags); cli(); if (!IS_CYC_Z(cy_card[info->card])) { /* Let the transmit ISR take care of this (since it requires stuffing characters into the output stream). */ - info->x_break = duration; - if (!info->xmit_cnt ) { - start_xmit(info); + if (break_state == -1) { + if (!info->breakon) { + info->breakon = 1; + if (!info->xmit_cnt ) { + start_xmit(info); + } + } + } else { + if (!info->breakoff) { + info->breakoff = 1; + if (!info->xmit_cnt ) { + start_xmit(info); + } + } } } else { - /* For the moment we ignore the duration parameter!!! - A better implementation will use C_CM_SET_BREAK - and C_CM_CLR_BREAK with the appropriate delay. - */ -#if 1 -// this appears to wedge the output data stream -int retval; - retval = cyz_issue_cmd(&cy_card[info->card], + int retval; + + if (break_state == -1) { + retval = cyz_issue_cmd(&cy_card[info->card], (info->line) - (cy_card[info->card].first_line), - C_CM_SENDBRK, 0L); - if (retval != 0){ - printk("cyc:send_break retval at %d was %x\n", - __LINE__, retval); + C_CM_SET_BREAK, 0L); + if (retval != 0) { + printk("cyc:cy_break (set) retval at %d was %x\n", + __LINE__, retval); + } + } else { + retval = cyz_issue_cmd(&cy_card[info->card], + (info->line) - (cy_card[info->card].first_line), + C_CM_CLR_BREAK, 0L); + if (retval != 0) { + printk("cyc:cy_break (clr) retval at %d was %x\n", + __LINE__, retval); + } } -#endif } -} /* send_break */ + restore_flags(flags); + +} /* cy_break */ static int get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon) @@ -4026,21 +4067,6 @@ case CYGETWAIT: ret_val = info->closing_wait / (HZ/100); break; - case TCSBRK: /* SVID version: non-zero arg --> no break */ - ret_val = tty_check_change(tty); - if (ret_val) - return ret_val; - tty_wait_until_sent(tty,0); - if (!arg) - send_break(info, HZ/4); /* 1/4 second */ - break; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - ret_val = tty_check_change(tty); - if (ret_val) - return ret_val; - tty_wait_until_sent(tty,0); - send_break(info, arg ? arg*(HZ/10) : HZ/4); - break; case TIOCMGET: ret_val = get_modem_info(info, (unsigned int *) arg); break; @@ -4091,7 +4117,13 @@ tty->stopped = 0; cy_start(tty); } -#ifdef tytso_patch_94Nov25_1726 +#if 0 + /* + * No need to wake up processes in open wait, since they + * sample the CLOCAL flag once, and don't recheck it. + * XXX It's not clear whether the current behavior is correct + * or not. Hence, this may change..... + */ if (!(old_termios->c_cflag & CLOCAL) && (tty->termios->c_cflag & CLOCAL)) wake_up_interruptible(&info->open_wait); @@ -4100,16 +4132,6 @@ return; } /* cy_set_termios */ - -/* - * void (*set_ldisc)(struct tty_struct *tty); - * - * This routine allows the tty driver to be notified when the - * device's termios settings have changed. - * - */ - - /* This routine is called by the upper-layer tty layer to signal that incoming characters should be throttled because the input buffers are close to full. @@ -4467,6 +4489,7 @@ return chip_number; } /* cyy_init_card */ +#ifndef CONFIG_COBALT_27 /* * --------------------------------------------------------------------- * cy_detect_isa() - Probe for Cyclom-Y/ISA boards. @@ -4530,7 +4553,7 @@ /* allocate IRQ */ if(request_irq(cy_isa_irq, cyy_interrupt, - SA_INTERRUPT, "cyclomY", NULL)) + SA_INTERRUPT, "Cyclom-Y", &cy_card[j])) { printk("Cyclom-Y/ISA found at 0x%lx ", (unsigned long) cy_isa_address); @@ -4546,7 +4569,6 @@ cy_card[j].bus_index = 0; cy_card[j].first_line = cy_next_channel; cy_card[j].num_chips = cy_isa_nchan/4; - IRQ_cards[cy_isa_irq] = &cy_card[j]; nboard++; /* print message */ @@ -4561,6 +4583,20 @@ return(nboard); } /* cy_detect_isa */ +#endif /* CONFIG_COBALT_27 */ + +static void plx_init(uclong addr, uclong initctl) +{ + /* Reset PLX */ + cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000); + udelay(100L); + cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000); + + /* Reload Config. Registers from EEPROM */ + cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000); + udelay(100L); + cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000); +} /* * --------------------------------------------------------------------- @@ -4621,6 +4657,12 @@ cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK; cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK; + if (cy_pci_addr2 & ~PCI_BASE_ADDRESS_IO_MASK) { + printk(" Warning: PCI I/O bit incorrectly set. " + "Ignoring it...\n"); + cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK; + } + #if defined(__alpha__) if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", @@ -4673,7 +4715,7 @@ /* allocate IRQ */ if(request_irq(cy_pci_irq, cyy_interrupt, - SA_INTERRUPT, "cyclomY", NULL)) + SA_SHIRQ, "Cyclom-Y", &cy_card[j])) { printk("Cyclom-Y/PCI found at 0x%lx ", (ulong) cy_pci_addr2); @@ -4689,13 +4731,14 @@ cy_card[j].bus_index = 1; cy_card[j].first_line = cy_next_channel; cy_card[j].num_chips = cy_pci_nchan/4; - IRQ_cards[cy_pci_irq] = &cy_card[j]; /* enable interrupts in the PCI interface */ plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; switch (plx_ver) { case PLX_9050: + plx_init(cy_pci_addr0, 0x50); + cy_writew(cy_pci_addr0+0x4c, cy_readw(cy_pci_addr0+0x4c)|0x0040); break; @@ -4704,6 +4747,8 @@ case PLX_9080: default: /* Old boards, use PLX_9060 */ + plx_init(cy_pci_addr0, 0x6c); + cy_writew(cy_pci_addr0+0x68, cy_readw(cy_pci_addr0+0x68)|0x0900); break; @@ -4742,9 +4787,18 @@ #if !defined(__alpha__) cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Zctl); #endif + + plx_init(cy_pci_addr0, 0x6c); + mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) cy_pci_addr0)->mail_box_0); cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK; + + if (cy_pci_addr2 & ~PCI_BASE_ADDRESS_IO_MASK) { + printk(" Warning: PCI I/O bit incorrectly set. " + "Ignoring it...\n"); + cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK; + } if (mailbox == ZE_V1) { #if !defined(__alpha__) cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ze_win); @@ -4821,7 +4875,7 @@ /* allocate IRQ only if board has an IRQ */ if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) { if(request_irq(cy_pci_irq,cyz_interrupt, - SA_INTERRUPT,"cyclomZ",NULL)) + SA_SHIRQ,"Cyclades-Z",&cy_card[j])) { printk("Could not allocate IRQ%d ", cy_pci_irq); @@ -4839,7 +4893,6 @@ cy_card[j].bus_index = 1; cy_card[j].first_line = cy_next_channel; cy_card[j].num_chips = -1; - IRQ_cards[cy_pci_irq] = &cy_card[j]; /* print message */ /* don't report IRQ if board is no IRQ */ @@ -4905,7 +4958,7 @@ /* allocate IRQ only if board has an IRQ */ if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) { if(request_irq(cy_pci_irq,cyz_interrupt, - SA_INTERRUPT,"cyclomZ",NULL)) + SA_SHIRQ,"Cyclades-Z",&cy_card[j])) { printk("Could not allocate IRQ%d ", cy_pci_irq); @@ -4922,7 +4975,6 @@ cy_card[j].bus_index = 1; cy_card[j].first_line = cy_next_channel; cy_card[j].num_chips = -1; - IRQ_cards[cy_pci_irq] = &cy_card[j]; /* print message */ /* don't report IRQ if board is no IRQ */ @@ -4971,7 +5023,6 @@ __DATE__, __TIME__); } /* show_version */ -#ifdef CY_PROC static int cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, int *eof, void *data) @@ -5028,7 +5079,6 @@ len = 0; return len; } -#endif /* The serial driver boot-time initialization code! Hardware I/O ports are mapped to character special devices on a @@ -5062,13 +5112,15 @@ struct proc_dir_entry *ent; #endif + init_bh(CYCLADES_BH, do_cyclades_bh); + show_version(); /* Initialize the tty_driver structure */ memset(&cy_serial_driver, 0, sizeof(struct tty_driver)); cy_serial_driver.magic = TTY_DRIVER_MAGIC; - cy_serial_driver.name = "cyclades"; + cy_serial_driver.driver_name = "cyclades"; cy_serial_driver.name = "ttyC"; cy_serial_driver.major = CYCLADES_MAJOR; cy_serial_driver.minor_start = 0; @@ -5083,6 +5135,7 @@ cy_serial_driver.table = serial_table; cy_serial_driver.termios = serial_termios; cy_serial_driver.termios_locked = serial_termios_locked; + cy_serial_driver.open = cy_open; cy_serial_driver.close = cy_close; cy_serial_driver.write = cy_write; @@ -5098,7 +5151,9 @@ cy_serial_driver.stop = cy_stop; cy_serial_driver.start = cy_start; cy_serial_driver.hangup = cy_hangup; + cy_serial_driver.break_ctl = cy_break; cy_serial_driver.wait_until_sent = cy_wait_until_sent; + cy_serial_driver.read_proc = cyclades_get_proc_info; /* * The callout device is just like normal device except for @@ -5117,12 +5172,6 @@ if (tty_register_driver(&cy_callout_driver)) panic("Couldn't register Cyclades callout driver\n"); - init_bh(CYCLADES_BH, do_cyclades_bh); - - for (i = 0; i < NR_IRQS; i++) { - IRQ_cards[i] = 0; - } - for (i = 0; i < NR_CARDS; i++) { /* base_addr=0 indicates board not found */ cy_card[i].base_addr = 0; @@ -5135,9 +5184,11 @@ availability of cy_card and cy_port data structures and updating the cy_next_channel. */ +#ifndef CONFIG_COBALT_27 /* look for isa boards */ cy_isa_nboard = cy_detect_isa(); - +#endif /* CONFIG_COBALT_27 */ + /* look for pci boards */ cy_pci_nboard = cy_detect_pci(); @@ -5323,6 +5374,7 @@ cleanup_module(void) { int i; + int e1, e2; unsigned long flags; if (cyz_timeron){ @@ -5333,11 +5385,12 @@ save_flags(flags); cli(); remove_bh(CYCLADES_BH); - free_page((unsigned long)tmp_buf); - if (tty_unregister_driver(&cy_callout_driver)) - printk("Couldn't unregister Cyclades callout driver\n"); - if (tty_unregister_driver(&cy_serial_driver)) - printk("Couldn't unregister Cyclades serial driver\n"); + if ((e1 = tty_unregister_driver(&cy_serial_driver))) + printk("cyc: failed to unregister Cyclades serial driver(%d)\n", + e1); + if ((e2 = tty_unregister_driver(&cy_callout_driver))) + printk("cyc: failed to unregister Cyclades callout driver (%d)\n", + e2); restore_flags(flags); @@ -5345,9 +5398,13 @@ if (cy_card[i].base_addr != 0 && cy_card[i].irq) { - free_irq(cy_card[i].irq,NULL); + free_irq(cy_card[i].irq, &cy_card[i]); } } + if (tmp_buf) { + free_page((unsigned long) tmp_buf); + tmp_buf = NULL; + } #ifdef CY_PROC remove_proc_entry("cyclades", 0); #endif @@ -5358,6 +5415,7 @@ void cy_setup(char *str, int *ints) { +#ifndef CONFIG_COBALT_27 int i, j; for (i = 0 ; i < NR_ISA_ADDRS ; i++) { @@ -5368,6 +5426,7 @@ cy_isa_addresses[i++] = (unsigned char *)(ints[j]); } } +#endif /* CONFIG_COBALT_27 */ } /* cy_setup */ #endif diff -u --recursive --new-file v2.2.9/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c --- v2.2.9/linux/drivers/misc/parport_pc.c Tue May 11 13:10:29 1999 +++ linux/drivers/misc/parport_pc.c Tue Jun 1 16:43:43 1999 @@ -371,12 +371,12 @@ * copy. Some ports _do_ allow reads, so bypass the software * copy here. In addition, some bits aren't writable. */ r = inb (pb->base+CONTROL); - if ((r & 0x3f) == w) { + if ((r & 0xf) == w) { w = 0xe; parport_pc_write_control (pb, w); r = inb (pb->base+CONTROL); parport_pc_write_control (pb, 0xc); - if ((r & 0x3f) == w) + if ((r & 0xf) == w) return PARPORT_MODE_PCSPP; } @@ -832,8 +832,11 @@ * Put the ECP detected port in the more SPP like mode. */ parport_pc_write_econtrol(p, 0x0); - parport_pc_write_control(p, 0xc); + parport_pc_write_control(p, 0x8); parport_pc_write_data(p, 0); + udelay (50); + parport_pc_write_control(p, 0xc); + udelay (50); if (parport_probe_hook) (*parport_probe_hook)(p); diff -u --recursive --new-file v2.2.9/linux/drivers/net/cosa.c linux/drivers/net/cosa.c --- v2.2.9/linux/drivers/net/cosa.c Wed Mar 10 15:29:46 1999 +++ linux/drivers/net/cosa.c Sun May 30 10:17:03 1999 @@ -2,6 +2,9 @@ /* * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak + * + * 5/25/1999 : Marcelo Tosatti + * fixed a deadlock in cosa_sppp_open * * 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 @@ -598,6 +601,7 @@ if (chan->usage != 0) { printk(KERN_WARNING "%s: sppp_open called with usage count %d\n", chan->name, chan->usage); + spin_unlock_irqrestore(&chan->cosa->lock, flags); return -EBUSY; } chan->setup_rx = sppp_setup_rx; diff -u --recursive --new-file v2.2.9/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c --- v2.2.9/linux/drivers/net/eexpress.c Tue May 11 13:10:29 1999 +++ linux/drivers/net/eexpress.c Sun May 30 10:17:03 1999 @@ -81,7 +81,20 @@ * ftp's, which is significantly better than I get in DOS, so the overhead of * stopping and restarting the CU with each transmit is not prohibitive in * practice. + * + * Update by David Woodhouse 11/5/99: + * + * I've seen "CU wedged" messages in 16-bit mode, on the Alpha architecture. + * I assume that this is because 16-bit accesses are actually handled as two + * 8-bit accesses. */ + +#ifdef __alpha__ +#define LOCKUP16 1 +#endif +#ifndef LOCKUP16 +#define LOCKUP16 0 +#endif #include #include @@ -297,7 +310,7 @@ outb(inb(dev->base_addr + Config) & ~2, dev->base_addr + Config); } -static inline short int SHADOW(short int addr) +static inline unsigned short int SHADOW(short int addr) { addr &= 0x1f; if (addr > 0xf) addr += 0x3ff0; @@ -400,7 +413,10 @@ outb(0,ioaddr+SIGNAL_CA); free_irq(irq,dev); outb(i586_RST,ioaddr+EEPROM_Ctrl); - release_region(ioaddr,16); + release_region(ioaddr, EEXP_IO_EXTENT); + release_region(ioaddr+0x4000, 16); + release_region(ioaddr+0x8000, 16); + release_region(ioaddr+0xc000, 16); MOD_DEC_USE_COUNT; return 0; @@ -887,7 +903,7 @@ struct net_local *lp = (struct net_local *)dev->priv; unsigned short ioaddr = dev->base_addr; - if (lp->width) { + if (LOCKUP16 || lp->width) { /* Stop the CU so that there is no chance that it jumps off to a bogus address while we are writing the pointer to the next transmit packet in 8-bit mode -- @@ -927,7 +943,7 @@ if (lp->tx_head != lp->tx_reap) dev->tbusy = 0; - if (lp->width) { + if (LOCKUP16 || lp->width) { /* Restart the CU so that the packet can actually be transmitted. (Zoltan Szilagyi 10-12-96) */ scb_command(dev, SCB_CUresume); diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in --- v2.2.9/linux/drivers/net/irda/Config.in Wed Mar 10 15:29:46 1999 +++ linux/drivers/net/irda/Config.in Sun May 30 10:17:03 1999 @@ -1,18 +1,24 @@ mainmenu_option next_comment comment 'Infrared-port device drivers' -dep_tristate 'IrTTY (uses serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA -if [ "$CONFIG_IRTTY_SIR" != "n" ]; then - comment ' Dongle support' - bool ' Serial dongle support' CONFIG_DONGLE - if [ "$CONFIG_DONGLE" != "n" ]; then - dep_tristate ' ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRTTY_SIR - dep_tristate ' ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRTTY_SIR - dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRTTY_SIR - dep_tristate ' Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRTTY_SIR - fi +comment 'SIR device drivers' +dep_tristate 'IrTTY (uses Linux serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA +dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA + +comment 'FIR device drivers' +dep_tristate 'NSC PC87108' CONFIG_NSC_FIR $CONFIG_IRDA +dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA +dep_tristate 'Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA +dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA + +comment 'Dongle support' +bool 'Serial dongle support' CONFIG_DONGLE +if [ "$CONFIG_DONGLE" != "n" ]; then + dep_tristate ' ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRDA + dep_tristate ' ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRDA + dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA + dep_tristate ' Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA + dep_tristate ' Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA fi -dep_tristate ' NSC PC87108' CONFIG_NSC_FIR $CONFIG_IRDA -dep_tristate ' Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA -dep_tristate ' Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA + endmenu diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile --- v2.2.9/linux/drivers/net/irda/Makefile Fri Apr 16 14:47:30 1999 +++ linux/drivers/net/irda/Makefile Sun May 30 10:17:03 1999 @@ -20,6 +20,14 @@ endif endif +ifeq ($(CONFIG_IRPORT_SIR),y) +L_OBJS += irport.o +else + ifeq ($(CONFIG_IRPORT_SIR),m) + M_OBJS += irport.o + endif +endif + ifeq ($(CONFIG_NSC_FIR),y) L_OBJS += pc87108.o else @@ -44,6 +52,14 @@ endif endif +ifeq ($(CONFIG_TOSHIBA_FIR),y) +L_OBJS += toshoboe.o +else + ifeq ($(CONFIG_TOSHIBA_FIR),m) + M_OBJS += toshoboe.o + endif +endif + ifeq ($(CONFIG_ESI_DONGLE),y) L_OBJS += esi.o else @@ -73,6 +89,14 @@ else ifeq ($(CONFIG_GIRBIL_DONGLE),m) M_OBJS += girbil.o + endif +endif + +ifeq ($(CONFIG_LITELINK_DONGLE),y) +L_OBJS += litelink.o +else + ifeq ($(CONFIG_LITELINK_DONGLE),m) + M_OBJS += litelink.o endif endif diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c --- v2.2.9/linux/drivers/net/irda/actisys.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/net/irda/actisys.c Sun May 30 10:17:03 1999 @@ -1,16 +1,16 @@ /********************************************************************* * * Filename: actisys.c - * Version: 0.5 + * Version: 0.8 * Description: Implementation for the ACTiSYS IR-220L and IR-220L+ * dongles * Status: Experimental. * Author: Dag Brattli * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Mon Apr 12 11:56:35 1999 + * Modified at: Mon May 10 15:12:54 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -36,15 +36,14 @@ #include #include #include -#include #include -static void actisys_reset( struct irda_device *dev, int unused); -static void actisys_open( struct irda_device *idev, int type); -static void actisys_close( struct irda_device *dev); +static void actisys_reset(struct irda_device *dev, int unused); +static void actisys_open(struct irda_device *idev, int type); +static void actisys_close(struct irda_device *dev); static void actisys_change_speed( struct irda_device *dev, int baudrate); -static void actisys_reset( struct irda_device *dev, int unused); -static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos); +static void actisys_reset(struct irda_device *dev, int unused); +static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos); /* These are the baudrates supported */ static int baud_rates[] = { 9600, 19200, 57600, 115200, 38400}; @@ -58,17 +57,37 @@ actisys_init_qos, }; -__initfunc(void actisys_init(void)) +static struct dongle dongle_plus = { + ACTISYS_PLUS_DONGLE, + actisys_open, + actisys_close, + actisys_reset, + actisys_change_speed, + actisys_init_qos, +}; + +__initfunc(int actisys_init(void)) { - irtty_register_dongle(&dongle); + int ret; + + ret = irda_device_register_dongle(&dongle); + if (ret < 0) + return ret; + ret = irda_device_register_dongle(&dongle_plus); + if (ret < 0) { + irda_device_unregister_dongle(&dongle); + return ret; + } + return 0; } void actisys_cleanup(void) { - irtty_unregister_dongle(&dongle); + irda_device_unregister_dongle(&dongle); + irda_device_unregister_dongle(&dongle_plus); } -static void actisys_open( struct irda_device *idev, int type) +static void actisys_open(struct irda_device *idev, int type) { strcat(idev->description, " <-> actisys"); @@ -78,8 +97,11 @@ MOD_INC_USE_COUNT; } -static void actisys_close( struct irda_device *dev) +static void actisys_close(struct irda_device *idev) { + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + MOD_DEC_USE_COUNT; } @@ -90,25 +112,16 @@ * To cycle through the available baud rates, pulse RTS low for a few * ms. */ -static void actisys_change_speed( struct irda_device *idev, int baudrate) +static void actisys_change_speed(struct irda_device *idev, int baudrate) { - struct irtty_cb *self; - struct tty_struct *tty; - struct termios old_termios; - int cflag; int current_baudrate; int index = 0; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) idev->priv; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); - current_baudrate = idev->qos.baud_rate.value; /* Find the correct baudrate index for the currently used baudrate */ @@ -117,69 +130,34 @@ DEBUG( 4, __FUNCTION__ "(), index=%d\n", index); - if ( !self->tty) - return; - - tty = self->tty; - /* Cycle through avaiable baudrates until we reach the correct one */ - while ( current_baudrate != baudrate) { - DEBUG( 4, __FUNCTION__ "(), current baudrate = %d\n", - baud_rates[index]); + while (current_baudrate != baudrate) { + DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", + baud_rates[index]); /* Set DTR, clear RTS */ - irtty_set_dtr_rts(tty, TRUE, FALSE); + irda_device_set_dtr_rts(idev, TRUE, FALSE); /* Wait at a few ms */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Set DTR, Set RTS */ - irtty_set_dtr_rts(tty, TRUE, TRUE); + irda_device_set_dtr_rts(idev, TRUE, TRUE); /* Wait at a few ms again */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout( 2); + schedule_timeout(2); /* Go to next baudrate */ - if ( idev->io.dongle_id == ACTISYS_DONGLE) + if (idev->io.dongle_id == ACTISYS_DONGLE) index = (index+1) % 4; /* IR-220L */ else index = (index+1) % 5; /* IR-220L+ */ current_baudrate = baud_rates[index]; } - DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", - baud_rates[index]); - - /* Now change the speed of the serial port */ - old_termios = *(tty->termios); - cflag = tty->termios->c_cflag; - - cflag &= ~CBAUD; - - switch ( baudrate) { - case 9600: - default: - cflag |= B9600; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - } - - /* Change speed of serial port */ - tty->termios->c_cflag = cflag; - tty->driver.set_termios( tty, &old_termios); + DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",baud_rates[index]); } /* @@ -191,32 +169,20 @@ * 1. Clear DTR for a few ms. * */ -static void actisys_reset( struct irda_device *idev, int unused) +static void actisys_reset(struct irda_device *idev, int unused) { - struct irtty_cb *self; - struct tty_struct *tty; - - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) idev->priv; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); - - tty = self->tty; - if ( !tty) - return; - /* Clear DTR */ - irtty_set_dtr_rts(tty, FALSE, TRUE); + irda_device_set_dtr_rts(idev, FALSE, TRUE); /* Sleep 10-20 ms*/ current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Go back to normal mode */ - irtty_set_dtr_rts(tty, TRUE, TRUE); + irda_device_set_dtr_rts(idev, TRUE, TRUE); idev->qos.baud_rate.value = 9600; } @@ -227,12 +193,12 @@ * Initialize QoS capabilities * */ -static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos) +static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; /* Remove support for 38400 if this is not a 220L+ dongle */ - if ( idev->io.dongle_id == ACTISYS_DONGLE) + if (idev->io.dongle_id == ACTISYS_DONGLE) qos->baud_rate.bits &= ~IR_38400; qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ @@ -251,8 +217,7 @@ */ int init_module(void) { - actisys_init(); - return(0); + return actisys_init(); } /* diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c --- v2.2.9/linux/drivers/net/irda/esi.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/net/irda/esi.c Sun May 30 10:17:03 1999 @@ -1,17 +1,17 @@ /********************************************************************* * * Filename: esi.c - * Version: 1.2 + * Version: 1.4 * Description: Driver for the Extended Systems JetEye PC dongle * Status: Experimental. * Author: Thomas Davis, * Created at: Sat Feb 21 18:54:38 1998 - * Modified at: Mon Apr 12 11:55:30 1999 + * Modified at: Mon May 10 15:13:12 1999 * Modified by: Dag Brattli * Sources: esi.c * + * Copyright (c) 1998-1999, Dag Brattli, * Copyright (c) 1998, Thomas Davis, , - * Copyright (c) 1998, Dag Brattli, * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -41,11 +41,11 @@ #include #include -static void esi_open( struct irda_device *idev, int type); -static void esi_close( struct irda_device *driver); -static void esi_change_speed( struct irda_device *idev, int baud); -static void esi_reset( struct irda_device *idev, int unused); -static void esi_qos_init( struct irda_device *idev, struct qos_info *qos); +static void esi_open(struct irda_device *idev, int type); +static void esi_close(struct irda_device *driver); +static void esi_change_speed(struct irda_device *idev, int baud); +static void esi_reset(struct irda_device *idev, int unused); +static void esi_qos_init(struct irda_device *idev, struct qos_info *qos); static struct dongle dongle = { ESI_DONGLE, @@ -58,17 +58,17 @@ __initfunc(int esi_init(void)) { - return irtty_register_dongle(&dongle); + return irda_device_register_dongle(&dongle); } void esi_cleanup(void) { - irtty_unregister_dongle( &dongle); + irda_device_unregister_dongle(&dongle); } -static void esi_open( struct irda_device *idev, int type) +static void esi_open(struct irda_device *idev, int type) { - strcat( idev->description, " <-> esi"); + strcat(idev->description, " <-> esi"); idev->io.dongle_id = type; idev->flags |= IFF_DONGLE; @@ -76,8 +76,11 @@ MOD_INC_USE_COUNT; } -static void esi_close( struct irda_device *driver) -{ +static void esi_close(struct irda_device *idev) +{ + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + MOD_DEC_USE_COUNT; } @@ -87,54 +90,30 @@ * Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle * */ -static void esi_change_speed( struct irda_device *idev, int baud) +static void esi_change_speed(struct irda_device *idev, int baud) { - struct irtty_cb *self; - struct tty_struct *tty; int dtr, rts; - struct termios old_termios; - int cflag; - - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); - self = (struct irtty_cb *) idev->priv; - - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); - - if ( !self->tty) - return; - - tty = self->tty; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - old_termios = *(tty->termios); - cflag = tty->termios->c_cflag; - - cflag &= ~CBAUD; - switch (baud) { case 19200: - cflag |= B19200; dtr = TRUE; rts = FALSE; break; case 115200: - cflag |= B115200; dtr = rts = TRUE; break; case 9600: default: - cflag |= B9600; dtr = FALSE; rts = TRUE; break; } - /* Change speed of serial driver */ - tty->termios->c_cflag = cflag; - tty->driver.set_termios(tty, &old_termios); - irtty_set_dtr_rts(tty, dtr, rts); + /* Change speed of dongle */ + irda_device_set_dtr_rts(idev, dtr, rts); } static void esi_reset( struct irda_device *idev, int unused) @@ -148,14 +127,17 @@ * Init QoS capabilities for the dongle * */ -static void esi_qos_init( struct irda_device *idev, struct qos_info *qos) +static void esi_qos_init(struct irda_device *idev, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200; qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ } #ifdef MODULE - + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver"); + /* * Function init_module (void) * diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c --- v2.2.9/linux/drivers/net/irda/girbil.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/net/irda/girbil.c Sun May 30 10:17:03 1999 @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: girbil.c - * Version: 1.0 + * Version: 1.1 * Description: Implementation for the Greenwich GIrBIL dongle * Status: Experimental. * Author: Dag Brattli * Created at: Sat Feb 6 21:02:33 1999 - * Modified at: Sat Apr 10 19:53:12 1999 + * Modified at: Mon May 10 16:01:33 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -80,19 +80,19 @@ girbil_init_qos, }; -__initfunc(void girbil_init(void)) +__initfunc(int girbil_init(void)) { - irtty_register_dongle(&dongle); + return irda_device_register_dongle(&dongle); } void girbil_cleanup(void) { - irtty_unregister_dongle(&dongle); + irda_device_unregister_dongle(&dongle); } static void girbil_open(struct irda_device *idev, int type) { - strcat( idev->description, " <-> girbil"); + strcat(idev->description, " <-> girbil"); idev->io.dongle_id = type; idev->flags |= IFF_DONGLE; @@ -100,8 +100,11 @@ MOD_INC_USE_COUNT; } -static void girbil_close(struct irda_device *dev) +static void girbil_close(struct irda_device *idev) { + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + MOD_DEC_USE_COUNT; } @@ -114,71 +117,42 @@ */ static void girbil_change_speed(struct irda_device *idev, int speed) { - struct irtty_cb *self; - struct tty_struct *tty; - struct termios old_termios; - int cflag; __u8 control[2]; ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - self = (struct irtty_cb *) idev->priv; - - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - if (!self->tty) - return; - - tty = self->tty; - - old_termios = *(tty->termios); - cflag = tty->termios->c_cflag; - - cflag &= ~CBAUD; - switch (speed) { case 9600: default: - cflag |= B9600; control[0] = GIRBIL_9600; break; case 19200: - cflag |= B19200; control[0] = GIRBIL_19200; break; case 34800: - cflag |= B38400; control[0] = GIRBIL_38400; break; case 57600: - cflag |= B57600; control[0] = GIRBIL_57600; break; case 115200: - cflag |= B115200; control[0] = GIRBIL_115200; break; } control[1] = GIRBIL_LOAD; /* Set DTR and Clear RTS to enter command mode */ - irtty_set_dtr_rts(tty, FALSE, TRUE); + irda_device_set_dtr_rts(idev, FALSE, TRUE); /* Write control bytes */ - if (tty->driver.write) - tty->driver.write(self->tty, 0, control, 2); + irda_device_raw_write(idev, control, 2); current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Go back to normal mode */ - irtty_set_dtr_rts(tty, TRUE, TRUE); - - /* Now change the speed of the serial port */ - tty->termios->c_cflag = cflag; - tty->driver.set_termios(tty, &old_termios); + irda_device_set_dtr_rts(idev, TRUE, TRUE); } /* @@ -193,44 +167,32 @@ */ void girbil_reset(struct irda_device *idev, int unused) { - struct irtty_cb *self; - struct tty_struct *tty; __u8 control = GIRBIL_TXEN | GIRBIL_RXEN; ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - self = (struct irtty_cb *) idev->priv; - - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - tty = self->tty; - if (!tty) - return; - /* Reset dongle */ - irtty_set_dtr_rts(tty, TRUE, FALSE); + irda_device_set_dtr_rts(idev, TRUE, FALSE); /* Sleep at least 5 ms */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Set DTR and clear RTS to enter command mode */ - irtty_set_dtr_rts(tty, FALSE, TRUE); + irda_device_set_dtr_rts(idev, FALSE, TRUE); current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Write control byte */ - if (tty->driver.write) - tty->driver.write(self->tty, 0, &control, 1); + irda_device_raw_write(idev, &control, 1); current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Go back to normal mode */ - irtty_set_dtr_rts(tty, TRUE, TRUE); + irda_device_set_dtr_rts(idev, TRUE, TRUE); } /* @@ -258,8 +220,7 @@ */ int init_module(void) { - girbil_init(); - return(0); + return girbil_init(); } /* diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c --- v2.2.9/linux/drivers/net/irda/irport.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/net/irda/irport.c Sun May 30 10:17:03 1999 @@ -64,58 +64,168 @@ #define IO_EXTENT 8 -/* static unsigned int io[] = { 0x3e8, ~0, ~0, ~0 }; */ -/* static unsigned int irq[] = { 11, 0, 0, 0 }; */ +/* + * Currently you'll need to set these values using insmod like this: + * insmod irport io=0x3e8 irq=11 + */ +static unsigned int io[] = { ~0, ~0, ~0, ~0 }; +static unsigned int irq[] = { 0, 0, 0, 0 }; + +static unsigned int qos_mtt_bits = 0x03; + +static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL}; +static char *driver_name = "irport"; + +static int irport_open(int i, unsigned int iobase, unsigned int irq); +static int irport_close(struct irda_device *idev); static void irport_write_wakeup(struct irda_device *idev); static int irport_write(int iobase, int fifo_size, __u8 *buf, int len); static void irport_receive(struct irda_device *idev); +static int irport_net_init(struct device *dev); +static int irport_net_open(struct device *dev); +static int irport_net_close(struct device *dev); +static void irport_wait_until_sent(struct irda_device *idev); +static int irport_is_receiving(struct irda_device *idev); +static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts); +static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len); + __initfunc(int irport_init(void)) { -/* int i; */ + int i; -/* for ( i=0; (io[i] < 2000) && (i < 4); i++) { */ -/* int ioaddr = io[i]; */ -/* if (check_region(ioaddr, IO_EXTENT)) */ -/* continue; */ -/* if (irport_open( i, io[i], io2[i], irq[i], dma[i]) == 0) */ -/* return 0; */ -/* } */ -/* return -ENODEV; */ - return 0; + for (i=0; (io[i] < 2000) && (i < 4); i++) { + int ioaddr = io[i]; + if (check_region(ioaddr, IO_EXTENT)) + continue; + if (irport_open(i, io[i], irq[i]) == 0) + return 0; + } + /* + * Maybe something failed, but we can still be usable for FIR drivers + */ + return 0; } /* - * Function pc87108_cleanup () + * Function irport_cleanup () * - * Close all configured chips + * Close all configured ports * */ #ifdef MODULE static void irport_cleanup(void) { -/* int i; */ + int i; DEBUG( 4, __FUNCTION__ "()\n"); - /* for ( i=0; i < 4; i++) { */ -/* if ( dev_self[i]) */ -/* irport_close( &(dev_self[i]->idev)); */ -/* } */ + for (i=0; i < 4; i++) { + if (dev_self[i]) + irport_close(dev_self[i]); + } } #endif /* MODULE */ -/* - * Function irport_open (void) - * - * Start IO port - * - */ -int irport_open(int iobase) +static int irport_open(int i, unsigned int iobase, unsigned int irq) { - DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase); + struct irda_device *idev; + int ret; + + DEBUG( 0, __FUNCTION__ "()\n"); + +/* if (irport_probe(iobase, irq) == -1) */ +/* return -1; */ + + /* + * Allocate new instance of the driver + */ + idev = kmalloc(sizeof(struct irda_device), GFP_KERNEL); + if (idev == NULL) { + printk( KERN_ERR "IrDA: Can't allocate memory for " + "IrDA control block!\n"); + return -ENOMEM; + } + memset(idev, 0, sizeof(struct irda_device)); + + /* Need to store self somewhere */ + dev_self[i] = idev; + + /* Initialize IO */ + idev->io.iobase2 = iobase; + idev->io.irq2 = irq; + idev->io.io_ext = IO_EXTENT; + idev->io.fifo_size = 16; + + /* Lock the port that we need */ + ret = check_region(idev->io.iobase2, idev->io.io_ext); + if (ret < 0) { + DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + idev->io.iobase2); + /* w83977af_cleanup( self->idev); */ + return -ENODEV; + } + request_region(idev->io.iobase2, idev->io.io_ext, idev->name); + + /* Initialize QoS for this device */ + irda_init_max_qos_capabilies(&idev->qos); + + idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + IR_115200; + + idev->qos.min_turn_time.bits = qos_mtt_bits; + irda_qos_bits_to_value(&idev->qos); + + idev->flags = IFF_SIR|IFF_PIO; + + /* Specify which buffer allocation policy we need */ + idev->rx_buff.flags = GFP_KERNEL; + idev->tx_buff.flags = GFP_KERNEL; + + idev->rx_buff.truesize = 4000; + idev->tx_buff.truesize = 4000; + + /* Initialize callbacks */ + idev->change_speed = irport_change_speed; + idev->wait_until_sent = irport_wait_until_sent; + idev->is_receiving = irport_is_receiving; + idev->set_dtr_rts = irport_set_dtr_rts; + idev->raw_write = irport_raw_write; + + /* Override the network functions we need to use */ + idev->netdev.init = irport_net_init; + idev->netdev.hard_start_xmit = irport_hard_xmit; + idev->netdev.open = irport_net_open; + idev->netdev.stop = irport_net_close; + + /* Open the IrDA device */ + irda_device_open(idev, driver_name, NULL); + + return 0; +} + +static int irport_close(struct irda_device *idev) +{ + DEBUG(0, __FUNCTION__ "()\n"); + + ASSERT(idev != NULL, return -1;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + /* Release the PORT that this driver is using */ + DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", + idev->io.iobase2); + release_region(idev->io.iobase2, idev->io.io_ext); + + irda_device_close(idev); + + kfree(idev); + + return 0; +} + +void irport_start(int iobase) +{ /* Initialize UART */ outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR); @@ -123,24 +233,29 @@ /* Turn on interrups */ outb((UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER); - return 0; +} + +void irport_stop(int iobase) +{ + /* Reset UART */ + outb(0, iobase+UART_MCR); + + /* Turn off interrupts */ + outb(0, iobase+UART_IER); } /* - * Function irport_cleanup () + * Function irport_probe (void) * - * Stop IO port + * Start IO port * */ -void irport_close(int iobase) +int irport_probe(int iobase) { - DEBUG(4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase); - /* Reset UART */ - outb(0, iobase+UART_MCR); - /* Turn off interrupts */ - outb(0, iobase+UART_IER); + return 0; } /* @@ -149,14 +264,23 @@ * Set speed of port to specified baudrate * */ -void irport_change_speed( int iobase, int speed) +void irport_change_speed(struct irda_device *idev, int speed) { + int iobase; int fcr; /* FIFO control reg */ int lcr; /* Line control reg */ int divisor; DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed); + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase2; + + /* Update accounting for new speed */ + idev->io.baudrate = speed; + /* Turn off interrupts */ outb(0, iobase+UART_IER); @@ -373,8 +497,145 @@ idev->netdev.interrupt = 0; } +static int irport_net_init(struct device *dev) +{ + /* Set up to be a normal IrDA network device driver */ + irda_device_setup(dev); + + /* Insert overrides below this line! */ + + return 0; +} + +/* + * Function irport_net_open (dev) + * + * + * + */ +static int irport_net_open(struct device *dev) +{ + struct irda_device *idev; + int iobase; + + ASSERT(dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + iobase = idev->io.iobase2; + + if (request_irq(idev->io.irq2, irport_interrupt, 0, idev->name, + (void *) idev)) { + return -EAGAIN; + } + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + MOD_INC_USE_COUNT; + + irport_start(iobase); + + return 0; +} + +/* + * Function irport_net_close (idev) + * + * + * + */ +static int irport_net_close(struct device *dev) +{ + struct irda_device *idev; + int iobase; + + ASSERT(dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + DEBUG(4, __FUNCTION__ "()\n"); + + iobase = idev->io.iobase2; + + irport_stop(iobase); + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + free_irq(idev->io.irq2, idev); + + MOD_DEC_USE_COUNT; + + return 0; +} + +static void irport_wait_until_sent(struct irda_device *idev) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(60*HZ/1000); +} + +static int irport_is_receiving(struct irda_device *idev) +{ + return (idev->rx_buff.state != OUTSIDE_FRAME); +} + +/* + * Function irtty_set_dtr_rts (tty, dtr, rts) + * + * This function can be used by dongles etc. to set or reset the status + * of the dtr and rts lines + */ +static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts) +{ + int iobase; + + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase2; + + if (dtr) + dtr = UART_MCR_DTR; + if (rts) + rts = UART_MCR_RTS; + + outb(dtr|rts|UART_MCR_OUT2, iobase+UART_MCR); +} + +static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len) +{ + int iobase; + int actual = 0; + + ASSERT(idev != NULL, return -1;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + iobase = idev->io.iobase2; + + /* Tx FIFO should be empty! */ + if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { + DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n"); + return -1; + } + + /* Fill FIFO with current frame */ + while (actual < len) { + /* Transmit next byte */ + outb(buf[actual], iobase+UART_TX); + actual++; + } + + return actual; +} + #ifdef MODULE +MODULE_PARM(io, "1-4i"); +MODULE_PARM(irq, "1-4i"); + /* * Function cleanup_module (void) * @@ -393,11 +654,7 @@ */ int init_module(void) { - if (irport_init() < 0) { - cleanup_module(); - return 1; - } - return(0); + return irport_init(); } #endif /* MODULE */ diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c --- v2.2.9/linux/drivers/net/irda/irtty.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/net/irda/irtty.c Sun May 30 10:17:03 1999 @@ -6,12 +6,12 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:18:38 1997 - * Modified at: Thu Apr 22 09:20:24 1999 + * Modified at: Mon May 10 15:45:50 1999 * Modified by: Dag Brattli * Sources: slip.c by Laurence Culhane, * Fred N. van Kempen, * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -38,19 +38,21 @@ #include #include #include -#include static hashbin_t *irtty = NULL; -static hashbin_t *dongles = NULL; static struct tty_ldisc irda_ldisc; -static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev); +static int qos_mtt_bits = 0x03; /* 5 ms or more */ + +static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev); static void irtty_wait_until_sent(struct irda_device *driver); -static int irtty_is_receiving(struct irda_device *idev); -static int irtty_net_init(struct device *dev); -static int irtty_net_open(struct device *dev); -static int irtty_net_close(struct device *dev); +static int irtty_is_receiving(struct irda_device *idev); +static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts); +static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len); +static int irtty_net_init(struct device *dev); +static int irtty_net_open(struct device *dev); +static int irtty_net_close(struct device *dev); static int irtty_open(struct tty_struct *tty); static void irtty_close(struct tty_struct *tty); @@ -73,13 +75,6 @@ return -ENOMEM; } - dongles = hashbin_new(HB_LOCAL); - if (dongles == NULL) { - printk(KERN_WARNING - "IrDA: Can't allocate dongles hashbin!\n"); - return -ENOMEM; - } - /* Fill in our line protocol discipline, and register it */ memset(&irda_ldisc, 0, sizeof( irda_ldisc)); @@ -132,7 +127,6 @@ * function to hashbin_destroy(). */ hashbin_delete(irtty, NULL); - hashbin_delete(dongles, NULL); } #endif /* MODULE */ @@ -201,7 +195,7 @@ /* The only value we must override it the baudrate */ self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200; - self->idev.qos.min_turn_time.bits = 0x0f; + self->idev.qos.min_turn_time.bits = qos_mtt_bits; self->idev.flags = IFF_SIR | IFF_PIO; irda_qos_bits_to_value(&self->idev.qos); @@ -216,7 +210,8 @@ /* Initialize callbacks */ self->idev.change_speed = irtty_change_speed; self->idev.is_receiving = irtty_is_receiving; - /* self->idev.is_tbusy = irtty_is_tbusy; */ + self->idev.set_dtr_rts = irtty_set_dtr_rts; + self->idev.raw_write = irtty_raw_write; self->idev.wait_until_sent = irtty_wait_until_sent; /* Override the network functions we need to use */ @@ -248,10 +243,6 @@ ASSERT(self != NULL, return;); ASSERT(self->magic == IRTTY_MAGIC, return;); - /* We are not using any dongle anymore! */ - if (self->dongle_q) - self->dongle_q->dongle->close(&self->idev); - /* Remove driver */ irda_device_close(&self->idev); @@ -359,68 +350,6 @@ } /* - * Function irtty_init_dongle (self, type) - * - * Initialize attached dongle. Warning, must be called with a process - * context! - */ -static void irtty_init_dongle(struct irtty_cb *self, int type) -{ - struct dongle_q *node; - - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - -#ifdef CONFIG_KMOD - /* Try to load the module needed */ - switch( type) { - case ESI_DONGLE: - MESSAGE("IrDA: Trying to initialize ESI dongle!\n"); - request_module("esi"); - break; - case TEKRAM_DONGLE: - MESSAGE("IrDA: Trying to initialize Tekram dongle!\n"); - request_module("tekram"); - break; - case ACTISYS_DONGLE: /* FALLTHROUGH */ - case ACTISYS_PLUS_DONGLE: - MESSAGE("IrDA: Trying to initialize ACTiSYS dongle!\n"); - request_module("actisys"); - break; - case GIRBIL_DONGLE: - MESSAGE("IrDA: Trying to initialize GIrBIL dongle!\n"); - request_module("girbil"); - break; - default: - ERROR("Unknown dongle type!\n"); - return; - } -#endif /* CONFIG_KMOD */ - - node = hashbin_find(dongles, type, NULL); - if ( !node) { - ERROR("Unable to find requested dongle\n"); - return; - } - self->dongle_q = node; - - /* Use this change speed function instead of the default */ - self->idev.change_speed = node->dongle->change_speed; - - /* - * Now initialize the dongle! - */ - node->dongle->open(&self->idev, type); - node->dongle->qos_init(&self->idev, &self->idev.qos); - - /* Reset dongle */ - node->dongle->reset(&self->idev, 0); - - /* Set to default baudrate */ - node->dongle->change_speed(&self->idev, 9600); -} - -/* * Function irtty_ioctl (tty, file, cmd, arg) * * The Swiss army knife of system calls :-) @@ -452,7 +381,7 @@ break; case IRTTY_IOCTDONGLE: /* Initialize dongle */ - irtty_init_dongle(self, (int) arg); + irda_device_init_dongle(&self->idev, (int) arg); break; default: return -ENOIOCTLCMD; @@ -645,54 +574,23 @@ tty_wait_until_sent(self->tty, 0); } -int irtty_register_dongle(struct dongle *dongle) -{ - struct dongle_q *new; - - /* Check if this compressor has been registred before */ - if ( hashbin_find ( dongles, dongle->type, NULL)) { - DEBUG( 0, __FUNCTION__ "(), Dongle already registered\n"); - return 0; - } - - /* Make new IrDA dongle */ - new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL); - if (new == NULL) - return -1; - - memset(new, 0, sizeof( struct dongle_q)); - new->dongle = dongle; - - /* Insert IrDA dongle into hashbin */ - hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL); - - return 0; -} - -void irtty_unregister_dongle(struct dongle *dongle) -{ - struct dongle_q *node; - - node = hashbin_remove(dongles, dongle->type, NULL); - if (!node) { - ERROR(__FUNCTION__ "(), dongle not found!\n"); - return; - } - kfree(node); -} - - /* * Function irtty_set_dtr_rts (tty, dtr, rts) * * This function can be used by dongles etc. to set or reset the status * of the dtr and rts lines */ -void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts) +static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts) { + struct tty_struct *tty; + struct irtty_cb *self; mm_segment_t fs; int arg = 0; + self = (struct irtty_cb *) idev->priv; + + tty = self->tty; + #ifdef TIOCM_OUT2 /* Not defined for ARM */ arg = TIOCM_OUT2; #endif @@ -718,6 +616,25 @@ set_fs(fs); } +static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len) +{ + struct irtty_cb *self; + int actual = 0; + + ASSERT(idev != NULL, return 0;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + self = (struct irtty_cb *) idev->priv; + + ASSERT(self != NULL, return 0;); + ASSERT(self->magic == IRTTY_MAGIC, return 0;); + + if (self->tty->driver.write) + actual = self->tty->driver.write(self->tty, 0, buf, len); + + return actual; +} + static int irtty_net_init(struct device *dev) { /* Set up to be a normal IrDA network device driver */ @@ -759,6 +676,8 @@ MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("IrDA TTY device driver"); + +MODULE_PARM(qos_mtt_bits, "i"); /* * Function init_module (void) diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/litelink.c linux/drivers/net/irda/litelink.c --- v2.2.9/linux/drivers/net/irda/litelink.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/irda/litelink.c Sun May 30 10:17:03 1999 @@ -0,0 +1,209 @@ +/********************************************************************* + * + * Filename: litelink.c + * Version: 1.0 + * Description: Driver for the Parallax LiteLink dongle + * Status: Stable + * Author: Dag Brattli + * Created at: Fri May 7 12:50:33 1999 + * Modified at: Mon May 10 15:12:18 1999 + * Modified by: Dag Brattli + * + * Copyright (c) 1999 Dag Brattli, All Rights Reserved. + * + * 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 + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static void litelink_reset(struct irda_device *dev, int unused); +static void litelink_open(struct irda_device *idev, int type); +static void litelink_close(struct irda_device *dev); +static void litelink_change_speed( struct irda_device *dev, int baudrate); +static void litelink_reset(struct irda_device *dev, int unused); +static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos); + +/* These are the baudrates supported */ +static int baud_rates[] = { 115200, 57600, 38400, 19200, 9600 }; + +static struct dongle dongle = { + LITELINK_DONGLE, + litelink_open, + litelink_close, + litelink_reset, + litelink_change_speed, + litelink_init_qos, +}; + +__initfunc(int litelink_init(void)) +{ + return irda_device_register_dongle(&dongle); +} + +void litelink_cleanup(void) +{ + irda_device_unregister_dongle(&dongle); +} + +static void litelink_open(struct irda_device *idev, int type) +{ + strcat(idev->description, " <-> litelink"); + + idev->io.dongle_id = type; + idev->flags |= IFF_DONGLE; + + MOD_INC_USE_COUNT; +} + +static void litelink_close(struct irda_device *idev) +{ + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + + MOD_DEC_USE_COUNT; +} + +/* + * Function litelink_change_speed (tty, baud) + * + * Change speed of the Litelink dongle. To cycle through the available + * baud rates, pulse RTS low for a few ms. + */ +static void litelink_change_speed(struct irda_device *idev, int baudrate) +{ + int i; + + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + + /* Clear RTS to reset dongle */ + irda_device_set_dtr_rts(idev, TRUE, FALSE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Go back to normal mode */ + irda_device_set_dtr_rts(idev, TRUE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Cycle through avaiable baudrates until we reach the correct one */ + for (i=0; i<5 && baud_rates[i] != baudrate; i++) { + + /* Set DTR, clear RTS */ + irda_device_set_dtr_rts(idev, FALSE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Set DTR, Set RTS */ + irda_device_set_dtr_rts(idev, TRUE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + } +} + +/* + * Function litelink_reset (dev) + * + * Reset the Litelink type dongle. Warning, this function must only be + * called with a process context! + * + */ +static void litelink_reset(struct irda_device *idev, int unused) +{ + struct irtty_cb *self; + struct tty_struct *tty; + + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + + /* Power on dongle */ + irda_device_set_dtr_rts(idev, TRUE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Clear RTS to reset dongle */ + irda_device_set_dtr_rts(idev, TRUE, FALSE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Go back to normal mode */ + irda_device_set_dtr_rts(idev, TRUE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* This dongles speed defaults to 115200 bps */ + idev->qos.baud_rate.value = 115200; +} + +/* + * Function litelink_init_qos (qos) + * + * Initialize QoS capabilities + * + */ +static void litelink_init_qos( struct irda_device *idev, struct qos_info *qos) +{ + qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ +} + +#ifdef MODULE + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("Parallax Litelink dongle driver"); + +/* + * Function init_module (void) + * + * Initialize Litelink module + * + */ +int init_module(void) +{ + return litelink_init(); +} + +/* + * Function cleanup_module (void) + * + * Cleanup Litelink module + * + */ +void cleanup_module(void) +{ + litelink_cleanup(); +} + +#endif diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c --- v2.2.9/linux/drivers/net/irda/pc87108.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/net/irda/pc87108.c Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Nov 7 21:43:15 1998 - * Modified at: Tue Apr 20 11:11:39 1999 + * Modified at: Sun May 9 12:57:46 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli + * Copyright (c) 1998-1999 Dag Brattli * Copyright (c) 1998 Lichen Wang, * Copyright (c) 1998 Actisys Corp., www.actisys.com * All Rights Reserved @@ -67,6 +67,7 @@ #define BROKEN_DONGLE_ID static char *driver_name = "pc87108"; +static int qos_mtt_bits = 0x07; /* 1 ms or more */ #define CHIP_IO_EXTENT 8 @@ -219,7 +220,7 @@ idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); - idev->qos.min_turn_time.bits = 0x07; + idev->qos.min_turn_time.bits = qos_mtt_bits; irda_qos_bits_to_value( &idev->qos); idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE; @@ -259,8 +260,9 @@ * Close driver instance * */ -static int pc87108_close( struct irda_device *idev) +static int pc87108_close(struct irda_device *idev) { + struct pc87108 *self; int iobase; DEBUG( 4, __FUNCTION__ "()\n"); @@ -269,13 +271,16 @@ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); iobase = idev->io.iobase; + self = (struct pc87108 *) idev->priv; /* Release the PORT that this driver is using */ DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); - release_region( idev->io.iobase, idev->io.io_ext); + release_region(idev->io.iobase, idev->io.io_ext); + + irda_device_close(idev); - irda_device_close( idev); + kfree(self); return 0; } @@ -805,7 +810,6 @@ setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, DMA_MODE_WRITE); - /* idev->media_busy = TRUE; */ idev->io.direction = IO_XMIT; /* Choose transmit DMA channel */ @@ -973,7 +977,7 @@ * * */ -static int pc87108_dma_receive_complete( struct irda_device *idev, int iobase) +static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase) { struct sk_buff *skb; struct pc87108 *self; @@ -988,8 +992,6 @@ /* Save current bank */ bank = inb( iobase+BSR); - iobase = idev->io.iobase; - /* Read status FIFO */ switch_bank(iobase, BANK5); while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) { @@ -1003,18 +1005,18 @@ } /* Try to process all entries in status FIFO */ - switch_bank( iobase, BANK0); - while ( st_fifo->len) { + switch_bank(iobase, BANK0); + while (st_fifo->len) { /* Get first entry */ - status = st_fifo->entries[ st_fifo->head].status; - len = st_fifo->entries[ st_fifo->head].len; + status = st_fifo->entries[st_fifo->head].status; + len = st_fifo->entries[st_fifo->head].len; st_fifo->head++; st_fifo->len--; /* Check for errors */ - if ( status & FRM_ST_ERR_MSK) { - if ( status & FRM_ST_LOST_FR) { + if (status & FRM_ST_ERR_MSK) { + if (status & FRM_ST_LOST_FR) { /* Add number of lost frames to stats */ idev->stats.rx_errors += len; } else { @@ -1188,8 +1190,8 @@ bank = inb( iobase+BSR); /* Status event, or end of frame detected in FIFO */ - if ( eir & (EIR_SFIF_EV|EIR_LS_EV)) { - if ( pc87108_dma_receive_complete( idev, iobase)) { + if (eir & (EIR_SFIF_EV|EIR_LS_EV)) { + if (pc87108_dma_receive_complete( idev, iobase)) { /* Wait for next status FIFO interrupt */ new_ier |= IER_SFIF_IE; @@ -1459,6 +1461,11 @@ } #ifdef MODULE + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("NSC PC87108 IrDA Device Driver"); + +MODULE_PARM(qos_mtt_bits, "i"); /* * Function init_module (void) diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c --- v2.2.9/linux/drivers/net/irda/tekram.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/net/irda/tekram.c Sun May 30 10:17:03 1999 @@ -1,15 +1,15 @@ /********************************************************************* * * Filename: tekram.c - * Version: 1.0 + * Version: 1.1 * Description: Implementation of the Tekram IrMate IR-210B dongle * Status: Experimental. * Author: Dag Brattli * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Tue Apr 13 16:33:54 1999 + * Modified at: Mon May 10 16:10:17 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -62,15 +62,15 @@ __initfunc(int tekram_init(void)) { - return irtty_register_dongle(&dongle); + return irda_device_register_dongle(&dongle); } void tekram_cleanup(void) { - irtty_unregister_dongle( &dongle); + irda_device_unregister_dongle(&dongle); } -static void tekram_open( struct irda_device *idev, int type) +static void tekram_open(struct irda_device *idev, int type) { strcat(idev->description, " <-> tekram"); @@ -80,8 +80,11 @@ MOD_INC_USE_COUNT; } -static void tekram_close( struct irda_device *dev) -{ +static void tekram_close(struct irda_device *idev) +{ + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + MOD_DEC_USE_COUNT; } @@ -101,79 +104,49 @@ * 6. wait at least 50 us, new setting (baud rate, etc) takes effect here * after */ -static void tekram_change_speed( struct irda_device *dev, int baud) +static void tekram_change_speed(struct irda_device *idev, int baud) { - struct irtty_cb *self; - struct tty_struct *tty; - struct termios old_termios; - int cflag; __u8 byte; DEBUG(4, __FUNCTION__ "()\n"); - ASSERT(dev != NULL, return;); - ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) dev->priv; - - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - if (!self->tty) - return; - - tty = self->tty; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - old_termios = *(tty->termios); - cflag = tty->termios->c_cflag; - - cflag &= ~CBAUD; - switch (baud) { default: - /* FALLTHROUGH */ case 9600: - cflag |= B9600; byte = TEKRAM_PW|TEKRAM_9600; break; case 19200: - cflag |= B19200; byte = TEKRAM_PW|TEKRAM_19200; break; case 34800: - cflag |= B38400; byte = TEKRAM_PW|TEKRAM_38400; break; case 57600: - cflag |= B57600; byte = TEKRAM_PW|TEKRAM_57600; break; case 115200: - cflag |= B115200; byte = TEKRAM_PW|TEKRAM_115200; break; } /* Set DTR, Clear RTS */ - irtty_set_dtr_rts(tty, TRUE, FALSE); + irda_device_set_dtr_rts(idev, TRUE, FALSE); /* Wait at least 7us */ udelay(7); /* Write control byte */ - if (tty->driver.write) - tty->driver.write(self->tty, 0, &byte, 1); + irda_device_raw_write(idev, &byte, 1); /* Wait at least 100 ms */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(100)); /* Set DTR, Set RTS */ - irtty_set_dtr_rts(tty, TRUE, TRUE); - - /* Now change the speed of the serial port */ - tty->termios->c_cflag = cflag; - tty->driver.set_termios(tty, &old_termios); + irda_device_set_dtr_rts(idev, TRUE, TRUE); } /* @@ -189,41 +162,27 @@ * 3. clear DTR to SPACE state, wait at least 50 us for further * operation */ -void tekram_reset(struct irda_device *dev, int unused) +void tekram_reset(struct irda_device *idev, int unused) { - struct irtty_cb *self; - struct tty_struct *tty; - - DEBUG(4, __FUNCTION__ "()\n"); - - ASSERT(dev != NULL, return;); - ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) dev->priv; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - tty = self->tty; - if (!tty) - return; - /* Power off dongle */ - irtty_set_dtr_rts(tty, FALSE, FALSE); + irda_device_set_dtr_rts(idev, FALSE, FALSE); /* Sleep 50 ms */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(50)); /* Clear DTR, Set RTS */ - irtty_set_dtr_rts(tty, FALSE, TRUE); + irda_device_set_dtr_rts(idev, FALSE, TRUE); /* Should sleep 1 ms, but 10-20 should not do any harm */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(20)); /* Set DTR, Set RTS */ - irtty_set_dtr_rts(tty, TRUE, TRUE); + irda_device_set_dtr_rts(idev, TRUE, TRUE); udelay(50); diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c --- v2.2.9/linux/drivers/net/irda/toshoboe.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/irda/toshoboe.c Sun May 30 10:17:03 1999 @@ -0,0 +1,901 @@ +/********************************************************************* + * + * Filename: toshoboe.c + * Version: 0.1 + * Description: Driver for the Toshiba OBOE (or type-O or 700 or 701) + * FIR Chipset. + * Status: Experimental. + * Author: James McKenzie + * Created at: Sat May 8 12:35:27 1999 + * + * Copyright (c) 1999 James McKenzie, All Rights Reserved. + * + * 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. + * + * Neither James McKenzie nor Cambridge University admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + * Applicable Models : Libretto 100CT. and many more + * Toshiba refers to this chip as the type-O IR port. + * + ********************************************************************/ + +/* This driver is experimental, I have only three ir devices */ +/* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */ +/* an hp printer, this works fine at 4MBPS with my HP printer */ + +static char *rcsid = "$Id: toshoboe.c,v 1.5 1999/05/12 12:24:39 root Exp root $"; + +/* + * $Log: toshoboe.c,v $ + * Revision 1.5 1999/05/12 12:24:39 root + * *** empty log message *** + * + * Revision 1.4 1999/05/12 11:55:08 root + * *** empty log message *** + * + * Revision 1.3 1999/05/09 01:33:12 root + * *** empty log message *** + * + * Revision 1.2 1999/05/09 01:30:38 root + * *** empty log message *** + * + * Revision 1.1 1999/05/09 01:25:04 root + * Initial revision + * + */ + +/* Define this to have only one frame in the XMIT or RECV queue */ +/* Toshiba's drivers do this, but it disables back to back tansfers */ +/* I think that the chip may have some problems certainly, I have */ +/* seen it jump over tasks in the taskfile->xmit with this turned on */ +#define ONETASK + +/* To adjust the number of tasks in use edit toshoboe.h */ + +/* Define this to enable FIR and MIR support */ +#define ENABLE_FAST + +/* Number of ports this driver can support, you also need to edit dev_self below */ +#define NSELFS 4 + +/* Size of IO window */ +#define CHIP_IO_EXTENT 0x1f + +/* Transmit and receive buffer sizes, adjust at your peril */ +#define RX_BUF_SZ 4196 +#define TX_BUF_SZ 4196 + +/* No user servicable parts below here */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +static char *driver_name = "toshoboe"; + +static struct toshoboe_cb *dev_self[NSELFS + 1] = +{NULL, NULL, NULL, NULL, NULL}; + +/* Shutdown the chip and point the taskfile reg somewhere else */ +static void +toshoboe_stopchip (struct toshoboe_cb *self) +{ + DEBUG (4, __FUNCTION__ "()\n"); + + outb_p (0x0e, OBOE_REG_11); + + outb_p (0x00, OBOE_RST); + outb_p (0x3f, OBOE_TFP2); /*Write the taskfile address */ + outb_p (0xff, OBOE_TFP1); + outb_p (0xff, OBOE_TFP0); + outb_p (0x0f, OBOE_REG_1B); + outb_p (0xff, OBOE_REG_1A); + outb_p (0x00, OBOE_ISR); /*FIXME: should i do this to disbale ints */ + outb_p (0x80, OBOE_RST); + outb_p (0xe, OBOE_LOCK); +} + +/*Set the baud rate */ +static void +toshoboe_setbaud (struct toshoboe_cb *self, int baud) +{ + DEBUG (4, __FUNCTION__ "()\n"); + + printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud); + + cli (); + switch (baud) + { + case 2400: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0xbf, OBOE_UDIV); + break; + case 4800: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x5f, OBOE_UDIV); + break; + case 9600: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x2f, OBOE_UDIV); + break; + case 19200: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x17, OBOE_UDIV); + break; + case 38400: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0xb, OBOE_UDIV); + break; + case 57600: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x7, OBOE_UDIV); + break; + case 115200: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x3, OBOE_UDIV); + break; + case 1152000: + outb_p (OBOE_PMDL_MIR, OBOE_PMDL); + outb_p (OBOE_SMDL_MIR, OBOE_SMDL); + outb_p (0x1, OBOE_UDIV); + break; + case 4000000: + outb_p (OBOE_PMDL_FIR, OBOE_PMDL); + outb_p (OBOE_SMDL_FIR, OBOE_SMDL); + outb_p (0x0, OBOE_UDIV); + break; + } + + sti (); + + outb_p (0x00, OBOE_RST); + outb_p (0x80, OBOE_RST); + outb_p (0x01, OBOE_REG_9); + +} + +/* Wake the chip up and get it looking at the taskfile */ +static void +toshoboe_startchip (struct toshoboe_cb *self) +{ + __u32 physaddr; + + DEBUG (4, __FUNCTION__ "()\n"); + + + outb_p (0, OBOE_LOCK); + outb_p (0, OBOE_RST); + outb_p (OBOE_NTR_VAL, OBOE_NTR); + outb_p (0xf0, OBOE_REG_D); + outb_p (0xff, OBOE_ISR); + outb_p (0x0f, OBOE_REG_1A); + outb_p (0xff, OBOE_REG_1B); + + + physaddr = virt_to_bus (self->taskfile); + + outb_p ((physaddr >> 0x0a) & 0xff, OBOE_TFP0); + outb_p ((physaddr >> 0x12) & 0xff, OBOE_TFP1); + outb_p ((physaddr >> 0x1a) & 0x3f, OBOE_TFP2); + + outb_p (0x0e, OBOE_REG_11); + outb_p (0x80, OBOE_RST); + + toshoboe_setbaud (self, 9600); + +} + +/*Let the chip look at memory */ +static void +toshoboe_enablebm (struct toshoboe_cb *self) +{ + DEBUG (4, __FUNCTION__ "()\n"); + pci_set_master (self->pdev); +} + +/*Don't let the chip look at memory */ +static void +toshoboe_disablebm (struct toshoboe_cb *self) +{ + __u8 command; + DEBUG (4, __FUNCTION__ "()\n"); + + pci_read_config_byte (self->pdev, PCI_COMMAND, &command); + command &= ~PCI_COMMAND_MASTER; + pci_write_config_byte (self->pdev, PCI_COMMAND, command); + +} + +/*setup the taskfile */ +static void +toshoboe_initbuffs (struct toshoboe_cb *self) +{ + int i; + + DEBUG (4, __FUNCTION__ "()\n"); + + cli (); + + for (i = 0; i < TX_SLOTS; ++i) + { + self->taskfile->xmit[i].len = 0; + self->taskfile->xmit[i].control = 0x00; + self->taskfile->xmit[i].buffer = virt_to_bus (self->xmit_bufs[i]); + } + + for (i = 0; i < RX_SLOTS; ++i) + { + self->taskfile->recv[i].len = 0; + self->taskfile->recv[i].control = 0x83; + self->taskfile->recv[i].buffer = virt_to_bus (self->recv_bufs[i]); + } + + sti (); +} + + +/*Transmit something */ +static int +toshoboe_hard_xmit (struct sk_buff *skb, struct device *dev) +{ + struct irda_device *idev; + struct toshoboe_cb *self; + int mtt, len; + + idev = (struct irda_device *) dev->priv; + ASSERT (idev != NULL, return 0;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + self = idev->priv; + ASSERT (self != NULL, return 0;); + + +#ifdef ONETASK + if (self->txpending) + return -EBUSY; + + self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET; + + self->txs &= 0x3f; + +#endif + + if (self->taskfile->xmit[self->txs].control) + return -EBUSY; + + + if (inb_p (OBOE_RST) & OBOE_RST_WRAP) + { + len = async_wrap_skb (skb, self->xmit_bufs[self->txs], TX_BUF_SZ); + } + else + { + len = skb->len; + memcpy (self->xmit_bufs[self->txs], skb->data, len); + } + self->taskfile->xmit[self->txs].len = len & 0x0fff; + + + + outb_p (0, OBOE_RST); + outb_p (0x1e, OBOE_REG_11); + + self->taskfile->xmit[self->txs].control = 0x84; + + mtt = irda_get_mtt (skb); + if (mtt) + udelay (mtt); + + self->txpending++; + + /*FIXME: ask about tbusy,media_busy stuff, for the moment */ + /*tbusy means can't queue any more */ +#ifndef ONETASK + if (self->txpending == TX_SLOTS) + { +#else + { +#endif + if (irda_lock ((void *) &dev->tbusy) == FALSE) + return -EBUSY; + } + + outb_p (0x80, OBOE_RST); + outb_p (1, OBOE_REG_9); + + self->txs++; + self->txs %= TX_SLOTS; + + dev_kfree_skb (skb); + + return 0; +} + +/*interrupt handler */ +static void +toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs) +{ + struct irda_device *idev = (struct irda_device *) dev_id; + struct toshoboe_cb *self; + __u8 irqstat; + struct sk_buff *skb; + + if (idev == NULL) + { + printk (KERN_WARNING "%s: irq %d for unknown device.\n", + driver_name, irq); + return; + } + + self = idev->priv; + + if (!self) + return; + + DEBUG (4, __FUNCTION__ "()\n"); + + irqstat = inb_p (OBOE_ISR); + +/* woz it us */ + if (!(irqstat & 0xf8)) + return; + + outb_p (irqstat, OBOE_ISR); /*Acknologede it */ + + +/* Txdone */ + if (irqstat & OBOE_ISR_TXDONE) + { + self->txpending--; + + idev->stats.tx_packets++; + + idev->media_busy = FALSE; + idev->netdev.tbusy = 0; + + mark_bh (NET_BH); + } + + if (irqstat & OBOE_ISR_RXDONE) + { + +#ifdef ONETASK + self->rxs = inb_p (OBOE_RCVT); + self->rxs += (RX_SLOTS - 1); + self->rxs %= RX_SLOTS; +#else + while (self->taskfile->recv[self->rxs].control == 0) +#endif + { + int len = self->taskfile->recv[self->rxs].len; + + if (len>2) len-=2; + + skb = dev_alloc_skb (len + 1); + if (skb) + { + skb_reserve (skb, 1); + + skb_put (skb, len); + memcpy (skb->data, self->recv_bufs[self->rxs], len); + + idev->stats.rx_packets++; + skb->dev = &idev->netdev; + skb->mac.raw = skb->data; + skb->protocol = htons (ETH_P_IRDA); + } + else + { + printk (KERN_INFO __FUNCTION__ + "(), memory squeeze, dropping frame.\n"); + } + + + + self->taskfile->recv[self->rxs].control = 0x83; + self->taskfile->recv[self->rxs].len = 0x0; + + self->rxs++; + self->rxs %= RX_SLOTS; + + if (skb) + netif_rx (skb); + + } + + } + + if (irqstat & OBOE_ISR_20) + { + printk (KERN_WARNING "Oboe_irq: 20\n"); + } + if (irqstat & OBOE_ISR_10) + { + printk (KERN_WARNING "Oboe_irq: 10\n"); + } + if (irqstat & 0x8) + { + /*FIXME: I think this is a TX or RX error of some sort */ + + idev->stats.tx_errors++; + idev->stats.rx_errors++; + + } + + +} + + + +/* Change the baud rate */ +static void +toshoboe_change_speed (struct irda_device *idev, int speed) +{ + struct toshoboe_cb *self; + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (idev != NULL, return;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;); + + self = idev->priv; + ASSERT (self != NULL, return;); + + idev->io.baudrate = speed; + + toshoboe_setbaud (self, speed); + +} + + +/* Check all xmit_tasks finished */ +static void +toshoboe_wait_until_sent (struct irda_device *idev) +{ + struct toshoboe_cb *self; + int i; + + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (idev != NULL, return;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;); + + self = idev->priv; + ASSERT (self != NULL, return;); + + for (i = 0; i < TX_SLOTS; ++i) + { + while (self->taskfile->xmit[i].control) + { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout (6); + } + } + +} + +static int +toshoboe_is_receiving (struct irda_device *idev) +{ + DEBUG (4, __FUNCTION__ "()\n"); + +/*FIXME Can't tell! */ + return (FALSE); +} + + +static int +toshoboe_net_init (struct device *dev) +{ + DEBUG (4, __FUNCTION__ "()\n"); + + /* Setup to be a normal IrDA network device driver */ + irda_device_setup (dev); + + /* Insert overrides below this line! */ + return 0; +} + + + + +static int +toshoboe_net_open (struct device *dev) +{ + struct irda_device *idev; + struct toshoboe_cb *self; + + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + ASSERT (idev != NULL, return 0;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + self = idev->priv; + ASSERT (self != NULL, return 0;); + + if (request_irq (idev->io.irq, toshoboe_interrupt, + SA_SHIRQ | SA_INTERRUPT, idev->name, (void *) idev)) + { + + return -EAGAIN; + } + + toshoboe_initbuffs (self); + toshoboe_enablebm (self); + toshoboe_startchip (self); + + + cli (); + + /*FIXME: need to test this carefully to check which one */ + /*of the two possible startup logics the chip uses */ + /*although it won't make any difference if no-one xmits durining init */ + /*and none what soever if using ONETASK */ + + self->rxs = inb_p (OBOE_RCVT); + self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET; + +#ifdef 0 + self->rxs = 0; + self->txs = 0; +#endif +#ifdef 0 + self->rxs = RX_SLOTS - 1; + self->txs = 0; +#endif + + + self->txpending = 0; + + sti (); + + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + MOD_INC_USE_COUNT; + + return 0; + +} + +static int +toshoboe_net_close (struct device *dev) +{ + struct irda_device *idev; + struct toshoboe_cb *self; + + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + ASSERT (idev != NULL, return 0;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + dev->tbusy = 1; + dev->start = 0; + + + self = idev->priv; + + ASSERT (self != NULL, return 0;); + + free_irq (idev->io.irq, (void *) idev); + + toshoboe_stopchip (self); + toshoboe_disablebm (self); + + MOD_DEC_USE_COUNT; + + return 0; + +} + + + +#ifdef MODULE + +static int +toshoboe_close (struct irda_device *idev) +{ + struct toshoboe_cb *self; + int i; + + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (idev != NULL, return -1;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + self = idev->priv; + + ASSERT (self != NULL, return -1;); + + toshoboe_stopchip (self); + + release_region (idev->io.iobase, idev->io.io_ext); + + + for (i = 0; i < TX_SLOTS; ++i) + { + kfree (self->xmit_bufs[i]); + self->xmit_bufs[i] = NULL; + } + + for (i = 0; i < RX_SLOTS; ++i) + { + kfree (self->recv_bufs[i]); + self->recv_bufs[i] = NULL; + } + + + kfree (self->taskfilebuf); + self->taskfilebuf = NULL; + self->taskfile = NULL; + + + irda_device_close (idev); + + return (0); + +} + +#endif + + + +static int +toshoboe_open (struct pci_dev *pci_dev) +{ + struct toshoboe_cb *self; + struct irda_device *idev; + int i = 0; + int ok=0; + + + DEBUG (4, __FUNCTION__ "()\n"); + + while (dev_self[i]) + i++; + + if (i == NSELFS) + { + printk (KERN_ERR "Oboe: No more instances available"); + return -ENOMEM; + } + + self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL); + + if (self == NULL) + { + printk (KERN_ERR "IrDA: Can't allocate memory for " + "IrDA control block!\n"); + return -ENOMEM; + } + + memset (self, 0, sizeof (struct toshoboe_cb)); + + + dev_self[i] = self; + + self->pdev = pci_dev; + self->base = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + + idev = &self->idev; + + /*Setup idev */ + + idev->io.iobase = self->base; + idev->io.irq = pci_dev->irq; + idev->io.io_ext = CHIP_IO_EXTENT; + + /* Lock the port that we need */ + i = check_region (idev->io.iobase, idev->io.io_ext); + if (i < 0) + { + DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + idev->io.iobase); + + dev_self[i] = NULL; + kfree (self); + + return -ENODEV; + } + + request_region (idev->io.iobase, idev->io.io_ext, driver_name); + + irda_init_max_qos_capabilies (&idev->qos); + + idev->qos.baud_rate.bits = IR_2400 | /*IR_4800 | */ IR_9600 | IR_19200 | + IR_115200; +#ifdef ENABLE_FAST + idev->qos.baud_rate.bits|= IR_576000 | IR_1152000 | (IR_4000000 << 8); +#endif + + idev->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */ + + irda_qos_bits_to_value (&idev->qos); + + idev->flags = IFF_SIR | IFF_DMA | IFF_PIO; + +#ifdef ENABLE_FAST + idev->flags |= IFF_FIR; +#endif + + /* These aren't much use as we need to have a whole panoply of + * buffers running */ + + idev->rx_buff.flags = 0; + idev->tx_buff.flags = 0; + idev->rx_buff.truesize = 0; + idev->rx_buff.truesize = 0; + + idev->change_speed = toshoboe_change_speed; + idev->wait_until_sent = toshoboe_wait_until_sent; + idev->is_receiving = toshoboe_is_receiving; + + idev->netdev.init = toshoboe_net_init; + idev->netdev.hard_start_xmit = toshoboe_hard_xmit; + idev->netdev.open = toshoboe_net_open; + idev->netdev.stop = toshoboe_net_close; + + + /* Now setup the endless buffers we need */ + + self->txs = 0; + self->rxs = 0; + + self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL | GFP_DMA); + if (!self->taskfilebuf) { + printk(KERN_ERR "toshoboe: kmalloc for DMA failed()\n"); + kfree(self); + return -ENOMEM; + } + + + memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN); + + /*We need to align the taskfile on a taskfile size boundary */ + { + __u32 addr; + + addr = (__u32) self->taskfilebuf; + addr &= ~(sizeof (struct OboeTaskFile) - 1); + addr += sizeof (struct OboeTaskFile); + + self->taskfile = (struct OboeTaskFile *) addr; + } + + for (i = 0; i < TX_SLOTS; ++i) + { + self->xmit_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA); + if (self->xmit_bufs[i]) ok++; + } + + for (i = 0; i < RX_SLOTS; ++i) + { + self->recv_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA); + if (self->recv_bufs[i]) ok++; + } + + if (ok!=RX_SLOTS+TX_SLOTS) { + printk(KERN_ERR "toshoboe: kmalloc for buffers failed()\n"); + + + for (i = 0; i < TX_SLOTS; ++i) if (self->xmit_bufs[i]) kfree(self->xmit_bufs[i]); + for (i = 0; i < RX_SLOTS; ++i) if (self->recv_bufs[i]) kfree(self->recv_bufs[i]); + + kfree(self); + return -ENOMEM; + + } + + + irda_device_open (idev, driver_name, self); + + printk (KERN_WARNING "ToshOboe: Using "); +#ifdef ONETASK + printk ("single"); +#else + printk ("multiple"); +#endif + printk (" tasks, version %s\n", rcsid); + + return (0); +} + +__initfunc (int toshoboe_init (void)) +{ + struct pci_dev *pci_dev = NULL; + int found = 0; + + do + { + pci_dev = pci_find_device (PCI_VENDOR_ID_TOSHIBA, + PCI_DEVICE_ID_FIR701, pci_dev); + if (pci_dev) + { + printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n", + pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK, + pci_dev->irq); + + if (!toshoboe_open (pci_dev)) + found++; + } + + } + while (pci_dev); + + if (found) + return 0; + + return -ENODEV; +} + +#ifdef MODULE + +static void +toshoboe_cleanup (void) +{ + int i; + + DEBUG (4, __FUNCTION__ "()\n"); + + for (i = 0; i < 4; i++) + { + if (dev_self[i]) + toshoboe_close (&(dev_self[i]->idev)); + } +} + + + +int +init_module (void) +{ + return toshoboe_init (); +} + + +void +cleanup_module (void) +{ + toshoboe_cleanup (); +} + + +#endif diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c --- v2.2.9/linux/drivers/net/irda/uircc.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/net/irda/uircc.c Sun May 30 10:17:03 1999 @@ -7,10 +7,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Dec 26 10:59:03 1998 - * Modified at: Tue Apr 20 11:15:52 1999 + * Modified at: Mon May 10 22:11:09 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -216,7 +216,7 @@ idev->netdev.open = uircc_net_open; idev->netdev.stop = uircc_net_close; - irport_open(iobase2); + irport_start(iobase2); /* Open the IrDA device */ irda_device_open(idev, driver_name, self); @@ -233,6 +233,7 @@ #ifdef MODULE static int uircc_close(struct irda_device *idev) { + struct uircc_cb *self; int iobase; int status; @@ -242,6 +243,7 @@ ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); iobase = idev->io.iobase; + self = (struct uircc_cb *) idev->priv; /* Some magic to disable FIR and enable SIR */ uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000); @@ -249,7 +251,7 @@ /* Disable modem */ outb(0x00, iobase+UIRCC_CR10); - irport_close(idev->io.iobase2); + irport_stop(idev->io.iobase2); /* Release the PORT that this driver is using */ DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); @@ -262,6 +264,8 @@ } irda_device_close(idev); + kfree(self); + return 0; } #endif /* MODULE */ @@ -346,8 +350,8 @@ case 37600: case 57600: case 115200: - irport_open(idev->io.iobase2); - irport_change_speed( idev->io.iobase2, speed); + irport_start(idev->io.iobase2); + irport_change_speed(idev, speed); /* Some magic to disable FIR and enable SIR */ uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000); @@ -363,7 +367,7 @@ DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); break; case 4000000: - irport_close(idev->io.iobase2); + irport_stop(idev->io.iobase2); /* Some magic to disable SIR and enable FIR */ uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0001); diff -u --recursive --new-file v2.2.9/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c --- v2.2.9/linux/drivers/net/irda/w83977af_ir.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/net/irda/w83977af_ir.c Sun May 30 10:17:03 1999 @@ -1,16 +1,16 @@ /********************************************************************* * * Filename: w83977af_ir.c - * Version: 0.8 - * Description: FIR/MIR driver for the Winbond W83977AF Super I/O chip + * Version: 1.0 + * Description: FIR driver for the Winbond W83977AF Super I/O chip * Status: Experimental. * Author: Paul VanderSpek * Created at: Wed Nov 4 11:46:16 1998 - * Modified at: Tue Apr 20 11:15:00 1999 + * Modified at: Thu May 13 08:03:27 1999 * Modified by: Dag Brattli * + * Copyright (c) 1998-1999 Dag Brattli * Copyright (c) 1998 Corel Computer Corp. - * Copyright (c) 1998 Dag Brattli * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -40,7 +40,7 @@ ********************************************************************/ #include - + #include #include #include @@ -61,44 +61,45 @@ #include #include -#define NETWINDER +#define CONFIG_NETWINDER /* Adjust to NetWinder differences */ +#undef CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */ +#define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */ +#undef CONFIG_USE_INTERNAL_TIMER /* Just cannot make that timer work */ +#define CONFIG_USE_W977_PNP /* Currently needed */ +#define PIO_MAX_SPEED 115200 static char *driver_name = "w83977af_ir"; +static int qos_mtt_bits = 0x07; /* 1 ms or more */ #define CHIP_IO_EXTENT 8 static unsigned int io[] = { 0x180, ~0, ~0, ~0 }; static unsigned int irq[] = { 6, 0, 0, 0 }; -static unsigned int dma[] = { 0, 0, 0, 0 }; - -static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL}; +static unsigned int dma[] = +{ 1, 0, 0, 0 }; -/* For storing entries in the status FIFO */ -struct st_fifo_entry { - int status; - int len; -}; +static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL}; static struct st_fifo_entry prev; /* Some prototypes */ -static int w83977af_open( int i, unsigned int iobase, unsigned int irq, - unsigned int dma); -static int w83977af_close( struct irda_device *idev); -static int w83977af_probe( int iobase, int irq, int dma); +static int w83977af_open(int i, unsigned int iobase, unsigned int irq, + unsigned int dma); +static int w83977af_close(struct irda_device *idev); +static int w83977af_probe(int iobase, int irq, int dma); static int w83977af_dma_receive(struct irda_device *idev); static int w83977af_dma_receive_complete(struct irda_device *idev); -static int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev); -static int w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size); -static void w83977af_dma_write( struct irda_device *idev, int iobase); -static void w83977af_change_speed( struct irda_device *idev, int baud); +static int w83977af_hard_xmit(struct sk_buff *skb, struct device *dev); +static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size); +static void w83977af_dma_write(struct irda_device *idev, int iobase); +static void w83977af_change_speed(struct irda_device *idev, int baud); static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void w83977af_wait_until_sent( struct irda_device *idev); -static int w83977af_is_receiving( struct irda_device *idev); +static void w83977af_wait_until_sent(struct irda_device *idev); +static int w83977af_is_receiving(struct irda_device *idev); -static int w83977af_net_init( struct device *dev); -static int w83977af_net_open( struct device *dev); -static int w83977af_net_close( struct device *dev); +static int w83977af_net_init(struct device *dev); +static int w83977af_net_open(struct device *dev); +static int w83977af_net_close(struct device *dev); /* * Function w83977af_init () @@ -108,13 +109,13 @@ */ __initfunc(int w83977af_init(void)) { - int i; + int i; - DEBUG( 0, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); prev.status = 0; - for ( i=0; (io[i] < 2000) && (i < 4); i++) { + for (i=0; (io[i] < 2000) && (i < 4); i++) { int ioaddr = io[i]; if (check_region(ioaddr, CHIP_IO_EXTENT) < 0) continue; @@ -135,11 +136,11 @@ { int i; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - for ( i=0; i < 4; i++) { - if ( dev_self[i]) - w83977af_close( dev_self[i]); + for (i=0; i < 4; i++) { + if (dev_self[i]) + w83977af_close(&(dev_self[i]->idev)); } } #endif /* MODULE */ @@ -154,26 +155,29 @@ unsigned int dma) { struct irda_device *idev; + struct w83977af_ir *self; int ret; DEBUG( 0, __FUNCTION__ "()\n"); - if ( w83977af_probe( iobase, irq, dma) == -1) + if (w83977af_probe(iobase, irq, dma) == -1) return -1; /* * Allocate new instance of the driver */ - idev = kmalloc( sizeof(struct irda_device), GFP_KERNEL); - if ( idev == NULL) { + self = kmalloc(sizeof(struct w83977af_ir), GFP_KERNEL); + if (self == NULL) { printk( KERN_ERR "IrDA: Can't allocate memory for " "IrDA control block!\n"); return -ENOMEM; } - memset( idev, 0, sizeof(struct irda_device)); + memset(self, 0, sizeof(struct w83977af_ir)); /* Need to store self somewhere */ - dev_self[i] = idev; + dev_self[i] = self; + + idev = &self->idev; /* Initialize IO */ idev->io.iobase = iobase; @@ -183,17 +187,17 @@ idev->io.fifo_size = 32; /* Lock the port that we need */ - ret = check_region( idev->io.iobase, idev->io.io_ext); - if ( ret < 0) { + ret = check_region(idev->io.iobase, idev->io.io_ext); + if (ret < 0) { DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", idev->io.iobase); /* w83977af_cleanup( self->idev); */ return -ENODEV; } - request_region( idev->io.iobase, idev->io.io_ext, idev->name); + request_region(idev->io.iobase, idev->io.io_ext, idev->name); /* Initialize QoS for this device */ - irda_init_max_qos_capabilies( &idev->qos); + irda_init_max_qos_capabilies(&idev->qos); /* The only value we must override it the baudrate */ @@ -202,8 +206,8 @@ IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); /* The HP HDLS-1100 needs 1 ms according to the specs */ - idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */ - irda_qos_bits_to_value( &idev->qos); + idev->qos.min_turn_time.bits = qos_mtt_bits; + irda_qos_bits_to_value(&idev->qos); idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO; @@ -221,13 +225,13 @@ idev->is_receiving = w83977af_is_receiving; /* Override the network functions we need to use */ - idev->netdev.init = w83977af_net_init; + idev->netdev.init = w83977af_net_init; idev->netdev.hard_start_xmit = w83977af_hard_xmit; - idev->netdev.open = w83977af_net_open; - idev->netdev.stop = w83977af_net_close; + idev->netdev.open = w83977af_net_open; + idev->netdev.stop = w83977af_net_close; /* Open the IrDA device */ - irda_device_open( idev, driver_name, NULL); + irda_device_open(idev, driver_name, self); return 0; } @@ -240,15 +244,18 @@ */ static int w83977af_close( struct irda_device *idev) { + struct w83977af_ir *self; int iobase; - DEBUG( 0, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); - ASSERT( idev != NULL, return -1;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); + ASSERT(idev != NULL, return -1;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); iobase = idev->io.iobase; + self = (struct w83977af_ir *) idev->priv; +#ifdef CONFIG_USE_W977_PNP /* enter PnP configuration mode */ w977_efm_enter(); @@ -258,13 +265,15 @@ w977_write_reg(0x30, 0x00); w977_efm_exit(); - +#endif /* CONFIG_USE_W977_PNP */ /* Release the PORT that this driver is using */ DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); - release_region( idev->io.iobase, idev->io.io_ext); + release_region(idev->io.iobase, idev->io.io_ext); + + irda_device_close(idev); - irda_device_close( idev); + kfree(self); return 0; } @@ -280,7 +289,7 @@ int version; DEBUG( 0, __FUNCTION__ "()\n"); - +#ifdef CONFIG_USE_W977_PNP /* Enter PnP configuration mode */ w977_efm_enter(); @@ -289,14 +298,14 @@ /* Configure PnP port, IRQ, and DMA channel */ w977_write_reg(0x60, (iobase >> 8) & 0xff); w977_write_reg(0x61, (iobase) & 0xff); - /* w977_write_reg(0x70, 0x06); */ + w977_write_reg(0x70, irq); -#ifdef NETWINDER - w977_write_reg(0x74, dma+1); /* Netwinder uses one higher than Linux */ +#ifdef CONFIG_NETWINDER + w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */ #else w977_write_reg(0x74, dma); #endif - w977_write_reg(0x75, dma); /* Disable Tx DMA */ + w977_write_reg(0x75, 0x04); /* Disable Tx DMA */ /* Set append hardware CRC, enable IR bank selection */ w977_write_reg(0xf0, APEDCRC|ENBNKSEL); @@ -305,26 +314,26 @@ w977_write_reg(0x30, 0x01); w977_efm_exit(); - +#endif /* Disable Advanced mode */ - switch_bank( iobase, SET2); + switch_bank(iobase, SET2); outb(iobase+2, 0x00); /* Turn on UART (global) interrupts */ - switch_bank( iobase, SET0); - outb( HCR_EN_IRQ, iobase+HCR); + switch_bank(iobase, SET0); + outb(HCR_EN_IRQ, iobase+HCR); /* Switch to advanced mode */ - switch_bank( iobase, SET2); - outb( inb( iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1); + switch_bank(iobase, SET2); + outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1); /* Set default IR-mode */ - switch_bank( iobase, SET0); - outb( HCR_SIR, iobase+HCR); + switch_bank(iobase, SET0); + outb(HCR_SIR, iobase+HCR); /* Read the Advanced IR ID */ switch_bank(iobase, SET3); - version = inb( iobase+AUID); + version = inb(iobase+AUID); /* Should be 0x1? */ if (0x10 != (version & 0xf0)) { @@ -333,18 +342,17 @@ } /* Set FIFO size to 32 */ - switch_bank( iobase, SET2); - outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); + switch_bank(iobase, SET2); + outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); /* Set FIFO threshold to TX17, RX16 */ switch_bank(iobase, SET0); outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR); -/* outb( 0xa7, iobase+UFR); */ /* Receiver frame length */ - switch_bank( iobase, SET4); - outb( 2048 & 0xff, iobase+6); - outb(( 2048 >> 8) & 0x1f, iobase+7); + switch_bank(iobase, SET4); + outb(2048 & 0xff, iobase+6); + outb((2048 >> 8) & 0x1f, iobase+7); /* * Init HP HSDL-1100 transceiver. @@ -358,8 +366,8 @@ * FIRRX pin 39 connected to receiver (IRSL0) * CIRRX pin 40 connected to pin 37 */ - switch_bank( iobase, SET7); - outb( 0x40, iobase+7); + switch_bank(iobase, SET7); + outb(0x40, iobase+7); DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version); @@ -372,16 +380,14 @@ * Change the speed of the device * */ -void w83977af_change_speed( struct irda_device *idev, int speed) +void w83977af_change_speed(struct irda_device *idev, int speed) { int ir_mode = HCR_SIR; int iobase; __u8 set; - DEBUG( 0, __FUNCTION__ "()\n"); - - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); iobase = idev->io.iobase; @@ -389,22 +395,22 @@ idev->io.baudrate = speed; /* Save current bank */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); /* Disable interrupts */ - switch_bank( iobase, SET0); - outb( 0, iobase+ICR); + switch_bank(iobase, SET0); + outb(0, iobase+ICR); /* Select Set 2 */ - switch_bank( iobase, SET2); + switch_bank(iobase, SET2); + outb(0x00, iobase+ABHL); - outb( 0x00, iobase+ABHL); - switch ( speed) { - case 9600: outb( 0x0c, iobase+ABLL); break; - case 19200: outb( 0x06, iobase+ABLL); break; - case 37600: outb( 0x03, iobase+ABLL); break; - case 57600: outb( 0x02, iobase+ABLL); break; - case 115200: outb( 0x01, iobase+ABLL); break; + switch (speed) { + case 9600: outb(0x0c, iobase+ABLL); break; + case 19200: outb(0x06, iobase+ABLL); break; + case 37600: outb(0x03, iobase+ABLL); break; + case 57600: outb(0x02, iobase+ABLL); break; + case 115200: outb(0x01, iobase+ABLL); break; case 576000: ir_mode = HCR_MIR_576; DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); @@ -419,34 +425,37 @@ break; default: ir_mode = HCR_FIR; - DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); + DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); break; } /* Set speed mode */ switch_bank(iobase, SET0); - outb( ir_mode, iobase+HCR); + outb(ir_mode, iobase+HCR); /* set FIFO size to 32 */ - switch_bank( iobase, SET2); - outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); + switch_bank(iobase, SET2); + outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); /* set FIFO threshold to TX17, RX16 */ switch_bank(iobase, SET0); - outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR); - + + outb(0x00, iobase+UFR); /* Reset */ + outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */ + outb(0xa7, iobase+UFR); + idev->netdev.tbusy = 0; /* Enable some interrupts so we can receive frames */ switch_bank(iobase, SET0); - if ( speed > 115200) { - outb( ICR_EFSFI, iobase+ICR); - w83977af_dma_receive( idev); + if (speed > PIO_MAX_SPEED) { + outb(ICR_EFSFI, iobase+ICR); + w83977af_dma_receive(idev); } else - outb( ICR_ERBRI, iobase+ICR); + outb(ICR_ERBRI, iobase+ICR); /* Restore SSR */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); } /* @@ -455,7 +464,7 @@ * Sets up a DMA transfer to send the current frame. * */ -int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev) +int w83977af_hard_xmit(struct sk_buff *skb, struct device *dev) { struct irda_device *idev; int iobase; @@ -474,20 +483,21 @@ /* Lock transmit buffer */ if (irda_lock((void *) &dev->tbusy) == FALSE) return -EBUSY; - + /* Save current set */ set = inb(iobase+SSR); /* Decide if we should use PIO or DMA transfer */ - if (idev->io.baudrate > 115200) { + if (idev->io.baudrate > PIO_MAX_SPEED) { + idev->tx_buff.data = idev->tx_buff.head; memcpy(idev->tx_buff.data, skb->data, skb->len); idev->tx_buff.len = skb->len; - idev->tx_buff.data = idev->tx_buff.head; mtt = irda_get_mtt(skb); +#ifdef CONFIG_USE_INTERNAL_TIMER if (mtt > 50) { /* Adjust for timer resolution */ - mtt = mtt / 1000 + 1; + mtt /= 1000+1; /* Setup timer */ switch_bank(iobase, SET4); @@ -502,6 +512,8 @@ switch_bank(iobase, SET0); outb(ICR_ETMRI, iobase+ICR); } else { +#endif + DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt); if (mtt) udelay(mtt); @@ -509,7 +521,9 @@ switch_bank(iobase, SET0); outb(ICR_EDMAI, iobase+ICR); w83977af_dma_write(idev, iobase); +#ifdef CONFIG_USE_INTERNAL_TIMER } +#endif } else { idev->tx_buff.data = idev->tx_buff.head; idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, @@ -527,41 +541,57 @@ return 0; } - /* * Function w83977af_dma_write (idev, iobase) * - * + * Send frame using DMA * */ -static void w83977af_dma_write( struct irda_device *idev, int iobase) +static void w83977af_dma_write(struct irda_device *idev, int iobase) { __u8 set; - - DEBUG( 4, __FUNCTION__ "()\n"); +#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS + unsigned long flags; + __u8 hcr; +#endif + DEBUG(4, __FUNCTION__ "(), len=%d\n", idev->tx_buff.len); /* Save current set */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); /* Disable DMA */ switch_bank(iobase, SET0); - outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); - - setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, - DMA_MODE_WRITE); - - /* idev->media_busy = TRUE; */ - idev->io.direction = IO_XMIT; - + outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); + /* Choose transmit DMA channel */ switch_bank(iobase, SET2); - outb(inb(iobase+ADCR1) | ADCR1_D_CHSW|ADCR1_DMA_F|ADCR1_ADV_SL, - iobase+ADCR1); + outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1); +#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS + save_flags(flags); + cli(); + + disable_dma(idev->io.dma); + clear_dma_ff(idev->io.dma); + set_dma_mode(idev->io.dma, DMA_MODE_READ); + set_dma_addr(idev->io.dma, virt_to_bus(idev->tx_buff.data)); + set_dma_count(idev->io.dma, idev->tx_buff.len); +#else + setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, + DMA_MODE_WRITE); +#endif + idev->io.direction = IO_XMIT; /* Enable DMA */ switch_bank(iobase, SET0); - outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR); - +#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS + hcr = inb(iobase+HCR); + outb(hcr | HCR_EN_DMA, iobase+HCR); + enable_dma(idev->io.dma); + restore_flags(flags); +#else + outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR); +#endif + /* Restore set register */ outb(set, iobase+SSR); } @@ -577,17 +607,17 @@ int actual = 0; __u8 set; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); /* Save current bank */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); - switch_bank( iobase, SET0); + switch_bank(iobase, SET0); if (!(inb_p(iobase+USR) & USR_TSRE)) { - DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); + DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); fifo_size -= 17; - DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); + DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); } /* Fill FIFO with current frame */ @@ -597,7 +627,7 @@ } DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", - fifo_size, actual, len); + fifo_size, actual, len); /* Restore bank */ outb(set, iobase+SSR); @@ -617,7 +647,7 @@ int iobase; __u8 set; - DEBUG(4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies); ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); @@ -663,9 +693,10 @@ */ int w83977af_dma_receive(struct irda_device *idev) { + struct w83977af_ir *self; int iobase; __u8 set; -#ifdef NETWINDER +#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS unsigned long flags; __u8 hcr; #endif @@ -673,62 +704,60 @@ ASSERT(idev != NULL, return -1;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); - DEBUG(0, __FUNCTION__ "\n"); + DEBUG(4, __FUNCTION__ "\n"); + self = idev->priv; iobase= idev->io.iobase; /* Save current set */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); /* Disable DMA */ - switch_bank( iobase, SET0); - outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); + switch_bank(iobase, SET0); + outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); -#ifdef NETWINDER + /* Choose DMA Rx, DMA Fairness, and Advanced mode */ + switch_bank(iobase, SET2); + outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL, + iobase+ADCR1); + + idev->io.direction = IO_RECV; + idev->rx_buff.data = idev->rx_buff.head; + +#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS save_flags(flags); cli(); - disable_dma( idev->io.dma); - clear_dma_ff( idev->io.dma); - set_dma_mode( idev->io.dma, DMA_MODE_READ); - set_dma_addr( idev->io.dma, virt_to_bus(idev->rx_buff.data)); - set_dma_count( idev->io.dma, idev->rx_buff.truesize); + disable_dma(idev->io.dma); + clear_dma_ff(idev->io.dma); + set_dma_mode(idev->io.dma, DMA_MODE_READ); + set_dma_addr(idev->io.dma, virt_to_bus(idev->rx_buff.data)); + set_dma_count(idev->io.dma, idev->rx_buff.truesize); #else - setup_dma(idev->io.dma, idev->rx_buff.data, - idev->rx_buff.truesize, DMA_MODE_READ); + setup_dma(idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, + DMA_MODE_READ); #endif - /* driver->media_busy = FALSE; */ - idev->io.direction = IO_RECV; - idev->rx_buff.data = idev->rx_buff.head; - /* * Reset Rx FIFO. This will also flush the ST_FIFO, it's very * important that we don't reset the Tx FIFO since it might not * be finished transmitting yet */ - outb( UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR); - prev.status = 0; - - /* Choose DMA Rx, DMA Fairness, and Advanced mode */ - switch_bank(iobase, SET2); - outb(( inb( iobase+ADCR1) & ~ADCR1_D_CHSW)|ADCR1_DMA_F|ADCR1_ADV_SL, - iobase+ADCR1); + switch_bank(iobase, SET0); + outb(UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR); + self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0; /* Enable DMA */ switch_bank(iobase, SET0); -#ifdef NETWINDER - hcr = inb( iobase+HCR); - enable_dma( idev->io.dma); - outb( hcr | HCR_EN_DMA, iobase+HCR); +#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS + hcr = inb(iobase+HCR); + outb(hcr | HCR_EN_DMA, iobase+HCR); + enable_dma(idev->io.dma); restore_flags(flags); #else - outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR); + outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR); #endif - /* Restore set */ - outb( set, iobase+SSR); - - DEBUG( 4, __FUNCTION__ "(), done!\n"); + outb(set, iobase+SSR); return 0; } @@ -742,12 +771,17 @@ int w83977af_dma_receive_complete(struct irda_device *idev) { struct sk_buff *skb; + struct w83977af_ir *self; + struct st_fifo *st_fifo; int len; int iobase; __u8 set; __u8 status; - DEBUG(0, __FUNCTION__ "\n"); + DEBUG(4, __FUNCTION__ "\n"); + + self = idev->priv; + st_fifo = &self->st_fifo; iobase = idev->io.iobase; @@ -756,22 +790,28 @@ iobase = idev->io.iobase; + /* Read status FIFO */ switch_bank(iobase, SET5); - if (prev.status & FS_FO_FSFDR) { - status = prev.status; - len = prev.len; + while ((status = inb(iobase+FS_FO)) & FS_FO_FSFDR) { + st_fifo->entries[st_fifo->tail].status = status; - prev.status = 0; - } else { - status = inb(iobase+FS_FO); - len = inb(iobase+RFLFL); - len |= inb(iobase+RFLFH) << 8; + st_fifo->entries[st_fifo->tail].len = inb(iobase+RFLFL); + st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8; + + st_fifo->tail++; + st_fifo->len++; } + + while (st_fifo->len) { + /* Get first entry */ + status = st_fifo->entries[st_fifo->head].status; + len = st_fifo->entries[st_fifo->head].len; + st_fifo->head++; + st_fifo->len--; - while (status & FS_FO_FSFDR) { /* Check for errors */ if (status & FS_FO_ERR_MSK) { - if ( status & FS_FO_LST_FR) { + if (status & FS_FO_LST_FR) { /* Add number of lost frames to stats */ idev->stats.rx_errors += len; } else { @@ -800,14 +840,20 @@ /* Check if we have transfered all data to memory */ switch_bank(iobase, SET0); if (inb(iobase+USR) & USR_RDR) { +#ifdef CONFIG_USE_INTERNAL_TIMER /* Put this entry back in fifo */ - prev.status = status; - prev.len = len; - + st_fifo->head--; + st_fifo->len++; + st_fifo->entries[st_fifo->head].status = status; + st_fifo->entries[st_fifo->head].len = len; + /* Restore set register */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); return FALSE; /* I'll be back! */ +#else + udelay(80); /* Should be enough!? */ +#endif } skb = dev_alloc_skb(len+1); @@ -824,28 +870,23 @@ skb_reserve(skb, 1); /* Copy frame without CRC */ - if ( idev->io.baudrate < 4000000) { - skb_put( skb, len-2); - memcpy( skb->data, idev->rx_buff.data, len-2); + if (idev->io.baudrate < 4000000) { + skb_put(skb, len-2); + memcpy(skb->data, idev->rx_buff.data, len-2); } else { - skb_put( skb, len-4); - memcpy( skb->data, idev->rx_buff.data, len-4); + skb_put(skb, len-4); + memcpy(skb->data, idev->rx_buff.data, len-4); } /* Move to next frame */ idev->rx_buff.data += len; + idev->stats.rx_packets++; skb->dev = &idev->netdev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); - netif_rx( skb); - idev->stats.rx_packets++; + netif_rx(skb); } - /* Read next entry in ST_FIFO */ - switch_bank(iobase, SET5); - status = inb( iobase+FS_FO); - len = inb( iobase+RFLFL); - len |= inb( iobase+RFLFH) << 8; } /* Restore set register */ outb(set, iobase+SSR); @@ -875,7 +916,6 @@ do { byte = inb(iobase+RBR); async_unwrap_char(idev, byte); - } while (inb(iobase+USR) & USR_RDR); /* Data available */ } @@ -889,9 +929,12 @@ { int actual; __u8 new_icr = 0; + __u8 set; + int iobase; DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr); + iobase = idev->io.iobase; /* Transmit FIFO low on data */ if (isr & ISR_TXTH_I) { /* Write data left in transmit buffer */ @@ -899,16 +942,21 @@ idev->tx_buff.data, idev->tx_buff.len, idev->io.fifo_size); + idev->tx_buff.data += actual; idev->tx_buff.len -= actual; idev->io.direction = IO_XMIT; /* Check if finished */ - if (idev->tx_buff.len > 0) + if (idev->tx_buff.len > 0) { new_icr |= ICR_ETXTHI; - else { - DEBUG( 4, __FUNCTION__ "(), finished with frame!\n"); + } else { + set = inb(iobase+SSR); + switch_bank(iobase, SET0); + outb(AUDR_SFEND, iobase+AUDR); + outb(set, iobase+SSR); + idev->netdev.tbusy = 0; /* Unlock */ idev->stats.tx_packets++; @@ -917,7 +965,6 @@ new_icr |= ICR_ETBREI; } - } /* Check if transmission has completed */ if (isr & ISR_TXEMP_I) { @@ -943,22 +990,20 @@ * Handle MIR/FIR interrupt * */ -static __u8 w83977af_fir_interrupt( struct irda_device *idev, int isr) +static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr) { __u8 new_icr = 0; __u8 set; int iobase; - DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr); - iobase = idev->io.iobase; - set = inb(iobase+SSR); /* End of frame detected in FIFO */ if (isr & (ISR_FEND_I|ISR_FSF_I)) { if (w83977af_dma_receive_complete(idev)) { + /* Wait for next status FIFO interrupt */ new_icr |= ICR_EFSFI; } else { /* DMA not finished yet */ @@ -982,7 +1027,7 @@ /* Clear timer event */ /* switch_bank(iobase, SET0); */ -/* outb( ASCR_CTE, iobase+ASCR); */ +/* outb(ASCR_CTE, iobase+ASCR); */ /* Check if this is a TX timer interrupt */ if (idev->io.direction == IO_XMIT) { @@ -998,15 +1043,18 @@ } /* Finished with DMA */ if (isr & ISR_DMA_I) { - w83977af_dma_xmit_complete( idev); - + w83977af_dma_xmit_complete(idev); + /* Check if there are more frames to be transmitted */ - if (irda_device_txqueue_empty( idev)) { + /* if (irda_device_txqueue_empty(idev)) { */ - /* Prepare for receive */ - w83977af_dma_receive(idev); - new_icr = ICR_EFSFI; - } + /* Prepare for receive + * + * ** Netwinder Tx DMA likes that we do this anyway ** + */ + w83977af_dma_receive(idev); + new_icr = ICR_EFSFI; + /* } */ } /* Restore set */ @@ -1030,7 +1078,7 @@ if (idev == NULL) { printk(KERN_WARNING "%s: irq %d for unknown device.\n", - driver_name, irq); + driver_name, irq); return; } @@ -1049,7 +1097,7 @@ if (isr) { /* Dispatch interrupt handler for the current speed */ - if ( idev->io.baudrate > 115200) + if (idev->io.baudrate > PIO_MAX_SPEED ) icr = w83977af_fir_interrupt(idev, isr); else icr = w83977af_sir_interrupt(idev, isr); @@ -1070,7 +1118,7 @@ static void w83977af_wait_until_sent(struct irda_device *idev) { current->state = TASK_INTERRUPTIBLE; - schedule_timeout(6); + schedule_timeout(60*HZ/1000); } /* @@ -1085,16 +1133,16 @@ int iobase; __u8 set; - ASSERT( idev != NULL, return FALSE;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;); + ASSERT(idev != NULL, return FALSE;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return FALSE;); - if ( idev->io.baudrate > 115200) { + if (idev->io.baudrate > 115200) { iobase = idev->io.iobase; /* Check if rx FIFO is not empty */ set = inb(iobase+SSR); - switch_bank( iobase, SET2); - if (( inb( iobase+RXFDTH) & 0x3f) != 0) { + switch_bank(iobase, SET2); + if ((inb(iobase+RXFDTH) & 0x3f) != 0) { /* We are receiving something */ status = TRUE; } @@ -1111,12 +1159,12 @@ * * */ -static int w83977af_net_init( struct device *dev) +static int w83977af_net_init(struct device *dev) { DEBUG(0, __FUNCTION__ "()\n"); /* Set up to be a normal IrDA network device driver */ - irda_device_setup( dev); + irda_device_setup(dev); /* Insert overrides below this line! */ @@ -1130,7 +1178,7 @@ * Start the device * */ -static int w83977af_net_open( struct device *dev) +static int w83977af_net_open(struct device *dev) { struct irda_device *idev; int iobase; @@ -1147,7 +1195,7 @@ iobase = idev->io.iobase; if (request_irq(idev->io.irq, w83977af_interrupt, 0, idev->name, - (void *) idev)) { + (void *) idev)) { return -EAGAIN; } /* @@ -1170,13 +1218,13 @@ /* Enable some interrupts so we can receive frames again */ switch_bank(iobase, SET0); if (idev->io.baudrate > 115200) { - outb( ICR_EFSFI, iobase+ICR); - w83977af_dma_receive( idev); + outb(ICR_EFSFI, iobase+ICR); + w83977af_dma_receive(idev); } else - outb( ICR_ERBRI, iobase+ICR); + outb(ICR_ERBRI, iobase+ICR); /* Restore bank register */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); MOD_INC_USE_COUNT; @@ -1195,34 +1243,34 @@ int iobase; __u8 set; - DEBUG( 0, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); /* Stop device */ dev->tbusy = 1; dev->start = 0; - ASSERT( dev != NULL, return -1;); + ASSERT(dev != NULL, return -1;); idev = (struct irda_device *) dev->priv; - ASSERT( idev != NULL, return 0;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + ASSERT(idev != NULL, return 0;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;); iobase = idev->io.iobase; - disable_dma( idev->io.dma); + disable_dma(idev->io.dma); /* Save current set */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); /* Disable interrupts */ - switch_bank( iobase, SET0); - outb( 0, iobase+ICR); + switch_bank(iobase, SET0); + outb(0, iobase+ICR); - free_irq( idev->io.irq, idev); - free_dma( idev->io.dma); + free_irq(idev->io.irq, idev); + free_dma(idev->io.dma); /* Restore bank register */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); MOD_DEC_USE_COUNT; @@ -1230,6 +1278,11 @@ } #ifdef MODULE + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver"); + +MODULE_PARM(qos_mtt_bits, "i"); /* * Function init_module (void) diff -u --recursive --new-file v2.2.9/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c --- v2.2.9/linux/drivers/net/smc-ultra.c Wed Mar 10 15:29:46 1999 +++ linux/drivers/net/smc-ultra.c Wed May 26 09:33:02 1999 @@ -483,9 +483,9 @@ /* NB: ultra_close_card() does free_irq + irq2dev */ int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; kfree(dev->priv); - dev->priv = NULL; release_region(ioaddr, ULTRA_IO_EXTENT); unregister_netdev(dev); + dev->priv = NULL; } } } diff -u --recursive --new-file v2.2.9/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.2.9/linux/drivers/net/sunhme.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/net/sunhme.c Sat May 29 11:10:15 1999 @@ -1834,7 +1834,7 @@ #define RXD(x) #endif -/* Originally I use to handle the allocation failure by just giving back just +/* Originally I used to handle the allocation failure by just giving back just * that one ring buffer to the happy meal. Problem is that usually when that * condition is triggered, the happy meal expects you to do something reasonable * with all of the packets it has DMA'd in. So now I just drop the entire diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/README.st linux/drivers/scsi/README.st --- v2.2.9/linux/drivers/scsi/README.st Wed Mar 10 15:29:47 1999 +++ linux/drivers/scsi/README.st Sat May 22 14:51:26 1999 @@ -2,7 +2,7 @@ The driver is currently maintained by Kai M{kisara (email Kai.Makisara@metla.fi) -Last modified: Sun Jan 17 10:57:41 1999 by makisara@home +Last modified: Sun Apr 18 13:24:43 1999 by makisara@home BASICS @@ -348,15 +348,6 @@ The GMT_xxx status bits reflect the drive status. GMT_DR_OPEN is set if there is no tape in the drive. GMT_EOD means either end of recorded data or end of tape. GMT_EOT means end of tape. - -The following ioctls use the structure mtlocation that contains both -the block number and the partition number. These ioctls are available -only for SCSI-2 tape drives and the block number is the -device-independent logical block number defined by the standard. - -MTGETLOC Returns the current block and partition number. -MTSETLOC Sets the tape to the block and partition specified by the - arguments. MISCELLANEOUS COMPILE OPTIONS diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.2.9/linux/drivers/scsi/scsi.c Tue May 11 13:10:30 1999 +++ linux/drivers/scsi/scsi.c Wed May 26 09:33:31 1999 @@ -109,6 +109,7 @@ #define BLIST_SINGLELUN 0x10 #define BLIST_NOTQ 0x20 #define BLIST_SPARSELUN 0x40 +#define BLIST_MAX5LUN 0x80 /* * Data declarations. @@ -273,6 +274,7 @@ {"INSITE","I325VM","*", BLIST_KEY}, {"NRC","MBR-7","*", BLIST_FORCELUN | BLIST_SINGLELUN}, {"NRC","MBR-7.4","*", BLIST_FORCELUN | BLIST_SINGLELUN}, +{"REGAL","CDC-4X","*", BLIST_MAX5LUN | BLIST_SINGLELUN}, {"NAKAMICH","MJ-4.8S","*", BLIST_FORCELUN | BLIST_SINGLELUN}, {"NAKAMICH","MJ-5.16S","*", BLIST_FORCELUN | BLIST_SINGLELUN}, {"PIONEER","CD-ROM DRM-600","*", BLIST_FORCELUN | BLIST_SINGLELUN}, @@ -932,6 +934,15 @@ *max_dev_lun = 8; return 1; } + + /* + * REGAL CDC-4X: avoid hang after LUN 4 + */ + if (bflags & BLIST_MAX5LUN) { + *max_dev_lun = 5; + return 1; + } + /* * We assume the device can't handle lun!=0 if: - it reports scsi-0 (ANSI * SCSI Revision 0) (old drives like MAXTOR XT-3280) or - it reports scsi-1 diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c --- v2.2.9/linux/drivers/scsi/sr_ioctl.c Tue May 11 13:10:30 1999 +++ linux/drivers/scsi/sr_ioctl.c Fri May 14 16:04:16 1999 @@ -122,11 +122,9 @@ if (!quiet) printk(KERN_ERR "sr%d: CDROM (ioctl) reports ILLEGAL " "REQUEST.\n", target); - if ((SCpnt->sense_buffer[12] == 0x20 || - SCpnt->sense_buffer[12] == 0x24) && + if (SCpnt->sense_buffer[12] == 0x20 && SCpnt->sense_buffer[13] == 0x00) { /* sense: Invalid command operation code */ - /* or Invalid field in cdb */ err = -EDRIVE_CANT_DO_THIS; } else { err = -EINVAL; diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v2.2.9/linux/drivers/scsi/st.c Wed Mar 10 15:29:47 1999 +++ linux/drivers/scsi/st.c Sat May 22 14:51:26 1999 @@ -11,7 +11,7 @@ Copyright 1992 - 1999 Kai Makisara email Kai.Makisara@metla.fi - Last modified: Sun Mar 7 09:03:17 1999 by makisara@home + Last modified: Tue May 18 09:29:52 1999 by makisara@home Some small formal changes - aeb, 950809 */ @@ -164,8 +164,6 @@ SCpnt->request_bufflen); if (driver_byte(result) & DRIVER_SENSE) print_sense("st", SCpnt); - else - printk("\n"); } else #endif @@ -289,6 +287,7 @@ } else bp = (STp->buffer)->b_data; + SCpnt->cmd_len = 0; SCpnt->request.sem = &(STp->sem); SCpnt->request.rq_status = RQ_SCSI_BUSY; SCpnt->request.rq_dev = STp->devt; @@ -3380,7 +3379,6 @@ tpnt->devt = MKDEV(SCSI_TAPE_MAJOR, i); tpnt->dirty = 0; - tpnt->waiting = NULL; tpnt->in_use = 0; tpnt->drv_buffer = 1; /* Try buffering if no mode sense */ tpnt->restr_dma = (SDp->host)->unchecked_isa_dma; diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/st.h linux/drivers/scsi/st.h --- v2.2.9/linux/drivers/scsi/st.h Wed Sep 9 14:51:09 1998 +++ linux/drivers/scsi/st.h Sat May 22 14:51:26 1999 @@ -65,7 +65,6 @@ typedef struct { kdev_t devt; unsigned capacity; - struct wait_queue * waiting; Scsi_Device* device; struct semaphore sem; ST_buffer * buffer; diff -u --recursive --new-file v2.2.9/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c --- v2.2.9/linux/drivers/scsi/sym53c8xx.c Fri Apr 16 14:47:31 1999 +++ linux/drivers/scsi/sym53c8xx.c Sat May 22 13:42:53 1999 @@ -572,6 +572,8 @@ #define remap_pci_mem(base, size) ((u_long) __va(base)) #define unmap_pci_mem(vaddr, size) #define pcivtobus(p) ((p) & pci_dvma_mask) +#elif defined(__alpha__) +#define pcivtobus(p) ((p) & 0xfffffffful) #else /* __sparc__ */ #define pcivtobus(p) (p) diff -u --recursive --new-file v2.2.9/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- v2.2.9/linux/drivers/sound/es1370.c Fri Apr 16 14:47:31 1999 +++ linux/drivers/sound/es1370.c Sat May 22 13:05:43 1999 @@ -33,8 +33,8 @@ * to make the card a four channel one: use dsp to output two * channels to LINE and dac to output the other two channels to * SPKR. Set the mixer to only output synth to SPKR. - * micz it looks like this changes the MIC input impedance. I don't know - * any detail though. + * micbias sets the +5V bias to the mic if using an electretmic. + * * * Note: sync mode is not yet supported (i.e. running dsp and dac from the same * clock source) @@ -92,6 +92,12 @@ * Alpha fixes reported by Peter Jones * Note: joystick address handling might still be wrong on archs * other than i386 + * 10.05.99 0.21 Added support for an electret mic for SB PCI64 + * to the Linux kernel sound driver. This mod also straighten + * out the question marks around the mic impedance setting + * (micz). From Kim.Berts@fisub.mail.abb.com + * 11.05.99 0.22 Implemented the IMIX call to mute recording monitor. + * Guenter Geiger * * some important things missing in Ensoniq documentation: * @@ -107,8 +113,8 @@ * The card uses a 22.5792 MHz crystal. * The LINEIN jack may be converted to an AOUT jack by * setting pin 47 (XCTL0) of the ES1370 to high. - * Pin 48 (XCTL1) of the ES1370 presumably changes the input impedance of the - * MIC jack. + * Pin 48 (XCTL1) of the ES1370 sets the +5V bias for an electretmic + * * */ @@ -190,7 +196,7 @@ #define DAC2_DIVTOSR(x) (1411200/((x)+2)) #define CTRL_ADC_STOP 0x80000000 /* 1 = ADC stopped */ -#define CTRL_XCTL1 0x40000000 /* ? mic impedance */ +#define CTRL_XCTL1 0x40000000 /* electret mic bias */ #define CTRL_OPEN 0x20000000 /* no function, can be read and written */ #define CTRL_PCLKDIV 0x1fff0000 /* ADC/DAC2 clock divider */ #define CTRL_SH_PCLKDIV 16 @@ -301,6 +307,7 @@ unsigned int recsrc; unsigned int modcnt; unsigned short micpreamp; + unsigned int imix; } mix; /* wave stuff */ @@ -839,7 +846,8 @@ return put_user(s->mix.recsrc, (int *)arg); case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ - for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++) + val = SOUND_MASK_IMIX; + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) if (mixtable[i].avail) val |= 1 << i; return put_user(val, (int *)arg); @@ -858,6 +866,9 @@ case SOUND_MIXER_CAPS: return put_user(0, (int *)arg); + + case SOUND_MIXER_IMIX: + return put_user(s->mix.imix, (int *)arg); default: i = _IOC_NR(cmd); @@ -870,6 +881,14 @@ return -EINVAL; s->mix.modcnt++; switch (_IOC_NR(cmd)) { + + case SOUND_MIXER_IMIX: + if (arg == 0) + return -EFAULT; + get_user_ret(s->mix.imix,(int *)arg, -EFAULT); + val = s->mix.recsrc; + /* fall through */ + case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ get_user_ret(val, (int *)arg, -EFAULT); for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) { @@ -886,7 +905,10 @@ wrcodec(s, 0x13, j & 0xaa); wrcodec(s, 0x14, (j >> 8) & 0x17); wrcodec(s, 0x15, (j >> 8) & 0x0f); - i = (j & 0x37f) | ((j << 1) & 0x3000) | 0xc30; + i = (j & 0x37f) | ((j << 1) & 0x3000) | 0xc60; + if (!s->mix.imix) { + i &= 0xff60; /* mute record and line monitor */ + } wrcodec(s, 0x10, i); wrcodec(s, 0x11, i >> 8); return 0; @@ -2262,7 +2284,7 @@ static int joystick[NR_DEVICE] = { 0, }; #endif static int lineout[NR_DEVICE] = { 0, }; -static int micz[NR_DEVICE] = { 0, }; +static int micbias[NR_DEVICE] = { 0, }; /* --------------------------------------------------------------------- */ @@ -2295,7 +2317,7 @@ if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1370: version v0.20 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1370: version v0.22 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) { if (pcidev->base_address[0] == 0 || @@ -2328,8 +2350,10 @@ goto err_irq; } /* initialize codec registers */ - s->ctrl = CTRL_CDC_EN | CTRL_SERR_DIS | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL); - if (joystick[index]) { + /* note: setting CTRL_SERR_DIS is reported to break + * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */ + s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL); + if (joystick[index]) { if (check_region(0x200, JOY_EXTENT)) printk(KERN_ERR "es1370: io port 0x200 in use\n"); else @@ -2337,7 +2361,7 @@ } if (lineout[index]) s->ctrl |= CTRL_XCTL0; - if (micz[index]) + if (micbias[index]) s->ctrl |= CTRL_XCTL1; s->sctrl = 0; printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n" @@ -2361,6 +2385,7 @@ wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!! */ wrcodec(s, 0x18, 0); /* recording source is mixer */ wrcodec(s, 0x19, s->mix.micpreamp = 1); /* turn on MIC preamp */ + s->mix.imix = 1; fs = get_fs(); set_fs(KERNEL_DS); val = SOUND_MASK_LINE|SOUND_MASK_SYNTH|SOUND_MASK_CD; @@ -2403,8 +2428,8 @@ MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)"); MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i"); MODULE_PARM_DESC(lineout, "if 1 the LINE input is converted to LINE out"); -MODULE_PARM(micz, "1-" __MODULE_STRING(NR_DEVICE) "i"); -MODULE_PARM_DESC(micz, "changes (??) the microphone impedance"); +MODULE_PARM(micbias, "1-" __MODULE_STRING(NR_DEVICE) "i"); +MODULE_PARM_DESC(micbias, "sets the +5V bias for an electret microphone"); MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); MODULE_DESCRIPTION("ES1370 AudioPCI Driver"); diff -u --recursive --new-file v2.2.9/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c --- v2.2.9/linux/drivers/video/cgsixfb.c Tue Mar 23 14:35:48 1999 +++ linux/drivers/video/cgsixfb.c Sat May 29 11:10:15 1999 @@ -1,4 +1,4 @@ -/* $Id: cgsixfb.c,v 1.16 1999/03/09 14:01:49 davem Exp $ +/* $Id: cgsixfb.c,v 1.16.2.1 1999/05/25 00:59:35 davem Exp $ * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -588,7 +588,7 @@ p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); } -static char idstring[60] __initdata = { 0 }; +static char idstring[70] __initdata = { 0 }; __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb)) { @@ -599,6 +599,7 @@ unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; u32 conf; char *p; + char *cardtype; struct bt_regs *bt; strcpy(fb->info.modename, "CGsix"); @@ -656,15 +657,29 @@ case CG6_FHC_CPU_68020: p = "68020"; break; default: p = "i386"; break; } + + if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) { + if (fix->smem_len <= 0x100000) { + cardtype = "TurboGX"; + } else { + cardtype = "TurboGX+"; + } + } else { + if (fix->smem_len <= 0x100000) { + cardtype = "GX"; + } else { + cardtype = "GX+"; + } + } sprintf(idstring, #ifdef __sparc_v9__ - "cgsix at %016lx TEC Rev %x CPU %s Rev %x", phys, + "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys, #else - "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x", fb->iospace, phys, + "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", fb->iospace, phys, #endif (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK, - p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK); + p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK, cardtype); cg6_reset(fb); diff -u --recursive --new-file v2.2.9/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c --- v2.2.9/linux/drivers/video/fbcon.c Wed Apr 28 11:37:30 1999 +++ linux/drivers/video/fbcon.c Fri May 14 12:49:59 1999 @@ -2300,3 +2300,4 @@ EXPORT_SYMBOL(fb_display); EXPORT_SYMBOL(fbcon_redraw_bmove); EXPORT_SYMBOL(fbcon_dummy); +EXPORT_SYMBOL(fb_con); diff -u --recursive --new-file v2.2.9/linux/drivers/video/mdacon.c linux/drivers/video/mdacon.c --- v2.2.9/linux/drivers/video/mdacon.c Wed Mar 10 15:29:48 1999 +++ linux/drivers/video/mdacon.c Fri May 14 17:46:16 1999 @@ -597,7 +597,7 @@ if (mda_first_vc > mda_last_vc) return; - take_over_console(&mda_con, mda_first_vc, mda_last_vc, 0); + take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0); } #ifdef MODULE diff -u --recursive --new-file v2.2.9/linux/fs/adfs/dir.c linux/fs/adfs/dir.c --- v2.2.9/linux/fs/adfs/dir.c Thu May 13 23:10:30 1999 +++ linux/fs/adfs/dir.c Thu May 13 23:25:58 1999 @@ -138,9 +138,6 @@ struct super_block *sb; int i, size; - if (!inode) - return 0; - sb = inode->i_sb; size = 2048 >> sb->s_blocksize_bits; diff -u --recursive --new-file v2.2.9/linux/fs/adfs/namei.c linux/fs/adfs/namei.c --- v2.2.9/linux/fs/adfs/namei.c Tue May 11 13:10:30 1999 +++ linux/fs/adfs/namei.c Thu May 13 23:25:58 1999 @@ -46,9 +46,6 @@ unsigned long parent_object_id, dir_object_id; int buffers, pos; - if (!S_ISDIR(dir->i_mode)) - return 0; - sb = dir->i_sb; if (adfs_inode_validate (dir)) { @@ -56,9 +53,6 @@ "invalid inode number: %lu", dir->i_ino); return 0; } - - if (namelen > ADFS_NAME_LEN) - return 0; if (!(buffers = adfs_dir_read (dir, bh))) { adfs_error (sb, "adfs_find_entry", "unable to read directory"); diff -u --recursive --new-file v2.2.9/linux/fs/autofs/dir.c linux/fs/autofs/dir.c --- v2.2.9/linux/fs/autofs/dir.c Wed Apr 28 11:37:30 1999 +++ linux/fs/autofs/dir.c Thu May 13 23:25:58 1999 @@ -16,8 +16,6 @@ void *dirent, filldir_t filldir) { struct inode *inode=filp->f_dentry->d_inode; - if (!inode || !S_ISDIR(inode->i_mode)) - return -ENOTDIR; switch((unsigned long) filp->f_pos) { diff -u --recursive --new-file v2.2.9/linux/fs/autofs/root.c linux/fs/autofs/root.c --- v2.2.9/linux/fs/autofs/root.c Tue May 11 13:10:30 1999 +++ linux/fs/autofs/root.c Thu May 13 23:25:58 1999 @@ -72,9 +72,6 @@ struct inode * inode = filp->f_dentry->d_inode; off_t onr, nr; - if (!inode || !S_ISDIR(inode->i_mode)) - return -ENOTDIR; - sbi = autofs_sbi(inode->i_sb); dirhash = &sbi->dirhash; nr = filp->f_pos; diff -u --recursive --new-file v2.2.9/linux/fs/block_dev.c linux/fs/block_dev.c --- v2.2.9/linux/fs/block_dev.c Thu Nov 19 09:56:28 1998 +++ linux/fs/block_dev.c Fri May 28 09:20:36 1999 @@ -273,6 +273,8 @@ if (++bhe == &buflist[NBUF]) bhe = buflist; } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe))); + if (bhe == bhb && !blocks) + break; } while (left > 0); /* Release the read-ahead blocks */ diff -u --recursive --new-file v2.2.9/linux/fs/ext2/file.c linux/fs/ext2/file.c --- v2.2.9/linux/fs/ext2/file.c Tue Dec 22 14:16:57 1998 +++ linux/fs/ext2/file.c Tue Jun 1 12:43:35 1999 @@ -162,7 +162,7 @@ struct buffer_head * bh, *bufferlist[NBUF]; struct super_block * sb; int err; - int i,buffercount,write_error; + int i,buffercount,write_error, new_buffer; /* POSIX: mtime/ctime may not change for 0 count */ if (!count) @@ -247,30 +247,59 @@ } if (c > count) c = count; - if (c != sb->s_blocksize && !buffer_uptodate(bh)) { - ll_rw_block (READ, 1, &bh); - wait_on_buffer (bh); - if (!buffer_uptodate(bh)) { - brelse (bh); + + /* Tricky: what happens if we are writing the complete + * contents of a block which is not currently + * initialised? We have to obey the same + * synchronisation rules as the IO code, to prevent some + * other process from stomping on the buffer contents by + * refreshing them from disk while we are setting up the + * buffer. The copy_from_user() can page fault, after + * all. We also have to throw away partially successful + * copy_from_users to such buffers, since we can't trust + * the rest of the buffer_head in that case. --sct */ + + new_buffer = (!buffer_uptodate(bh) && !buffer_locked(bh) && + c == sb->s_blocksize); + + if (new_buffer) { + set_bit(BH_Lock, &bh->b_state); + c -= copy_from_user (bh->b_data + offset, buf, c); + if (c != sb->s_blocksize) { + c = 0; + unlock_buffer(bh); + brelse(bh); if (!written) - written = -EIO; + written = -EFAULT; break; } + mark_buffer_uptodate(bh, 1); + unlock_buffer(bh); + } else { + if (!buffer_uptodate(bh)) { + ll_rw_block (READ, 1, &bh); + wait_on_buffer (bh); + if (!buffer_uptodate(bh)) { + brelse (bh); + if (!written) + written = -EIO; + break; + } + } + c -= copy_from_user (bh->b_data + offset, buf, c); } - c -= copy_from_user (bh->b_data + offset, buf, c); if (!c) { brelse(bh); if (!written) written = -EFAULT; break; } + mark_buffer_dirty(bh, 0); update_vm_cache(inode, pos, bh->b_data + offset, c); pos += c; written += c; buf += c; count -= c; - mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 0); if (filp->f_flags & O_SYNC) bufferlist[buffercount++] = bh; diff -u --recursive --new-file v2.2.9/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v2.2.9/linux/fs/ext2/namei.c Tue May 11 13:10:31 1999 +++ linux/fs/ext2/namei.c Thu May 13 23:25:58 1999 @@ -869,7 +869,8 @@ if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) goto end_rename; retval = -EMLINK; - if (!new_inode && new_dir->i_nlink >= EXT2_LINK_MAX) + if (!new_inode && new_dir!=old_dir && + new_dir->i_nlink >= EXT2_LINK_MAX) goto end_rename; } if (!new_bh) { diff -u --recursive --new-file v2.2.9/linux/fs/ext2/truncate.c linux/fs/ext2/truncate.c --- v2.2.9/linux/fs/ext2/truncate.c Fri Oct 9 13:27:13 1998 +++ linux/fs/ext2/truncate.c Thu May 13 17:37:23 1999 @@ -407,7 +407,8 @@ break; if (IS_SYNC(inode) && (inode->i_state & I_DIRTY)) ext2_sync_inode (inode); - current->counter = 0; + run_task_queue(&tq_disk); + current->policy |= SCHED_YIELD; schedule (); } /* diff -u --recursive --new-file v2.2.9/linux/fs/hfs/dir_cap.c linux/fs/hfs/dir_cap.c --- v2.2.9/linux/fs/hfs/dir_cap.c Wed Apr 28 11:37:31 1999 +++ linux/fs/hfs/dir_cap.c Thu May 13 23:25:58 1999 @@ -237,10 +237,6 @@ struct hfs_cat_entry *entry; struct inode *dir = filp->f_dentry->d_inode; - if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) { - return -EBADF; - } - entry = HFS_I(dir)->entry; type = HFS_ITYPE(dir->i_ino); skip_dirs = (type == HFS_CAP_RDIR); diff -u --recursive --new-file v2.2.9/linux/fs/hfs/dir_dbl.c linux/fs/hfs/dir_dbl.c --- v2.2.9/linux/fs/hfs/dir_dbl.c Wed Apr 28 11:37:31 1999 +++ linux/fs/hfs/dir_dbl.c Thu May 13 23:25:58 1999 @@ -202,10 +202,6 @@ struct hfs_cat_entry *entry; struct inode *dir = filp->f_dentry->d_inode; - if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) { - return -EBADF; - } - entry = HFS_I(dir)->entry; if (filp->f_pos == 0) { diff -u --recursive --new-file v2.2.9/linux/fs/hfs/dir_nat.c linux/fs/hfs/dir_nat.c --- v2.2.9/linux/fs/hfs/dir_nat.c Wed Apr 28 11:37:31 1999 +++ linux/fs/hfs/dir_nat.c Thu May 13 23:25:58 1999 @@ -225,10 +225,6 @@ struct hfs_cat_entry *entry; struct inode *dir = filp->f_dentry->d_inode; - if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) { - return -EBADF; - } - entry = HFS_I(dir)->entry; type = HFS_ITYPE(dir->i_ino); skip_dirs = (type == HFS_NAT_HDIR); diff -u --recursive --new-file v2.2.9/linux/fs/minix/namei.c linux/fs/minix/namei.c --- v2.2.9/linux/fs/minix/namei.c Tue May 11 13:10:31 1999 +++ linux/fs/minix/namei.c Thu May 13 23:25:58 1999 @@ -45,8 +45,6 @@ struct minix_dir_entry *de; *res_dir = NULL; - if (!dir->i_sb) - return NULL; info = &dir->i_sb->u.minix_sb; if (namelen > info->s_namelen) { #ifdef NO_TRUNCATE @@ -161,8 +159,6 @@ *res_buf = NULL; *res_dir = NULL; - if (!dir || !dir->i_sb) - return -ENOENT; info = &dir->i_sb->u.minix_sb; if (namelen > info->s_namelen) { #ifdef NO_TRUNCATE @@ -342,8 +338,6 @@ struct minix_dir_entry * de; struct minix_sb_info * info; - if (!inode || !inode->i_sb) - return 1; info = &inode->i_sb->u.minix_sb; block = 0; bh = NULL; @@ -442,26 +436,12 @@ struct buffer_head * bh; struct minix_dir_entry * de; -repeat: retval = -ENOENT; - inode = NULL; + inode = dentry->d_inode; bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); - if (!bh) - goto end_unlink; - inode = dentry->d_inode; - - retval = -EPERM; - if (de->inode != inode->i_ino) { - brelse(bh); - current->counter = 0; - schedule(); - goto repeat; - } - if (de->inode != inode->i_ino) { - retval = -ENOENT; + if (!bh || de->inode != inode->i_ino) goto end_unlink; - } if (!inode->i_nlink) { printk("Deleting nonexistent file (%s:%lu), %d\n", kdevname(inode->i_dev), @@ -562,12 +542,6 @@ (((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode) /* - * rename uses retrying to avoid race-conditions: at least they should be minimal. - * it tries to allocate all the blocks, then sanity-checks, and if the sanity- - * checks fail, it tries to restart itself again. Very practical - no changes - * are done until we know everything works ok.. and then all the changes can be - * done in one fell swoop when we have claimed all the buffers needed. - * * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */ @@ -581,24 +555,15 @@ int retval; info = &old_dir->i_sb->u.minix_sb; - goto start_up; -try_again: - brelse(old_bh); - brelse(new_bh); - brelse(dir_bh); - current->counter = 0; - schedule(); -start_up: - old_inode = new_inode = NULL; - old_bh = new_bh = dir_bh = NULL; + new_bh = dir_bh = NULL; + old_inode = old_dentry->d_inode; + new_inode = new_dentry->d_inode; old_bh = minix_find_entry(old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); retval = -ENOENT; - if (!old_bh) + if (!old_bh || old_de->inode != old_inode->i_ino) goto end_rename; - old_inode = old_dentry->d_inode; retval = -EPERM; - new_inode = new_dentry->d_inode; new_bh = minix_find_entry(new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de); if (new_bh) { @@ -620,7 +585,8 @@ if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino) goto end_rename; retval = -EMLINK; - if (!new_inode && new_dir->i_nlink >= info->s_link_max) + if (!new_inode && new_dir != old_dir && + new_dir->i_nlink >= info->s_link_max) goto end_rename; } if (!new_bh) { @@ -631,22 +597,15 @@ if (retval) goto end_rename; } -/* sanity checking before doing the rename - avoid races */ - if (new_inode && (new_de->inode != new_inode->i_ino)) - goto try_again; - if (new_de->inode && !new_inode) - goto try_again; - if (old_de->inode != old_inode->i_ino) - goto try_again; /* ok, that's it */ - old_de->inode = 0; new_de->inode = old_inode->i_ino; + old_de->inode = 0; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; - mark_inode_dirty(old_dir); old_dir->i_version = ++event; + mark_inode_dirty(old_dir); new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME; - mark_inode_dirty(new_dir); new_dir->i_version = ++event; + mark_inode_dirty(new_dir); if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; diff -u --recursive --new-file v2.2.9/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c --- v2.2.9/linux/fs/ncpfs/dir.c Tue May 11 13:10:31 1999 +++ linux/fs/ncpfs/dir.c Fri May 14 12:43:13 1999 @@ -38,8 +38,7 @@ static int c_seen_eof; static int c_last_returned_index; static struct ncp_dirent *c_entry = NULL; -static int c_lock = 0; -static struct wait_queue *c_wait = NULL; +static struct semaphore c_sem = MUTEX; static int ncp_read_volume_list(struct ncp_server *, int, int, struct ncp_dirent *); @@ -230,15 +229,12 @@ static inline void ncp_lock_dircache(void) { - while (c_lock) - sleep_on(&c_wait); - c_lock = 1; + down(&c_sem); } static inline void ncp_unlock_dircache(void) { - c_lock = 0; - wake_up(&c_wait); + up(&c_sem); } @@ -354,16 +350,7 @@ int len = dentry->d_name.len; struct ncpfs_inode_info finfo; __u8 __name[dentry->d_name.len + 1]; - - if (!dentry->d_inode) { - DPRINTK(KERN_DEBUG "ncp_lookup_validate: called with dentry->d_inode already NULL.\n"); - return 0; - } - if (!dir || !S_ISDIR(dir->i_mode)) { - printk(KERN_WARNING "ncp_lookup_validate: inode is NULL or not a directory.\n"); - goto finished; - } server = NCP_SERVER(dir); if (!ncp_conn_valid(server)) diff -u --recursive --new-file v2.2.9/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c --- v2.2.9/linux/fs/ncpfs/file.c Wed Aug 26 11:37:41 1998 +++ linux/fs/ncpfs/file.c Fri May 14 12:43:13 1999 @@ -100,6 +100,8 @@ size_t already_read = 0; off_t pos; int bufsize, error; + void* freepage; + int freelen; DPRINTK(KERN_DEBUG "ncp_file_read: enter %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); @@ -135,16 +137,24 @@ bufsize = NCP_SERVER(inode)->buffer_size; + error = -EIO; + freelen = ncp_read_bounce_size(bufsize); + freepage = kmalloc(freelen, GFP_NFS); + if (!freepage) + goto out; + error = 0; /* First read in as much as possible for each bufsize. */ while (already_read < count) { int read_this_time; int to_read = min(bufsize - (pos % bufsize), count - already_read); - error = ncp_read(NCP_SERVER(inode), + error = ncp_read_bounce(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, - pos, to_read, buf, &read_this_time); + pos, to_read, buf, &read_this_time, + freepage, freelen); if (error) { + kfree(freepage); error = -EIO; /* This is not exact, i know.. */ goto out; } @@ -156,6 +166,7 @@ break; } } + kfree(freepage); file->f_pos = pos; @@ -177,6 +188,7 @@ size_t already_written = 0; off_t pos; int bufsize, errno; + void* bouncebuffer; DPRINTK(KERN_DEBUG "ncp_file_write: enter %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); @@ -210,14 +222,23 @@ already_written = 0; + bouncebuffer = kmalloc(bufsize, GFP_NFS); + if (!bouncebuffer) + return -EIO; /* -ENOMEM */ while (already_written < count) { int written_this_time; int to_write = min(bufsize - (pos % bufsize), count - already_written); - if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, - pos, to_write, buf, &written_this_time) != 0) { - return -EIO; + if (copy_from_user(bouncebuffer, buf, to_write)) { + errno = -EFAULT; + break; + } + if (ncp_write_kernel(NCP_SERVER(inode), + NCP_FINFO(inode)->file_handle, + pos, to_write, buf, &written_this_time) != 0) { + errno = -EIO; + break; } pos += written_this_time; buf += written_this_time; @@ -227,7 +248,7 @@ break; } } - + kfree(bouncebuffer); inode->i_mtime = inode->i_atime = CURRENT_TIME; file->f_pos = pos; diff -u --recursive --new-file v2.2.9/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c --- v2.2.9/linux/fs/ncpfs/inode.c Wed Apr 28 11:37:31 1999 +++ linux/fs/ncpfs/inode.c Fri May 14 12:43:13 1999 @@ -346,11 +346,12 @@ GFP_KERNEL); if (server == NULL) goto out_no_server; + memset(server, 0, sizeof(*server)); NCP_SBP(sb) = server; server->ncp_filp = ncp_filp; server->lock = 0; - server->wait = NULL; + sema_init(&server->sem, 1); server->packet = NULL; server->buffer_size = 0; server->conn_status = 0; @@ -687,7 +688,7 @@ if ((result = ncp_make_open(inode, O_RDWR)) < 0) { return -EACCES; } - ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, + ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, attr->ia_size, 0, "", &written); /* According to ndir, the changes only take effect after diff -u --recursive --new-file v2.2.9/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c --- v2.2.9/linux/fs/ncpfs/ioctl.c Wed Apr 28 11:37:31 1999 +++ linux/fs/ncpfs/ioctl.c Wed May 26 09:27:46 1999 @@ -33,6 +33,7 @@ int result; struct ncp_ioctl_request request; struct ncp_fs_info info; + char* bouncebuffer; #ifdef NCP_IOC_GETMOUNTUID_INT /* remove after ncpfs-2.0.13/2.2.0 gets released */ @@ -57,12 +58,9 @@ && (current->uid != server->m.mounted_uid)) { return -EACCES; } - if ((result = verify_area(VERIFY_READ, (char *) arg, - sizeof(request))) != 0) { - return result; - } - copy_from_user(&request, (struct ncp_ioctl_request *) arg, - sizeof(request)); + if (copy_from_user(&request, (struct ncp_ioctl_request *) arg, + sizeof(request))) + return -EFAULT; if ((request.function > 255) || (request.size > @@ -73,6 +71,13 @@ NCP_PACKET_SIZE)) != 0) { return result; } + bouncebuffer = kmalloc(NCP_PACKET_SIZE, GFP_NFS); + if (!bouncebuffer) + return -ENOMEM; + if (copy_from_user(bouncebuffer, request.data, request.size)) { + kfree(bouncebuffer); + return -EFAULT; + } ncp_lock_server(server); /* FIXME: We hack around in the server's structures @@ -80,17 +85,22 @@ server->has_subfunction = 0; server->current_size = request.size; - copy_from_user(server->packet, request.data, request.size); - - ncp_request(server, request.function); - - DPRINTK(KERN_DEBUG "ncp_ioctl: copy %d bytes\n", - server->reply_size); - copy_to_user(request.data, server->packet, server->reply_size); + memcpy(server->packet, bouncebuffer, request.size); + result = ncp_request2(server, request.function, + bouncebuffer, NCP_PACKET_SIZE); + if (result < 0) + result = -EIO; + else + result = server->reply_size; ncp_unlock_server(server); - - return server->reply_size; + DPRINTK(KERN_DEBUG "ncp_ioctl: copy %d bytes\n", + result); + if (result >= 0) + if (copy_to_user(request.data, bouncebuffer, result)) + result = -EFAULT; + kfree(bouncebuffer); + return result; case NCP_IOC_CONN_LOGGED_IN: diff -u --recursive --new-file v2.2.9/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c --- v2.2.9/linux/fs/ncpfs/mmap.c Wed Mar 10 15:29:49 1999 +++ linux/fs/ncpfs/mmap.c Fri May 14 12:43:13 1999 @@ -37,11 +37,10 @@ struct dentry *dentry = file->f_dentry; struct inode *inode = dentry->d_inode; unsigned long page; - unsigned int clear; - unsigned long tmp; + unsigned int already_read; + unsigned int count; int bufsize; int pos; - mm_segment_t fs; page = __get_free_page(GFP_KERNEL); if (!page) @@ -49,35 +48,24 @@ address &= PAGE_MASK; pos = address - area->vm_start + area->vm_offset; - clear = 0; + count = PAGE_SIZE; if (address + PAGE_SIZE > area->vm_end) { - clear = address + PAGE_SIZE - area->vm_end; + count = area->vm_end - address; } /* what we can read in one go */ bufsize = NCP_SERVER(inode)->buffer_size; - fs = get_fs(); - set_fs(get_ds()); - - if (ncp_make_open(inode, O_RDONLY) < 0) { - clear = PAGE_SIZE; - } else { - int already_read = 0; - int count = PAGE_SIZE - clear; - int to_read; - + already_read = 0; + if (ncp_make_open(inode, O_RDONLY) >= 0) { while (already_read < count) { int read_this_time; + int to_read; - if ((pos % bufsize) != 0) { - to_read = bufsize - (pos % bufsize); - } else { - to_read = bufsize; - } + to_read = bufsize - (pos % bufsize); to_read = min(to_read, count - already_read); - if (ncp_read(NCP_SERVER(inode), + if (ncp_read_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, pos, to_read, (char *) (page + already_read), @@ -94,12 +82,9 @@ } - set_fs(fs); - - tmp = page + PAGE_SIZE; - while (clear--) { - *(char *) --tmp = 0; - } + if (already_read < PAGE_SIZE) + memset((char*)(page + already_read), 0, + PAGE_SIZE - already_read); return page; } diff -u --recursive --new-file v2.2.9/linux/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c --- v2.2.9/linux/fs/ncpfs/ncplib_kernel.c Wed Apr 28 11:37:31 1999 +++ linux/fs/ncpfs/ncplib_kernel.c Fri May 14 12:43:13 1999 @@ -754,7 +754,7 @@ /* We have to transfer to/from user space */ int -ncp_read(struct ncp_server *server, const char *file_id, +ncp_read_kernel(struct ncp_server *server, const char *file_id, __u32 offset, __u16 to_read, char *target, int *bytes_read) { char *source; @@ -772,18 +772,27 @@ *bytes_read = ntohs(ncp_reply_word(server, 0)); source = ncp_reply_data(server, 2 + (offset & 1)); - result = -EFAULT; - if (!copy_to_user(target, source, *bytes_read)) - result = 0; + memcpy(target, source, *bytes_read); out: ncp_unlock_server(server); return result; } +/* There is a problem... egrep and some other silly tools do: + x = mmap(NULL, MAP_PRIVATE, PROT_READ|PROT_WRITE, , 32768); + read(, x, 32768); + Now copying read result by copy_to_user causes pagefault. This pagefault + could not be handled because of server was locked due to read. So we have + to use temporary buffer. So ncp_unlock_server must be done before + copy_to_user (and for write, copy_from_user must be done before + ncp_init_request... same applies for send raw packet ioctl). Because of + file is normally read in bigger chunks, caller provides kmalloced + (vmalloced) chunk of memory with size >= to_read... + */ int -ncp_write(struct ncp_server *server, const char *file_id, - __u32 offset, __u16 to_write, - const char *source, int *bytes_written) +ncp_read_bounce(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_read, char *target, int *bytes_read, + void* bounce, __u32 bufsize) { int result; @@ -791,46 +800,47 @@ ncp_add_byte(server, 0); ncp_add_mem(server, file_id, 6); ncp_add_dword(server, htonl(offset)); - ncp_add_word(server, htons(to_write)); - ncp_add_mem_fromfs(server, source, to_write); - - if ((result = ncp_request(server, 73)) != 0) - goto out; - *bytes_written = to_write; - result = 0; -out: + ncp_add_word(server, htons(to_read)); + result = ncp_request2(server, 72, bounce, bufsize); ncp_unlock_server(server); + if (!result) { + int len = be16_to_cpu(get_unaligned((__u16*)((char*)bounce + + sizeof(struct ncp_reply_header)))); + result = -EIO; + if (len <= to_read) { + char* source; + + source = (char*)bounce + + sizeof(struct ncp_reply_header) + 2 + + (offset & 1); + *bytes_read = len; + result = 0; + if (copy_to_user(target, source, len)) + result = -EFAULT; + } + } return result; } -#ifdef CONFIG_NCPFS_EXTRAS -int -ncp_read_kernel(struct ncp_server *server, const char *file_id, - __u32 offset, __u16 to_read, char *target, int *bytes_read) { - int error; - mm_segment_t old_fs; - - old_fs = get_fs(); - set_fs(get_ds()); - error = ncp_read(server, file_id, offset, to_read, target, bytes_read); - set_fs(old_fs); - return error; -} - int ncp_write_kernel(struct ncp_server *server, const char *file_id, __u32 offset, __u16 to_write, - const char *source, int *bytes_written) { - int error; - mm_segment_t old_fs; + const char *source, int *bytes_written) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_dword(server, htonl(offset)); + ncp_add_word(server, htons(to_write)); + ncp_add_mem(server, source, to_write); - old_fs = get_fs(); - set_fs(get_ds()); - error = ncp_write(server, file_id, offset, to_write, source, bytes_written); - set_fs(old_fs); - return error; + if ((result = ncp_request(server, 73)) == 0) + *bytes_written = to_write; + ncp_unlock_server(server); + return result; } -#endif #ifdef CONFIG_NCPFS_IOCTL_LOCKING int @@ -876,4 +886,5 @@ return 0; } #endif /* CONFIG_NCPFS_IOCTL_LOCKING */ + diff -u --recursive --new-file v2.2.9/linux/fs/ncpfs/ncplib_kernel.h linux/fs/ncpfs/ncplib_kernel.h --- v2.2.9/linux/fs/ncpfs/ncplib_kernel.h Wed Apr 28 11:37:31 1999 +++ linux/fs/ncpfs/ncplib_kernel.h Fri May 14 12:43:13 1999 @@ -32,20 +32,24 @@ #include #include +#define NCP_MIN_SYMLINK_SIZE 8 +#define NCP_MAX_SYMLINK_SIZE 512 + int ncp_negotiate_buffersize(struct ncp_server *, int, int *); int ncp_negotiate_size_and_options(struct ncp_server *server, int size, int options, int *ret_size, int *ret_options); int ncp_get_volume_info_with_number(struct ncp_server *, int, struct ncp_volume_info *); int ncp_close_file(struct ncp_server *, const char *); -int ncp_read(struct ncp_server *, const char *, __u32, __u16, char *, int *); -int ncp_write(struct ncp_server *, const char *, __u32, __u16, - const char *, int *); -#ifdef CONFIG_NCPFS_EXTRAS -int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, char *, int *); +static inline int ncp_read_bounce_size(__u32 size) { + return sizeof(struct ncp_reply_header) + 2 + 2 + size + 8; +}; +int ncp_read_bounce(struct ncp_server *, const char *, __u32, __u16, + char *, int *, void* bounce, __u32 bouncelen); +int ncp_read_kernel(struct ncp_server *, const char *, __u32, __u16, + char *, int *); int ncp_write_kernel(struct ncp_server *, const char *, __u32, __u16, const char *, int *); -#endif int ncp_obtain_info(struct ncp_server *server, struct inode *, char *, struct nw_info_struct *target); diff -u --recursive --new-file v2.2.9/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c --- v2.2.9/linux/fs/ncpfs/sock.c Mon Mar 29 11:09:12 1999 +++ linux/fs/ncpfs/sock.c Fri May 14 12:43:13 1999 @@ -83,7 +83,8 @@ #define NCP_SLACK_SPACE 1024 -static int do_ncp_rpc_call(struct ncp_server *server, int size) +static int do_ncp_rpc_call(struct ncp_server *server, int size, + struct ncp_reply_header* reply_buf, int max_reply_size) { struct file *file; struct inode *inode; @@ -276,7 +277,7 @@ * we have the correct reply, so read into the correct place and * return it */ - result = _recv(sock, (void *) start, server->packet_size, MSG_DONTWAIT); + result = _recv(sock, (void *)reply_buf, max_reply_size, MSG_DONTWAIT); if (result < 0) { printk(KERN_WARNING "NCP: notice message: result=%d\n", result); } else if (result < sizeof(struct ncp_reply_header)) { @@ -299,7 +300,8 @@ * We need the server to be locked here, so check! */ -static int ncp_do_request(struct ncp_server *server, int size) +static int ncp_do_request(struct ncp_server *server, int size, + void* reply, int max_reply_size) { int result; @@ -316,7 +318,7 @@ sign_packet(server, &size); } #endif /* CONFIG_NCPFS_PACKET_SIGNING */ - result = do_ncp_rpc_call(server, size); + result = do_ncp_rpc_call(server, size, reply, max_reply_size); DDPRINTK(KERN_DEBUG "do_ncp_rpc_call returned %d\n", result); @@ -332,10 +334,11 @@ * received. It assumes that server->current_size contains the ncp * request size */ -int ncp_request(struct ncp_server *server, int function) +int ncp_request2(struct ncp_server *server, int function, + void* rpl, int size) { struct ncp_request_header *h; - struct ncp_reply_header *reply; + struct ncp_reply_header* reply = rpl; int request_size = server->current_size - sizeof(struct ncp_request_header); int result; @@ -357,12 +360,11 @@ h->task = 2; /* (current->pid) & 0xff; */ h->function = function; - result = ncp_do_request(server, request_size + sizeof(*h)); + result = ncp_do_request(server, request_size + sizeof(*h), reply, size); if (result < 0) { DPRINTK(KERN_WARNING "ncp_request_error: %d\n", result); goto out; } - reply = (struct ncp_reply_header *) (server->packet); server->completion = reply->completion_code; server->conn_status = reply->connection_state; server->reply_size = result; @@ -393,7 +395,7 @@ h->task = 2; /* see above */ h->function = 0; - result = ncp_do_request(server, sizeof(*h)); + result = ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); if (result < 0) goto out; server->sequence = 0; @@ -417,7 +419,7 @@ h->task = 2; /* see above */ h->function = 0; - return ncp_do_request(server, sizeof(*h)); + return ncp_do_request(server, sizeof(*h), server->packet, server->packet_size); } void ncp_lock_server(struct ncp_server *server) @@ -428,16 +430,18 @@ DPRINTK(KERN_WARNING "ncpfs: server locked!!!\n"); } #endif - while (server->lock) - sleep_on(&server->wait); + down(&server->sem); + if (server->lock) + printk(KERN_WARNING "ncp_lock_server: was locked!\n"); server->lock = 1; } void ncp_unlock_server(struct ncp_server *server) { - if (server->lock != 1) { + if (!server->lock) { printk(KERN_WARNING "ncp_unlock_server: was not locked!\n"); + return; } server->lock = 0; - wake_up(&server->wait); + up(&server->sem); } diff -u --recursive --new-file v2.2.9/linux/fs/select.c linux/fs/select.c --- v2.2.9/linux/fs/select.c Wed Jan 20 23:14:06 1999 +++ linux/fs/select.c Sun May 23 23:54:52 1999 @@ -268,8 +268,12 @@ } ret = -EINVAL; - if (n < 0 || n > KFDS_NR) + if (n < 0) goto out_nofds; + + if (n > KFDS_NR) + n = KFDS_NR; + /* * We need 6 bitmaps (in/out/ex for both incoming and outgoing), * since we used fdset we need to allocate memory in units of diff -u --recursive --new-file v2.2.9/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c --- v2.2.9/linux/fs/smbfs/inode.c Mon Dec 28 15:00:53 1998 +++ linux/fs/smbfs/inode.c Sat May 29 11:11:02 1999 @@ -36,6 +36,7 @@ static void smb_delete_inode(struct inode *); static void smb_put_super(struct super_block *); static int smb_statfs(struct super_block *, struct statfs *, int); +static void smb_set_inode_attr(struct inode *, struct smb_fattr *); static struct super_operations smb_sops = { @@ -67,9 +68,7 @@ return ino; } -static struct smb_fattr *read_fattr = NULL; -static struct semaphore read_semaphore = MUTEX; - +/* We are always generating a new inode here */ struct inode * smb_iget(struct super_block *sb, struct smb_fattr *fattr) { @@ -77,11 +76,19 @@ pr_debug("smb_iget: %p\n", fattr); - down(&read_semaphore); - read_fattr = fattr; - result = iget(sb, fattr->f_ino); - read_fattr = NULL; - up(&read_semaphore); + result = get_empty_inode(); + result->i_sb = sb; + result->i_dev = sb->s_dev; + result->i_ino = fattr->f_ino; + memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i)); + smb_set_inode_attr(result, fattr); + if (S_ISREG(result->i_mode)) + result->i_op = &smb_file_inode_operations; + else if (S_ISDIR(result->i_mode)) + result->i_op = &smb_dir_inode_operations; + else + result->i_op = NULL; + insert_inode_hash(result); return result; } @@ -147,24 +154,9 @@ static void smb_read_inode(struct inode *inode) { - pr_debug("smb_iget: %p\n", read_fattr); - - if (!read_fattr || inode->i_ino != read_fattr->f_ino) - { - printk("smb_read_inode called from invalid point\n"); - return; - } - - inode->i_dev = inode->i_sb->s_dev; - memset(&(inode->u.smbfs_i), 0, sizeof(inode->u.smbfs_i)); - smb_set_inode_attr(inode, read_fattr); - - if (S_ISREG(inode->i_mode)) - inode->i_op = &smb_file_inode_operations; - else if (S_ISDIR(inode->i_mode)) - inode->i_op = &smb_dir_inode_operations; - else - inode->i_op = NULL; + /* Now it can be called only by NFS */ + printk("smb_read_inode called from invalid point\n"); + return; } /* @@ -608,8 +600,6 @@ smb_current_kmalloced = 0; smb_current_vmalloced = 0; #endif - - read_semaphore = MUTEX; return init_smb_fs(); } diff -u --recursive --new-file v2.2.9/linux/fs/super.c linux/fs/super.c --- v2.2.9/linux/fs/super.c Tue May 11 13:10:31 1999 +++ linux/fs/super.c Thu May 13 23:25:58 1999 @@ -952,16 +952,19 @@ if (!IS_ERR(dentry)) { struct super_block * sb = dentry->d_inode->i_sb; - retval = -EINVAL; - if (dentry == sb->s_root) { - /* - * Shrink the dcache and sync the device. - */ - shrink_dcache_sb(sb); - fsync_dev(sb->s_dev); - if (flags & MS_RDONLY) - acct_auto_close(sb->s_dev); - retval = do_remount_sb(sb, flags, data); + retval = -ENODEV; + if (sb) { + retval = -EINVAL; + if (dentry == sb->s_root) { + /* + * Shrink the dcache and sync the device. + */ + shrink_dcache_sb(sb); + fsync_dev(sb->s_dev); + if (flags & MS_RDONLY) + acct_auto_close(sb->s_dev); + retval = do_remount_sb(sb, flags, data); + } } dput(dentry); } diff -u --recursive --new-file v2.2.9/linux/fs/sysv/namei.c linux/fs/sysv/namei.c --- v2.2.9/linux/fs/sysv/namei.c Tue May 11 13:10:31 1999 +++ linux/fs/sysv/namei.c Thu May 13 23:25:58 1999 @@ -144,8 +144,6 @@ *res_buf = NULL; *res_dir = NULL; - if (!dir) - return -ENOENT; sb = dir->i_sb; if (namelen > SYSV_NAMELEN) { if (sb->sv_truncate) @@ -334,8 +332,6 @@ struct buffer_head * bh; struct sysv_dir_entry * de; - if (!inode) - return 1; block = 0; bh = NULL; pos = offset = 2*SYSV_DIRSIZE; @@ -391,22 +387,16 @@ struct buffer_head * bh; struct sysv_dir_entry * de; - inode = NULL; - bh = sysv_find_entry(dir, dentry->d_name.name, - dentry->d_name.len, &de); + inode = dentry->d_inode; + bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); retval = -ENOENT; - if (!bh) + if (!bh || de->inode != inode->i_ino) goto end_rmdir; - inode = dentry->d_inode; if (!empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } - if (de->inode != inode->i_ino) { - retval = -ENOENT; - goto end_rmdir; - } if (!list_empty(&dentry->d_hash)) { retval = -EBUSY; goto end_rmdir; @@ -416,9 +406,9 @@ de->inode = 0; mark_buffer_dirty(bh, 1); inode->i_nlink=0; - mark_inode_dirty(inode); dir->i_nlink--; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; + mark_inode_dirty(inode); mark_inode_dirty(dir); d_delete(dentry); retval = 0; @@ -434,26 +424,11 @@ struct buffer_head * bh; struct sysv_dir_entry * de; -repeat: retval = -ENOENT; - inode = NULL; - bh = sysv_find_entry(dir, dentry->d_name.name, - dentry->d_name.len, &de); - if (!bh) - goto end_unlink; inode = dentry->d_inode; - - retval = -EPERM; - if (de->inode != inode->i_ino) { - brelse(bh); - current->counter = 0; - schedule(); - goto repeat; - } - if (de->inode != inode->i_ino) { - retval = -ENOENT; + bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); + if (!bh || de->inode != inode->i_ino) goto end_unlink; - } if (!inode->i_nlink) { printk("Deleting nonexistent file (%s:%lu), %d\n", kdevname(inode->i_dev), inode->i_ino, inode->i_nlink); @@ -572,12 +547,6 @@ (((struct sysv_dir_entry *) ((buffer) + 1*SYSV_DIRSIZE))->inode) /* - * rename uses retrying to avoid race-conditions: at least they should be minimal. - * it tries to allocate all the blocks, then sanity-checks, and if the sanity- - * checks fail, it tries to restart itself again. Very practical - no changes - * are done until we know everything works ok.. and then all the changes can be - * done in one fell swoop when we have claimed all the buffers needed. - * * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */ @@ -589,24 +558,15 @@ struct sysv_dir_entry * old_de, * new_de; int retval; - goto start_up; -try_again: - brelse(old_bh); - brelse(new_bh); - brelse(dir_bh); - current->counter = 0; - schedule(); -start_up: - old_inode = new_inode = NULL; - old_bh = new_bh = dir_bh = NULL; + old_inode = old_dentry->d_inode; + new_inode = new_dentry->d_inode; + new_bh = dir_bh = NULL; old_bh = sysv_find_entry(old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); retval = -ENOENT; - if (!old_bh) + if (!old_bh || old_de->inode != old_inode->i_ino) goto end_rename; - old_inode = old_dentry->d_inode; /* don't cross mnt-points */ retval = -EPERM; - new_inode = new_dentry->d_inode; new_bh = sysv_find_entry(new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de); if (new_bh) { @@ -628,7 +588,8 @@ if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino) goto end_rename; retval = -EMLINK; - if (!new_inode && new_dir->i_nlink >= new_dir->i_sb->sv_link_max) + if (!new_inode && new_dir != old_dir && + new_dir->i_nlink >= new_dir->i_sb->sv_link_max) goto end_rename; } if (!new_bh) { @@ -637,16 +598,8 @@ if (retval) goto end_rename; } -/* sanity checking before doing the rename - avoid races */ - if (new_inode && (new_de->inode != new_inode->i_ino)) - goto try_again; - if (new_de->inode && !new_inode) - goto try_again; - if (old_de->inode != old_inode->i_ino) - goto try_again; -/* ok, that's it */ - old_de->inode = 0; new_de->inode = old_inode->i_ino; + old_de->inode = 0; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(old_dir); new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME; diff -u --recursive --new-file v2.2.9/linux/include/asm-alpha/atomic.h linux/include/asm-alpha/atomic.h --- v2.2.9/linux/include/asm-alpha/atomic.h Mon Dec 28 15:00:53 1998 +++ linux/include/asm-alpha/atomic.h Sat May 22 13:42:53 1999 @@ -75,6 +75,7 @@ " mov %0,%2\n" " stl_c %0,%1\n" " beq %0,2f\n" + " mb\n" ".section .text2,\"ax\"\n" "2: br 1b\n" ".previous" @@ -92,6 +93,7 @@ " mov %0,%2\n" " stl_c %0,%1\n" " beq %0,2f\n" + " mb\n" ".section .text2,\"ax\"\n" "2: br 1b\n" ".previous" diff -u --recursive --new-file v2.2.9/linux/include/asm-alpha/bitops.h linux/include/asm-alpha/bitops.h --- v2.2.9/linux/include/asm-alpha/bitops.h Wed Sep 9 14:51:09 1998 +++ linux/include/asm-alpha/bitops.h Sat May 22 13:42:53 1999 @@ -90,6 +90,7 @@ " xor %0,%3,%0\n" " stl_c %0,%1\n" " beq %0,3f\n" + " mb\n" "2:\n" ".section .text2,\"ax\"\n" "3: br 1b\n" @@ -114,6 +115,7 @@ " xor %0,%3,%0\n" " stl_c %0,%1\n" " beq %0,3f\n" + " mb\n" "2:\n" ".section .text2,\"ax\"\n" "3: br 1b\n" @@ -137,6 +139,7 @@ " xor %0,%3,%0\n" " stl_c %0,%1\n" " beq %0,3f\n" + " mb\n" ".section .text2,\"ax\"\n" "3: br 1b\n" ".previous" @@ -172,7 +175,10 @@ extern inline unsigned long ffz(unsigned long word) { -#ifdef __alpha_cix__ +#if 0 && defined(__alpha_cix__) + /* Swine architects -- a year after they publish v3 of the + handbook, in the 21264 data sheet they quietly change CIX + to FIX and remove the spiffy counting instructions. */ /* Whee. EV6 can calculate it directly. */ unsigned long result; __asm__("ctlz %1,%0" : "=r"(result) : "r"(~word)); @@ -208,7 +214,10 @@ * of bits set) of a N-bit word */ -#ifdef __alpha_cix__ +#if 0 && defined(__alpha_cix__) +/* Swine architects -- a year after they publish v3 of the handbook, in + the 21264 data sheet they quietly change CIX to FIX and remove the + spiffy counting instructions. */ /* Whee. EV6 can calculate it directly. */ extern __inline__ unsigned long hweight64(unsigned long w) { diff -u --recursive --new-file v2.2.9/linux/include/asm-alpha/init.h linux/include/asm-alpha/init.h --- v2.2.9/linux/include/asm-alpha/init.h Thu Dec 31 10:29:02 1998 +++ linux/include/asm-alpha/init.h Fri May 14 12:41:17 1999 @@ -12,6 +12,6 @@ #define __FINIT .previous #define __INITDATA .section .data.init,"a" -#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES))) +#define __cacheline_aligned __attribute__((__aligned__(32))) #endif diff -u --recursive --new-file v2.2.9/linux/include/asm-alpha/irq.h linux/include/asm-alpha/irq.h --- v2.2.9/linux/include/asm-alpha/irq.h Wed Jan 13 15:00:43 1999 +++ linux/include/asm-alpha/irq.h Sat May 22 13:42:57 1999 @@ -92,7 +92,11 @@ } extern void disable_irq(unsigned int); +extern void disable_irq_nosync(unsigned int); extern void enable_irq(unsigned int); + +extern void irq_enter(int cpu, int irq); +extern void irq_exit(int cpu, int irq); struct pt_regs; extern void (*perf_irq)(unsigned long, struct pt_regs *); diff -u --recursive --new-file v2.2.9/linux/include/asm-alpha/mmu_context.h linux/include/asm-alpha/mmu_context.h --- v2.2.9/linux/include/asm-alpha/mmu_context.h Mon Mar 29 11:09:12 1999 +++ linux/include/asm-alpha/mmu_context.h Sat May 22 13:42:57 1999 @@ -107,7 +107,8 @@ if (mm) { unsigned long asn = asn_cache; - /* Check if our ASN is of an older version and thus invalid */ + /* Check if our ASN is of an older version, + or on a different CPU, and thus invalid */ if ((mm->context ^ asn) & ~HARDWARE_ASN_MASK) get_new_mmu_context(p, mm); } diff -u --recursive --new-file v2.2.9/linux/include/asm-alpha/smp.h linux/include/asm-alpha/smp.h --- v2.2.9/linux/include/asm-alpha/smp.h Thu Dec 31 10:29:02 1998 +++ linux/include/asm-alpha/smp.h Sat May 22 13:42:59 1999 @@ -4,22 +4,30 @@ #ifdef __SMP__ #include +#include #include struct cpuinfo_alpha { unsigned long loops_per_sec; - unsigned int next; unsigned long *pgd_cache; unsigned long *pte_cache; unsigned long pgtable_cache_sz; unsigned long ipi_count; -} __attribute__((aligned(32))); + unsigned long prof_multiplier; + unsigned long prof_counter; +} __cacheline_aligned; extern struct cpuinfo_alpha cpu_data[NR_CPUS]; #define PROC_CHANGE_PENALTY 20 -extern __volatile__ int cpu_number_map[NR_CPUS]; +/* Map from cpu id to sequential logical cpu number. This will only + not be idempotent when cpus failed to come on-line. */ +extern int cpu_number_map[NR_CPUS]; + +/* The reverse map from sequential logical cpu number to cpu id. */ +extern int __cpu_logical_map[NR_CPUS]; +#define cpu_logical_map(cpu) __cpu_logical_map[cpu] /* HACK: Cabrio WHAMI return value is bogus if more than 8 bits used.. :-( */ @@ -35,7 +43,6 @@ } #define smp_processor_id() (current->processor) -#define cpu_logical_map(cpu) (cpu) #endif /* __SMP__ */ diff -u --recursive --new-file v2.2.9/linux/include/asm-alpha/spinlock.h linux/include/asm-alpha/spinlock.h --- v2.2.9/linux/include/asm-alpha/spinlock.h Wed Jan 13 15:00:43 1999 +++ linux/include/asm-alpha/spinlock.h Sat May 22 13:42:59 1999 @@ -79,19 +79,20 @@ */ typedef struct { - volatile unsigned int lock; + volatile unsigned int lock /*__attribute__((aligned(32))) */; #if DEBUG_SPINLOCK - char debug_state, target_ipl, saved_ipl, on_cpu; + int on_cpu; + int line_no; void *previous; struct task_struct * task; + const char *base_file; #endif } spinlock_t; #if DEBUG_SPINLOCK -#define SPIN_LOCK_UNLOCKED (spinlock_t) {0, 1, 0, 0, 0, 0} +#define SPIN_LOCK_UNLOCKED (spinlock_t) {0, -1, 0, 0, 0, 0} #define spin_lock_init(x) \ - ((x)->lock = 0, (x)->target_ipl = 0, (x)->debug_state = 1, \ - (x)->previous = 0, (x)->task = 0) + ((x)->lock = 0, (x)->on_cpu = -1, (x)->previous = 0, (x)->task = 0) #else #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } #define spin_lock_init(x) ((x)->lock = 0) @@ -105,8 +106,11 @@ #if DEBUG_SPINLOCK extern void spin_unlock(spinlock_t * lock); -extern void spin_lock(spinlock_t * lock); -extern int spin_trylock(spinlock_t * lock); +extern void debug_spin_lock(spinlock_t * lock, const char *, int); +extern int debug_spin_trylock(spinlock_t * lock, const char *, int); + +#define spin_lock(LOCK) debug_spin_lock(LOCK, __BASE_FILE__, __LINE__) +#define spin_trylock(LOCK) debug_spin_trylock(LOCK, __BASE_FILE__, __LINE__) #define spin_lock_own(LOCK, LOCATION) \ do { \ @@ -161,7 +165,9 @@ /***********************************************************/ -typedef struct { volatile int write_lock:1, read_counter:31; } rwlock_t; +typedef struct { + volatile int write_lock:1, read_counter:31; +} /*__attribute__((aligned(32)))*/ rwlock_t; #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 } diff -u --recursive --new-file v2.2.9/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h --- v2.2.9/linux/include/asm-alpha/system.h Tue May 11 13:10:31 1999 +++ linux/include/asm-alpha/system.h Sat May 22 13:43:02 1999 @@ -147,6 +147,20 @@ #endif #endif +enum amask_enum { + AMASK_BWX = (1UL << 0), + AMASK_FIX = (1UL << 1), + AMASK_MAX = (1UL << 8), + AMASK_PRECISE_TRAP = (1UL << 9), +}; + +enum amask_enum { + AMASK_BWX = (1UL << 0), + AMASK_FIX = (1UL << 1), + AMASK_MAX = (1UL << 8), + AMASK_PRECISE_TRAP = (1UL << 9), +}; + #define amask(mask) \ ({ unsigned long __amask, __input = (mask); \ __asm__ ("amask %1,%0" : "=r"(__amask) : "rI"(__input)); \ @@ -282,6 +296,7 @@ " bis $31,%3,%1\n" " stl_c %1,%2\n" " beq %1,2f\n" + " mb\n" ".section .text2,\"ax\"\n" "2: br 1b\n" ".previous" @@ -300,6 +315,7 @@ " bis $31,%3,%1\n" " stq_c %1,%2\n" " beq %1,2f\n" + " mb\n" ".section .text2,\"ax\"\n" "2: br 1b\n" ".previous" diff -u --recursive --new-file v2.2.9/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h --- v2.2.9/linux/include/asm-arm/arch-ebsa285/irq.h Thu May 13 23:10:30 1999 +++ linux/include/asm-arm/arch-ebsa285/irq.h Thu May 13 23:16:21 1999 @@ -10,6 +10,7 @@ * 26-Jan-1999 PJB Don't use IACK on CATS * 16-Mar-1999 RMK Added autodetect of ISA PICs */ +#include #include #include #include diff -u --recursive --new-file v2.2.9/linux/include/asm-arm/arch-ebsa285/memory.h linux/include/asm-arm/arch-ebsa285/memory.h --- v2.2.9/linux/include/asm-arm/arch-ebsa285/memory.h Thu May 13 23:10:30 1999 +++ linux/include/asm-arm/arch-ebsa285/memory.h Thu May 13 23:16:21 1999 @@ -15,6 +15,8 @@ #ifndef __ASM_ARCH_MMU_H #define __ASM_ARCH_MMU_H +#include + #if defined(CONFIG_HOST_FOOTBRIDGE) /* diff -u --recursive --new-file v2.2.9/linux/include/linux/cyclades.h linux/include/linux/cyclades.h --- v2.2.9/linux/include/linux/cyclades.h Fri Apr 16 14:47:31 1999 +++ linux/include/linux/cyclades.h Mon May 24 22:38:02 1999 @@ -557,7 +557,8 @@ unsigned long event; unsigned long last_active; int count; /* # of fd on device */ - int x_break; + int breakon; + int breakoff; int blocked_open; /* # of blocked opens */ long session; /* Session of opening process */ long pgrp; /* pgrp of opening process */ diff -u --recursive --new-file v2.2.9/linux/include/linux/ncp.h linux/include/linux/ncp.h --- v2.2.9/linux/include/linux/ncp.h Wed Apr 28 11:37:31 1999 +++ linux/include/linux/ncp.h Fri May 14 12:43:13 1999 @@ -72,9 +72,6 @@ #define aDELETEINHIBIT (ntohl(1L<<(18-8))) #define aDONTCOMPRESS (nothl(1L<<(27-24))) -#define NCP_MIN_SYMLINK_SIZE 8 -#define NCP_MAX_SYMLINK_SIZE 512 - #define AR_READ (ntohs(0x0100)) #define AR_WRITE (ntohs(0x0200)) #define AR_EXCLUSIVE (ntohs(0x2000)) diff -u --recursive --new-file v2.2.9/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h --- v2.2.9/linux/include/linux/ncp_fs.h Wed Apr 28 11:37:31 1999 +++ linux/include/linux/ncp_fs.h Fri May 14 12:43:13 1999 @@ -248,7 +248,11 @@ int ncp_ioctl(struct inode *, struct file *, unsigned int, unsigned long); /* linux/fs/ncpfs/sock.c */ -int ncp_request(struct ncp_server *server, int function); +int ncp_request2(struct ncp_server *server, int function, + void* reply, int max_reply_size); +static int inline ncp_request(struct ncp_server *server, int function) { + return ncp_request2(server, function, server->packet, server->packet_size); +} int ncp_connect(struct ncp_server *server); int ncp_disconnect(struct ncp_server *server); void ncp_lock_server(struct ncp_server *server); diff -u --recursive --new-file v2.2.9/linux/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h --- v2.2.9/linux/include/linux/ncp_fs_sb.h Wed Apr 28 11:37:31 1999 +++ linux/include/linux/ncp_fs_sb.h Fri May 14 12:43:13 1999 @@ -8,6 +8,7 @@ #ifndef _NCP_FS_SB #define _NCP_FS_SB +#include #include #include @@ -44,7 +45,7 @@ receive replies */ int lock; /* To prevent mismatch in protocols. */ - struct wait_queue *wait; + struct semaphore sem; int current_size; /* for packet preparation */ int has_subfunction; diff -u --recursive --new-file v2.2.9/linux/include/linux/netdevice.h linux/include/linux/netdevice.h --- v2.2.9/linux/include/linux/netdevice.h Tue Mar 23 14:35:48 1999 +++ linux/include/linux/netdevice.h Sun May 16 18:28:41 1999 @@ -405,7 +405,7 @@ extern __inline__ void dev_lock_wait(void) { while (atomic_read(&dev_lockct)) { - current->counter = 0; + current->policy |= SCHED_YIELD; schedule(); } } diff -u --recursive --new-file v2.2.9/linux/include/net/irda/crc.h linux/include/net/irda/crc.h --- v2.2.9/linux/include/net/irda/crc.h Wed Jan 20 23:14:06 1999 +++ linux/include/net/irda/crc.h Sun May 30 10:17:03 1999 @@ -6,25 +6,28 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Tue Dec 15 22:18:53 1998 + * Modified at: Sun May 2 20:25:23 1999 * Modified by: Dag Brattli * ********************************************************************/ -#ifndef IR_CRC_H -#define IR_CRC_H +#ifndef IRDA_CRC_H +#define IRDA_CRC_H #include #define INIT_FCS 0xffff /* Initial FCS value */ #define GOOD_FCS 0xf0b8 /* Good final FCS value */ +extern __u16 const irda_crc16_table[]; + /* Recompute the FCS with one more character appended. */ -#define IR_FCS(fcs, c) (((fcs) >> 8) ^ irda_crc16_table[((fcs) ^ (c)) & 0xff]) +static inline __u16 irda_fcs(__u16 fcs, __u8 c) +{ + return (((fcs) >> 8) ^ irda_crc16_table[((fcs) ^ (c)) & 0xff]); +} /* Recompute the FCS with len bytes appended. */ unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len); - -extern __u16 const irda_crc16_table[]; #endif diff -u --recursive --new-file v2.2.9/linux/include/net/irda/dongle.h linux/include/net/irda/dongle.h --- v2.2.9/linux/include/net/irda/dongle.h Wed Mar 10 15:29:50 1999 +++ linux/include/net/irda/dongle.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Wed Oct 21 22:47:12 1998 - * Modified at: Sat Feb 6 07:37:49 1999 + * Modified at: Mon May 10 14:51:06 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -26,7 +26,6 @@ #define DONGLE_H #include -#include /* These are the currently known dongles */ typedef enum { @@ -35,7 +34,10 @@ ACTISYS_DONGLE, ACTISYS_PLUS_DONGLE, GIRBIL_DONGLE, + LITELINK_DONGLE, } DONGLE_T; + +struct irda_device; struct dongle { DONGLE_T type; diff -u --recursive --new-file v2.2.9/linux/include/net/irda/ircomm_common.h linux/include/net/irda/ircomm_common.h --- v2.2.9/linux/include/net/irda/ircomm_common.h Wed Apr 28 11:37:32 1999 +++ linux/include/net/irda/ircomm_common.h Sun May 30 10:17:03 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Takahide Higuchi * - * Copyright (c) 1998, Takahide Higuchi, , + * Copyright (c) 1998-1999, Takahide Higuchi, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -78,7 +78,7 @@ #define IRCOMM_MAGIC 0x434f4d4d #define COMM_INIT_CTRL_PARAM 3 /* length of initial control parameters */ #define COMM_HEADER 1 /* length of clen field */ -#define COMM_HEADER_SIZE (LAP_HEADER+LMP_HEADER+TTP_HEADER+COMM_HEADER) +#define COMM_HEADER_SIZE (TTP_MAX_HEADER+COMM_HEADER) #define COMM_DEFAULT_DATA_SIZE 64 #define IRCOMM_MAX_CONNECTION 1 /* Don't change for now */ @@ -167,7 +167,7 @@ #define LSR_BI 0x01 /* Break interrupt indicator */ -struct ircomm_cb{ +struct ircomm_cb { int magic; int state; /* Current state of IrCOMM layer: * DISCOVERY,COMM_IDLE, COMM_WAITR, @@ -178,7 +178,8 @@ int ttp_stop; int max_txbuff_size; - __u32 maxsdusize; + __u32 max_sdu_size; + __u8 max_header_size; __u32 daddr; /* Device address of the peer device */ __u32 saddr; @@ -211,8 +212,6 @@ int pending_control_tuples; int ignored_control_tuples; - - __u8 pi ; /* instruction of control channel*/ __u8 port_type; @@ -252,8 +251,6 @@ char port_name[33]; int port_name_critical; }; - - void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype); void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irda.h linux/include/net/irda/irda.h --- v2.2.9/linux/include/net/irda/irda.h Wed Apr 28 11:37:32 1999 +++ linux/include/net/irda/irda.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:13:12 1997 - * Modified at: Wed Apr 21 17:49:00 1999 + * Modified at: Mon May 10 09:51:13 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -109,6 +109,8 @@ __u32 max_sdu_size_rx; __u32 max_sdu_size_tx; + __u32 max_data_size; + __u8 max_header_size; struct qos_info qos_tx; __u16 mask; /* Hint bits mask */ @@ -225,10 +227,10 @@ int (*udata_indication)(void *priv, void *sap, struct sk_buff *skb); void (*connect_confirm)(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, - struct sk_buff *skb); + __u8 max_header_size, struct sk_buff *skb); void (*connect_indication)(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, - struct sk_buff *skb); + __u8 max_header_size, struct sk_buff *skb); void (*disconnect_indication)(void *instance, void *sap, LM_REASON reason, struct sk_buff *); void (*flow_indication)(void *instance, void *sap, LOCAL_FLOW flow); diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h --- v2.2.9/linux/include/net/irda/irda_device.h Wed Apr 28 11:37:32 1999 +++ linux/include/net/irda/irda_device.h Sun May 30 10:17:03 1999 @@ -4,24 +4,29 @@ * Version: * Description: * Status: Experimental. - * Author: Haris Zukanovic + * Author: Dag Brattli * Created at: Tue Apr 14 12:41:42 1998 - * Modified at: Tue Apr 20 11:06:28 1999 + * Modified at: Mon May 10 15:46:02 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Haris Zukanovic, - * Copyright (c) 1998 Dag Brattli, + * Copyright (c) 1999 Dag Brattli, All Rights Reserved. * Copyright (c) 1998 Thomas Davis, , - * All Rights Reserved. - * + * Copyright (c) 1998 Haris Zukanovic, + * * 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. - * - * Neither Haris Zukanovic nor University of Tromsø admit liability nor - * provide warranty for any of this software. This material is - * provided "AS-IS" and at no charge. + * + * 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 * ********************************************************************/ @@ -35,6 +40,7 @@ #include #include +#include #include #include @@ -52,6 +58,11 @@ #define IO_XMIT 0x01 #define IO_RECV 0x02 +struct dongle_q { + QUEUE q; + struct dongle *dongle; +}; + /* Chip specific info */ struct chipio_t { int iobase, iobase2; /* IO base */ @@ -111,6 +122,8 @@ struct iobuff_t tx_buff; struct iobuff_t rx_buff; + struct dongle *dongle; /* Dongle driver */ + /* spinlock_t lock; */ /* For serializing operations */ /* Media busy stuff */ @@ -120,7 +133,8 @@ /* Callbacks for driver specific implementation */ void (*change_speed)(struct irda_device *driver, int baud); int (*is_receiving)(struct irda_device *); /* receiving? */ - /* int (*is_tbusy)(struct irda_device *); */ /* transmitting? */ + void (*set_dtr_rts)(struct irda_device *idev, int dtr, int rts); + int (*raw_write)(struct irda_device *idev, __u8 *buf, int len); void (*wait_until_sent)(struct irda_device *); void (*set_caddr)(struct irda_device *); /* Set connection addr */ }; @@ -142,6 +156,9 @@ inline struct qos_info *irda_device_get_qos(struct irda_device *self); int irda_device_txqueue_empty(struct irda_device *self); +void irda_device_init_dongle(struct irda_device *self, int type); +void irda_device_unregister_dongle(struct dongle *dongle); +int irda_device_register_dongle(struct dongle *dongle); int irda_device_setup(struct device *dev); @@ -153,7 +170,7 @@ * Utility function for getting the minimum turnaround time out of * the skb, where it has been hidden in the cb field. */ -inline static __u16 irda_get_mtt(struct sk_buff *skb) +extern inline __u16 irda_get_mtt(struct sk_buff *skb) { __u16 mtt; @@ -165,6 +182,23 @@ ASSERT(mtt <= 10000, return 10000;); return mtt; +} + +extern inline void irda_device_set_dtr_rts(struct irda_device *self, int dtr, + int rts) +{ + if (self->set_dtr_rts) + self->set_dtr_rts(self, dtr, rts); +} + +extern inline int irda_device_raw_write(struct irda_device *self, __u8 *buf, + int len) +{ + int ret = -1; + + if (self->raw_write) + ret = self->raw_write(self, buf, len); + return ret; } #endif diff -u --recursive --new-file v2.2.9/linux/include/net/irda/iriap.h linux/include/net/irda/iriap.h --- v2.2.9/linux/include/net/irda/iriap.h Wed Apr 28 11:37:32 1999 +++ linux/include/net/irda/iriap.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Aug 21 00:02:07 1997 - * Modified at: Wed Apr 21 16:37:21 1999 + * Modified at: Sun May 9 10:56:57 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * Copyright (c) 1997, 1999 Dag Brattli , All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -81,6 +81,8 @@ CONFIRM_CALLBACK confirm; void *priv; + __u8 max_header_size; + struct timer_list watchdog_timer; }; @@ -92,8 +94,6 @@ void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb); void iriap_send_ack( struct iriap_cb *self); -void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb); void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb); void iriap_register_server(void); diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irlan_common.h linux/include/net/irda/irlan_common.h --- v2.2.9/linux/include/net/irda/irlan_common.h Wed Apr 28 11:37:32 1999 +++ linux/include/net/irda/irlan_common.h Sun May 30 10:17:03 1999 @@ -6,10 +6,11 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 14:30:37 1999 + * Modified at: Sun May 9 11:45:33 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -98,7 +99,7 @@ #define IRLAN_SHORT 1 #define IRLAN_ARRAY 2 -#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER) +#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_MAX_HEADER) /* * IrLAN client @@ -109,7 +110,10 @@ int open_retries; struct tsap_cb *tsap_ctrl; + __u32 max_sdu_size; + __u8 max_header_size; + int access_type; /* Access type of provider */ __u8 reconnect_key[255]; __u8 key_len; @@ -130,6 +134,8 @@ int state; struct tsap_cb *tsap_ctrl; + __u32 max_sdu_size; + __u8 max_header_size; /* * Store some values here which are used by the provider to parse @@ -140,42 +146,45 @@ int filter_mode; int filter_operation; int filter_entry; - + int access_type; /* Access type */ __u16 send_arb_val; __u8 mac_address[6]; /* Generated MAC address for peer device */ }; /* - * IrLAN + * IrLAN control block */ struct irlan_cb { QUEUE queue; /* Must be first */ int magic; char ifname[9]; - struct device dev; /* Ethernet device structure*/ + struct device dev; /* Ethernet device structure*/ struct enet_statistics stats; - __u32 saddr; /* Source devcie address */ - __u32 daddr; /* Destination device address */ + __u32 saddr; /* Source devcie address */ + __u32 daddr; /* Destination device address */ int netdev_registered; int notify_irmanager; - int media; /* Media type */ - int access_type; /* Currently used access type */ - __u8 version[2]; /* IrLAN version */ + int media; /* Media type */ + __u8 version[2]; /* IrLAN version */ struct tsap_cb *tsap_data; - int use_udata; /* Use Unit Data transfers */ + int master; /* Master instance? */ + int use_udata; /* Use Unit Data transfers */ - __u8 stsap_sel_data; /* Source data TSAP selector */ - __u8 dtsap_sel_data; /* Destination data TSAP selector */ - __u8 dtsap_sel_ctrl; /* Destination ctrl TSAP selector */ + __u8 stsap_sel_data; /* Source data TSAP selector */ + __u8 dtsap_sel_data; /* Destination data TSAP selector */ + __u8 dtsap_sel_ctrl; /* Destination ctrl TSAP selector */ - struct irlan_client_cb client; /* Client specific fields */ + struct irlan_client_cb client; /* Client specific fields */ struct irlan_provider_cb provider; /* Provider specific fields */ + + __u32 max_sdu_size; + __u8 max_header_size; struct timer_list watchdog_timer; }; diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irlan_provider.h linux/include/net/irda/irlan_provider.h --- v2.2.9/linux/include/net/irda/irlan_provider.h Wed Apr 28 11:37:32 1999 +++ linux/include/net/irda/irlan_provider.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 14:29:16 1999 + * Modified at: Sun May 9 12:26:11 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -36,13 +36,7 @@ LM_REASON reason, struct sk_buff *skb); -void irlan_provider_ctrl_data_indication(void *instance, void *sap, - struct sk_buff *skb); -void irlan_provider_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 max_sdu_size, - struct sk_buff *skb); void irlan_provider_connect_response(struct irlan_cb *, struct tsap_cb *); int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb); diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h --- v2.2.9/linux/include/net/irda/irlap.h Wed Apr 28 11:37:32 1999 +++ linux/include/net/irda/irlap.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Fri Apr 23 09:51:15 1999 + * Modified at: Sun May 9 11:38:18 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -42,11 +42,11 @@ #define LAP_COMP_HEADER 1 /* IrLAP Compression Header */ #ifdef CONFIG_IRDA_COMPRESSION -# define LAP_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER) +# define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER) # define IRDA_COMPRESSED 1 # define IRDA_NORMAL 0 #else -#define LAP_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER) +#define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER) #endif #define BROADCAST 0xffffffff /* Broadcast device address */ @@ -138,7 +138,7 @@ __u8 vs; /* Next frame to be sent */ __u8 vr; /* Next frame to be received */ - int tmp; +/* int tmp; */ __u8 va; /* Last frame acked */ int window; /* Nr of I-frames allowed to send */ int window_size; /* Current negotiated window size */ @@ -155,8 +155,7 @@ __u8 s; /* Current slot */ int frame_sent; /* Have we sent reply? */ - int discovery_count; - hashbin_t *discovery_log; + hashbin_t *discovery_log; discovery_t *discovery_cmd; struct qos_info qos_tx; /* QoS requested by peer */ @@ -226,5 +225,10 @@ void irlap_init_qos_capabilities(struct irlap_cb *, struct qos_info *); void irlap_apply_default_connection_parameters(struct irlap_cb *self); void irlap_apply_connection_parameters(struct irlap_cb *, struct qos_info *); + +extern inline __u8 irlap_get_header_size(struct irlap_cb *self) +{ + return 2; +} #endif diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h --- v2.2.9/linux/include/net/irda/irlmp.h Wed Apr 28 11:37:32 1999 +++ linux/include/net/irda/irlmp.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 17 20:54:32 1997 - * Modified at: Fri Apr 23 09:15:07 1999 + * Modified at: Sun May 9 11:01:34 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -52,7 +52,7 @@ #define LMP_HEADER 2 /* Dest LSAP + Source LSAP */ #define LMP_CONTROL_HEADER 4 -#define LMP_MAX_HEADER (LAP_HEADER+LMP_HEADER) +#define LMP_MAX_HEADER (LMP_CONTROL_HEADER+LAP_MAX_HEADER) #define LM_MAX_CONNECTIONS 10 diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irlpt_common.h linux/include/net/irda/irlpt_common.h --- v2.2.9/linux/include/net/irda/irlpt_common.h Wed Mar 10 15:29:50 1999 +++ linux/include/net/irda/irlpt_common.h Sun May 30 10:17:03 1999 @@ -158,7 +158,8 @@ struct miscdevice ir_dev; /* used to register the misc device. */ int count; /* open count */ - int irlap_data_size; /* max frame size we can send */ + int max_data_size; /* max frame size we can send */ + int max_header_size; /* how much header space is needed */ int pkt_count; /* how many packets are queued up */ struct wait_queue *read_wait; /* wait queues */ diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irport.h linux/include/net/irda/irport.h --- v2.2.9/linux/include/net/irda/irport.h Wed Jan 20 23:14:06 1999 +++ linux/include/net/irda/irport.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 3 13:49:59 1997 - * Modified at: Thu Jan 7 14:17:31 1999 + * Modified at: Mon May 10 22:12:56 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997, 1998 Dag Brattli + * Copyright (c) 1997, 1998-1999 Dag Brattli * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -49,13 +49,13 @@ #define FRAME_MAX_SIZE 2048 -void irport_close( int iobase); -int irport_open( int iobase); -int irport_detect(struct irda_device *idev); +void irport_start(int iobase); +void irport_stop(int iobase); +int irport_probe(int iobase); -void irport_change_speed( int iobase, int speed); +void irport_change_speed(struct irda_device *idev, int speed); void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs); -int irport_hard_xmit( struct sk_buff *skb, struct device *dev); +int irport_hard_xmit(struct sk_buff *skb, struct device *dev); #endif diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irttp.h linux/include/net/irda/irttp.h --- v2.2.9/linux/include/net/irda/irttp.h Wed Apr 28 11:37:32 1999 +++ linux/include/net/irda/irttp.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:31 1997 - * Modified at: Sat Apr 10 10:19:56 1999 + * Modified at: Mon May 10 19:14:51 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -36,7 +36,8 @@ #define TTP_MAX_CONNECTIONS LM_MAX_CONNECTIONS #define TTP_HEADER 1 -#define TTP_HEADER_WITH_SAR 6 +#define TTP_MAX_HEADER (TTP_HEADER + LMP_MAX_HEADER) +#define TTP_SAR_HEADER 5 #define TTP_PARAMETERS 0x80 #define TTP_MORE 0x80 @@ -61,8 +62,6 @@ QUEUE queue; /* For linking it into the hashbin */ int magic; /* Just in case */ - int max_seg_size; /* Max data that fit into an IrLAP frame */ - __u8 stsap_sel; /* Source TSAP */ __u8 dtsap_sel; /* Destination TSAP */ @@ -88,6 +87,9 @@ struct irda_statistics stats; struct timer_list todo_timer; + __u32 max_seg_size; /* Max data that fit into an IrLAP frame */ + __u8 max_header_size; + int rx_sdu_busy; /* RxSdu.busy */ __u32 rx_sdu_size; /* Current size of a partially received frame */ __u32 rx_max_sdu_size; /* Max receive user data size */ @@ -120,8 +122,6 @@ __u32 saddr, __u32 daddr, struct qos_info *qos, __u32 max_sdu_size, struct sk_buff *userdata); -void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb); void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, struct sk_buff *userdata); struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance); diff -u --recursive --new-file v2.2.9/linux/include/net/irda/irtty.h linux/include/net/irda/irtty.h --- v2.2.9/linux/include/net/irda/irtty.h Wed Mar 10 15:29:50 1999 +++ linux/include/net/irda/irtty.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:13:12 1997 - * Modified at: Sun Feb 7 01:57:33 1999 + * Modified at: Mon May 10 13:22:23 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -33,8 +33,6 @@ #include #include -#include - #define IRTTY_IOC_MAGIC 'e' #define IRTTY_IOCTDONGLE _IO(IRTTY_IOC_MAGIC, 1) #define IRTTY_IOC_MAXNR 1 @@ -43,28 +41,21 @@ #define N_IRDA 11 /* This one should go in */ #endif -struct dongle_q { - QUEUE q; - - struct dongle *dongle; -}; - struct irtty_cb { QUEUE q; /* Must be first */ -/* char name[16]; */ - int magic; struct tty_struct *tty; /* Ptr to TTY structure */ struct irda_device idev; - - struct dongle_q *dongle_q; /* Has this tty got a dongle attached? */ }; -int irtty_register_dongle( struct dongle *dongle); -void irtty_unregister_dongle( struct dongle *dongle); - -void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts); +int irtty_register_dongle(struct dongle *dongle); +void irtty_unregister_dongle(struct dongle *dongle); #endif + + + + + diff -u --recursive --new-file v2.2.9/linux/include/net/irda/toshoboe.h linux/include/net/irda/toshoboe.h --- v2.2.9/linux/include/net/irda/toshoboe.h Wed Dec 31 16:00:00 1969 +++ linux/include/net/irda/toshoboe.h Sun May 30 10:17:03 1999 @@ -0,0 +1,165 @@ +/********************************************************************* + * + * Filename: toshoboe.h + * Version: 0.1 + * Description: Driver for the Toshiba OBOE (or type-O) + * FIR Chipset. + * Status: Experimental. + * Author: James McKenzie + * Created at: Sat May 8 12:35:27 1999 + * + * Copyright (c) 1999 James McKenzie, All Rights Reserved. + * + * 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. + * + * Neither James McKenzie nor Cambridge University admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + * Applicable Models : Libretto 100CT. and many more + * + ********************************************************************/ + +/* + * $Log: toshoboe.h,v $ + * Revision 1.2 1999/05/09 01:43:08 root + * *** empty log message *** + * + * Revision 1.1 1999/05/09 01:25:58 root + * Initial revision + * + */ + +#ifndef TOSHOBOE_H +#define TOSHOBOE_H + +/* Registers */ +/*Receive and transmit task registers (read only) */ +#define OBOE_RCVT (0x00+(self->base)) +#define OBOE_XMTT (0x01+(self->base)) +#define OBOE_XMTT_OFFSET 0x40 + +/*Page pointers to the TaskFile structure */ +#define OBOE_TFP2 (0x02+(self->base)) +#define OBOE_TFP0 (0x04+(self->base)) +#define OBOE_TFP1 (0x05+(self->base)) + +/*Dunno */ +#define OBOE_REG_3 (0x03+(self->base)) + +/*Number of tasks to use in Xmit and Recv queues */ +#define OBOE_NTR (0x07+(self->base)) +#define OBOE_NTR_XMIT4 0x00 +#define OBOE_NTR_XMIT8 0x10 +#define OBOE_NTR_XMIT16 0x30 +#define OBOE_NTR_XMIT32 0x70 +#define OBOE_NTR_XMIT64 0xf0 +#define OBOE_NTR_RECV4 0x00 +#define OBOE_NTR_RECV8 0x01 +#define OBOE_NTR_RECV6 0x03 +#define OBOE_NTR_RECV32 0x07 +#define OBOE_NTR_RECV64 0x0f + +/* Dunno */ +#define OBOE_REG_9 (0x09+(self->base)) + +/* Interrupt Status Register */ +#define OBOE_ISR (0x0c+(self->base)) +#define OBOE_ISR_TXDONE 0x80 +#define OBOE_ISR_RXDONE 0x40 +#define OBOE_ISR_20 0x20 +#define OBOE_ISR_10 0x10 +#define OBOE_ISR_8 0x08 /*This is collision or parity or something */ +#define OBOE_ISR_4 0x08 +#define OBOE_ISR_2 0x08 +#define OBOE_ISR_1 0x08 + +/*Dunno */ +#define OBOE_REG_D (0x0d+(self->base)) + +/*Register Lock Register */ +#define OBOE_LOCK ((self->base)+0x0e) + + + +/*Speed control registers */ +#define OBOE_PMDL (0x10+(self->base)) +#define OBOE_PMDL_SIR 0x18 +#define OBOE_PMDL_MIR 0xa0 +#define OBOE_PMDL_FIR 0x40 + +#define OBOE_SMDL (0x18+(self->base)) +#define OBOE_SMDL_SIR 0x20 +#define OBOE_SMDL_MIR 0x01 +#define OBOE_SMDL_FIR 0x0f + +#define OBOE_UDIV (0x19+(self->base)) + +/*Dunno */ +#define OBOE_REG_11 (0x11+(self->base)) + +/*Chip Reset Register */ +#define OBOE_RST (0x15+(self->base)) +#define OBOE_RST_WRAP 0x8 + +/*Dunno */ +#define OBOE_REG_1A (0x1a+(self->base)) +#define OBOE_REG_1B (0x1b+(self->base)) + +/* The PCI ID of the OBOE chip */ +#ifndef PCI_DEVICE_ID_FIR701 +#define PCI_DEVICE_ID_FIR701 0x0701 +#endif + +typedef unsigned int dword; +typedef unsigned short int word; +typedef unsigned char byte; +typedef dword Paddr; + +struct OboeTask + { + __u16 len; + __u8 unused; + __u8 control; + __u32 buffer; + }; + +#define OBOE_NTASKS 64 + +struct OboeTaskFile + { + struct OboeTask recv[OBOE_NTASKS]; + struct OboeTask xmit[OBOE_NTASKS]; + }; + +#define OBOE_TASK_BUF_LEN (sizeof(struct OboeTaskFile) << 1) + +/*These set the number of slots in use */ +#define TX_SLOTS 4 +#define RX_SLOTS 4 + +/* You need also to change this, toshiba uses 4,8 and 4,4 */ +/* It makes no difference if you are only going to use ONETASK mode */ +/* remember each buffer use XX_BUF_SZ more _PHYSICAL_ memory */ +#define OBOE_NTR_VAL (OBOE_NTR_XMIT4 | OBOE_NTR_RECV4) + +struct toshoboe_cb + { + struct irda_device idev; /*IRDA device */ + struct pci_dev *pdev; /*PCI device */ + int base; /*IO base */ + int txpending; /*how many tx's are pending */ + int txs, rxs; /*Which slots are we at */ + void *taskfilebuf; /*The unaligned taskfile buffer */ + struct OboeTaskFile *taskfile; /*The taskfile */ + void *xmit_bufs[TX_SLOTS]; /*The buffers */ + void *recv_bufs[RX_SLOTS]; + }; + + +#endif + + diff -u --recursive --new-file v2.2.9/linux/include/net/irda/w83977af_ir.h linux/include/net/irda/w83977af_ir.h --- v2.2.9/linux/include/net/irda/w83977af_ir.h Tue Dec 22 14:16:58 1998 +++ linux/include/net/irda/w83977af_ir.h Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Paul VanderSpek * Created at: Thu Nov 19 13:55:34 1998 - * Modified at: Thu Dec 10 14:06:18 1998 + * Modified at: Mon May 3 12:07:25 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -149,6 +149,29 @@ #define IRM_CR 0x07 /* Infrared module control register */ #define IRM_CR_IRX_MSL 0x40 #define IRM_CR_AF_MNT 0x80 /* Automatic format */ + +/* For storing entries in the status FIFO */ +struct st_fifo_entry { + int status; + int len; +}; + +struct st_fifo { + struct st_fifo_entry entries[10]; + int head; + int tail; + int len; +}; + +/* Private data for each instance */ +struct w83977af_ir { + struct st_fifo st_fifo; + + int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */ + int tx_len; /* Number of frames in tx_buff */ + + struct irda_device idev; +}; static inline void switch_bank( int iobase, int set) { diff -u --recursive --new-file v2.2.9/linux/include/net/irda/wrapper.h linux/include/net/irda/wrapper.h --- v2.2.9/linux/include/net/irda/wrapper.h Wed Mar 10 15:29:50 1999 +++ linux/include/net/irda/wrapper.h Sun May 30 10:17:03 1999 @@ -1,15 +1,16 @@ /********************************************************************* * * Filename: wrapper.h - * Version: 1.0 - * Description: IrDA Wrapper layer + * Version: 1.2 + * Description: IrDA SIR async wrapper layer * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Fri Jan 29 10:15:46 1999 + * Modified at: Mon May 3 09:02:36 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -38,17 +39,18 @@ #define STA BOF /* Start flag */ #define STO EOF /* End flag */ -#define IR_TRANS 0x20 /* Asynchronous transparency modifier */ +#define IRDA_TRANS 0x20 /* Asynchronous transparency modifier */ +/* States for receving a frame in async mode */ enum { - OUTSIDE_FRAME = 1, + OUTSIDE_FRAME, BEGIN_FRAME, LINK_ESCAPE, INSIDE_FRAME }; /* Proto definitions */ -int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize); -void async_unwrap_char( struct irda_device *, __u8 byte); +int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize); +inline void async_unwrap_char(struct irda_device *idev, __u8 byte); #endif diff -u --recursive --new-file v2.2.9/linux/net/core/filter.c linux/net/core/filter.c --- v2.2.9/linux/net/core/filter.c Mon Mar 29 11:09:12 1999 +++ linux/net/core/filter.c Sat May 15 17:43:52 1999 @@ -106,7 +106,7 @@ continue; case BPF_ALU|BPF_MUL|BPF_K: - A *= X; + A *= fentry->k; continue; case BPF_ALU|BPF_DIV|BPF_X: diff -u --recursive --new-file v2.2.9/linux/net/ipv4/ip_options.c linux/net/ipv4/ip_options.c --- v2.2.9/linux/net/ipv4/ip_options.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv4/ip_options.c Tue Jun 1 16:44:20 1999 @@ -452,7 +452,6 @@ error: if (skb) { icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24)); - kfree_skb(skb); } return -EINVAL; } diff -u --recursive --new-file v2.2.9/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.2.9/linux/net/ipv4/tcp.c Wed Apr 28 11:37:32 1999 +++ linux/net/ipv4/tcp.c Thu May 27 11:32:11 1999 @@ -896,6 +896,7 @@ err = -ERESTARTSYS; goto do_interrupted; } + tcp_push_pending_frames(sk, tp); wait_for_tcp_memory(sk); /* If SACK's were formed or PMTU events happened, diff -u --recursive --new-file v2.2.9/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.2.9/linux/net/ipv4/tcp_input.c Tue May 11 13:10:32 1999 +++ linux/net/ipv4/tcp_input.c Fri May 14 17:48:11 1999 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.164 1999/05/08 21:09:52 davem Exp $ + * Version: $Id: tcp_input.c,v 1.165 1999/05/14 23:10:08 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -748,7 +748,6 @@ static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp) { struct sk_buff *skb = skb_peek(&sk->write_queue); - __u32 when = tp->rto - (tcp_time_stamp - TCP_SKB_CB(skb)->when); /* Some data was ACK'd, if still retransmitting (due to a * timeout), resend more of the retransmit queue. The @@ -758,6 +757,9 @@ tcp_xmit_retransmit_queue(sk); tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto); } else { + __u32 when = tp->rto - (tcp_time_stamp - TCP_SKB_CB(skb)->when); + if ((__s32)when < 0) + when = 1; tcp_reset_xmit_timer(sk, TIME_RETRANS, when); } } @@ -785,8 +787,6 @@ if (after(ack, tp->snd_nxt) || before(ack, tp->snd_una)) goto uninteresting_ack; - dst_confirm(sk->dst_cache); - /* If there is data set flag 1 */ if (len != th->doff*4) { flag |= FLAG_DATA; @@ -882,6 +882,24 @@ /* Clear any aborted fast retransmit starts. */ tp->dup_acks = 0; } + /* It is not a brain fart, I thought a bit now. 8) + * + * Forward progress is indicated, if: + * 1. the ack acknowledges new data. + * 2. or the ack is duplicate, but it is caused by new segment + * arrival. This case is filtered by: + * - it contains no data, syn or fin. + * - it does not update window. + * 3. or new SACK. It is difficult to check, so that we ignore it. + * + * Forward progress is also indicated by arrival new data, + * which was caused by window open from our side. This case is more + * difficult and it is made (alas, incorrectly) in tcp_data_queue(). + * --ANK (990513) + */ + if (ack != tp->snd_una || (flag == 0 && !th->fin)) + dst_confirm(sk->dst_cache); + /* Remember the highest ack received. */ tp->snd_una = ack; return 1; @@ -2067,20 +2085,80 @@ * not be in line code. [AC] */ if(th->ack) { - tp->snd_wl1 = TCP_SKB_CB(skb)->seq; - - /* We got an ack, but it's not a good ack. */ - if(!tcp_ack(sk,th, TCP_SKB_CB(skb)->seq, - TCP_SKB_CB(skb)->ack_seq, len)) + /* rfc793: + * "If the state is SYN-SENT then + * first check the ACK bit + * If the ACK bit is set + * If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send + * a reset (unless the RST bit is set, if so drop + * the segment and return)" + * + * I cite this place to emphasize one essential + * detail, this check is different of one + * in established state: SND.UNA <= SEG.ACK <= SND.NXT. + * SEG_ACK == SND.UNA == ISS is invalid in SYN-SENT, + * because we have no previous data sent before SYN. + * --ANK(990513) + * + * We do not send data with SYN, so that RFC-correct + * test reduces to: + */ + if (sk->zapped || + TCP_SKB_CB(skb)->ack_seq != tp->snd_nxt) return 1; - if(th->rst) { + /* Now ACK is acceptable. + * + * "If the RST bit is set + * If the ACK was acceptable then signal the user "error: + * connection reset", drop the segment, enter CLOSED state, + * delete TCB, and return." + */ + + if (th->rst) { tcp_reset(sk); goto discard; } - if(!th->syn) + /* rfc793: + * "fifth, if neither of the SYN or RST bits is set then + * drop the segment and return." + * + * See note below! + * --ANK(990513) + */ + + if (!th->syn) goto discard; + + /* rfc793: + * "If the SYN bit is on ... + * are acceptable then ... + * (our SYN has been ACKed), change the connection + * state to ESTABLISHED..." + * + * Do you see? SYN-less ACKs in SYN-SENT state are + * completely ignored. + * + * The bug causing stalled SYN-SENT sockets + * was here: tcp_ack advanced snd_una and canceled + * retransmit timer, so that bare ACK received + * in SYN-SENT state (even with invalid ack==ISS, + * because tcp_ack check is too weak for SYN-SENT) + * causes moving socket to invalid semi-SYN-SENT, + * semi-ESTABLISHED state and connection hangs. + * + * There exist buggy stacks, which really send + * such ACKs: f.e. 202.226.91.94 (okigate.oki.co.jp) + * Actually, if this host did not try to get something + * from ftp.inr.ac.ru I'd never find this bug 8) + * + * --ANK (990514) + */ + + tp->snd_wl1 = TCP_SKB_CB(skb)->seq; + tcp_ack(sk,th, TCP_SKB_CB(skb)->seq, + TCP_SKB_CB(skb)->ack_seq, len); /* Ok.. it's good. Set up sequence numbers and * move to established. diff -u --recursive --new-file v2.2.9/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.2.9/linux/net/ipv4/tcp_output.c Tue May 11 13:10:32 1999 +++ linux/net/ipv4/tcp_output.c Fri May 14 17:48:11 1999 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.108 1999/05/08 21:48:59 davem Exp $ + * Version: $Id: tcp_output.c,v 1.109 1999/05/14 23:10:13 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -239,6 +239,11 @@ /* Rechecksum original buffer. */ skb->csum = csum_partial(skb->data, skb->len, 0); + + /* Looks stupid, but our code really uses when of + * skbs, which it never sent before. --ANK + */ + TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when; /* Link BUFF into the send queue. */ __skb_append(skb, buff); diff -u --recursive --new-file v2.2.9/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c --- v2.2.9/linux/net/ipv4/tcp_timer.c Tue May 11 13:10:32 1999 +++ linux/net/ipv4/tcp_timer.c Sat May 15 16:58:13 1999 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_timer.c,v 1.62 1999/05/08 21:09:55 davem Exp $ + * Version: $Id: tcp_timer.c,v 1.63 1999/05/15 23:02:21 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -541,10 +541,6 @@ prev = conn; continue; } - - if ((long)(now - conn->expires) <= 0) - break; - tcp_synq_unlink(tp, conn, prev); if (conn->retrans >= sysctl_tcp_retries1) { diff -u --recursive --new-file v2.2.9/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c --- v2.2.9/linux/net/ipv6/icmp.c Tue Mar 23 14:35:48 1999 +++ linux/net/ipv6/icmp.c Sat May 29 11:10:33 1999 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: icmp.c,v 1.21 1999/03/21 05:22:51 davem Exp $ + * $Id: icmp.c,v 1.21.2.1 1999/05/19 22:07:36 davem Exp $ * * Based on net/ipv4/icmp.c * @@ -315,6 +315,7 @@ fl.nl_u.ip6_u.daddr = &hdr->saddr; fl.nl_u.ip6_u.saddr = saddr; fl.oif = iif; + fl.fl6_flowlabel = 0; fl.uli_u.icmpt.type = type; fl.uli_u.icmpt.code = code; @@ -388,6 +389,7 @@ fl.nl_u.ip6_u.daddr = &hdr->saddr; fl.nl_u.ip6_u.saddr = saddr; fl.oif = skb->dev->ifindex; + fl.fl6_flowlabel = 0; fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY; fl.uli_u.icmpt.code = 0; diff -u --recursive --new-file v2.2.9/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.2.9/linux/net/ipv6/tcp_ipv6.c Wed Apr 28 11:37:32 1999 +++ linux/net/ipv6/tcp_ipv6.c Tue May 25 13:09:38 1999 @@ -551,7 +551,7 @@ failure: dst_release(xchg(&sk->dst_cache, NULL)); - memcpy(&np->daddr, 0, sizeof(struct in6_addr)); + memset(&np->daddr, 0, sizeof(struct in6_addr)); sk->daddr = 0; return err; } diff -u --recursive --new-file v2.2.9/linux/net/irda/af_irda.c linux/net/irda/af_irda.c --- v2.2.9/linux/net/irda/af_irda.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/af_irda.c Sun May 30 10:17:03 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun May 31 10:12:43 1998 - * Modified at: Thu Apr 22 12:08:04 1999 + * Modified at: Tue May 11 12:42:26 1999 * Modified by: Dag Brattli * Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc. * @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -46,11 +47,12 @@ extern int irlap_driver_rcv(struct sk_buff *, struct device *, struct packet_type *); -static struct proto_ops irda_proto_ops; +static struct proto_ops irda_stream_ops; +static struct proto_ops irda_dgram_ops; static hashbin_t *cachelog = NULL; static struct wait_queue *discovery_wait; /* Wait for discovery */ -#define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER) +#define IRDA_MAX_HEADER (TTP_MAX_HEADER) /* * Function irda_data_indication (instance, sap, skb) @@ -121,7 +123,8 @@ */ static void irda_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { struct irda_sock *self; struct sock *sk; @@ -130,13 +133,28 @@ self = (struct irda_sock *) instance; + /* How much header space do we need to reserve */ + self->max_header_size = max_header_size; + + /* IrTTP max SDU size in transmit direction */ self->max_sdu_size_tx = max_sdu_size; + + /* Find out what the largest chunk of data that we can transmit is */ + if (max_sdu_size == SAR_DISABLE) + self->max_data_size = qos->data_size.value - max_header_size; + else + self->max_data_size = max_sdu_size; + + DEBUG(0, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size); + memcpy(&self->qos_tx, qos, sizeof(struct qos_info)); sk = self->sk; if (sk == NULL) return; + skb_queue_tail(&sk->receive_queue, skb); + /* We are now connected! */ sk->state = TCP_ESTABLISHED; sk->state_change(sk); @@ -150,7 +168,7 @@ */ static void irda_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, - struct sk_buff *skb) + __u8 max_header_size, struct sk_buff *skb) { struct irda_sock *self; struct sock *sk; @@ -158,8 +176,21 @@ DEBUG(1, __FUNCTION__ "()\n"); self = (struct irda_sock *) instance; - - self->max_sdu_size_tx = max_sdu_size; + + /* How much header space do we need to reserve */ + self->max_header_size = max_header_size; + + /* IrTTP max SDU size in transmit direction */ + self->max_sdu_size_tx = max_sdu_size; + + /* Find out what the largest chunk of data that we can transmit is */ + if (max_sdu_size == SAR_DISABLE) + self->max_data_size = qos->data_size.value - max_header_size; + else + self->max_data_size = max_sdu_size; + + DEBUG(0, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size); + memcpy(&self->qos_tx, qos, sizeof(struct qos_info)); sk = self->sk; @@ -187,12 +218,12 @@ skb = dev_alloc_skb(64); if (skb == NULL) { - DEBUG( 0, __FUNCTION__ "() Could not allocate sk_buff!\n"); + DEBUG(0, __FUNCTION__ "() Unable to allocate sk_buff!\n"); return; } /* Reserve space for MUX_CONTROL and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, IRDA_MAX_HEADER); irttp_connect_response(self->tsap, self->max_sdu_size_rx, skb); } @@ -514,10 +545,13 @@ new->stsap_sel = new->tsap->stsap_sel; new->dtsap_sel = new->tsap->dtsap_sel; new->saddr = irttp_get_saddr(new->tsap); - new->saddr = irttp_get_saddr(new->tsap); + new->daddr = irttp_get_daddr(new->tsap); new->max_sdu_size_tx = self->max_sdu_size_tx; new->max_sdu_size_rx = self->max_sdu_size_rx; + new->max_data_size = self->max_data_size; + new->max_header_size = self->max_header_size; + memcpy(&new->qos_tx, &self->qos_tx, sizeof(struct qos_info)); /* Clean up the original one to keep it in listen state */ @@ -669,7 +703,7 @@ sock_init_data(sock, sk); - sock->ops = &irda_proto_ops; + sock->ops = &irda_stream_ops; sk->protocol = protocol; /* Register as a client with IrLMP */ @@ -786,12 +820,20 @@ return -ENOTCONN; } - skb = sock_alloc_send_skb(sk, len + IRDA_MAX_HEADER, 0, + /* Check that we don't send out to big frames */ + if (len > self->max_data_size) { + DEBUG(0, __FUNCTION__ "(), Warning to much data! " + "Chopping frame from %d to %d bytes!\n", len, + self->max_data_size); + len = self->max_data_size; + } + + skb = sock_alloc_send_skb(sk, len + self->max_header_size, 0, msg->msg_flags & MSG_DONTWAIT, &err); if (!skb) return -ENOBUFS; - skb_reserve(skb, IRDA_MAX_HEADER); + skb_reserve(skb, self->max_header_size); DEBUG(4, __FUNCTION__ "(), appending user data\n"); asmptr = skb->h.raw = skb_put(skb, len); @@ -815,8 +857,8 @@ * Try to receive message and copy it to user * */ -static int irda_recvmsg(struct socket *sock, struct msghdr *msg, int size, - int flags, struct scm_cookie *scm) +static int irda_recvmsg_dgram(struct socket *sock, struct msghdr *msg, + int size, int flags, struct scm_cookie *scm) { struct irda_sock *self; struct sock *sk = sock->sk; @@ -862,6 +904,161 @@ } /* + * Function irda_data_wait (sk) + * + * Sleep until data has arrive. But check for races.. + * + */ +static void irda_data_wait(struct sock *sk) +{ + if (!skb_peek(&sk->receive_queue)) { + sk->socket->flags |= SO_WAITDATA; + interruptible_sleep_on(sk->sleep); + sk->socket->flags &= ~SO_WAITDATA; + } +} + +/* + * Function irda_recvmsg_stream (sock, msg, size, flags, scm) + * + * + * + */ +static int irda_recvmsg_stream(struct socket *sock, struct msghdr *msg, + int size, int flags, struct scm_cookie *scm) +{ + struct irda_sock *self; + struct sock *sk = sock->sk; + int noblock = flags & MSG_DONTWAIT; + int copied = 0; + int target = 1; + + DEBUG(3, __FUNCTION__ "()\n"); + + self = sk->protinfo.irda; + ASSERT(self != NULL, return -1;); + + if (sock->flags & SO_ACCEPTCON) + return(-EINVAL); + + if (flags & MSG_OOB) + return -EOPNOTSUPP; + + if (flags & MSG_WAITALL) + target = size; + + + msg->msg_namelen = 0; + + /* Lock the socket to prevent queue disordering + * while sleeps in memcpy_tomsg + */ +/* down(&self->readsem); */ + + do { + int chunk; + struct sk_buff *skb; + + skb=skb_dequeue(&sk->receive_queue); + if (skb==NULL) { + if (copied >= target) + break; + + /* + * POSIX 1003.1g mandates this order. + */ + + if (sk->err) { + /* up(&self->readsem); */ + return sock_error(sk); + } + + if (sk->shutdown & RCV_SHUTDOWN) + break; + + /* up(&self->readsem); */ + + if (noblock) + return -EAGAIN; + irda_data_wait(sk); + if (signal_pending(current)) + return -ERESTARTSYS; + /* down(&self->readsem); */ + continue; + } + + /* Never glue messages from different writers */ +/* if (check_creds && */ +/* memcmp(UNIXCREDS(skb), &scm->creds, sizeof(scm->creds)) != 0) */ +/* { */ +/* skb_queue_head(&sk->receive_queue, skb); */ +/* break; */ +/* } */ + + chunk = min(skb->len, size); + if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { + skb_queue_head(&sk->receive_queue, skb); + if (copied == 0) + copied = -EFAULT; + break; + } + copied += chunk; + size -= chunk; + + /* Copy credentials */ +/* scm->creds = *UNIXCREDS(skb); */ +/* check_creds = 1; */ + + /* Mark read part of skb as used */ + if (!(flags & MSG_PEEK)) { + skb_pull(skb, chunk); + +/* if (UNIXCB(skb).fp) */ +/* unix_detach_fds(scm, skb); */ + + /* put the skb back if we didn't use it up.. */ + if (skb->len) { + DEBUG(1, __FUNCTION__ "(), back on q!\n"); + skb_queue_head(&sk->receive_queue, skb); + break; + } + + kfree_skb(skb); + +/* if (scm->fp) */ +/* break; */ + } else { + DEBUG(0, __FUNCTION__ "() questionable!?\n"); + /* It is questionable, see note in unix_dgram_recvmsg. */ +/* if (UNIXCB(skb).fp) */ +/* scm->fp = scm_fp_dup(UNIXCB(skb).fp); */ + + /* put message back and return */ + skb_queue_head(&sk->receive_queue, skb); + break; + } + } while (size); + + /* + * Check if we have previously stopped IrTTP and we know + * have more free space in our rx_queue. If so tell IrTTP + * to start delivering frames again before our rx_queue gets + * empty + */ + if (self->rx_flow == FLOW_STOP) { + if ((atomic_read(&sk->rmem_alloc) << 2) <= sk->rcvbuf) { + DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n"); + self->rx_flow = FLOW_START; + irttp_flow_request(self->tsap, FLOW_START); + } + } + + /* up(&self->readsem); */ + + return copied; +} + +/* * Function irda_shutdown (sk, how) * * @@ -875,19 +1072,45 @@ return -EOPNOTSUPP; } - /* * Function irda_poll (file, sock, wait) * * * */ -unsigned int irda_poll(struct file *file, struct socket *sock, - struct poll_table_struct *wait) +static unsigned int irda_poll(struct file * file, struct socket *sock, + poll_table *wait) { - DEBUG(0, __FUNCTION__ "()\n"); + struct sock *sk = sock->sk; + unsigned int mask; - return 0; + DEBUG(1, __FUNCTION__ "()\n"); + + poll_wait(file, sk->sleep, wait); + mask = 0; + + /* exceptional events? */ + if (sk->err) + mask |= POLLERR; + if (sk->shutdown & RCV_SHUTDOWN) + mask |= POLLHUP; + + /* readable? */ + if (!skb_queue_empty(&sk->receive_queue)) + mask |= POLLIN | POLLRDNORM; + + /* Connection-based need to check for termination and startup */ + if (sk->type == SOCK_STREAM && sk->state==TCP_CLOSE) + mask |= POLLHUP; + + /* + * we set writable also when the other side has shut down the + * connection. This prevents stuck sockets. + */ + if (sk->sndbuf - (int)atomic_read(&sk->wmem_alloc) >= MIN_WRITE_SPACE) + mask |= POLLOUT | POLLWRNORM | POLLWRBAND; + + return mask; } /* @@ -947,6 +1170,7 @@ return -EINVAL; default: + DEBUG(0, __FUNCTION__ "(), doing device ioctl!\n"); return dev_ioctl(cmd, (void *) arg); } @@ -1082,13 +1306,7 @@ return -EFAULT; break; case IRTTP_MAX_SDU_SIZE: - if (self->max_sdu_size_tx != SAR_DISABLE) - val = self->max_sdu_size_tx; - else - /* SAR is disabled, so use the IrLAP data size - * instead */ - val = self->qos_tx.data_size.value - IRDA_MAX_HEADER; - + val = self->max_data_size; DEBUG(0, __FUNCTION__ "(), getting max_sdu_size = %d\n", val); len = sizeof(int); if (put_user(len, optlen)) @@ -1110,7 +1328,7 @@ irda_create }; -static struct proto_ops irda_proto_ops = { +static struct proto_ops irda_stream_ops = { PF_IRDA, sock_no_dup, @@ -1128,7 +1346,28 @@ irda_getsockopt, sock_no_fcntl, irda_sendmsg, - irda_recvmsg + irda_recvmsg_stream +}; + +static struct proto_ops irda_dgram_ops = { + PF_IRDA, + + sock_no_dup, + irda_release, + irda_bind, + irda_connect, + sock_no_socketpair, + irda_accept, + irda_getname, + datagram_poll, + irda_ioctl, + irda_listen, + irda_shutdown, + irda_setsockopt, + irda_getsockopt, + sock_no_fcntl, + irda_sendmsg, + irda_recvmsg_dgram }; /* @@ -1215,7 +1454,7 @@ irda_packet_type.type = htons(ETH_P_IRDA); dev_remove_pack(&irda_packet_type); - unregister_netdevice_notifier( &irda_dev_notifier); + unregister_netdevice_notifier(&irda_dev_notifier); sock_unregister(PF_IRDA); irda_cleanup(); diff -u --recursive --new-file v2.2.9/linux/net/irda/crc.c linux/net/irda/crc.c --- v2.2.9/linux/net/irda/crc.c Tue Dec 22 14:16:59 1998 +++ linux/net/irda/crc.c Sun May 30 10:17:03 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Sat Dec 12 09:56:35 1998 + * Modified at: Sun May 2 20:28:08 1999 * Modified by: Dag Brattli * Sources: ppp.c by Michael Callahan * Al Longyear @@ -59,7 +59,7 @@ unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len) { - while ( len--) - fcs = IR_FCS(fcs, *buf++); - return fcs; + while (len--) + fcs = irda_fcs(fcs, *buf++); + return fcs; } diff -u --recursive --new-file v2.2.9/linux/net/irda/discovery.c linux/net/irda/discovery.c --- v2.2.9/linux/net/irda/discovery.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/discovery.c Sun May 30 10:17:03 1999 @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Apr 6 15:33:50 1999 - * Modified at: Sun Apr 11 00:41:58 1999 + * Modified at: Sun May 9 22:40:43 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -39,28 +39,51 @@ /* * Function irlmp_add_discovery (cachelog, discovery) * - * - * + * Add a new discovery to the cachelog, and remove any old discoveries + * from the same device */ -void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery) +void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new) { - discovery_t *old; + discovery_t *discovery, *node; + unsigned long flags; + + spin_lock_irqsave(&irlmp->lock, flags); - DEBUG(4, __FUNCTION__ "()\n"); + /* + * Remove all discoveries of devices that has previously been + * discovered on the same link with the same name (info), or the + * same daddr. We do this since some devices (mostly PDAs) change + * their device address between every discovery. + */ + discovery = (discovery_t *) hashbin_get_first(cachelog); + while (discovery != NULL ) { + node = discovery; + + /* Be sure to stay one item ahead */ + discovery = (discovery_t *) hashbin_get_next(cachelog); + + if ((node->daddr == new->daddr) || + (strcmp(node->info, new->info) == 0)) + { + /* This discovery is a previous discovery + * from the same device, so just remove it + */ + hashbin_remove(cachelog, node->daddr, NULL); + kfree(node); + } + } - /* Check if we have discovered this device before */ - old = hashbin_remove(cachelog, discovery->daddr, NULL); - if (old) - kfree(old); /* Insert the new and updated version */ - hashbin_insert(cachelog, (QUEUE *) discovery, discovery->daddr, NULL); + hashbin_insert(cachelog, (QUEUE *) new, new->daddr, NULL); + + spin_unlock_irqrestore(&irlmp->lock, flags); } /* * Function irlmp_add_discovery_log (cachelog, log) * - * + * Merge a disovery log into the cachlog. * */ void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log) diff -u --recursive --new-file v2.2.9/linux/net/irda/ircomm/ircomm_common.c linux/net/irda/ircomm/ircomm_common.c --- v2.2.9/linux/net/irda/ircomm/ircomm_common.c Tue May 11 13:10:32 1999 +++ linux/net/irda/ircomm/ircomm_common.c Sun May 30 10:17:03 1999 @@ -8,7 +8,7 @@ * Author: Takahide Higuchi * Source: irlpt_event.c * - * Copyright (c) 1998, Takahide Higuchi, , + * Copyright (c) 1998-1999, Takahide Higuchi, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -44,18 +44,17 @@ static char *revision_date = "Sun Apr 18 00:40:19 1999"; -static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ); - -static void ircomm_state_discoverywait( struct ircomm_cb *self, IRCOMM_EVENT event, +static void ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_state_discoverywait(struct ircomm_cb *self, + IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_state_queryparamwait(struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ); - -static void ircomm_state_queryparamwait( struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ); - -static void ircomm_state_querylsapwait( struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ); - +static void ircomm_state_querylsapwait(struct ircomm_cb *self, + IRCOMM_EVENT event, + struct sk_buff *skb ); static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ); static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, @@ -207,7 +206,7 @@ ircomm[i]->ack_char = 0x06; ircomm[i]->max_txbuff_size = COMM_DEFAULT_DATA_SIZE; /* 64 */ - ircomm[i]->maxsdusize = SAR_DISABLE; + ircomm[i]->max_sdu_size = SAR_DISABLE; ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); if (ircomm[i]->ctrl_skb == NULL){ DEBUG(0,"ircomm:init_module:alloc_skb failed!\n"); @@ -226,7 +225,6 @@ create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read; #endif /* CONFIG_PROC_FS */ - discovering_instance = NULL; return 0; } @@ -275,51 +273,53 @@ static int ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb) { - - struct ircomm_cb *self = (struct ircomm_cb *)instance; + struct ircomm_cb *self = (struct ircomm_cb *) instance; - ASSERT( self != NULL, return -1;); - ASSERT( self->magic == IRCOMM_MAGIC, return -1;); - ASSERT( skb != NULL, return -1;); + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRCOMM_MAGIC, return -1;); + ASSERT(skb != NULL, return -1;); DEBUG(4,__FUNCTION__"():\n"); - ircomm_do_event( self, TTP_DATA_INDICATION, skb); + ircomm_do_event(self, TTP_DATA_INDICATION, skb); self->rx_packets++; return 0; } static void ircomm_accept_connect_confirm(void *instance, void *sap, - struct qos_info *qos, - __u32 maxsdusize, struct sk_buff *skb) + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb) { + struct ircomm_cb *self = (struct ircomm_cb *) instance; - struct ircomm_cb *self = (struct ircomm_cb *)instance; - - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRCOMM_MAGIC, return;); - ASSERT( skb != NULL, return;); - ASSERT( qos != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRCOMM_MAGIC, return;); + ASSERT(skb != NULL, return;); + ASSERT(qos != NULL, return;); DEBUG(0,__FUNCTION__"(): got connected!\n"); - if(maxsdusize == SAR_DISABLE) - self->max_txbuff_size = qos->data_size.value; + if (max_sdu_size == SAR_DISABLE) + self->max_txbuff_size = qos->data_size.value - max_header_size; else { - ASSERT(maxsdusize >= COMM_DEFAULT_DATA_SIZE, return;); - self->max_txbuff_size = maxsdusize; /* use fragmentation */ + ASSERT(max_sdu_size >= COMM_DEFAULT_DATA_SIZE, return;); + self->max_txbuff_size = max_sdu_size; /* use fragmentation */ } self->qos = qos; - self->null_modem_mode = 0; /* disable null modem emulation */ + self->max_header_size = max_header_size; + self->null_modem_mode = 0; /* disable null modem emulation */ - ircomm_do_event( self, TTP_CONNECT_CONFIRM, skb); + ircomm_do_event(self, TTP_CONNECT_CONFIRM, skb); } static void ircomm_accept_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 maxsdusize, - struct sk_buff *skb ) + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb) { struct ircomm_cb *self = (struct ircomm_cb *)instance; @@ -330,12 +330,14 @@ DEBUG(0,__FUNCTION__"()\n"); - if(maxsdusize == SAR_DISABLE) - self->max_txbuff_size = qos->data_size.value; + if (max_sdu_size == SAR_DISABLE) + self->max_txbuff_size = qos->data_size.value - max_header_size; else - self->max_txbuff_size = maxsdusize; + self->max_txbuff_size = max_sdu_size; self->qos = qos; + self->max_header_size = max_header_size; + ircomm_do_event( self, TTP_CONNECT_INDICATION, skb); /* stop connecting */ @@ -556,7 +558,7 @@ irttp_connect_request(self->tsap, self->dlsap, self->saddr, self->daddr, - NULL, self->maxsdusize, userdata); + NULL, self->max_sdu_size, userdata); break; default: @@ -588,9 +590,9 @@ /* if( !ircomm_parse_controlchannel( self, data)) */ /* self->servicetype = DEFAULT; TODOD:fix this! TH */ - if(self->notify.connect_indication) + if (self->notify.connect_indication) self->notify.connect_indication(self->notify.instance, self, - qos, 0, skb); + qos, 0, 0, skb); } #if 0 @@ -602,28 +604,26 @@ #endif -static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb) +static void connect_confirm(struct ircomm_cb *self, struct sk_buff *skb) { DEBUG(4 ,__FUNCTION__"()\n"); /* give a connect_confirm to the client */ if( self->notify.connect_confirm ) self->notify.connect_confirm(self->notify.instance, - self, NULL, SAR_DISABLE, skb); + self, NULL, SAR_DISABLE, 0, skb); } static void issue_connect_response(struct ircomm_cb *self, struct sk_buff *skb) { - DEBUG(0,__FUNCTION__"()\n"); if( self->servicetype == THREE_WIRE_RAW){ DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n"); /* irlmp_connect_rsp(); */ - } else { - irttp_connect_response(self->tsap, self->maxsdusize, skb); - } + } else + irttp_connect_response(self->tsap, self->max_sdu_size, skb); } static void issue_disconnect_request(struct ircomm_cb *self, @@ -642,30 +642,29 @@ { int err; - if(self->servicetype == THREE_WIRE_RAW){ + if (self->servicetype == THREE_WIRE_RAW){ /* irlmp_data_request(self->lmhandle,userdata); */ DEBUG(0,__FUNCTION__"():not implemented!"); return; } DEBUG(4,__FUNCTION__"():sending frame\n"); - err = irttp_data_request(self->tsap , userdata ); - if(err){ + err = irttp_data_request(self->tsap, userdata); + if (err){ printk(KERN_ERR __FUNCTION__":ttp_data_request failed\n"); - if(userdata) + if (userdata) dev_kfree_skb( userdata); } self->tx_packets++; } static void issue_control_request(struct ircomm_cb *self, - struct sk_buff *userdata ) + struct sk_buff *userdata) { int err; DEBUG(4,__FUNCTION__"()\n"); - if(self->servicetype == THREE_WIRE_RAW) - { + if (self->servicetype == THREE_WIRE_RAW) { DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented\n"); } @@ -676,7 +675,7 @@ { printk( __FUNCTION__"():ttp_data_request failed\n"); if(userdata) - dev_kfree_skb( userdata); + dev_kfree_skb(userdata); } else self->tx_controls++; @@ -701,7 +700,7 @@ /* ircomm_parse_control(self, skb, CONTROL_CHANNEL); */ - if(self->notify.data_indication && skb->len) + if (self->notify.data_indication && skb->len) self->notify.data_indication(self->notify.instance, self, skb); } @@ -728,7 +727,7 @@ DEBUG( 4, __FUNCTION__": STATE = %s, EVENT = %s\n", ircommstate[self->state], ircommevent[event]); - (*state[ self->state ]) ( self, event, skb); + (*state[self->state])(self, event, skb); } static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) @@ -747,7 +746,7 @@ static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event){ case IRCOMM_CONNECT_REQUEST: /* ircomm_next_state(self, COMM_WAITI); */ @@ -779,7 +778,8 @@ /* * ircomm_state_discoverywait */ -static void ircomm_state_discoverywait(struct ircomm_cb *self, IRCOMM_EVENT event, +static void ircomm_state_discoverywait(struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ) { switch(event){ @@ -817,11 +817,11 @@ * ircomm_state_queryparamwait */ -static void ircomm_state_queryparamwait(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ) +static void ircomm_state_queryparamwait(struct ircomm_cb *self, + IRCOMM_EVENT event, + struct sk_buff *skb) { - switch(event){ - + switch (event) { case TTP_CONNECT_INDICATION: ircomm_next_state(self, COMM_WAITR); @@ -855,10 +855,11 @@ * ircomm_state_querylsapwait */ -static void ircomm_state_querylsapwait(struct ircomm_cb *self, IRCOMM_EVENT event, +static void ircomm_state_querylsapwait(struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event) { case TTP_CONNECT_INDICATION: @@ -898,10 +899,10 @@ static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event) { case TTP_CONNECT_CONFIRM: ircomm_next_state(self, COMM_CONN); - connect_confirmation( self, skb ); + connect_confirm(self, skb ); break; case TTP_DISCONNECT_INDICATION: ircomm_next_state(self, COMM_IDLE); @@ -921,21 +922,18 @@ } } - - /* * ircomm_state_waitr */ static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ) + struct sk_buff *skb ) { - - switch(event){ + switch (event) { case IRCOMM_CONNECT_RESPONSE: /* issue_connect_response */ - if(self->servicetype==THREE_WIRE_RAW){ + if (self->servicetype==THREE_WIRE_RAW) { DEBUG(0,__FUNCTION__"():3WIRE_RAW is not implemented\n"); /* irlmp_connect_response(Vpeersap, * ACCEPT,null); @@ -987,7 +985,7 @@ static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event) { case TTP_DATA_INDICATION: process_data(self, skb); break; @@ -1033,8 +1031,6 @@ } } - - /* * ---------------------------------------------------------------------- * IrCOMM service interfaces and supporting functions @@ -1042,12 +1038,12 @@ * ---------------------------------------------------------------------- */ -/* - * start_discovering() +/* + * Function start_discovering (self) + * + * Start discovering and enter DISCOVERY_WAIT state * - * start discovering and enter DISCOVERY_WAIT state */ - static void start_discovering(struct ircomm_cb *self) { __u16 hints; @@ -1092,19 +1088,26 @@ /* * queryias_done(self) * - * called when discovery process got wrong results, completed, or terminated. + * */ +/* + * Function queryias_done (self) + * + * Called when discovery process got wrong results, completed, or + * terminated. + * + */ static void queryias_done(struct ircomm_cb *self) { DEBUG(0, __FUNCTION__"():\n"); - if(self->queryias_lock){ + if (self->queryias_lock){ self->queryias_lock = 0; discovering_instance = NULL; MOD_DEC_USE_COUNT; irlmp_unregister_client(self->ckey); } - if(ircomm_cs != 1) + if (ircomm_cs != 1) irlmp_unregister_service(self->skey); return; } @@ -1120,7 +1123,6 @@ ircomm_getvalue_confirm, self ); } - static void query_lsapsel(struct ircomm_cb * self) { DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n"); @@ -1135,13 +1137,13 @@ } } -/* - * ircomm_connect_request() - * Impl. of this function is differ from one of the reference. - * This functin does discovery as well as sending connect request +/* + * Function ircomm_connect_request (self, servicetype) + * + * Impl. of this function is differ from one of the reference. This + * function does discovery as well as sending connect request + * */ - - void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype) { /* @@ -1158,12 +1160,12 @@ self->servicetype= servicetype; /* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/ - self->maxsdusize = SAR_DISABLE; - ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL); + self->max_sdu_size = SAR_DISABLE; + ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, NULL); } void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, - __u32 maxsdusize) + __u32 max_sdu_size) { ASSERT( self != NULL, return;); @@ -1177,10 +1179,11 @@ * and send it with connect_response */ - if(!userdata){ + if (!userdata){ /* FIXME: check for errors and initialize? DB */ userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); - ASSERT(userdata != NULL, return;); + if (userdata == NULL) + return; skb_reserve(userdata,COMM_HEADER_SIZE); } @@ -1188,9 +1191,10 @@ /* enable null-modem emulation (i.e. server mode )*/ self->null_modem_mode = 1; - self->maxsdusize = maxsdusize; - if(maxsdusize != SAR_DISABLE) - self->max_txbuff_size = maxsdusize; + self->max_sdu_size = max_sdu_size; + if (max_sdu_size != SAR_DISABLE) + self->max_txbuff_size = max_sdu_size; + ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata); } @@ -1341,14 +1345,13 @@ self->control_ch_pending = 1; } - - /* - * ircomm_control_request(); - * this function is exported as a request to send some control-channel tuples - * to peer device + * Function ircomm_control_request (self, instruction) + * + * This function is exported as a request to send some control-channel + * tuples * to peer device + * */ - void ircomm_control_request(struct ircomm_cb *self, __u8 instruction) { diff -u --recursive --new-file v2.2.9/linux/net/irda/ircomm/irvtd_driver.c linux/net/irda/ircomm/irvtd_driver.c --- v2.2.9/linux/net/irda/ircomm/irvtd_driver.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/ircomm/irvtd_driver.c Sun May 30 10:17:03 1999 @@ -8,7 +8,7 @@ * Source: serial.c by Linus Torvalds * isdn_tty.c by Fritz Elfert * - * Copyright (c) 1998, Takahide Higuchi, , + * Copyright (c) 1998-1999, Takahide Higuchi, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -341,15 +341,15 @@ *********************************************************************** */ - /* * Function irvtd_connect_confirm (instance, sap, qos, max_sdu_size, skb) * - * ircomm_connect_request which we have send have succeed! + * ircomm_connect_request which we have send, has succeeded! * */ void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { struct irvtd_cb *driver = (struct irvtd_cb *)instance; ASSERT(driver != NULL, return;); @@ -364,7 +364,7 @@ /* * sending initial control parameters here */ - if(driver->comm->servicetype == THREE_WIRE_RAW) + if (driver->comm->servicetype == THREE_WIRE_RAW) return; /* do nothing */ driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS); @@ -376,7 +376,7 @@ ircomm_control_request(driver->comm, XON_XOFF_CHAR); /* ircomm_control_request(driver->comm, ENQ_ACK_CHAR); */ - switch(driver->comm->servicetype){ + switch (driver->comm->servicetype) { case CENTRONICS: break; @@ -397,17 +397,18 @@ * */ void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { - struct irvtd_cb *driver = (struct irvtd_cb *)instance; struct ircomm_cb *comm = (struct ircomm_cb *)sap; + ASSERT(driver != NULL, return;); ASSERT(driver->magic == IRVTD_MAGIC, return;); ASSERT(comm != NULL, return;); ASSERT(comm->magic == IRCOMM_MAGIC, return;); - DEBUG(4,"irvtd_connect_indication:sending connect_response...\n"); + DEBUG(4, __FUNCTION__ "():sending connect_response...\n"); ircomm_connect_response(comm, NULL, SAR_DISABLE ); @@ -416,7 +417,7 @@ /* * send initial control parameters */ - if(driver->comm->servicetype == THREE_WIRE_RAW) + if (driver->comm->servicetype == THREE_WIRE_RAW) return; /* do nothing */ driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS); @@ -426,6 +427,7 @@ ircomm_control_request(driver->comm, DTELINE_STATE); break; default: + DEBUG(0, __FUNCTION__ "(), not implemented!\n"); } @@ -576,6 +578,7 @@ case DATA_RATE: case XON_XOFF_CHAR: case DTELINE_STATE: + case ENQ_ACK_CHAR: /* got this from win95 */ /* (maybe) nothing to do */ break; default: @@ -778,7 +781,7 @@ skb_queue_head_init(&driver->rxbuff); driver->txbuff = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); if (!driver->txbuff){ - DEBUG(0,__FUNCTION__"():alloc_skb failed!\n"); + DEBUG(0,__FUNCTION__"(), alloc_skb failed!\n"); return -ENOMEM; } skb_reserve(driver->txbuff, COMM_HEADER_SIZE); @@ -793,9 +796,8 @@ irvtd_notify.instance = driver; driver->comm = ircomm_open_instance(irvtd_notify); - if(!driver->comm){ + if (!driver->comm) return -ENODEV; - } /* diff -u --recursive --new-file v2.2.9/linux/net/irda/irda_device.c linux/net/irda/irda_device.c --- v2.2.9/linux/net/irda/irda_device.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irda_device.c Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Wed Sep 2 20:22:08 1998 - * Modified at: Wed Apr 21 09:48:19 1999 + * Modified at: Mon May 10 23:02:47 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -53,7 +55,8 @@ extern int actisys_init(void); extern int girbil_init(void); -hashbin_t *irda_device = NULL; +static hashbin_t *irda_device = NULL; +static hashbin_t *dongles = NULL; /* Netdevice functions */ static int irda_device_net_rebuild_header(struct sk_buff *skb); @@ -61,9 +64,9 @@ struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len); -static int irda_device_net_set_config( struct device *dev, struct ifmap *map); -static int irda_device_net_change_mtu( struct device *dev, int new_mtu); - +static int irda_device_net_set_config(struct device *dev, struct ifmap *map); +static int irda_device_net_change_mtu(struct device *dev, int new_mtu); +static int irda_device_net_ioctl(struct device *dev, struct ifreq *rq,int cmd); #ifdef CONFIG_PROC_FS int irda_device_proc_read( char *buf, char **start, off_t offset, int len, int unused); @@ -74,8 +77,15 @@ { /* Allocate master array */ irda_device = hashbin_new( HB_LOCAL); - if ( irda_device == NULL) { - printk( KERN_WARNING "IrDA: Can't allocate irda_device hashbin!\n"); + if (irda_device == NULL) { + WARNING("IrDA: Can't allocate irda_device hashbin!\n"); + return -ENOMEM; + } + + dongles = hashbin_new(HB_LOCAL); + if (dongles == NULL) { + printk(KERN_WARNING + "IrDA: Can't allocate dongles hashbin!\n"); return -ENOMEM; } @@ -113,6 +123,7 @@ ASSERT(irda_device != NULL, return;); + hashbin_delete(dongles, NULL); hashbin_delete(irda_device, (FREE_FUNC) irda_device_close); } @@ -238,7 +249,7 @@ /* * Function irda_device_close (self) * - * + * Close the device * */ void irda_device_close(struct irda_device *self) @@ -248,6 +259,10 @@ ASSERT(self != NULL, return;); ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;); + /* We are not using any dongle anymore! */ + if (self->dongle) + self->dongle->close(self); + /* Stop and remove instance of IrLAP */ if (self->irlap) irlap_close(self->irlap); @@ -298,15 +313,19 @@ */ if (self->wait_until_sent) { self->wait_until_sent(self); + + if (self->dongle) + self->dongle->change_speed(self, speed); + if (self->change_speed) { self->change_speed(self, speed); - + /* Update the QoS value only */ self->qos.baud_rate.value = speed; } } else { - printk(KERN_WARNING "wait_until_sent() " - "has not implemented by the IrDA device driver!\n"); + WARNING("IrDA: wait_until_sent() " + "has not implemented by the IrDA device driver!\n"); } } @@ -386,6 +405,7 @@ dev->set_config = irda_device_net_set_config; dev->change_mtu = irda_device_net_change_mtu; /* dev->hard_header = irda_device_net_hard_header; */ + dev->do_ioctl = irda_device_net_ioctl; dev->hard_header_len = 0; dev->addr_len = 0; @@ -444,6 +464,125 @@ return 0; } +static int irda_device_net_ioctl(struct device *dev, /* ioctl device */ + struct ifreq *rq, /* Data passed */ + int cmd) /* Ioctl number */ +{ + unsigned long flags; + int ret = 0; +#ifdef WIRELESS_EXT + struct iwreq *wrq = (struct iwreq *) rq; +#endif + struct irda_device *self; + + DEBUG(4, __FUNCTION__ "()\n"); + + ASSERT(dev != NULL, return -1;); + + self = (struct irda_device *) dev->priv; + + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;); + + DEBUG(0, "%s: ->irda_device_net_ioctl(cmd=0x%X)\n", dev->name, cmd); + + /* Disable interrupts & save flags */ + save_flags(flags); + cli(); + + /* Look what is the request */ + switch (cmd) { +#ifdef WIRELESS_EXT + case SIOCGIWNAME: + /* Get name */ + strcpy(wrq->u.name, self->name); + break; + case SIOCSIWNWID: + /* Set domain */ + if (wrq->u.nwid.on) { + + } break; + case SIOCGIWNWID: + /* Read domain*/ +/* wrq->u.nwid.nwid = domain; */ +/* wrq->u.nwid.on = 1; */ + break; + case SIOCGIWENCODE: + /* Get scramble key */ + /* wrq->u.encoding.code = scramble_key; */ +/* wrq->u.encoding.method = 1; */ + break; + case SIOCSIWENCODE: + /* Set scramble key */ + /* scramble_key = wrq->u.encoding.code; */ + break; + case SIOCGIWRANGE: + /* Basic checking... */ + if(wrq->u.data.pointer != (caddr_t) 0) { + struct iw_range range; + + /* Verify the user buffer */ + ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, + sizeof(struct iw_range)); + if(ret) + break; + + /* Set the length (useless : its constant...) */ + wrq->u.data.length = sizeof(struct iw_range); + + /* Set information in the range struct */ + range.throughput = 1.6 * 1024 * 1024; /* don't argue on this ! */ + range.min_nwid = 0x0000; + range.max_nwid = 0x01FF; + + range.num_channels = range.num_frequency = 0; + + range.sensitivity = 0x3F; + range.max_qual.qual = 255; + range.max_qual.level = 255; + range.max_qual.noise = 0; + + /* Copy structure to the user buffer */ + copy_to_user(wrq->u.data.pointer, &range, + sizeof(struct iw_range)); + } + break; + case SIOCGIWPRIV: + /* Basic checking... */ +#if 0 + if (wrq->u.data.pointer != (caddr_t) 0) { + struct iw_priv_args priv[] = + { /* cmd, set_args, get_args, name */ + { SIOCGIPSNAP, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 0, + sizeof(struct site_survey), + "getsitesurvey" }, + }; + + /* Verify the user buffer */ + ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, + sizeof(priv)); + if (ret) + break; + + /* Set the number of ioctl available */ + wrq->u.data.length = 1; + + /* Copy structure to the user buffer */ + copy_to_user(wrq->u.data.pointer, (u_char *) priv, + sizeof(priv)); + } +#endif + break; +#endif + default: + ret = -EOPNOTSUPP; + } + + restore_flags(flags); + + return ret; +} + /* * Function irda_device_transmit_finished (void) * @@ -451,7 +590,7 @@ * device. Maybe we should use: q->q.qlen == 0. * */ -int irda_device_txqueue_empty( struct irda_device *self) +int irda_device_txqueue_empty(struct irda_device *self) { ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;); @@ -463,6 +602,117 @@ } /* + * Function irda_device_init_dongle (self, type) + * + * Initialize attached dongle. Warning, must be called with a process + * context! + */ +void irda_device_init_dongle(struct irda_device *self, int type) +{ + struct dongle_q *node; + + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;); + +#ifdef CONFIG_KMOD + /* Try to load the module needed */ + switch (type) { + case ESI_DONGLE: + MESSAGE("IrDA: Initializing ESI dongle!\n"); + request_module("esi"); + break; + case TEKRAM_DONGLE: + MESSAGE("IrDA: Initializing Tekram dongle!\n"); + request_module("tekram"); + break; + case ACTISYS_DONGLE: /* FALLTHROUGH */ + case ACTISYS_PLUS_DONGLE: + MESSAGE("IrDA: Initializing ACTiSYS dongle!\n"); + request_module("actisys"); + break; + case GIRBIL_DONGLE: + MESSAGE("IrDA: Initializing GIrBIL dongle!\n"); + request_module("girbil"); + break; + case LITELINK_DONGLE: + MESSAGE("IrDA: Initializing Litelink dongle!\n"); + request_module("litelink"); + break; + default: + ERROR("Unknown dongle type!\n"); + return; + } +#endif /* CONFIG_KMOD */ + + node = hashbin_find(dongles, type, NULL); + if (!node) { + ERROR("IrDA: Unable to find requested dongle\n"); + return; + } + + /* Set the dongle to be used by this driver */ + self->dongle = node->dongle; + + /* Now initialize the dongle! */ + node->dongle->open(self, type); + node->dongle->qos_init(self, &self->qos); + + /* Reset dongle */ + node->dongle->reset(self, 0); + + /* Set to default baudrate */ + irda_device_change_speed(self, 9600); +} + +/* + * Function irda_device_register_dongle (dongle) + * + * + * + */ +int irda_device_register_dongle(struct dongle *dongle) +{ + struct dongle_q *new; + + /* Check if this dongle has been registred before */ + if (hashbin_find(dongles, dongle->type, NULL)) { + MESSAGE(__FUNCTION__ "(), Dongle already registered\n"); + return 0; + } + + /* Make new IrDA dongle */ + new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL); + if (new == NULL) + return -1; + + memset(new, 0, sizeof( struct dongle_q)); + new->dongle = dongle; + + /* Insert IrDA dongle into hashbin */ + hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL); + + return 0; +} + +/* + * Function irda_device_unregister_dongle (dongle) + * + * + * + */ +void irda_device_unregister_dongle(struct dongle *dongle) +{ + struct dongle_q *node; + + node = hashbin_remove(dongles, dongle->type, NULL); + if (!node) { + ERROR(__FUNCTION__ "(), dongle not found!\n"); + return; + } + kfree(node); +} + +/* * Function setup_dma (idev, buffer, count, mode) * * Setup the DMA channel @@ -536,7 +786,7 @@ self = (struct irda_device *) hashbin_get_first(irda_device); while ( self != NULL) { - len += sprintf(buf+len, "%s,", self->name); + len += sprintf(buf+len, "\n%s,", self->name); len += sprintf(buf+len, "\tbinding: %s\n", self->description); diff -u --recursive --new-file v2.2.9/linux/net/irda/iriap.c linux/net/irda/iriap.c --- v2.2.9/linux/net/irda/iriap.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/iriap.c Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Aug 21 00:02:07 1997 - * Modified at: Fri Apr 23 09:57:12 1999 + * Modified at: Sun May 9 15:59:05 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -62,12 +62,17 @@ extern char *lmp_reasons[]; static struct iriap_cb *iriap_open( __u8 slsap, int mode); -static void __iriap_close( struct iriap_cb *self); +static void __iriap_close(struct iriap_cb *self); static void iriap_disconnect_indication(void *instance, void *sap, LM_REASON reason, struct sk_buff *skb); static void iriap_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, + __u8 max_header_size, struct sk_buff *skb); +static void iriap_connect_confirm(void *instance, void *sap, + struct qos_info *qos, + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb); static int iriap_data_indication(void *instance, void *sap, struct sk_buff *skb); @@ -181,7 +186,7 @@ self->slsap_sel = slsap_sel; self->mode = mode; - init_timer( &self->watchdog_timer); + init_timer(&self->watchdog_timer); hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL); @@ -206,7 +211,7 @@ ASSERT( self != NULL, return;); ASSERT( self->magic == IAS_MAGIC, return;); - del_timer( &self->watchdog_timer); + del_timer(&self->watchdog_timer); self->magic = 0; @@ -260,7 +265,7 @@ ASSERT( iriap != NULL, return;); - del_timer( &self->watchdog_timer); + del_timer(&self->watchdog_timer); if ( self->mode == IAS_CLIENT) { DEBUG( 4, __FUNCTION__ "(), disconnect as client\n"); @@ -284,9 +289,8 @@ NULL); } - if ( userdata) { + if (userdata) dev_kfree_skb( userdata); - } } /* @@ -295,28 +299,28 @@ * * */ -void iriap_disconnect_request( struct iriap_cb *self) +void iriap_disconnect_request(struct iriap_cb *self) { struct sk_buff *skb; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( self != NULL, return;); - ASSERT( self->magic == IAS_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IAS_MAGIC, return;); - skb = dev_alloc_skb( 64); + skb = dev_alloc_skb(64); if (skb == NULL) { - DEBUG( 0, __FUNCTION__ - "(), Could not allocate an sk_buff of length %d\n", 64); + DEBUG(0, __FUNCTION__ + "(), Could not allocate an sk_buff of length %d\n", 64); return; } /* - * Reserve space for MUX and LAP header + * Reserve space for MUX control and LAP header */ - skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, LMP_MAX_HEADER); - irlmp_disconnect_request( self->lsap, skb); + irlmp_disconnect_request(self->lsap, skb); } void iriap_getinfobasedetails_request(void) @@ -381,7 +385,7 @@ /* Give ourselves 10 secs to finish this operation */ iriap_start_watchdog_timer(self, 10*HZ); - skb = dev_alloc_skb( 64); + skb = dev_alloc_skb(64); if (!skb) return; @@ -389,7 +393,7 @@ attr_len = strlen(attr); /* Reserve space for MUX and LAP header */ - skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, self->max_header_size); skb_put(skb, 3+name_len+attr_len); frame = skb->data; @@ -535,13 +539,13 @@ * value. We add 9 bytes because of the 6 bytes for the frame and * max 3 bytes for the value coding. */ - skb = dev_alloc_skb(value->len + LMP_HEADER + LAP_HEADER + 9); + skb = dev_alloc_skb(value->len + self->max_header_size + 9); if (!skb) return; /* Reserve space for MUX and LAP header */ - skb_reserve( skb, LMP_HEADER+LAP_HEADER); - skb_put( skb, 6); + skb_reserve(skb, self->max_header_size); + skb_put(skb, 6); fp = skb->data; @@ -666,7 +670,7 @@ /* * Function iriap_send_ack (void) * - * + * Currently not used * */ void iriap_send_ack( struct iriap_cb *self) @@ -679,13 +683,13 @@ ASSERT( self != NULL, return;); ASSERT( self->magic == IAS_MAGIC, return;); - skb = dev_alloc_skb( 64); + skb = dev_alloc_skb(64); if (!skb) return; /* Reserve space for MUX and LAP header */ - skb_reserve( skb, 4); - skb_put( skb, 3); + skb_reserve(skb, self->max_header_size); + skb_put(skb, 1); frame = skb->data; /* Build frame */ @@ -698,8 +702,10 @@ * LSAP connection confirmed! * */ -void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *userdata) +static void iriap_connect_confirm(void *instance, void *sap, + struct qos_info *qos, + __u32 max_sdu_size, __u8 header_size, + struct sk_buff *userdata) { struct iriap_cb *self; @@ -711,7 +717,7 @@ DEBUG(4, __FUNCTION__ "()\n"); - /* del_timer( &self->watchdog_timer); */ + del_timer(&self->watchdog_timer); iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata); } @@ -724,19 +730,17 @@ */ static void iriap_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, + __u8 header_size, struct sk_buff *userdata) { struct iriap_cb *self; - DEBUG( 4, __FUNCTION__ "()\n"); - - self = ( struct iriap_cb *) instance; + self = (struct iriap_cb *) instance; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IAS_MAGIC, return;); - ASSERT( self->mode == IAS_SERVER, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IAS_MAGIC, return;); - iriap_do_server_event( self, IAP_LM_CONNECT_INDICATION, userdata); + iriap_do_server_event(self, IAP_LM_CONNECT_INDICATION, userdata); } /* @@ -856,7 +860,7 @@ } opcode &= 0x7f; /* Mask away LST bit */ - switch( opcode) { + switch (opcode) { case GET_INFO_BASE: DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n"); break; diff -u --recursive --new-file v2.2.9/linux/net/irda/iriap_event.c linux/net/irda/iriap_event.c --- v2.2.9/linux/net/irda/iriap_event.c Wed Mar 10 15:29:52 1999 +++ linux/net/irda/iriap_event.c Sun May 30 10:17:03 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Aug 21 00:02:07 1997 - * Modified at: Tue Jan 26 12:29:36 1999 + * Modified at: Sun May 9 11:01:47 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * Copyright (c) 1997, 1999 Dag Brattli , All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -387,9 +387,9 @@ } /* Reserve space for MUX_CONTROL and LAP header */ - skb_reserve( tx_skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(tx_skb, LMP_MAX_HEADER); - irlmp_connect_response( self->lsap, tx_skb); + irlmp_connect_response(self->lsap, tx_skb); /*LM_Idle_request(idle); */ iriap_next_server_state( self, R_CALL); diff -u --recursive --new-file v2.2.9/linux/net/irda/irlan/irlan_client.c linux/net/irda/irlan/irlan_client.c --- v2.2.9/linux/net/irda/irlan/irlan_client.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irlan/irlan_client.c Sun May 30 10:17:04 1999 @@ -6,13 +6,14 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 23:03:55 1999 + * Modified at: Tue May 11 00:22:39 1999 * Modified by: Dag Brattli * Sources: skeleton.c by Donald Becker * slip.c by Laurence Culhane, * Fred N. van Kempen, * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -61,6 +62,7 @@ static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, + __u8 max_header_size, struct sk_buff *); static void irlan_check_response_param(struct irlan_cb *self, char *param, char *value, int val_len); @@ -79,7 +81,7 @@ * indication it needs to make progress. If the client is still in * IDLE state, we must kick it to, but only if the provider is not IDLE */ - if ((self->access_type == ACCESS_PEER) && + if ((self->provider.access_type == ACCESS_PEER) && (self->client.state == IRLAN_IDLE) && (self->provider.state != IRLAN_IDLE)) { irlan_client_wakeup(self, self->saddr, self->daddr); @@ -105,23 +107,29 @@ { struct irmanager_event mgr_event; - DEBUG(0, __FUNCTION__ "()\n"); + DEBUG(1, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); - /* Check if we are already awake */ - if (self->client.state != IRLAN_IDLE) + /* + * Check if we are already awake, or if we are a provider in direct + * mode (in that case we must leave the client idle + */ + if ((self->client.state != IRLAN_IDLE) || + (self->provider.access_type == ACCESS_DIRECT)) return; /* saddr may have changed! */ self->saddr = saddr; - /* Check if network device is up */ + /* Before we try to connect, we check if network device is up. If it + * is up, that means that the "user" really wants to connect. If not + * we notify the user about the possibility of an IrLAN connection + */ if (self->dev.start) { /* Open TSAPs */ irlan_client_open_ctrl_tsap(self); - irlan_provider_open_ctrl_tsap(self); irlan_open_data_tsap(self); irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL); @@ -161,7 +169,7 @@ struct irlan_cb *self, *entry; __u32 saddr, daddr; - DEBUG(0, __FUNCTION__"()\n"); + DEBUG(1, __FUNCTION__"()\n"); ASSERT(irlan != NULL, return;); ASSERT(discovery != NULL, return;); @@ -176,7 +184,8 @@ if (self) { ASSERT(self->magic == IRLAN_MAGIC, return;); - DEBUG(2, __FUNCTION__ "(), Found instance!\n"); + DEBUG(1, __FUNCTION__ "(), Found instance (%08x)!\n", + daddr); irlan_client_wakeup(self, saddr, daddr); @@ -184,30 +193,13 @@ } /* - * We have no instance for daddr, so try and find an unused one + * We have no instance for daddr, so start a new one */ - self = hashbin_find(irlan, DEV_ADDR_ANY, NULL); - if (self) { - DEBUG(0, __FUNCTION__ "(), Found instance with DEV_ADDR_ANY!\n"); - /* - * Rehash instance, now we have a client (daddr) to serve. - */ - entry = hashbin_remove(irlan, self->daddr, NULL); - ASSERT(entry == self, return;); - - self->daddr = daddr; - self->saddr = saddr; + DEBUG(1, __FUNCTION__ "(), starting new instance!\n"); + self = irlan_open(saddr, daddr, TRUE); - DEBUG(0, __FUNCTION__ "(), daddr=%08x\n", self->daddr); - hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL); - - /* Check if network device has been registered */ - if (!self->netdev_registered) - irlan_register_netdev(self); - - /* Restart watchdog timer */ - irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); - } + /* Restart watchdog timer */ + irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); } /* @@ -302,6 +294,7 @@ static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, + __u8 max_header_size, struct sk_buff *skb) { struct irlan_cb *self; @@ -313,6 +306,9 @@ ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); + self->client.max_sdu_size = max_sdu_size; + self->client.max_header_size = max_header_size; + /* TODO: we could set the MTU depending on the max_sdu_size */ irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL); @@ -339,7 +335,7 @@ return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->max_header_size); skb_put(skb, 2); frame = skb->data; @@ -410,11 +406,11 @@ /* For all parameters */ for (i=0; iaccess_type = ACCESS_DIRECT; + self->client.access_type = ACCESS_DIRECT; else if (strcmp(value, "PEER") == 0) - self->access_type = ACCESS_PEER; + self->client.access_type = ACCESS_PEER; else if (strcmp(value, "HOSTED") == 0) - self->access_type = ACCESS_HOSTED; + self->client.access_type = ACCESS_HOSTED; else { DEBUG(2, __FUNCTION__ "(), unknown access type!\n"); } diff -u --recursive --new-file v2.2.9/linux/net/irda/irlan/irlan_client_event.c linux/net/irda/irlan/irlan_client_event.c --- v2.2.9/linux/net/irda/irlan/irlan_client_event.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irlan/irlan_client_event.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 12:23:22 1999 + * Modified at: Thu May 6 13:42:38 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -97,7 +97,7 @@ ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRLAN_MAGIC, return -1;); - switch(event) { + switch (event) { case IRLAN_DISCOVERY_INDICATION: /* Get some values from peer IAS */ iriap_getvaluebyclass_request( @@ -152,7 +152,7 @@ irlan_next_client_state(self, IRLAN_IDLE); /* Give the client a kick! */ - if ((self->access_type == ACCESS_PEER) && + if ((self->provider.access_type == ACCESS_PEER) && (self->provider.state != IRLAN_IDLE)) irlan_client_wakeup(self, self->saddr, self->daddr); break; @@ -222,7 +222,7 @@ ASSERT(self != NULL, return -1;); - switch(event) { + switch (event) { case IRLAN_DATA_INDICATION: ASSERT(skb != NULL, return -1;); @@ -314,7 +314,7 @@ ASSERT(self->dtsap_sel_data != 0, return -1;); /* Check which access type we are dealing with */ - switch(self->access_type) { + switch (self->client.access_type) { case ACCESS_PEER: if (self->provider.state == IRLAN_OPEN) { diff -u --recursive --new-file v2.2.9/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c --- v2.2.9/linux/net/irda/irlan/irlan_common.c Tue May 11 13:10:32 1999 +++ linux/net/irda/irlan/irlan_common.c Sun May 30 10:17:04 1999 @@ -6,10 +6,11 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 23:13:47 1999 + * Modified at: Sun May 9 11:48:49 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * Copyright (c) 1997, 1999 Dag Brattli , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -93,19 +94,25 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, __u8 value_byte, __u16 value_short, __u8 *value_array, __u16 value_len); -static void irlan_close_tsaps(struct irlan_cb *self); +void irlan_close_tsaps(struct irlan_cb *self); #ifdef CONFIG_PROC_FS static int irlan_proc_read(char *buf, char **start, off_t offset, int len, int unused); extern struct proc_dir_entry *proc_irda; -#endif +#endif /* CONFIG_PROC_FS */ +/* + * Function irlan_watchdog_timer_expired (data) + * + * + * + */ void irlan_watchdog_timer_expired(unsigned long data) { struct irmanager_event mgr_event; - struct irlan_cb *self, *entry; + struct irlan_cb *self; DEBUG(0, __FUNCTION__ "()\n"); @@ -116,6 +123,7 @@ /* Check if device still configured */ if (self->dev.start) { + DEBUG(0, __FUNCTION__ "(), notifying irmanager to stop irlan!\n"); mgr_event.event = EVENT_IRLAN_STOP; sprintf(mgr_event.devname, "%s", self->ifname); irmanager_notify(&mgr_event); @@ -128,22 +136,13 @@ */ self->notify_irmanager = FALSE; } else { - DEBUG(0, __FUNCTION__ "(), recycling instance!\n"); + DEBUG(0, __FUNCTION__ "(), closing instance!\n"); if (self->netdev_registered) { DEBUG(0, __FUNCTION__ "(), removing netdev!\n"); unregister_netdev(&self->dev); self->netdev_registered = FALSE; } - - /* Unbind from daddr */ - entry = hashbin_remove(irlan, self->daddr, NULL); - ASSERT(entry == self, return;); - - self->daddr = DEV_ADDR_ANY; - self->saddr = DEV_ADDR_ANY; - - DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr); - hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL); + irlan_close(self); } } @@ -195,12 +194,12 @@ /* Register with IrLMP as a service */ skey = irlmp_register_service(hints); - /* Start the first IrLAN instance */ + /* Start the master IrLAN instance */ new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE); - irlan_open_data_tsap(new); - irlan_client_open_ctrl_tsap(new); + /* The master will only open its (listen) control TSAP */ irlan_provider_open_ctrl_tsap(new); + new->master = TRUE; /* Do some fast discovery! */ irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS); @@ -293,7 +292,7 @@ self->daddr = daddr; /* Provider access can only be PEER, DIRECT, or HOSTED */ - self->access_type = access; + self->provider.access_type = access; self->media = MEDIA_802_3; self->notify_irmanager = TRUE; @@ -359,8 +358,11 @@ /* Check if device is still configured */ if (self->dev.start) { - DEBUG(2, __FUNCTION__ + DEBUG(0, __FUNCTION__ "(), Device still configured, closing later!\n"); + + /* Give it a chance to reconnect */ + irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); return; } DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr); @@ -371,8 +373,15 @@ __irlan_close(self); } +/* + * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb) + * + * Here we receive the connect indication for the data channel + * + */ void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { struct irlan_cb *self; struct tsap_cb *tsap; @@ -386,13 +395,17 @@ ASSERT(self->magic == IRLAN_MAGIC, return;); ASSERT(tsap == self->tsap_data,return;); - DEBUG(2, "IrLAN, We are now connected!\n"); + self->max_sdu_size = max_sdu_size; + self->max_header_size = max_header_size; + + DEBUG(0, "IrLAN, We are now connected!\n"); + del_timer(&self->watchdog_timer); irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, skb); irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, skb); - if (self->access_type == ACCESS_PEER) { + if (self->provider.access_type == ACCESS_PEER) { /* * Data channel is open, so we are now allowed to * configure the remote filter @@ -400,12 +413,13 @@ irlan_get_unicast_addr(self); irlan_open_unicast_addr(self); } - /* Ready to transfer Ethernet frames */ + /* Ready to transfer Ethernet frames (at last) */ self->dev.tbusy = 0; } void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { struct irlan_cb *self; @@ -416,6 +430,9 @@ ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); + self->max_sdu_size = max_sdu_size; + self->max_header_size = max_header_size; + /* TODO: we could set the MTU depending on the max_sdu_size */ DEBUG(2, "IrLAN, We are now connected!\n"); @@ -444,7 +461,7 @@ struct irlan_cb *self; struct tsap_cb *tsap; - DEBUG(2, __FUNCTION__ "(), reason=%d\n", reason); + DEBUG(0, __FUNCTION__ "(), reason=%d\n", reason); self = (struct irlan_cb *) instance; tsap = (struct tsap_cb *) sap; @@ -460,7 +477,7 @@ switch(reason) { case LM_USER_REQUEST: /* User request */ - //irlan_close(self); + irlan_close(self); break; case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */ irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); @@ -490,7 +507,7 @@ struct notify_t notify; struct tsap_cb *tsap; - DEBUG(4, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); @@ -500,7 +517,7 @@ return; irda_notify_init(¬ify); - + notify.data_indication = irlan_eth_receive; notify.udata_indication = irlan_eth_receive; notify.connect_indication = irlan_connect_indication; @@ -620,7 +637,7 @@ return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -651,7 +668,7 @@ if (!skb) return; - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -683,7 +700,7 @@ if (!skb) return; - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -719,7 +736,7 @@ return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->max_header_size); skb_put(skb, 2); frame = skb->data; @@ -757,7 +774,7 @@ return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -796,7 +813,7 @@ return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -836,7 +853,7 @@ return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -871,7 +888,7 @@ return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -1033,7 +1050,7 @@ /* get parameter name */ memcpy(name, buf+n, name_len); - name[ name_len] = '\0'; + name[name_len] = '\0'; n+=name_len; /* @@ -1051,7 +1068,7 @@ /* get parameter value */ memcpy(value, buf+n, val_len); - value[ val_len] = '\0'; + value[val_len] = '\0'; n+=val_len; DEBUG(4, "Parameter: %s ", name); @@ -1085,31 +1102,35 @@ while (self != NULL) { ASSERT(self->magic == IRLAN_MAGIC, return len;); - len += sprintf(buf+len, "ifname: %s,\n", - self->ifname); - len += sprintf(buf+len, "client state: %s, ", - irlan_state[ self->client.state]); - len += sprintf(buf+len, "provider state: %s,\n", - irlan_state[ self->provider.state]); - len += sprintf(buf+len, "saddr: %#08x, ", - self->saddr); - len += sprintf(buf+len, "daddr: %#08x\n", - self->daddr); - len += sprintf(buf+len, "version: %d.%d,\n", - self->version[1], self->version[0]); - len += sprintf(buf+len, "access type: %s\n", - irlan_access[ self->access_type]); - len += sprintf(buf+len, "media: %s\n", - irlan_media[ self->media]); - - len += sprintf(buf+len, "local filter:\n"); - len += sprintf(buf+len, "remote filter: "); - len += irlan_print_filter(self->client.filter_type, buf+len); - - len += sprintf(buf+len, "tx busy: %s\n", self->dev.tbusy ? - "TRUE" : "FALSE"); - - len += sprintf(buf+len, "\n"); + /* Don't display the master server */ + if (self->master == 0) { + len += sprintf(buf+len, "ifname: %s,\n", + self->ifname); + len += sprintf(buf+len, "client state: %s, ", + irlan_state[ self->client.state]); + len += sprintf(buf+len, "provider state: %s,\n", + irlan_state[ self->provider.state]); + len += sprintf(buf+len, "saddr: %#08x, ", + self->saddr); + len += sprintf(buf+len, "daddr: %#08x\n", + self->daddr); + len += sprintf(buf+len, "version: %d.%d,\n", + self->version[1], self->version[0]); + len += sprintf(buf+len, "access type: %s\n", + irlan_access[self->client.access_type]); + len += sprintf(buf+len, "media: %s\n", + irlan_media[self->media]); + + len += sprintf(buf+len, "local filter:\n"); + len += sprintf(buf+len, "remote filter: "); + len += irlan_print_filter(self->client.filter_type, + buf+len); + + len += sprintf(buf+len, "tx busy: %s\n", + self->dev.tbusy ? "TRUE" : "FALSE"); + + len += sprintf(buf+len, "\n"); + } self = (struct irlan_cb *) hashbin_get_next(irlan); } diff -u --recursive --new-file v2.2.9/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c --- v2.2.9/linux/net/irda/irlan/irlan_eth.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irlan/irlan_eth.c Sun May 30 10:17:04 1999 @@ -6,13 +6,13 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Oct 15 08:37:58 1998 - * Modified at: Thu Apr 22 14:26:39 1999 + * Modified at: Mon May 10 20:23:49 1999 * Modified by: Dag Brattli * Sources: skeleton.c by Donald Becker * slip.c by Laurence Culhane, * Fred N. van Kempen, * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -67,19 +68,19 @@ dev->tx_queue_len = TTP_MAX_QUEUE; -#if 0 - /* - * OK, since we are emulating an IrLAN sever we will have to give - * ourself an ethernet address! - * FIXME: this must be more dynamically - */ - dev->dev_addr[0] = 0x40; - dev->dev_addr[1] = 0x00; - dev->dev_addr[2] = 0x00; - dev->dev_addr[3] = 0x00; - dev->dev_addr[4] = 0x23; - dev->dev_addr[5] = 0x45; -#endif + if (self->provider.access_type == ACCESS_DIRECT) { + /* + * Since we are emulating an IrLAN sever we will have to + * give ourself an ethernet address! + */ + dev->dev_addr[0] = 0x40; + dev->dev_addr[1] = 0x00; + dev->dev_addr[2] = 0x00; + dev->dev_addr[3] = 0x00; + get_random_bytes(dev->dev_addr+4, 1); + get_random_bytes(dev->dev_addr+5, 1); + } + /* * Network device has now been registered, so tell irmanager about * it, so it can be configured with network parameters @@ -180,8 +181,6 @@ { struct irlan_cb *self; - DEBUG(4, __FUNCTION__ "()\n"); - self = (struct irlan_cb *) dev->priv; ASSERT(self != NULL, return 0;); @@ -202,19 +201,19 @@ dev->trans_start = jiffies; } - DEBUG(4, "Room left at head: %d\n", skb_headroom(skb)); - DEBUG(4, "Room left at tail: %d\n", skb_tailroom(skb)); - DEBUG(4, "Required room: %d\n", IRLAN_MAX_HEADER); - - /* skb headroom large enough to contain IR-headers? */ - if ((skb_headroom(skb) < IRLAN_MAX_HEADER) || (skb_shared(skb))) { + /* skb headroom large enough to contain all IrDA-headers? */ + if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) { struct sk_buff *new_skb = - skb_realloc_headroom(skb, IRLAN_MAX_HEADER); - ASSERT(new_skb != NULL, return 0;); - ASSERT(skb_headroom(new_skb) >= IRLAN_MAX_HEADER, return 0;); + skb_realloc_headroom(skb, self->max_header_size); - /* Free original skb, and use the new one */ + /* We have to free the original skb anyway */ dev_kfree_skb(skb); + + /* Did the realloc succeed? */ + if (new_skb == NULL) + return 0; + + /* Use the new skb instead */ skb = new_skb; } @@ -222,31 +221,26 @@ self->stats.tx_packets++; self->stats.tx_bytes += skb->len; - /* - * Now queue the packet in the transport layer - * FIXME: clean up the code below! DB - */ - if (self->use_udata) { + /* Now queue the packet in the transport layer */ + if (self->use_udata) irttp_udata_request(self->tsap_data, skb); - dev->tbusy = 0; - - return 0; - } - - if (irttp_data_request(self->tsap_data, skb) == -1) { - /* - * IrTTPs tx queue is full, so we just have to drop the - * frame! You might think that we should just return -1 - * and don't deallocate the frame, but that is dangerous - * since it's possible that we have replaced the original - * skb with a new one with larger headroom, and that would - * really confuse do_dev_queue_xmit() in dev.c! I have - * tried :-) DB - */ - dev_kfree_skb(skb); - ++self->stats.tx_dropped; + else { + if (irttp_data_request(self->tsap_data, skb) < 0) { + /* + * IrTTPs tx queue is full, so we just have to + * drop the frame! You might think that we should + * just return -1 and don't deallocate the frame, + * but that is dangerous since it's possible that + * we have replaced the original skb with a new + * one with larger headroom, and that would really + * confuse do_dev_queue_xmit() in dev.c! I have + * tried :-) DB + */ + dev_kfree_skb(skb); + ++self->stats.tx_dropped; - return 0; + return 0; + } } dev->tbusy = 0; /* Finished! */ @@ -314,26 +308,16 @@ switch (flow) { case FLOW_STOP: - DEBUG(4, "IrLAN, stopping Ethernet layer\n"); - dev->tbusy = 1; break; case FLOW_START: - /* - * Tell upper layers that its time to transmit frames again - */ - DEBUG(4, "IrLAN, starting Ethernet layer\n"); - + default: + /* Tell upper layers that its time to transmit frames again */ dev->tbusy = 0; - /* - * Ready to receive more frames, so schedule the network - * layer - */ + /* Schedule network layer */ mark_bh(NET_BH); break; - default: - DEBUG(0, __FUNCTION__ "(), Unknown flow command!\n"); } } @@ -373,7 +357,7 @@ in_dev = dev->ip_ptr; arp_send(ARPOP_REQUEST, ETH_P_ARP, in_dev->ifa_list->ifa_address, - &dev, + dev, in_dev->ifa_list->ifa_address, NULL, dev->dev_addr, NULL); } diff -u --recursive --new-file v2.2.9/linux/net/irda/irlan/irlan_event.c linux/net/irda/irlan/irlan_event.c --- v2.2.9/linux/net/irda/irlan/irlan_event.c Wed Mar 10 15:29:52 1999 +++ linux/net/irda/irlan/irlan_event.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Oct 20 09:10:16 1998 - * Modified at: Wed Feb 3 21:42:27 1999 + * Modified at: Sun May 9 21:17:44 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -38,22 +38,22 @@ "IRLAN_SYNC", }; -void irlan_next_client_state( struct irlan_cb *self, IRLAN_STATE state) +void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state) { DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]); - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRLAN_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRLAN_MAGIC, return;); self->client.state = state; } -void irlan_next_provider_state( struct irlan_cb *self, IRLAN_STATE state) +void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state) { DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]); - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRLAN_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRLAN_MAGIC, return;); self->provider.state = state; } diff -u --recursive --new-file v2.2.9/linux/net/irda/irlan/irlan_filter.c linux/net/irda/irlan/irlan_filter.c --- v2.2.9/linux/net/irda/irlan/irlan_filter.c Fri Apr 16 14:47:31 1999 +++ linux/net/irda/irlan/irlan_filter.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Fri Jan 29 11:16:38 1999 - * Modified at: Thu Feb 25 15:10:54 1999 + * Modified at: Sat May 8 15:25:23 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -41,29 +41,29 @@ (self->provider.filter_operation == DYNAMIC)) { DEBUG(0, "Giving peer a dynamic Ethernet address\n"); - self->provider.mac_address[0] = 0x40; self->provider.mac_address[1] = 0x00; self->provider.mac_address[2] = 0x00; self->provider.mac_address[3] = 0x00; /* Use arbitration value to generate MAC address */ - if (self->access_type == ACCESS_PEER) { + if (self->provider.access_type == ACCESS_PEER) { self->provider.mac_address[4] = self->provider.send_arb_val & 0xff; self->provider.mac_address[5] = (self->provider.send_arb_val >> 8) & 0xff;; } else { /* Just generate something for now */ - self->provider.mac_address[4] = jiffies & 0xff; - self->provider.mac_address[5] = (jiffies >> 8) & 0xff; + get_random_bytes(self->provider.mac_address+4, 1); + get_random_bytes(self->provider.mac_address+5, 1); } skb->data[0] = 0x00; /* Success */ skb->data[1] = 0x03; irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); irlan_insert_short_param(skb, "MAX_ENTRY", 0x0001); - irlan_insert_array_param(skb, "FILTER_ENTRY", self->provider.mac_address, 6); + irlan_insert_array_param(skb, "FILTER_ENTRY", + self->provider.mac_address, 6); return; } @@ -138,8 +138,7 @@ * Check parameters in request from peer device * */ -void irlan_check_command_param(struct irlan_cb *self, char *param, - char *value) +void irlan_check_command_param(struct irlan_cb *self, char *param, char *value) { __u8 *bytes; @@ -210,6 +209,12 @@ } } +/* + * Function irlan_print_filter (filter_type, buf) + * + * Print status of filter. Used by /proc file system + * + */ int irlan_print_filter(int filter_type, char *buf) { int len = 0; diff -u --recursive --new-file v2.2.9/linux/net/irda/irlan/irlan_provider.c linux/net/irda/irlan/irlan_provider.c --- v2.2.9/linux/net/irda/irlan/irlan_provider.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irlan/irlan_provider.c Sun May 30 10:17:04 1999 @@ -6,13 +6,14 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 14:28:52 1999 + * Modified at: Sun May 9 12:22:56 1999 * Modified by: Dag Brattli * Sources: skeleton.c by Donald Becker * slip.c by Laurence Culhane, * Fred N. van Kempen, * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -31,6 +32,7 @@ #include #include #include +#include #include #include @@ -50,14 +52,20 @@ #include #include +static void irlan_provider_connect_indication(void *instance, void *sap, + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb); + /* * Function irlan_provider_control_data_indication (handle, skb) * * This function gets the data that is received on the control channel * */ -int irlan_provider_data_indication(void *instance, void *sap, - struct sk_buff *skb) +static int irlan_provider_data_indication(void *instance, void *sap, + struct sk_buff *skb) { struct irlan_cb *self; __u8 code; @@ -111,14 +119,17 @@ * Got connection from peer IrLAN layer * */ -void irlan_provider_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) +static void irlan_provider_connect_indication(void *instance, void *sap, + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb) { - struct irlan_cb *self, *entry, *new; + struct irlan_cb *self, *new; struct tsap_cb *tsap; + __u32 saddr, daddr; - DEBUG(2, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); self = (struct irlan_cb *) instance; tsap = (struct tsap_cb *) sap; @@ -126,34 +137,69 @@ ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); + self->provider.max_sdu_size = max_sdu_size; + self->provider.max_header_size = max_header_size; + ASSERT(tsap == self->provider.tsap_ctrl,return;); ASSERT(self->provider.state == IRLAN_IDLE, return;); - /* Check if this provider is currently unused */ - if (self->daddr == DEV_ADDR_ANY) { - /* - * Rehash instance, now we have a client (daddr) to serve. - */ - entry = hashbin_remove(irlan, self->daddr, NULL); - ASSERT( entry == self, return;); - - self->daddr = irttp_get_daddr(tsap); - DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr); - hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL); + daddr = irttp_get_daddr(tsap); + saddr = irttp_get_saddr(tsap); + + /* Check if we already dealing with this client or peer */ + new = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL); + if (new) { + ASSERT(new->magic == IRLAN_MAGIC, return;); + DEBUG(0, __FUNCTION__ "(), found instance!\n"); + + /* Update saddr, since client may have moved to a new link */ + new->saddr = saddr; + DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", new->saddr); + + /* Make sure that any old provider control TSAP is removed */ + if ((new != self) && new->provider.tsap_ctrl) { + irttp_disconnect_request(new->provider.tsap_ctrl, + NULL, P_NORMAL); + irttp_close_tsap(new->provider.tsap_ctrl); + new->provider.tsap_ctrl = NULL; + } } else { - /* - * If we already have the daddr set, this means that the - * client must already have started (peer mode). We must - * make sure that this connection attempt is from the same - * device as the client is dealing with! + /* This must be the master instance, so start a new instance */ + DEBUG(0, __FUNCTION__ "(), starting new provider!\n"); + + new = irlan_open(saddr, daddr, TRUE); + } + + /* + * Check if the connection came in on the master server, or the + * slave server. If it came on the slave, then everything is + * really, OK (reconnect), if not we need to dup the connection and + * hand it over to the slave. + */ + if (new != self) { + + /* Now attach up the new "socket" */ + new->provider.tsap_ctrl = irttp_dup(self->provider.tsap_ctrl, + new); + if (!new->provider.tsap_ctrl) { + DEBUG(0, __FUNCTION__ "(), dup failed!\n"); + return; + } + + /* new->stsap_sel = new->tsap->stsap_sel; */ + new->dtsap_sel_ctrl = new->provider.tsap_ctrl->dtsap_sel; + + /* Clean up the original one to keep it in listen state */ + self->provider.tsap_ctrl->dtsap_sel = LSAP_ANY; + self->provider.tsap_ctrl->lsap->dlsap_sel = LSAP_ANY; + self->provider.tsap_ctrl->lsap->lsap_state = LSAP_DISCONNECTED; + + /* + * Use the new instance from here instead of the master + * struct! */ - ASSERT(self->daddr == irttp_get_daddr(tsap), return;); + self = new; } - - /* Update saddr, since client may have moved to a new link */ - self->saddr = irttp_get_saddr(tsap); - DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", self->saddr); - /* Check if network device has been registered */ if (!self->netdev_registered) irlan_register_netdev(self); @@ -165,9 +211,10 @@ * indication it needs to make progress. If the client is still in * IDLE state, we must kick it to */ - if ((self->access_type == ACCESS_PEER) && - (self->client.state == IRLAN_IDLE)) + if ((self->provider.access_type == ACCESS_PEER) && + (self->client.state == IRLAN_IDLE)) { irlan_client_wakeup(self, self->saddr, self->daddr); + } } /* @@ -225,6 +272,9 @@ ret = irlan_provider_parse_command(self, CMD_OPEN_DATA_CHANNEL, skb); + /* Open data channel */ + irlan_open_data_tsap(self); + return ret; } @@ -314,7 +364,7 @@ return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->provider.max_header_size); skb_put(skb, 2); switch (command) { @@ -334,6 +384,7 @@ } irlan_insert_short_param(skb, "IRLAN_VER", 0x0101); break; + case CMD_GET_MEDIA_CHAR: skb->data[0] = 0x00; /* Success */ skb->data[1] = 0x05; /* 5 parameters */ @@ -341,7 +392,7 @@ irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST"); irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST"); - switch(self->access_type) { + switch (self->provider.access_type) { case ACCESS_DIRECT: irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT"); break; diff -u --recursive --new-file v2.2.9/linux/net/irda/irlan/irlan_provider_event.c linux/net/irda/irlan/irlan_provider_event.c --- v2.2.9/linux/net/irda/irlan/irlan_provider_event.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irlan/irlan_provider_event.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 10:46:28 1999 + * Modified at: Fri May 7 10:53:58 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -108,7 +108,7 @@ switch(event) { case IRLAN_GET_INFO_CMD: /* Be sure to use 802.3 in case of peer mode */ - if (self->access_type == ACCESS_PEER) { + if (self->provider.access_type == ACCESS_PEER) { self->media = MEDIA_802_3; /* Check if client has started yet */ @@ -129,7 +129,7 @@ break; case IRLAN_OPEN_DATA_CMD: ret = irlan_parse_open_data_cmd(self, skb); - if (self->access_type == ACCESS_PEER) { + if (self->provider.access_type == ACCESS_PEER) { /* FIXME: make use of random functions! */ self->provider.send_arb_val = (jiffies & 0xffff); } @@ -205,8 +205,6 @@ static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, struct sk_buff *skb) { - struct irmanager_event mgr_event; - DEBUG(4, __FUNCTION__ "()\n"); ASSERT(self != NULL, return -1;); @@ -220,10 +218,6 @@ break; case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */ case IRLAN_LAP_DISCONNECT: - mgr_event.event = EVENT_IRLAN_STOP; - sprintf(mgr_event.devname, "%s", self->ifname); - irmanager_notify(&mgr_event); - irlan_next_provider_state(self, IRLAN_IDLE); break; default: diff -u --recursive --new-file v2.2.9/linux/net/irda/irlap_comp.c linux/net/irda/irlap_comp.c --- v2.2.9/linux/net/irda/irlap_comp.c Wed Mar 10 15:29:52 1999 +++ linux/net/irda/irlap_comp.c Sun May 30 10:17:04 1999 @@ -6,11 +6,11 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Fri Oct 9 09:18:07 1998 - * Modified at: Mon Feb 8 01:23:52 1999 + * Modified at: Sun May 9 11:37:06 1999 * Modified by: Dag Brattli * Sources: ppp.c, isdn_ppp.c * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -255,11 +255,11 @@ } /* FIXME: Find out what is the max overhead (not 10) */ - new_skb = dev_alloc_skb( skb->len+LAP_HEADER+10); + new_skb = dev_alloc_skb( skb->len+LAP_MAX_HEADER+10); if(!new_skb) return skb; - skb_reserve( new_skb, LAP_HEADER); + skb_reserve( new_skb, LAP_MAX_HEADER); skb_put( new_skb, skb->len+10); count = (self->compressor.cp->compress)( self->compressor.state, diff -u --recursive --new-file v2.2.9/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c --- v2.2.9/linux/net/irda/irlap_event.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irlap_event.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Aug 16 00:59:29 1997 - * Modified at: Fri Apr 23 11:55:12 1999 + * Modified at: Sun May 9 22:44:32 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * Thomas Davis * All Rights Reserved. * @@ -274,22 +274,22 @@ * Switches state and provides debug information * */ -void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state) +void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state) { - if ( !self || self->magic != LAP_MAGIC) + if (!self || self->magic != LAP_MAGIC) return; - DEBUG( 4, "next LAP state = %s\n", irlap_state[ state]); + DEBUG(4, "next LAP state = %s\n", irlap_state[ state]); self->state = state; /* * If we are swithing away from a XMIT state then we are allowed to * transmit a maximum number of bytes again when we enter the XMIT - * state again. Since its possible to "switch" from XMIT to XMIT and + * state again. Since its possible to "switch" from XMIT to XMIT, * we cannot do this when swithing into the XMIT state :-) */ - if (( state != LAP_XMIT_P) && ( state != LAP_XMIT_S)) + if ((state != LAP_XMIT_P) && (state != LAP_XMIT_S)) self->bytes_left = self->window_bytes; } @@ -310,7 +310,7 @@ ASSERT( self != NULL, return -1;); ASSERT( self->magic == LAP_MAGIC, return -1;); - switch( event) { + switch(event) { case CONNECT_REQUEST: ASSERT( self->irdev != NULL, return -1;); @@ -393,7 +393,6 @@ irlap_start_query_timer( self, QUERY_TIMEOUT); irlap_next_state( self, LAP_REPLY); } - dev_kfree_skb(skb); break; @@ -530,7 +529,7 @@ irlap_send_discovery_xid_frame(self, info->S, self->slot, FALSE, discovery_rsp); - + self->frame_sent = TRUE; irlap_next_state(self, LAP_REPLY); } @@ -568,27 +567,28 @@ switch (event) { case CONNECT_RESPONSE: - skb_pull( skb, 11); + /* skb_pull(skb, 11); */ + skb_pull(skb, sizeof(struct snrm_frame)); - ASSERT( self->irdev != NULL, return -1;); - irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb); + ASSERT(self->irdev != NULL, return -1;); + irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb); irlap_initiate_connection_state( self); /* * We are allowed to send two frames! */ - irlap_send_ua_response_frame( self, &self->qos_rx); - irlap_send_ua_response_frame( self, &self->qos_rx); + irlap_send_ua_response_frame(self, &self->qos_rx); + irlap_send_ua_response_frame(self, &self->qos_rx); - irlap_apply_connection_parameters( self, &self->qos_tx); + irlap_apply_connection_parameters(self, &self->qos_tx); /* * The WD-timer could be set to the duration of the P-timer - * for this case, but it is recommomended to use twice the + * for this case, but it is recommended to use twice the * value (note 3 IrLAP p. 60). */ - irlap_start_wd_timer( self, self->wd_timeout); + irlap_start_wd_timer(self, self->wd_timeout); irlap_next_state( self, LAP_NRM_S); break; @@ -669,28 +669,30 @@ * The device with the largest device address wins the battle * (both have sent a SNRM command!) */ - if ( info->daddr > self->saddr) { - del_timer( &self->final_timer); - irlap_initiate_connection_state( self); + if (info->daddr > self->saddr) { + del_timer(&self->final_timer); + irlap_initiate_connection_state(self); - ASSERT( self->irdev != NULL, return -1;); - irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb); + ASSERT(self->irdev != NULL, return -1;); + /* skb_pull(skb, 11); */ + skb_pull(skb, sizeof(struct snrm_frame)); + irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb); irlap_send_ua_response_frame(self, &self->qos_rx); - irlap_apply_connection_parameters( self, &self->qos_tx); - irlap_connect_confirm( self, skb); + irlap_apply_connection_parameters(self, &self->qos_tx); + irlap_connect_confirm(self, skb); /* * The WD-timer could be set to the duration of the - * P-timer for this case, but it is recommomended + * P-timer for this case, but it is recommended * to use twice the value (note 3 IrLAP p. 60). */ - irlap_start_wd_timer( self, self->wd_timeout); + irlap_start_wd_timer(self, self->wd_timeout); - irlap_next_state( self, LAP_NRM_S); + irlap_next_state(self, LAP_NRM_S); } else { /* We just ignore the other device! */ - irlap_next_state( self, LAP_SETUP); + irlap_next_state(self, LAP_SETUP); } break; case RECV_UA_RSP: @@ -702,9 +704,10 @@ /* Negotiate connection parameters */ ASSERT( skb->len > 10, return -1;); - skb_pull( skb, 10); + /* skb_pull(skb, 10); */ + skb_pull(skb, sizeof(struct ua_frame)); - ASSERT( self->irdev != NULL, return -1;); + ASSERT(self->irdev != NULL, return -1;); irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb); irlap_apply_connection_parameters( self, &self->qos_tx); @@ -1570,7 +1573,7 @@ /* * poll bit cleared? */ - if ( !info->pf) { + if (!info->pf) { self->vr = (self->vr + 1) % 8; /* Update Nr received */ @@ -1600,27 +1603,32 @@ * also before changing to XMIT_S * state. (note 1, IrLAP p. 82) */ - irlap_wait_min_turn_around( self, &self->qos_tx); - /* - * Any pending data requests? + irlap_wait_min_turn_around(self, &self->qos_tx); + + /* + * Give higher layers a chance to + * immediately reply with some data before + * we decide if we should send a RR frame + * or not */ - if (( skb_queue_len( &self->tx_list) > 0) && - ( self->window > 0)) + irlap_data_indication(self, skb); + + /* Any pending data requests? */ + if ((skb_queue_len(&self->tx_list) > 0) && + (self->window > 0)) { self->ack_required = TRUE; - del_timer( &self->wd_timer); + del_timer(&self->wd_timer); - irlap_next_state( self, LAP_XMIT_S); + irlap_next_state(self, LAP_XMIT_S); } else { - irlap_send_rr_frame( self, RSP_FRAME); - irlap_start_wd_timer( self, self->wd_timeout); + irlap_send_rr_frame(self, RSP_FRAME); + irlap_start_wd_timer(self, self->wd_timeout); /* Keep the state */ - irlap_next_state( self, LAP_NRM_S); + irlap_next_state(self, LAP_NRM_S); } - irlap_data_indication( self, skb); - break; } } diff -u --recursive --new-file v2.2.9/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c --- v2.2.9/linux/net/irda/irlap_frame.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irlap_frame.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Aug 19 10:27:26 1997 - * Modified at: Fri Apr 23 09:30:42 1999 + * Modified at: Sun May 9 22:55:11 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Resrved. + * Copyright (c) 1998-1999 Dag Brattli , All Rights Resrved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -1056,8 +1056,8 @@ * Receive and parse an Unnumbered Information (UI) frame * */ -static void irlap_recv_ui_frame( struct irlap_cb *self, struct sk_buff *skb, - struct irlap_info *info) +static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb, + struct irlap_info *info) { __u8 *frame; @@ -1254,7 +1254,7 @@ * Received S(upervisory) frame, check which frame type it is * only the first nibble is of interest */ - switch(control & 0x0f) { + switch (control & 0x0f) { case RR: irlap_recv_rr_frame( self, skb, &info, command); self->stats.rx_packets++; @@ -1279,7 +1279,7 @@ /* * This must be a C(ontrol) frame */ - switch(control) { + switch (control) { case XID_RSP: irlap_recv_discovery_xid_rsp(self, skb, &info); break; diff -u --recursive --new-file v2.2.9/linux/net/irda/irlmp.c linux/net/irda/irlmp.c --- v2.2.9/linux/net/irda/irlmp.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irlmp.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Stable. * Author: Dag Brattli * Created at: Sun Aug 17 20:54:32 1997 - * Modified at: Fri Apr 23 09:13:24 1999 + * Modified at: Sun May 9 22:45:06 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -197,7 +197,7 @@ } /* - * Function irlmp_close_lsap (self) + * Function __irlmp_close_lsap (self) * * Remove an instance of LSAP */ @@ -369,11 +369,11 @@ if (!skb) return -ENOMEM; - skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, LMP_MAX_HEADER); } else skb = userdata; - /* Make room for MUX control header ( 3 bytes) */ + /* Make room for MUX control header (3 bytes) */ ASSERT(skb_headroom(skb) >= LMP_CONTROL_HEADER, return -1;); skb_push(skb, LMP_CONTROL_HEADER); @@ -443,25 +443,36 @@ void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb) { int max_seg_size; - - DEBUG(3, __FUNCTION__ "()\n"); + int lap_header_size; + int max_header_size; ASSERT(self != NULL, return;); ASSERT(self->magic == LMP_LSAP_MAGIC, return;); ASSERT(skb != NULL, return;); ASSERT(self->lap != NULL, return;); + DEBUG(0, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", + self->slsap_sel, self->dlsap_sel); + self->qos = *self->lap->qos; - max_seg_size = self->lap->qos->data_size.value; - DEBUG(4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + lap_header_size = irlap_get_header_size(self->lap->irlap); + + max_seg_size = self->lap->qos->data_size.value-LMP_HEADER- + lap_header_size; + DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + max_header_size = LMP_HEADER + lap_header_size; + + DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size); + /* Hide LMP_CONTROL_HEADER header from layer above */ skb_pull(skb, LMP_CONTROL_HEADER); if (self->notify.connect_indication) self->notify.connect_indication(self->notify.instance, self, - &self->qos, max_seg_size, skb); + &self->qos, max_seg_size, + max_header_size, skb); } /* @@ -470,24 +481,22 @@ * Service user is accepting connection * */ -void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) +void irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) { - DEBUG(3, __FUNCTION__ "()\n"); - - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LSAP_MAGIC, return;); - ASSERT( userdata != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LSAP_MAGIC, return;); + ASSERT(userdata != NULL, return;); self->connected = TRUE; - DEBUG( 4, "irlmp_connect_response: slsap_sel=%02x, dlsap_sel=%02x\n", - self->slsap_sel, self->dlsap_sel); + DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", + self->slsap_sel, self->dlsap_sel); /* Make room for MUX control header ( 3 bytes) */ - ASSERT( skb_headroom( userdata) >= LMP_CONTROL_HEADER, return;); - skb_push( userdata, LMP_CONTROL_HEADER); + ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return;); + skb_push(userdata, LMP_CONTROL_HEADER); - irlmp_do_lsap_event( self, LM_CONNECT_RESPONSE, userdata); + irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata); } /* @@ -498,25 +507,35 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb) { int max_seg_size; + int max_header_size; + int lap_header_size; DEBUG(3, __FUNCTION__ "()\n"); - ASSERT( skb != NULL, return;); - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + ASSERT(skb != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LSAP_MAGIC, return;); - ASSERT( self->lap != NULL, return;); + ASSERT(self->lap != NULL, return;); self->qos = *self->lap->qos; - max_seg_size = self->qos.data_size.value; - DEBUG( 4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + lap_header_size = irlap_get_header_size(self->lap->irlap); + + max_seg_size = self->lap->qos->data_size.value-LMP_HEADER- + lap_header_size; + DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + max_header_size = LMP_HEADER + lap_header_size; + + DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size); + /* Hide LMP_CONTROL_HEADER header from layer above */ - skb_pull( skb, LMP_CONTROL_HEADER); + skb_pull(skb, LMP_CONTROL_HEADER); - if ( self->notify.connect_confirm) { - self->notify.connect_confirm( self->notify.instance, self, - &self->qos, max_seg_size, skb); + if (self->notify.connect_confirm) { + self->notify.connect_confirm(self->notify.instance, self, + &self->qos, max_seg_size, + max_header_size, skb); } } @@ -620,8 +639,8 @@ * * LSAP is being closed! */ -void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason, - struct sk_buff *userdata) +void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, + struct sk_buff *userdata) { struct lsap_cb *lsap; @@ -637,6 +656,10 @@ self->connected = FALSE; self->dlsap_sel = LSAP_ANY; +#ifdef CONFIG_IRDA_CACHE_LAST_LSAP + irlmp->cache.valid = FALSE; +#endif + /* * Remove association between this LSAP and the link it used */ @@ -975,7 +998,7 @@ DEBUG( 1, "irlmp_status_request(), Not implemented\n"); } -void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock) +void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock) { DEBUG( 4, "irlmp_status_indication(), Not implemented\n"); } @@ -1418,14 +1441,14 @@ * Give some info to the /proc file system * */ -int irlmp_proc_read( char *buf, char **start, off_t offset, int len, - int unused) +int irlmp_proc_read(char *buf, char **start, off_t offset, int len, + int unused) { struct lsap_cb *self; struct lap_cb *lap; unsigned long flags; - ASSERT( irlmp != NULL, return 0;); + ASSERT(irlmp != NULL, return 0;); save_flags( flags); cli(); @@ -1449,35 +1472,34 @@ } len += sprintf( buf+len, "\nRegistred Link Layers:\n"); - lap = (struct lap_cb *) hashbin_get_first( irlmp->links); - while ( lap != NULL) { - ASSERT( lap->magic == LMP_LAP_MAGIC, return 0;); - len += sprintf( buf+len, "lap state: %s, ", - irlmp_state[ lap->lap_state]); + lap = (struct lap_cb *) hashbin_get_first(irlmp->links); + while (lap != NULL) { + len += sprintf(buf+len, "lap state: %s, ", + irlmp_state[lap->lap_state]); - len += sprintf( buf+len, "saddr: %#08x, daddr: %#08x, ", - lap->saddr, lap->daddr); - len += sprintf( buf+len, "\n"); + len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ", + lap->saddr, lap->daddr); + len += sprintf(buf+len, "\n"); len += sprintf( buf+len, "\nConnected LSAPs:\n"); self = (struct lsap_cb *) hashbin_get_first( lap->lsaps); - while ( self != NULL) { - ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;); - len += sprintf( buf+len, "lsap state: %s, ", - irlsap_state[ self->lsap_state]); - len += sprintf( buf+len, - "slsap_sel: %#02x, dlsap_sel: %#02x, ", - self->slsap_sel, self->dlsap_sel); - len += sprintf( buf+len, "(%s)", self->notify.name); - len += sprintf( buf+len, "\n"); + while (self != NULL) { + ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;); + len += sprintf(buf+len, "lsap state: %s, ", + irlsap_state[ self->lsap_state]); + len += sprintf(buf+len, + "slsap_sel: %#02x, dlsap_sel: %#02x, ", + self->slsap_sel, self->dlsap_sel); + len += sprintf(buf+len, "(%s)", self->notify.name); + len += sprintf(buf+len, "\n"); - self = ( struct lsap_cb *) hashbin_get_next( + self = (struct lsap_cb *) hashbin_get_next( lap->lsaps); } + len += sprintf(buf+len, "\n"); - lap = ( struct lap_cb *) hashbin_get_next( - irlmp->links); + lap = (struct lap_cb *) hashbin_get_next(irlmp->links); } restore_flags( flags); diff -u --recursive --new-file v2.2.9/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c --- v2.2.9/linux/net/irda/irlmp_frame.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irlmp_frame.c Sun May 30 10:17:04 1999 @@ -1,15 +1,15 @@ /********************************************************************* * * Filename: irlmp_frame.c - * Version: 0.8 + * Version: 0.9 * Description: IrLMP frame implementation * Status: Experimental. * Author: Dag Brattli * Created at: Tue Aug 19 02:09:59 1997 - * Modified at: Fri Apr 23 09:12:23 1999 + * Modified at: Sun May 9 21:00:05 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli + * Copyright (c) 1998-1999 Dag Brattli * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -59,16 +59,16 @@ * * Send Link Control Frame to IrLAP */ -void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, - __u8 opcode, struct sk_buff *skb) +void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, + __u8 opcode, struct sk_buff *skb) { __u8 *frame; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LAP_MAGIC, return;); - ASSERT( skb != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LAP_MAGIC, return;); + ASSERT(skb != NULL, return;); frame = skb->data; @@ -82,8 +82,8 @@ else frame[3] = 0x00; /* rsvd */ - ASSERT( self->irlap != NULL, return;); - irlap_data_request( self->irlap, skb, TRUE); + ASSERT(self->irlap != NULL, return;); + irlap_data_request(self->irlap, skb, TRUE); } /* @@ -112,7 +112,7 @@ */ slsap_sel = fp[0] & LSAP_MASK; dlsap_sel = fp[1]; - + /* * Check if this is an incoming connection, since we must deal with * it in a different way than other established connections. @@ -224,11 +224,11 @@ * Incoming LAP connection! * */ -void irlmp_link_connect_indication( struct lap_cb *self, __u32 saddr, - __u32 daddr, struct qos_info *qos, - struct sk_buff *skb) +void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr, + __u32 daddr, struct qos_info *qos, + struct sk_buff *skb) { - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); /* Copy QoS settings for this session */ self->qos = qos; @@ -237,7 +237,7 @@ self->daddr = daddr; ASSERT(self->saddr == saddr, return;); - irlmp_do_lap_event( self, LM_LAP_CONNECT_INDICATION, skb); + irlmp_do_lap_event(self, LM_LAP_CONNECT_INDICATION, skb); } /* @@ -246,19 +246,19 @@ * LAP connection confirmed! * */ -void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, - struct sk_buff *userdata) +void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos, + struct sk_buff *userdata) { - DEBUG( 4, "irlmp_link_connect_confirm()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LAP_MAGIC, return;); - ASSERT( qos != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LAP_MAGIC, return;); + ASSERT(qos != NULL, return;); /* Copy QoS settings for this session */ self->qos = qos; - irlmp_do_lap_event( self, LM_LAP_CONNECT_CONFIRM, NULL); + irlmp_do_lap_event(self, LM_LAP_CONNECT_CONFIRM, NULL); } /* @@ -276,7 +276,9 @@ irlmp_add_discovery(irlmp->cachelog, discovery); /* Just handle it the same way as a discovery confirm */ +#if 0 irlmp_do_lap_event(self, LM_LAP_DISCOVERY_CONFIRM, NULL); +#endif } /* @@ -365,7 +367,7 @@ #endif return lsap; } - lsap = ( struct lsap_cb *) hashbin_get_next(queue); + lsap = (struct lsap_cb *) hashbin_get_next(queue); } /* Sorry not found! */ diff -u --recursive --new-file v2.2.9/linux/net/irda/irlpt/irlpt_cli.c linux/net/irda/irlpt/irlpt_cli.c --- v2.2.9/linux/net/irda/irlpt/irlpt_cli.c Tue May 11 13:10:32 1999 +++ linux/net/irda/irlpt/irlpt_cli.c Sun May 30 10:17:04 1999 @@ -51,10 +51,11 @@ static void irlpt_client_connect_confirm(void *instance, void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb); -static void irlpt_client_disconnect_indication( void *instance, void *sap, - LM_REASON reason, - struct sk_buff *userdata); +static void irlpt_client_disconnect_indication(void *instance, void *sap, + LM_REASON reason, + struct sk_buff *userdata); static void irlpt_client_expired(unsigned long data); #if 0 @@ -187,7 +188,7 @@ #ifdef CONFIG_PROC_FS create_proc_entry("irlpt_client", 0, proc_irda)->get_info - = irlpt_client_proc_read; + = irlpt_client_proc_read; #endif /* CONFIG_PROC_FS */ DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n"); @@ -215,7 +216,6 @@ #ifdef CONFIG_PROC_FS remove_proc_entry("irlpt_client", proc_irda); #endif - DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n"); } #endif /* MODULE */ @@ -403,9 +403,8 @@ irlpt_client_do_event( self, LMP_DISCONNECT, NULL, NULL); - if (skb) { + if (skb) dev_kfree_skb( skb); - } DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n"); } @@ -417,7 +416,8 @@ */ static void irlpt_client_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, + __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb) { struct irlpt_info info; @@ -443,14 +443,14 @@ } #endif - self->irlap_data_size = (qos->data_size.value - IRLPT_MAX_HEADER); + self->max_data_size = max_seg_size; + self->max_header_size = max_header_size; self->connected = TRUE; irlpt_client_do_event( self, LMP_CONNECT, NULL, NULL); - if (skb) { + if (skb) dev_kfree_skb( skb); - } DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n"); } @@ -603,7 +603,7 @@ return; } - skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, LMP_MAX_HEADER); irlmp_disconnect_request(self->lsap, skb); DEBUG(irlpt_client_debug, __FUNCTION__ ": irlmp_close_slap(self->lsap)\n"); diff -u --recursive --new-file v2.2.9/linux/net/irda/irlpt/irlpt_cli_fsm.c linux/net/irda/irlpt/irlpt_cli_fsm.c --- v2.2.9/linux/net/irda/irlpt/irlpt_cli_fsm.c Wed Mar 10 15:29:53 1999 +++ linux/net/irda/irlpt/irlpt_cli_fsm.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Jan 12 11:06:00 1999 - * Modified at: Tue Jan 26 12:02:31 1999 + * Modified at: Sun May 9 13:36:13 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998, Thomas Davis, + * Copyright (c) 1998-1999, Thomas Davis, * Copyright (c) 1998, Dag Brattli, * All Rights Reserved. * @@ -43,10 +43,10 @@ IRLPT_EVENT event, struct sk_buff *skb, struct irlpt_info *info); -static int irlpt_client_state_ready ( struct irlpt_cb *self, - IRLPT_EVENT event, - struct sk_buff *skb, - struct irlpt_info *info); +static int irlpt_client_state_ready ( struct irlpt_cb *self, + IRLPT_EVENT event, + struct sk_buff *skb, + struct irlpt_info *info); static int irlpt_client_state_waiti ( struct irlpt_cb *self, IRLPT_EVENT event, struct sk_buff *skb, diff -u --recursive --new-file v2.2.9/linux/net/irda/irlpt/irlpt_common.c linux/net/irda/irlpt/irlpt_common.c --- v2.2.9/linux/net/irda/irlpt/irlpt_common.c Wed Mar 10 15:29:53 1999 +++ linux/net/irda/irlpt/irlpt_common.c Sun May 30 10:17:04 1999 @@ -251,18 +251,18 @@ } DEBUG( irlpt_common_debug, __FUNCTION__ - ": count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n", - count, self->irlap_data_size, IRLPT_MAX_HEADER); + ": count = %d, max_data_size = %d, IRLPT_MAX_HEADER = %d\n", + count, self->max_data_size, IRLPT_MAX_HEADER); - if (count > (self->irlap_data_size - IRLPT_MAX_HEADER)) { - count = (self->irlap_data_size - IRLPT_MAX_HEADER); + if (count > self->max_data_size) { + count = self->max_data_size; DEBUG(irlpt_common_debug, __FUNCTION__ ": setting count to %d\n", count); } DEBUG( irlpt_common_debug, __FUNCTION__ ": count = %d\n", count); - skb = dev_alloc_skb(count + IRLPT_MAX_HEADER); + skb = dev_alloc_skb(count + self->max_header_size); if ( skb == NULL) { printk( KERN_INFO __FUNCTION__ ": couldn't allocate skbuff!\n"); @@ -417,7 +417,7 @@ return 0; } - skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve( skb, LMP_MAX_HEADER); irlmp_disconnect_request(self->lsap, skb); DEBUG(irlpt_common_debug, __FUNCTION__ ": irlmp_close_slap(self->lsap)\n"); diff -u --recursive --new-file v2.2.9/linux/net/irda/irlpt/irlpt_srvr.c linux/net/irda/irlpt/irlpt_srvr.c --- v2.2.9/linux/net/irda/irlpt/irlpt_srvr.c Tue May 11 13:10:32 1999 +++ linux/net/irda/irlpt/irlpt_srvr.c Sun May 30 10:17:04 1999 @@ -51,15 +51,21 @@ static void irlpt_server_disconnect_indication(void *instance, void *sap, LM_REASON reason, struct sk_buff *skb); + +#if 0 static void irlpt_server_connect_confirm(void *instance, void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb); static void irlpt_server_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb); +#endif + static int irlpt_server_data_indication(void *instance, void *sap, struct sk_buff *skb); static void register_irlpt_server(void); @@ -161,7 +167,6 @@ } extern struct proc_dir_entry *proc_irda; - #endif /* CONFIG_PROC_FS */ /* @@ -171,9 +176,9 @@ * */ -/*int irlpt_init( struct device *dev) {*/ __initfunc(int irlpt_server_init(void)) { + struct irmanager_event mgr_event; __u16 hints; DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n"); @@ -212,6 +217,10 @@ = irlpt_server_proc_read; #endif /* CONFIG_PROC_FS */ + mgr_event.event = EVENT_IRLPT_START; + sprintf(mgr_event.devname, "%s", irlpt_server->ifname); + irmanager_notify(&mgr_event); + DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n"); return 0; @@ -225,6 +234,7 @@ */ static void irlpt_server_cleanup(void) { + struct irmanager_event mgr_event; struct sk_buff *skb; DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n"); @@ -245,6 +255,10 @@ remove_proc_entry("irlpt_server", proc_irda); #endif + mgr_event.event = EVENT_IRLPT_STOP; + sprintf( mgr_event.devname, "%s", irlpt_server->ifname); + irmanager_notify( &mgr_event); + DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n"); } @@ -304,6 +318,7 @@ void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb) { struct irlpt_cb *self; @@ -314,6 +329,9 @@ ASSERT( self != NULL, return;); ASSERT( self->magic == IRLPT_MAGIC, return;); + self->max_data_size = max_seg_size; + self->max_header_size = max_header_size; + self->connected = TRUE; irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL); @@ -329,6 +347,7 @@ void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb) { struct irlpt_cb *self; @@ -343,14 +362,16 @@ ASSERT( self != NULL, return;); ASSERT( self->magic == IRLPT_MAGIC, return;); + self->max_data_size = max_seg_size; + self->max_header_size = max_header_size; + self->connected = IRLPT_CONNECTED; self->eof = FALSE; irlpt_server_do_event( self, LMP_CONNECT, NULL, &info); - if (skb) { + if (skb) dev_kfree_skb( skb); - } DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n"); } diff -u --recursive --new-file v2.2.9/linux/net/irda/irmod.c linux/net/irda/irmod.c --- v2.2.9/linux/net/irda/irmod.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irmod.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Dec 15 13:55:39 1997 - * Modified at: Mon Apr 12 11:31:01 1999 + * Modified at: Mon May 10 15:28:49 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -110,6 +110,7 @@ EXPORT_SYMBOL(irttp_flow_request); EXPORT_SYMBOL(irttp_connect_request); EXPORT_SYMBOL(irttp_udata_request); +EXPORT_SYMBOL(irttp_dup); /* Main IrDA module */ #ifdef CONFIG_IRDA_DEBUG @@ -151,6 +152,7 @@ EXPORT_SYMBOL(irlmp_disconnect_request); EXPORT_SYMBOL(irlmp_get_daddr); EXPORT_SYMBOL(irlmp_get_saddr); +EXPORT_SYMBOL(irlmp_dup); EXPORT_SYMBOL(lmp_reasons); /* Queue */ @@ -174,10 +176,15 @@ EXPORT_SYMBOL(irda_device_setup); EXPORT_SYMBOL(irda_device_set_media_busy); EXPORT_SYMBOL(irda_device_txqueue_empty); + +EXPORT_SYMBOL(irda_device_init_dongle); +EXPORT_SYMBOL(irda_device_register_dongle); +EXPORT_SYMBOL(irda_device_unregister_dongle); + EXPORT_SYMBOL(async_wrap_skb); EXPORT_SYMBOL(async_unwrap_char); EXPORT_SYMBOL(irda_start_timer); -EXPORT_SYMBOL(irda_get_mtt); +/* EXPORT_SYMBOL(irda_get_mtt); */ EXPORT_SYMBOL(setup_dma); #ifdef CONFIG_IRTTY @@ -505,19 +512,28 @@ #endif } -#ifdef MODULE -#ifdef CONFIG_PROC_FS +/* + * Function irda_proc_modcount (inode, fill) + * + * Use by the proc file system functions to prevent the irda module + * being removed while the use is standing in the net/irda directory + */ void irda_proc_modcount(struct inode *inode, int fill) { +#ifdef MODULE +#ifdef CONFIG_PROC_FS if (fill) MOD_INC_USE_COUNT; else MOD_DEC_USE_COUNT; -} #endif /* CONFIG_PROC_FS */ +#endif /* MODULE */ +} + +#ifdef MODULE MODULE_AUTHOR("Dag Brattli "); -MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); +MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); MODULE_PARM(irda_debug, "1l"); /* diff -u --recursive --new-file v2.2.9/linux/net/irda/irproc.c linux/net/irda/irproc.c --- v2.2.9/linux/net/irda/irproc.c Tue May 11 13:10:32 1999 +++ linux/net/irda/irproc.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Thomas Davis, * Created at: Sat Feb 21 21:33:24 1998 - * Modified at: Tue Apr 6 19:07:06 1999 + * Modified at: Fri May 7 08:06:49 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998, Thomas Davis, , + * Copyright (c) 1998-1999, Thomas Davis, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -20,8 +20,6 @@ * I, Thomas Davis, provide no warranty for any of this software. * This material is provided "AS-IS" and at no charge. * - * Portions lifted from the linux/fs/procfs/ files. - * ********************************************************************/ #include @@ -44,28 +42,27 @@ int unused); extern int discovery_proc_read(char *buf, char **start, off_t offset, int len, int unused); +static int proc_discovery_read(char *buf, char **start, off_t offset, int len, + int unused); -enum irda_directory_inos { - PROC_IRDA_LAP = 1, - PROC_IRDA_LMP, - PROC_IRDA_TTP, - PROC_IRDA_LPT, - PROC_IRDA_COMM, - PROC_IRDA_IRDA_DEVICE, - PROC_IRDA_IRIAS -}; +/* enum irda_directory_inos { */ +/* PROC_IRDA_LAP = 1, */ +/* PROC_IRDA_LMP, */ +/* PROC_IRDA_TTP, */ +/* PROC_IRDA_LPT, */ +/* PROC_IRDA_COMM, */ +/* PROC_IRDA_IRDA_DEVICE, */ +/* PROC_IRDA_IRIAS */ +/* }; */ struct irda_entry { char *name; - int (*fn)(char*,char**,off_t,int,int); + int (*fn)(char*, char**, off_t, int, int); }; struct proc_dir_entry *proc_irda; - + static struct irda_entry dir[] = { -#if 0 - {"lpt", irlpt_proc_read}, -#endif {"discovery", discovery_proc_read}, {"irda_device", irda_device_proc_read}, {"irttp", irttp_proc_read}, @@ -75,19 +72,22 @@ }; #define IRDA_ENTRIES_NUM (sizeof(dir)/sizeof(dir[0])) - + /* * Function irda_proc_register (void) * * Register irda entry in /proc file system * */ -void irda_proc_register(void) { +void irda_proc_register(void) +{ int i; + proc_irda = create_proc_entry("net/irda", S_IFDIR, NULL); #ifdef MODULE proc_irda->fill_inode = &irda_proc_modcount; #endif /* MODULE */ + for (i=0;iget_info=dir[i].fn; } @@ -98,9 +98,14 @@ * Unregister irda entry in /proc file system * */ -void irda_proc_unregister(void) { +void irda_proc_unregister(void) +{ int i; + for (i=0;i * Created at: Sun May 24 22:12:06 1998 - * Modified at: Fri Apr 23 09:46:38 1999 + * Modified at: Thu May 6 21:32:46 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as diff -u --recursive --new-file v2.2.9/linux/net/irda/irttp.c linux/net/irda/irttp.c --- v2.2.9/linux/net/irda/irttp.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/irttp.c Sun May 30 10:17:04 1999 @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:31 1997 - * Modified at: Sat Apr 10 10:32:21 1999 + * Modified at: Mon May 10 17:12:53 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -48,8 +48,10 @@ struct sk_buff *); static void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, - struct sk_buff *skb); - + __u8 header_size, struct sk_buff *skb); +static void irttp_connect_confirm(void *instance, void *sap, + struct qos_info *qos, __u32 max_sdu_size, + __u8 header_size, struct sk_buff *skb); static void irttp_run_tx_queue(struct tsap_cb *self); static void irttp_run_rx_queue(struct tsap_cb *self); @@ -337,6 +339,7 @@ /* Queue frame, or queue frame segments */ if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) { /* Queue frame */ + ASSERT(skb_headroom(skb) >= TTP_HEADER, return -1;); frame = skb_push(skb, TTP_HEADER); frame[0] = 0x00; /* Clear more bit */ @@ -360,8 +363,8 @@ self->tx_sdu_busy = TRUE; if (self->notify.flow_indication) { - self->notify.flow_indication( - self->notify.instance, self, FLOW_STOP); + self->notify.flow_indication(self->notify.instance, + self, FLOW_STOP); } } @@ -472,7 +475,7 @@ return; /* Reserve space for LMP, and LAP header */ - skb_reserve(tx_skb, LMP_HEADER+LAP_HEADER); + skb_reserve(tx_skb, self->max_header_size); /* * Since we can transmit and receive frames concurrently, @@ -655,15 +658,14 @@ return -ENOMEM; /* Reserve space for MUX_CONTROL and LAP header */ - skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER)); + skb_reserve(skb, TTP_MAX_HEADER); } else { skb = userdata; /* * Check that the client has reserved enough space for * headers */ - ASSERT(skb_headroom(userdata) >= - (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return -1;); + ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER, return -1;); } /* Initialize connection parameters */ @@ -691,12 +693,11 @@ /* SAR enabled? */ if (max_sdu_size > 0) { - ASSERT(skb_headroom(skb) >= - (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), - return -1;); + ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER), + return -1;); /* Insert SAR parameters */ - frame = skb_push(skb, TTP_HEADER_WITH_SAR); + frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER); frame[0] = TTP_PARAMETERS | n; frame[1] = 0x04; /* Length */ @@ -724,8 +725,10 @@ * Sevice user confirms TSAP connection with peer. * */ -void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_seg_size, struct sk_buff *skb) +static void irttp_connect_confirm(void *instance, void *sap, + struct qos_info *qos, + __u32 max_seg_size, __u8 max_header_size, + struct sk_buff *skb) { struct tsap_cb *self; int parameters; @@ -741,7 +744,8 @@ ASSERT(self->magic == TTP_TSAP_MAGIC, return;); ASSERT(skb != NULL, return;); - self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER; + self->max_seg_size = max_seg_size; + self->max_header_size = max_header_size + TTP_HEADER; /* * Check if we have got some QoS parameters back! This should be the @@ -797,9 +801,9 @@ skb_pull(skb, TTP_HEADER); if (self->notify.connect_confirm) { - self->notify.connect_confirm(self->notify.instance, self, - qos, self->tx_max_sdu_size, - skb); + self->notify.connect_confirm(self->notify.instance, self, qos, + self->tx_max_sdu_size, + self->max_header_size, skb); } } @@ -809,8 +813,8 @@ * Some other device is connecting to this TSAP * */ -void irttp_connect_indication(void *instance, void *sap, - struct qos_info *qos, __u32 max_seg_size, +void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos, + __u32 max_seg_size, __u8 max_header_size, struct sk_buff *skb) { struct tsap_cb *self; @@ -828,7 +832,9 @@ lsap = (struct lsap_cb *) sap; - self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER; + self->max_seg_size = max_seg_size; + + self->max_header_size = max_header_size+TTP_HEADER; DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel); @@ -850,7 +856,7 @@ switch (pl) { case 1: - self->tx_max_sdu_size = *(frame+4); + self->tx_max_sdu_size = frame[4]; break; case 2: self->tx_max_sdu_size = @@ -878,7 +884,7 @@ if (self->notify.connect_indication) { self->notify.connect_indication(self->notify.instance, self, qos, self->rx_max_sdu_size, - skb); + self->max_header_size, skb); } } @@ -909,15 +915,14 @@ return; /* Reserve space for MUX_CONTROL and LAP header */ - skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER)); + skb_reserve(skb, TTP_MAX_HEADER); } else { skb = userdata; /* * Check that the client has reserved enough space for * headers */ - ASSERT(skb_headroom(skb) >= - (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;); + ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return;); } self->avail_credit = 0; @@ -939,12 +944,11 @@ /* SAR enabled? */ if (max_sdu_size > 0) { - ASSERT(skb_headroom(skb) >= - (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), + ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER), return;); /* Insert TTP header with SAR parameters */ - frame = skb_push(skb, TTP_HEADER_WITH_SAR); + frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER); frame[0] = TTP_PARAMETERS | n; frame[1] = 0x04; /* Length */ @@ -1079,7 +1083,7 @@ /* * Reserve space for MUX and LAP header */ - skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, TTP_MAX_HEADER); userdata = skb; } @@ -1357,13 +1361,11 @@ } /* Make new segment */ - frag = dev_alloc_skb(self->max_seg_size+ - TTP_HEADER+LMP_HEADER+ - LAP_HEADER); + frag = dev_alloc_skb(self->max_seg_size+self->max_header_size); if (!frag) return; - skb_reserve(frag, LMP_HEADER+LAP_HEADER); + skb_reserve(frag, self->max_header_size); /* * Copy data from the original skb into this fragment. We diff -u --recursive --new-file v2.2.9/linux/net/irda/qos.c linux/net/irda/qos.c --- v2.2.9/linux/net/irda/qos.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/qos.c Sun May 30 10:17:04 1999 @@ -6,10 +6,11 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Sep 9 00:00:26 1997 - * Modified at: Mon Apr 12 11:49:24 1999 + * Modified at: Mon May 3 21:15:08 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-1999 Dag Brattli , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -52,10 +53,10 @@ * Compute the intersection of the old QoS capabilites with new ones * */ -void irda_qos_compute_intersection( struct qos_info *qos, struct qos_info *new) +void irda_qos_compute_intersection(struct qos_info *qos, struct qos_info *new) { - ASSERT( qos != NULL, return;); - ASSERT( new != NULL, return;); + ASSERT(qos != NULL, return;); + ASSERT(new != NULL, return;); /* Apply */ qos->baud_rate.bits &= new->baud_rate.bits; diff -u --recursive --new-file v2.2.9/linux/net/irda/wrapper.c linux/net/irda/wrapper.c --- v2.2.9/linux/net/irda/wrapper.c Wed Apr 28 11:37:32 1999 +++ linux/net/irda/wrapper.c Sun May 30 10:17:04 1999 @@ -1,15 +1,15 @@ /********************************************************************* * * Filename: wrapper.c - * Version: 1.1 - * Description: SIR wrapper layer + * Version: 1.2 + * Description: IrDA SIR async wrapper layer * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Wed Apr 21 12:45:55 1999 + * Modified at: Sun May 2 21:58:00 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -34,7 +34,20 @@ #include #include -inline static int stuff_byte(__u8 byte, __u8 *buf); +static inline int stuff_byte(__u8 byte, __u8 *buf); + +static void state_outside_frame(struct irda_device *idev, __u8 byte); +static void state_begin_frame(struct irda_device *idev, __u8 byte); +static void state_link_escape(struct irda_device *idev, __u8 byte); +static void state_inside_frame(struct irda_device *idev, __u8 byte); + +static void (*state[])(struct irda_device *idev, __u8 byte) = +{ + state_outside_frame, + state_begin_frame, + state_link_escape, + state_inside_frame, +}; /* * Function async_wrap (skb, *tx_buff) @@ -52,8 +65,6 @@ __u8 bytes[2]; } fcs; - ASSERT(skb != NULL, return 0;); - /* Initialize variables */ fcs.value = INIT_FCS; n = 0; @@ -74,13 +85,9 @@ } else xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs; -#if 0 - for (i=0; idata[i], tx_buff+n); - fcs.value = IR_FCS(fcs.value, skb->data[i]); + fcs.value = irda_fcs(fcs.value, skb->data[i]); } /* Insert CRC in little endian format (LSB first) */ @@ -108,15 +115,6 @@ #endif tx_buff[n++] = EOF; -#if 0 - { - int i; - - for (i=0;irx_buff.state) { - case OUTSIDE_FRAME: - switch(byte) { - case BOF: - idev->rx_buff.state = BEGIN_FRAME; - idev->rx_buff.in_frame = TRUE; - break; - case XBOF: - /* idev->xbofs++; */ - break; - case EOF: - irda_device_set_media_busy( idev, TRUE); - break; - default: - break; - } - break; - case BEGIN_FRAME: - switch (byte) { - case BOF: - /* Continue */ - break; - case CE: - /* Stuffed byte */ - idev->rx_buff.state = LINK_ESCAPE; - break; - case EOF: - /* Abort frame */ - idev->rx_buff.state = OUTSIDE_FRAME; - - idev->stats.rx_errors++; - idev->stats.rx_frame_errors++; - break; - default: - /* Got first byte of frame */ - idev->rx_buff.data = idev->rx_buff.head; - idev->rx_buff.len = 0; - - idev->rx_buff.data[idev->rx_buff.len++] = byte; - - idev->rx_buff.fcs = IR_FCS(INIT_FCS, byte); - idev->rx_buff.state = INSIDE_FRAME; - break; - } - break; - case LINK_ESCAPE: - switch (byte) { - case BOF: - /* New frame? */ - idev->rx_buff.state = BEGIN_FRAME; - irda_device_set_media_busy(idev, TRUE); - break; - case CE: - DEBUG(4, "WARNING: State not defined\n"); - break; - case EOF: - /* Abort frame */ - idev->rx_buff.state = OUTSIDE_FRAME; - break; - default: - /* - * Stuffed char, complement bit 5 of byte - * following CE, IrLAP p.114 - */ - byte ^= IR_TRANS; - if (idev->rx_buff.len < idev->rx_buff.truesize) { - idev->rx_buff.data[idev->rx_buff.len++] = byte; - idev->rx_buff.fcs = IR_FCS(idev->rx_buff.fcs, - byte); - idev->rx_buff.state = INSIDE_FRAME; - } else { - DEBUG(1, __FUNCTION__ - "(), Rx buffer overflow, aborting\n"); - idev->rx_buff.state = OUTSIDE_FRAME; - } - break; - } - break; - case INSIDE_FRAME: - switch (byte) { - case BOF: - /* New frame? */ - idev->rx_buff.state = BEGIN_FRAME; - irda_device_set_media_busy(idev, TRUE); - break; - case CE: - /* Stuffed char */ - idev->rx_buff.state = LINK_ESCAPE; - break; - case EOF: - /* End of frame */ - idev->rx_buff.state = OUTSIDE_FRAME; - idev->rx_buff.in_frame = FALSE; - - /* - * Test FCS and deliver frame if it's good - */ - if (idev->rx_buff.fcs == GOOD_FCS) { - async_bump(idev, idev->rx_buff.data, - idev->rx_buff.len); - } else { - /* Wrong CRC, discard frame! */ - irda_device_set_media_busy(idev, TRUE); - - idev->stats.rx_errors++; - idev->stats.rx_crc_errors++; - } - break; - default: - /* Next byte of frame */ - if (idev->rx_buff.len < idev->rx_buff.truesize) { - idev->rx_buff.data[idev->rx_buff.len++] = byte; - idev->rx_buff.fcs = IR_FCS(idev->rx_buff.fcs, - byte); - } else { - DEBUG(1, __FUNCTION__ - "(), Rx buffer overflow, aborting\n"); - idev->rx_buff.state = OUTSIDE_FRAME; - } - break; - } - break; - } -} - -/* * Function stuff_byte (byte, buf) * * Byte stuff one single byte and put the result in buffer pointed to by * buf. The buffer must at all times be able to have two bytes inserted. * */ -inline static int stuff_byte(__u8 byte, __u8 *buf) +static inline int stuff_byte(__u8 byte, __u8 *buf) { switch (byte) { case BOF: /* FALLTHROUGH */ @@ -303,7 +167,7 @@ case CE: /* Insert transparently coded */ buf[0] = CE; /* Send link escape */ - buf[1] = byte^IR_TRANS; /* Complement bit 5 */ + buf[1] = byte^IRDA_TRANS; /* Complement bit 5 */ return 2; /* break; */ default: @@ -313,7 +177,159 @@ /* break; */ } } + +/* + * Function async_unwrap (skb) + * + * Parse and de-stuff frame received from the IrDA-port + * + */ +inline void async_unwrap_char(struct irda_device *idev, __u8 byte) +{ + (*state[idev->rx_buff.state]) (idev, byte); +} +/* + * Function state_outside_frame (idev, byte) + * + * + * + */ +static void state_outside_frame(struct irda_device *idev, __u8 byte) +{ + switch (byte) { + case BOF: + idev->rx_buff.state = BEGIN_FRAME; + idev->rx_buff.in_frame = TRUE; + break; + case XBOF: + /* idev->xbofs++; */ + break; + case EOF: + irda_device_set_media_busy( idev, TRUE); + break; + default: + break; + } +} + +/* + * Function state_begin_frame (idev, byte) + * + * + * + */ +static void state_begin_frame(struct irda_device *idev, __u8 byte) +{ + switch (byte) { + case BOF: + /* Continue */ + break; + case CE: + /* Stuffed byte */ + idev->rx_buff.state = LINK_ESCAPE; + break; + case EOF: + /* Abort frame */ + idev->rx_buff.state = OUTSIDE_FRAME; + + idev->stats.rx_errors++; + idev->stats.rx_frame_errors++; + break; + default: + /* Got first byte of frame */ + idev->rx_buff.data = idev->rx_buff.head; + idev->rx_buff.len = 0; + + idev->rx_buff.data[idev->rx_buff.len++] = byte; + + idev->rx_buff.fcs = irda_fcs(INIT_FCS, byte); + idev->rx_buff.state = INSIDE_FRAME; + break; + } +} +/* + * Function state_link_escape (idev, byte) + * + * + * + */ +static void state_link_escape(struct irda_device *idev, __u8 byte) +{ + switch (byte) { + case BOF: /* New frame? */ + idev->rx_buff.state = BEGIN_FRAME; + irda_device_set_media_busy(idev, TRUE); + break; + case CE: + DEBUG(4, "WARNING: State not defined\n"); + break; + case EOF: /* Abort frame */ + idev->rx_buff.state = OUTSIDE_FRAME; + break; + default: + /* + * Stuffed char, complement bit 5 of byte + * following CE, IrLAP p.114 + */ + byte ^= IRDA_TRANS; + if (idev->rx_buff.len < idev->rx_buff.truesize) { + idev->rx_buff.data[idev->rx_buff.len++] = byte; + idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte); + idev->rx_buff.state = INSIDE_FRAME; + } else { + DEBUG(1, __FUNCTION__ + "(), Rx buffer overflow, aborting\n"); + idev->rx_buff.state = OUTSIDE_FRAME; + } + break; + } +} + +/* + * Function state_inside_frame (idev, byte) + * + * + * + */ +static void state_inside_frame(struct irda_device *idev, __u8 byte) +{ + switch (byte) { + case BOF: /* New frame? */ + idev->rx_buff.state = BEGIN_FRAME; + irda_device_set_media_busy(idev, TRUE); + break; + case CE: /* Stuffed char */ + idev->rx_buff.state = LINK_ESCAPE; + break; + case EOF: /* End of frame */ + idev->rx_buff.state = OUTSIDE_FRAME; + idev->rx_buff.in_frame = FALSE; + + /* Test FCS and deliver frame if it's good */ + if (idev->rx_buff.fcs == GOOD_FCS) { + async_bump(idev, idev->rx_buff.data, + idev->rx_buff.len); + } else { + /* Wrong CRC, discard frame! */ + irda_device_set_media_busy(idev, TRUE); + + idev->stats.rx_errors++; + idev->stats.rx_crc_errors++; + } + break; + default: /* Must be the next byte of the frame */ + if (idev->rx_buff.len < idev->rx_buff.truesize) { + idev->rx_buff.data[idev->rx_buff.len++] = byte; + idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte); + } else { + DEBUG(1, __FUNCTION__ + "(), Rx buffer overflow, aborting\n"); + idev->rx_buff.state = OUTSIDE_FRAME; + } + break; + } +} diff -u --recursive --new-file v2.2.9/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c --- v2.2.9/linux/net/netlink/af_netlink.c Fri Apr 16 14:47:31 1999 +++ linux/net/netlink/af_netlink.c Sun May 16 18:28:41 1999 @@ -203,7 +203,7 @@ */ while (netlink_locked(sk)) { - current->counter = 0; + current->policy |= SCHED_YIELD; schedule(); }