diff -u --recursive --new-file v1.3.32/linux/Documentation/networking/ppp.txt linux/Documentation/networking/ppp.txt --- v1.3.32/linux/Documentation/networking/ppp.txt Thu Jan 1 02:00:00 1970 +++ linux/Documentation/networking/ppp.txt Mon Oct 9 09:17:53 1995 @@ -0,0 +1,25 @@ +The PPP support for this kernel requires the 2.2.0a version of the +pppd daemon. You will find the current version of the daemon on +sunsite.unc.edu in the /pub/Linux/system/Network/serial directory. + +Sunsite has many mirror sites. Please feel free to obtain it from +a mirror site close to you. + +If you attempt to use a version of pppd which is not compatible +then you will have some error condition. It usually is reflected +in that an ioctl operation will generate a fatal error. + +Please do not use earlier versions of the 2.2 package. If you +obtained a copy from merit.edu or bellatrix then please get an +update from the sunsite site. + +The CCP (Compression Control Protocol) which is supported by this +code is functional. You will need a compatible BSD compressor on +your peer site to use the code. + +The BSD compression code will only build as a loadable module. There +was an earlier version which would build it into the kernel but that +functionality has been removed for various reasons. + +-- +Al Longyear longyear@netcom.com diff -u --recursive --new-file v1.3.32/linux/Documentation/smp.ez linux/Documentation/smp.ez --- v1.3.32/linux/Documentation/smp.ez Thu Jan 1 02:00:00 1970 +++ linux/Documentation/smp.ez Tue Oct 10 15:45:25 1995 @@ -0,0 +1,413 @@ +\begindata{text,748928} +\textdsversion{12} +\template{default} +\center{\underline{\bigger{\bigger{\bigger{An Implementation Of +Multiprocessor Linux + +}}}}} +\italic{ +}\indent{\indent{This document describes the implementation of a simple SMP +Linux kernel extension and how to use this to develop SMP Linux kernels for +architectures other than the Intel MP v1.1 architecture for Pentium and 486 +processors.}\italic{ + +}}\italic{ + + +Alan Cox, 1995 + + +The author wishes to thank Caldera Inc whose donation of an ASUS dual +pentium board made this project possible, and Thomas Radke, whose initial +work on multiprocessor Linux formed the backbone of this project. + +\begindata{bp,941568} +\enddata{bp,941568} +\view{bpv,941568,0,0,0} +} +\heading{Background: The Intel MP specification. + +} + Most IBM PC style multiprocessor motherboards combine Intel 486 or Pentium +processors and glue chipsets with a hardware/software specification. The +specification places much of the onus for hard work on the chipset and +hardware rather than the operating system. + + + The Intel pentium processors have a wide variety of inbuilt facilities for +supporting multiprocessing, including hardware cache coherency, built in +interprocessor interrupt handling and a set of atomic test and set, +exchange and similar operations. The cache coherency in paticular makes the +operating systems job far easier. + + + The specification defines a detailed configuration structure in ROM that +the boot up processor can read to find the full configuration of the +processors and busses. It also defines a procedure for starting up the +other processors. + + +\heading{Mutual Exclusion Within A Single Processor Linux Kernel + +} + For any kernel to function in a sane manner it has to provide internal +locking and protection of its own tables to prevent two processes updating +them at once and for example allocating the same memory block. There are +two strategies for this within current Unix and Unixlike kernels. +Traditional unix systems from the earliest of days use a scheme of 'Coarse +Grained Locking' where the entire kernel is protected as a small number of +locks only. Some modern systems use fine grained locking. Because fine +grained locking has more overhead it is normally used only on +multiprocessor kernels and real time kernels. In a real time kernel the +fine grained locking reduces the amount of time locks are held and reduces +the critical (to real time programming at least) latency times. + + + Within the Linux kernel certain guarantees are made. No process running in +kernel mode will be pre-empted by another kernel mode process unless it +voluntarily sleeps. This ensures that blocks of kernel code are +effectively atomic with respect to other processes and greatly simplifies +many operation. Secondly interrupts may pre-empt a kernel running process, +but will always return to that process. A process in kernel mode may +disable interrupts on the processor and guarantee such an interruption will +not occur. The final guarantee is that an interrupt will not bne pre-empted +by a kernel task. That is interrupts will run to completion or be +pre-empted by other interrupts only. + + + The SMP kernel chooses to continue these basic guarantees in order to make +initial implementation and deployment easier. A single lock is maintained +across all processors. This lock is required to access the kernel space. +Any processor may hold it and once it is held may also re-enter the kernel +for interrupts and other services whenever it likes until the lock is +relinquished. This lock ensures that a kernel mode process will not be +pre-empted and ensures that blocking interrupts in kernel mode behaves +correctly. This is guaranteed because only the processor holding the lock +can be in kernel mode, only kernel mode processes can disable interrupts +and only the processor holding the lock may handle an interrupt. + + + Such a choice is however poor for performance. In the longer term it is +neccessary to move to finer grained parallelism in order to get the best +system performance. This can be done heirarchically by gradually refining +the locks to cover smaller areas. With the current kernel highly CPU bound +process sets perform well but I/O bound task sets can easily degenerate to +near single processor performance levels. This refinement will be needed to +get the best from Linux/SMP. + + +\subheading{\heading{Changes To The Portable Kernel Components + + +}} The kernel changes are split into generic SMP support changes and +architecture specific changes neccessary to accomodate each different +processor type Linux is ported to. + + +\subsection{Initialisation} + + + The first problem with a multiprocessor kernel is starting the other +processors up. Linux/SMP defines that a single processor enters the normal +kernel entry point start_kernel(). Other processors are assumed not to be +started or to have been captured elsewhere. The first processor begins the +normal Linux initialisation sequences and sets up paging, interrupts and +trap handlers. After it has obtained the processor information about the +boot CPU, the architecture specific function \ + + +\description{ +\leftindent{\bold{void smp_store_cpu_info(int processor_id) + +}}} +is called to store any information about the processor into a per processor +array. This includes things like the bogomips speed ratings. + + + Having completed the kernel initialisation the architecture specific +function + + +\description{\leftindent{\bold{void smp_boot_cpus(void) + +}}} +is called and is expected to start up each other processor and cause it to +enter start_kernel() with its paging registers and other control +information correctly loaded. Each other processor skips the setup except +for calling the trap and irq initialisation functions that are needed on +some processors to set each CPU up correctly. These functions will +probably need to be modified in existing kernels to cope with this. + + + Each additional CPU the calls the architecture specific function + + +\description{\leftindent{\bold{void smp_callin(void) + + +}}}which does any final setup and then spins the processor while the boot +up processor forks off enough idle threads for each processor. This is +neccessary because the scheduler assumes there is always something to run. + Having generated these threads and forked init the architecture specific \ + + + +\bold{\description{\leftindent{void smp_commence(void)}}} + + +function is invoked. This does any final setup and indicates to the system +that multiprocessor mode is now active. All the processors spinning in the +smp_callin() function are now released to run the idle processes, which +they will run when they have no real work to process. + + +\subsection{Scheduling + +} + The kernel scheduler implements a simple but very and effective task +scheduler. The basic structure of this scheduler is unchanged in the +multiprocessor kernel. A processor field is added to each task, and this +maintains the number of the processor executing a given task, or a magic +constant (NO_PROC_ID) indicating the job is not allocated to a processor. \ + + + \ + + + Each processor executes the scheduler itself and will select the next task +to run from all runnable processes not allocated to a different processor. +The algorithm used by the selection is otherwise unchanged. This is +actually inadequate for the final system because there are advantages to +keeping a process on the same CPU, especially on processor boards with per +processor second level caches. + + + Throughout the kernel the variable 'current' is used as a global for the +current process. In Linux/SMP this becomes a macro which expands to +current_set[smp_processor_id()]. This enables almost the entire kernel to +be unaware of the array of running processors, but still allows the SMP +aware kernel modules to see all of the running processes. + + + The fork system call is modified to generate multiple processes with a +process id of zero until the SMP kernel starts up properly. This is +neccessary because process number 1 must be init, and it is desirable that +all the system threads are process 0. \ + + + + The final area within the scheduling of processes that does cause problems +is the fact the uniprocessor kernel hard codes tests for the idle threads +as task[0] and the init process as task[1]. Because there are multiple idle +threads it is neccessary to replace these with tests that the process id is +0 and a search for process ID 1, respectively. + +\subheading{ +}\subsection{Memory Management}\heading{ + + +} The memory management core of the existing Linux system functions +adequately within the multiprocessor framework providing the locking is +used. Certain processor specific areas do need changing, in paticular +invalidate() must invalidate the TLB's of all processors before it returns. + + +\subsection{Miscellaneous Functions} + +\heading{ +} The portable SMP code rests on a small set of functions and variables +that are provided by the processor specification functionality. These are + + +\display{\bold{int smp_processor_id(void) + + +}}which returns the identity of the process the call is executed upon. This +call is assumed to be valid at all times. This may mean additional tests +are needed during initialisation. + + + \display{\bold{int smp_num_cpus; + +}} + This is the number of processors in the system. \ + + + + \bold{void smp_message_pass(int target, int msg, unsigned long data, + + int wait) + +} + This function passes messages between processors. At the moment it is not +sufficiently defined to sensibly document and needs cleaning up and further +work. Refer to the processor specific code documentation for more details. + + +\heading{Architecture Specific Code For the Intel MP Port + +} + The architecture specific code for the intel port splits fairly cleanly +into four sections. Firstly the initialisation code used to boot the +system, secondly the message handling and support code, thirdly the +interrupt and kernel syscall entry function handling and finally the +extensions to standard kernel facilities to cope with multiple processors. + + +\subsection{Initialisation + + +} The intel MP architecture captures all the processors except for a single +processor known as the 'boot processor' in the BIOS at boot time. Thus a +single processor enters the kernel bootup code. The first processor +executes the bootstrap code, loads and uncompresses the kernel. Having +unpacked the kernel it sets up the paging and control registers then enters +the C kernel startup. + + + The assembler startup code for the kernel is modified so that it can be +used by the other processors to do the processor identification and various +other low level configurations but does not execute those parts of the +startup code that would damage the running system (such as clearing the BSS +segment). \ + + + + In the initialisation done by the first processor the arch/i386/mm/init +code is modified to scan the low page, top page and BIOS for intel MP +signature blocks. This is neccessary because the MP signature blocks must +be read and processed before the kernel is allowed to allocate and destroy +the page at the top of low memory. Having established the number of +processors it reserves a set of pages to provide a stack come boot up area +for each processor in the system. These must be allocated at startup to +ensure they fall below the 1Mb boundary. + + + Further processors are started up in smp_boot_cpus() by programming the +APIC controller registers and sending an inter-processor interrupt (IPI) to +the processor. This message causes the target processor to begin executing +code at the start of any page of memory within the lowest 1Mb, in 16bit +real mode. The kernel uses the single page it allocated for each processor +to use as stack. Before booting a given CPU the relocatable code from +trampoline.S and trampoline32.S is copied to the bottom of its stack page +and used as the target for the startup. \ + + + + The trampoline code calculates the desired stack base from the code +segment (since the code segment on startup is the bottom of the stack), + enters 32bit mode and jumps to the kernel entry assembler. This as +described above is modified to only execute the parts necessary for each +processor, and then to enter start_kernel(). On entering the kernel the +processor initialises its trap and interrupt handlers before entering +smp_callin(), where it reports its status and sets a flag that causes the +boot processor to continue and look for further processors. The processor +then spins until smp_commence() is invoked. + + + Having started each processor up the smp_commence( ) function flips a +flag. Each processor spinning in smp_callin() then loads the task register +with the task state segment (TSS) of its idle thread as is needed for task +switching. + + +\subsection{Message Handling and Support Code} + + + The architecture specific code implements the smp_processor_id() function +by querying the APIC logical identity register. Because the APIC isnt +mapped into the kernel address space at boot, the initial value returned is +rigged by setting the APIC base pointer to point at a suitable constant. +Once the system starts doing the SMP setup (in smp_boot_cpus()), the APIC +is mapped with a vremap() call and the apic pointer is adjusted +appropriately. From then on the real APIC logical identity register is +read. + + + Message passing is accomplished using a pair of IPI's on interrupt 13 +(unused by the 80486 FPU's in SMP mode) and interrupt 16. Two are used in +order to seperate messages that cannot be processed until the receiver +obtains the kernel spinlock from messages that can be processed +immediately. In effect IRQ 13 is a fast IRQ handler that does not obtain +the locks, and cannot cause a reschedule, while IRQ 16 is a slow IRQ that +must acquire the kernel spinlocks and can cause a reschedule. This +interrupt is used for passing on slave timer messages from the processor +that receives the timer interrupt to the rest of the processors, so that +they can reschedule running tasks. + + +\subsection{Entry And Exit Code} + + + A single spinlock protects the entire kernel. The interrupt handlers, the +syscall entry code and the exception handlers all acquire the lock before +entering the kernel proper. When the processor is trying to acquire the +spinlock it spins continually on the lock with interrupts disabled. This +causes a specific deadlock problem. The lock owner may need to send an +invalidate request to the rest of the processors and wait for these to +complete before continuing. A processor spinning on the lock would not be +able to do thus. Thus the loop of the spinlock tests and handles invalidate +requests. If the invalidate bit for the spinning CPU is set the processor +invalidates its TLB and atomically clears the bit. When the spinlock is +obtained that processor will take an IPI and in the IPI test the bit and +skip the invalidate as the bit is clear. + + + One complexity of the spinlock is that a process running in kernel mode +can sleep voluntarily and be pre-empted. A switch from such a process to a +process executing in user space may reduce the lock count. To track this +the kernel uses a syscall_count and a per process lock_depth parameter to +track the kernel lock state. The switch_to() function is modified in SMP +mode to adjust the lock appropriately. + + + The final problem is the idle thread. In the single processor kernel the +idle thread executes 'hlt' instructions. This saves power and reduces the +running temperature of the processors when they are idle. However it means +the process spends all its time in kernel mode and would thus hold the +kernel spinlock. The SMP idle thread continually reschedules a new task and +returns to user mode. This is far from ideal and will be modified to use +'hlt' instructions and release the spinlock soon. Using 'hlt' is even more +beneficial on a multiprocessor system as it almost completely takes an idle +processor off the bus. + + + Interrupts are distributed by an i82489 APIC. This chip is set up to work +as an emulation of the traditional PC interrupt controllers when the +machine boots (so that an Intel MP machine boots one CPU and PC +compatible). The kernel has all the relevant locks but does not yet +reprogram the 82489 to deliver interrupts to arbitary processors as it +should. This requires further modification of the standard Linux interrupt +handling code, and is paticularly messy as the interrupt handler behaviour +has to change as soon as the 82489 is switched into SMP mode. + + +\subsection{Extensions To Standard Facilities} + + + The kernel maintains a set of per processor control information such as +the speed of the processor for delay loops. These functions on the SMP +kernel look the values up in a per processor array that is set up from the +data generated at boot up by the smp_store_cpu_info() function. This +includes other facts such as whether there is an FPU on the processor. The +current kernel does not handle only some processors having floating point. + + + The highly useful atomic bit operations are prefixed with the 'lock' +prefix in the SMP kernel to maintain their atomic properties when used +outside of (and by) the spinlock and message code. Amongst other things +this is needed for the invalidate handler, as all CPU's will invalidate at +the same time without any locks. + + + Interrupt 13 floating point error reporting is removed. This facility is +not usable on a multiprocessor board, nor relevant to the Intel MP +architecture which does not cover the 80386/80387 processor pair. \ + + + + The /proc filesystem support is changed so that the /proc/cpuinfo file +contains a column for each processor present. This information is extracted +from the data save by smp_store_cpu_info(). + +\enddata{text,748928} diff -u --recursive --new-file v1.3.32/linux/Makefile linux/Makefile --- v1.3.32/linux/Makefile Fri Oct 6 14:35:13 1995 +++ linux/Makefile Fri Oct 6 14:35:44 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 3 -SUBLEVEL = 32 +SUBLEVEL = 33 ARCH = i386 diff -u --recursive --new-file v1.3.32/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v1.3.32/linux/arch/alpha/config.in Wed Sep 27 15:59:56 1995 +++ linux/arch/alpha/config.in Mon Oct 9 13:10:40 1995 @@ -39,6 +39,7 @@ if [ "$CONFIG_ALPHA_CABRIOLET" = "y" \ -o "$CONFIG_ALPHA_EB64" = "y" -o "$CONFIG_ALPHA_EB64P" = "y" ] then + bool 'Using SRM as bootloader' CONFIG_ALPHA_SRM n define_bool CONFIG_PCI y define_bool CONFIG_ALPHA_APECS y fi @@ -151,8 +152,8 @@ bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y fi tristate 'PPP (point-to-point) support' CONFIG_PPP n -if [ "$CONFIG_PPP" != "n" ]; then - bool ' 16 channels instead of 4' CONFIG_PPP_LOTS n +if [ ! "$CONFIG_PPP" = "n" ]; then +comment 'CCP compressors for PPP are only built as modules.' fi if [ "$CONFIG_AX25" = "y" ]; then bool 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC y diff -u --recursive --new-file v1.3.32/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v1.3.32/linux/arch/alpha/kernel/irq.c Wed Oct 4 14:14:28 1995 +++ linux/arch/alpha/kernel/irq.c Mon Oct 9 13:10:40 1995 @@ -578,7 +578,8 @@ machine_check(vector, la_ptr, ®s); break; case 3: -#if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME) +#if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME) || \ + defined(CONFIG_ALPHA_SRM) srm_device_interrupt(vector, ®s); #elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) cabriolet_and_eb66p_device_interrupt(vector, ®s); diff -u --recursive --new-file v1.3.32/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c --- v1.3.32/linux/arch/alpha/kernel/lca.c Fri Oct 6 14:35:13 1995 +++ linux/arch/alpha/kernel/lca.c Mon Oct 9 13:10:40 1995 @@ -305,10 +305,22 @@ +/* + * Constants used during machine-check handling. I suppose these + * could be moved into lca.h but I don't see much reason why anybody + * else would want to use them. + */ +#define ESR_EAV (1UL<< 0) /* error address valid */ +#define ESR_CEE (1UL<< 1) /* correctable error */ +#define ESR_UEE (1UL<< 2) /* uncorrectable error */ +#define ESR_NXM (1UL<<12) /* non-existent memory */ + + void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *regs) { const char * reason; union el_lca el; + char buf[128]; printk("lca: machine check (la=0x%lx)\n", la); el.c = (struct el_common *) la; @@ -332,31 +344,50 @@ case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break; case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break; case MCHK_K_UNKNOWN: - default: reason = "reason for machine-check unknown"; break; + default: + sprintf(buf, "reason for machine-check unknown (0x%lx)", el.s->reason); + reason = buf; + break; } + wrmces(rdmces()); /* reset machine check pending flag */ + switch (el.c->size) { case sizeof(struct el_lca_mcheck_short): printk(" Reason: %s (short frame%s):\n", - reason, el.h->retry ? ", retryable" : ""); - printk("\tesr: %lx ear: %lx\n", el.s->esr, el.s->ear); - printk("\tdc_stat: %lx ioc_stat0: %lx ioc_stat1: %lx\n", + reason, el.c->retry ? ", retryable" : ""); + printk(" esr: %lx ear: %lx\n", el.s->esr, el.s->ear); + printk(" dc_stat: %lx ioc_stat0: %lx ioc_stat1: %lx\n", el.s->dc_stat, el.s->ioc_stat0, el.s->ioc_stat1); + if (el.c->retry && + (el.s->esr & (ESR_EAV|ESR_CEE|ESR_UEE|ESR_NXM)) == (ESR_EAV|ESR_CEE)) + { + unsigned long addr, val; + + /* temporarily disable processor/system correctable error logging: */ + wrmces(0x18); + addr = el.s->ear & ~ (0x7<<29 | 0x7); + addr += IDENT_ADDR; + printk(" correcting quadword at address %lx\n", addr); + val = *(volatile long *)addr; + *(volatile long *)addr = val; + /* reenable all machine checks: */ + wrmces(0x00); + } break; case sizeof(struct el_lca_mcheck_long): printk(" Reason: %s (long frame%s):\n", - reason, el.h->retry ? ", retryable" : ""); - printk("\treason: %lx exc_addr: %lx dc_stat: %lx\n", + reason, el.c->retry ? ", retryable" : ""); + printk(" reason: %lx exc_addr: %lx dc_stat: %lx\n", el.l->pt[0], el.l->exc_addr, el.l->dc_stat); - printk("\tesr: %lx ear: %lx car: %lx\n", el.l->esr, el.l->ear, el.l->car); - printk("\tioc_stat0: %lx ioc_stat1: %lx\n", el.l->ioc_stat0, el.l->ioc_stat1); + printk(" esr: %lx ear: %lx car: %lx\n", el.l->esr, el.l->ear, el.l->car); + printk(" ioc_stat0: %lx ioc_stat1: %lx\n", el.l->ioc_stat0, el.l->ioc_stat1); break; default: printk(" Unknown errorlog size %d\n", el.c->size); } - wrmces(rdmces()); /* reset machine check asap */ } #endif /* CONFIG_ALPHA_LCA */ diff -u --recursive --new-file v1.3.32/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v1.3.32/linux/arch/alpha/kernel/process.c Fri Oct 6 14:35:13 1995 +++ linux/arch/alpha/kernel/process.c Mon Oct 9 13:10:40 1995 @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -144,8 +145,59 @@ /* * fill in the user structure for a core dump.. */ -void dump_thread(struct pt_regs * regs, struct user * dump) +void dump_thread(struct pt_regs * pt, struct user * dump) { + /* switch stack follows right below pt_regs: */ + struct switch_stack * sw = ((struct switch_stack *) pt) - 1; + + dump->magic = CMAGIC; + dump->start_code = current->mm->start_code; + dump->start_data = current->mm->start_data; + dump->start_stack = rdusp() & ~(PAGE_SIZE - 1); + dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT; + dump->u_dsize = (current->mm->brk + (PAGE_SIZE - 1) - dump->start_data) >> PAGE_SHIFT; + dump->u_ssize = + (current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT; + + /* + * We store the registers in an order/format that is + * compatible with DEC Unix/OSF/1 as this makes life easier + * for gdb. + */ + dump->regs[EF_V0] = pt->r0; + dump->regs[EF_T0] = pt->r1; + dump->regs[EF_T1] = pt->r2; + dump->regs[EF_T2] = pt->r3; + dump->regs[EF_T3] = pt->r4; + dump->regs[EF_T4] = pt->r5; + dump->regs[EF_T5] = pt->r6; + dump->regs[EF_T6] = pt->r7; + dump->regs[EF_T7] = pt->r8; + dump->regs[EF_S0] = sw->r9; + dump->regs[EF_S1] = sw->r10; + dump->regs[EF_S2] = sw->r11; + dump->regs[EF_S3] = sw->r12; + dump->regs[EF_S4] = sw->r13; + dump->regs[EF_S5] = sw->r14; + dump->regs[EF_S6] = sw->r15; + dump->regs[EF_A3] = pt->r19; + dump->regs[EF_A4] = pt->r20; + dump->regs[EF_A5] = pt->r21; + dump->regs[EF_T8] = pt->r22; + dump->regs[EF_T9] = pt->r23; + dump->regs[EF_T10] = pt->r24; + dump->regs[EF_T11] = pt->r25; + dump->regs[EF_RA] = pt->r26; + dump->regs[EF_T12] = pt->r27; + dump->regs[EF_AT] = pt->r28; + dump->regs[EF_SP] = rdusp(); + dump->regs[EF_PS] = pt->ps; + dump->regs[EF_PC] = pt->pc; + dump->regs[EF_GP] = pt->gp; + dump->regs[EF_A0] = pt->r16; + dump->regs[EF_A1] = pt->r17; + dump->regs[EF_A2] = pt->r18; + memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8); } /* diff -u --recursive --new-file v1.3.32/linux/arch/i386/config.in linux/arch/i386/config.in --- v1.3.32/linux/arch/i386/config.in Fri Oct 6 14:35:14 1995 +++ linux/arch/i386/config.in Tue Oct 10 15:45:26 1995 @@ -58,7 +58,7 @@ bool 'IP: firewall packet logging' CONFIG_IP_FIREWALL_VERBOSE y bool 'IP: masquerading (ALPHA)' CONFIG_IP_MASQUERADE n fi -if [ "$CONFIG_IP_FORWARD" = "y" -a "$CONFIG_IP_MULTICAST" = "y" -a "$CONFIG_NET_IPIP" = "y" ]; then +if [ "$CONFIG_IP_FORWARD" = "y" -a "$CONFIG_IP_MULTICAST" = "y" ]; then bool 'IP: multicast routing(in progress)' CONFIG_IP_MROUTE n fi comment '(it is safe to leave these untouched)' @@ -76,6 +76,9 @@ bool 'Amateur Radio NET/ROM' CONFIG_NETROM n fi bool 'Kernel/User network link driver(ALPHA)' CONFIG_NETLINK n +if [ "$CONFIG_NETLINK" = "y" ]; then + bool 'Routing messages' CONFIG_RTNETLINK y +fi fi comment 'SCSI support' @@ -137,17 +140,17 @@ comment 'Skipping network driver configuration options...' else -tristate 'Dummy net driver support' CONFIG_DUMMY y +tristate 'Dummy net driver support' CONFIG_DUMMY m tristate 'SLIP (serial line) support' CONFIG_SLIP n if [ "$CONFIG_SLIP" != "n" ]; then bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y fi tristate 'PPP (point-to-point) support' CONFIG_PPP n -if [ "$CONFIG_PPP" != "n" ]; then - bool ' 16 channels instead of 4' CONFIG_PPP_LOTS n +if [ ! "$CONFIG_PPP" = "n" ]; then +comment 'CCP compressors for PPP are only built as modules.' fi if [ "$CONFIG_AX25" = "y" ]; then - bool 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC y + bool 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC n else bool 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC n fi @@ -182,15 +185,15 @@ tristate 'EtherExpress support' CONFIG_EEXPRESS n bool 'NI5210 support' CONFIG_NI52 n bool 'NI6510 support' CONFIG_NI65 n - if [ "$CONFIG_AX25" = "y" ]; then - bool 'Ottawa PI and PI/2 support' CONFIG_PI y - fi tristate 'WaveLAN support' CONFIG_WAVELAN n fi tristate 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS n tristate 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN n tristate 'HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100 n tristate 'NE2000/NE1000 support' CONFIG_NE2000 y + if [ "$CONFIG_AX25" = "y" ]; then + bool 'Ottawa PI and PI/2 support' CONFIG_PI y + fi bool 'SK_G16 support' CONFIG_SK_G16 n fi bool 'EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA n diff -u --recursive --new-file v1.3.32/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v1.3.32/linux/arch/i386/kernel/Makefile Wed Oct 4 14:14:28 1995 +++ linux/arch/i386/kernel/Makefile Tue Oct 10 15:38:41 1995 @@ -33,6 +33,8 @@ hexify: $(HOSTCC) hexify.c -o hexify +smp.c: trampoline.hex + trampoline.hex: trampoline hexify (dd if=trampoline bs=1 skip=32 | ./hexify >trampoline.hex ) diff -u --recursive --new-file v1.3.32/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v1.3.32/linux/arch/i386/kernel/smp.c Wed Oct 4 14:14:28 1995 +++ linux/arch/i386/kernel/smp.c Tue Oct 10 15:45:26 1995 @@ -304,8 +304,14 @@ mpf->mpf_feature1); return; } + /* + * Read the physical hardware table. If there isn't one + * the processors present are 0 and 1. + */ if(mpf->mpf_physptr) smp_read_mpc((void *)mpf->mpf_physptr); + else + cpu_present_map=3; printk("Processors: %d\n", num_processors); } } diff -u --recursive --new-file v1.3.32/linux/drivers/block/aztcd.c linux/drivers/block/aztcd.c --- v1.3.32/linux/drivers/block/aztcd.c Mon Sep 18 14:53:49 1995 +++ linux/drivers/block/aztcd.c Tue Oct 10 11:10:42 1995 @@ -142,6 +142,7 @@ # ifndef CONFIG_MODVERSIONS char kernel_version[]= UTS_RELEASE; # endif +#define aztcd_init init_module #endif #include @@ -1524,22 +1525,15 @@ /* * Test for presence of drive and initialize it. Called at boot time. */ -#ifndef MODULE -unsigned long aztcd_init(unsigned long mem_start, unsigned long mem_end) -#else -int init_module(void) -#endif + +int aztcd_init(void) { long int count, max_count; unsigned char result[50]; int st; if (azt_port <= 0) { printk("aztcd: no Aztech CD-ROM Initialization"); -#ifndef MODULE - return (mem_start); -#else return -EIO; -#endif } printk("aztcd: Aztech, Orchid, Okano, Wearnes CD-ROM Driver (C) 1994,1995 W.Zimmermann\n"); printk("aztcd: DriverVersion=%s BaseAddress=0x%x \n",AZT_VERSION,azt_port); @@ -1547,22 +1541,14 @@ if (check_region(azt_port, 4)) { printk("aztcd: conflict, I/O port (%X) already used\n", azt_port); -#ifndef MODULE - return (mem_start); -#else return -EIO; -#endif } #ifdef AZT_SW32 /*CDROM connected to Soundwave32 card*/ if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) { printk("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n", AZT_SW32_BASE_ADDR,AZT_SW32_INIT,AZT_SW32_CONFIG_REG,AZT_SW32_ID_REG); -#ifndef MODULE - return (mem_start); -#else return -EIO; -#endif } else { printk("aztcd: Soundwave32 card detected at %x Version %x\n", @@ -1590,7 +1576,7 @@ #ifndef MODULE if (azt_cont!=0x79) { printk("aztcd: no AZTECH CD-ROM drive found-Try boot parameter aztcd=,0x79\n"); - return (mem_start); + return -EIO; } #else if (0) @@ -1611,11 +1597,7 @@ STEN_LOW; if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/ { printk("aztcd: no AZTECH CD-ROM drive found\n"); -#ifndef MODULE - return (mem_start); -#else return -EIO; -#endif } for (count = 0; count < AZT_TIMEOUT; count++); { count=count*2; /* delay a bit */ @@ -1623,11 +1605,7 @@ } if ((st=getAztStatus())==-1) { printk("aztcd: Drive Status Error Status=%x\n",st); -#ifndef MODULE - return (mem_start); -#else return -EIO; -#endif } #ifdef AZT_DEBUG printk("aztcd: Status = %x\n",st); @@ -1673,22 +1651,14 @@ for (count=1;count<5;count++) printk("%c",result[count]); printk("\n"); printk("aztcd: Aborted\n"); -#ifndef MODULE - return (mem_start); -#else return -EIO; -#endif } } if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) { printk("aztcd: Unable to get major %d for Aztech CD-ROM\n", MAJOR_NR); -#ifndef MODULE - return (mem_start); -#else return -EIO; -#endif } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = 4; @@ -1699,11 +1669,7 @@ aztPresent = 1; aztCloseDoor(); printk("aztcd: End Init\n"); -#ifndef MODULE - return (mem_start); -#else return (0); -#endif } diff -u --recursive --new-file v1.3.32/linux/drivers/block/blk.h linux/drivers/block/blk.h --- v1.3.32/linux/drivers/block/blk.h Mon Sep 18 14:53:49 1995 +++ linux/drivers/block/blk.h Tue Oct 10 15:52:51 1995 @@ -38,51 +38,51 @@ #define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) #ifdef CONFIG_CDU31A -extern unsigned long cdu31a_init(unsigned long, unsigned long); +extern int cdu31a_init(void); #endif CONFIG_CDU31A #ifdef CONFIG_MCD -extern unsigned long mcd_init(unsigned long, unsigned long); +extern int mcd_init(void); #endif CONFIG_MCD #ifdef CONFIG_MCDX -extern unsigned long mcdx_init(unsigned long, unsigned long); +extern int mcdx_init(void); #endif CONFIG_MCDX #ifdef CONFIG_SBPCD -extern unsigned long sbpcd_init(unsigned long, unsigned long); +extern int sbpcd_init(void); #endif CONFIG_SBPCD #ifdef CONFIG_AZTCD -extern unsigned long aztcd_init(unsigned long, unsigned long); +extern int aztcd_init(void); #endif CONFIG_AZTCD #ifdef CONFIG_CDU535 -extern unsigned long sony535_init(unsigned long, unsigned long); +extern int sony535_init(void); #endif CONFIG_CDU535 #ifdef CONFIG_GSCD -extern unsigned long gscd_init(unsigned long, unsigned long); +extern int gscd_init(void); #endif CONFIG_GSCD #ifdef CONFIG_CM206 -extern unsigned long cm206_init(unsigned long, unsigned long); +extern int cm206_init(void); #endif CONFIG_CM206 #ifdef CONFIG_OPTCD -extern unsigned long optcd_init(unsigned long, unsigned long); +extern int optcd_init(void); #endif CONFIG_OPTCD #ifdef CONFIG_SJCD -extern unsigned long sjcd_init(unsigned long, unsigned long); +extern int sjcd_init(void); #endif CONFIG_SJCD #ifdef CONFIG_BLK_DEV_HD -extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end); +extern int hd_init(void); #endif #ifdef CONFIG_BLK_DEV_IDE -extern unsigned long ide_init(unsigned long mem_start, unsigned long mem_end); +extern int ide_init(void); #endif +#ifdef CONFIG_BLK_DEV_XD +extern int xd_init(void); +#endif + extern void set_device_ro(kdev_t dev,int flag); extern int floppy_init(void); extern void rd_load(void); extern long rd_init(long mem_start, int length); extern int ramdisk_size; - -#ifdef CONFIG_BLK_DEV_XD -extern unsigned long xd_init(unsigned long mem_start, unsigned long mem_end); -#endif #define RO_IOCTLS(dev,where) \ case BLKROSET: if (!suser()) return -EACCES; \ diff -u --recursive --new-file v1.3.32/linux/drivers/block/cdu31a.c linux/drivers/block/cdu31a.c --- v1.3.32/linux/drivers/block/cdu31a.c Mon Sep 18 14:53:49 1995 +++ linux/drivers/block/cdu31a.c Tue Oct 10 11:11:36 1995 @@ -2918,13 +2918,12 @@ /* * Initialize the driver. */ -#ifndef MODULE -unsigned long -cdu31a_init(unsigned long mem_start, unsigned long mem_end) -#else -int -init_module(void) +#ifdef MODULE +#define cdu31a_init init_module #endif + +int +cdu31a_init(void) { struct s_sony_drive_config drive_config; unsigned int res_size; @@ -3000,11 +2999,7 @@ if (register_blkdev(MAJOR_NR,"cdu31a",&scd_fops)) { printk("Unable to get major %d for CDU-31a\n", MAJOR_NR); -#ifdef MODULE return -EIO; -#else - return mem_start; -#endif } if (SONY_HWC_DOUBLE_SPEED(drive_config)) @@ -3078,7 +3073,6 @@ disk_changed = 1; -#ifdef MODULE if (drive_found) { return(0); @@ -3087,9 +3081,6 @@ { return -EIO; } -#else - return mem_start; -#endif } #ifdef MODULE diff -u --recursive --new-file v1.3.32/linux/drivers/block/cm206.c linux/drivers/block/cm206.c --- v1.3.32/linux/drivers/block/cm206.c Mon Sep 18 14:53:49 1995 +++ linux/drivers/block/cm206.c Tue Oct 10 14:50:48 1995 @@ -84,7 +84,6 @@ #ifdef MODULE /* OK, so some of this is stolen */ #include #include -#include #ifndef CONFIG_MODVERSIONS char kernel_version[]=UTS_RELEASE; #endif @@ -102,6 +101,7 @@ #include #include #include +#include #include @@ -1064,9 +1064,7 @@ free_irq(cm206_irq); case 2: case 1: -#ifdef MODULE kfree(cd); -#endif release_region(cm206_base, 16); default: } @@ -1126,8 +1124,6 @@ #endif #ifdef MODULE -#define OK 0 -#define ERROR -EIO static int cm206[2] = {0,0}; /* for compatible `insmod' parameter passing */ void parse_options(void) @@ -1145,18 +1141,12 @@ } } -#else MODULE - -#define OK mem_start+size -#define ERROR mem_start +#define cm206_init init_module #endif MODULE -#ifdef MODULE -int init_module(void) -#else -unsigned long cm206_init(unsigned long mem_start, unsigned long mem_end) -#endif + +int cm206_init(void) { uch e=0; long int size=sizeof(struct cm206_struct); @@ -1171,16 +1161,12 @@ cm206_base = probe_base_port(auto_probe ? 0 : cm206_base); if (!cm206_base) { printk(" can't find adapter!\n"); - return ERROR; + return -EIO; } printk(" adapter at 0x%x", cm206_base); request_region(cm206_base, 16, "cm206"); -#ifdef MODULE cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL); - if (!cd) return ERROR; -#else - cd = (struct cm206_struct *) mem_start; -#endif + if (!cd) return -EIO; /* Now we have found the adaptor card, try to reset it. As we have * found out earlier, this process generates an interrupt as well, * so we might just exploit that fact for irq probing! */ @@ -1189,7 +1175,7 @@ if (cm206_irq<=0) { printk("can't find IRQ!\n"); cleanup(1); - return ERROR; + return -EIO; } else printk(" IRQ %d found\n", cm206_irq); #else @@ -1200,7 +1186,7 @@ { printk(" drive not there\n"); cleanup(1); - return ERROR; + return -EIO; } e = send_receive_polled(c_gimme); printk("Firmware revision %d", e & dcf_revision_code); @@ -1211,13 +1197,13 @@ if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206")) { printk("\nUnable to reserve IRQ---aborted\n"); cleanup(2); - return ERROR; + return -EIO; } printk(".\n"); if (register_blkdev(MAJOR_NR, "cm206", &cm206_fops) != 0) { printk("Cannot register for major %d!\n", MAJOR_NR); cleanup(3); - return ERROR; + return -EIO; } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = 16; /* reads ahead what? */ @@ -1231,10 +1217,8 @@ cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97; printk("%d kB adapter memory available, " " %ld bytes kernel memory used.\n", cd->max_sectors*2, size); - return OK; + return 0; } -#undef OK -#undef ERROR #ifdef MODULE void cleanup_module(void) diff -u --recursive --new-file v1.3.32/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v1.3.32/linux/drivers/block/genhd.c Wed Oct 4 14:14:29 1995 +++ linux/drivers/block/genhd.c Tue Oct 10 14:34:19 1995 @@ -23,6 +23,8 @@ #include #include +#include + struct gendisk *gendisk_head = NULL; static int current_minor = 0; @@ -30,6 +32,11 @@ extern void rd_load(void); extern int ramdisk_size; +extern int chr_dev_init(void); +extern int blk_dev_init(void); +extern int scsi_dev_init(void); +extern int net_dev_init(void); + static void print_minor_name (struct gendisk *hd, int minor) { unsigned int unit = minor >> hd->minor_shift; @@ -63,6 +70,12 @@ print_minor_name(hd, minor); } +static inline int is_extended_partition(struct partition *p) +{ + return (p->sys_ind == DOS_EXTENDED_PARTITION || + p->sys_ind == LINUX_EXTENDED_PARTITION); +} + #ifdef CONFIG_MSDOS_PARTITION /* * Create devices for each logical partition in an extended partition. @@ -120,7 +133,7 @@ * First process the data partition(s) */ for (i=0; i<4; i++, p++) { - if (!p->nr_sects || p->sys_ind == EXTENDED_PARTITION) + if (!p->nr_sects || is_extended_partition(p)) continue; /* Check the 3rd and 4th entries - @@ -149,7 +162,7 @@ */ p -= 4; for (i=0; i<4; i++, p++) - if(p->nr_sects && p->sys_ind == EXTENDED_PARTITION) + if(p->nr_sects && is_extended_partition(p)) break; if (i == 4) goto done; /* nothing left to do */ @@ -254,7 +267,7 @@ if (!p->nr_sects) continue; add_partition(hd, minor, first_sector+p->start_sect, p->nr_sects); - if (p->sys_ind == EXTENDED_PARTITION) { + if (is_extended_partition(p)) { printk(" <"); /* * If we are rereading the partition table, we need @@ -266,9 +279,10 @@ >> (BLOCK_SIZE_BITS - 9); extended_partition(hd, MKDEV(hd->major, minor)); printk(" >"); - /* prevent someone doing mkfs or mkswap on - an extended partition */ - hd->part[minor].nr_sects = 0; + /* prevent someone doing mkfs or mkswap on an + extended partition, but leave room for LILO */ + if (hd->part[minor].nr_sects > 2) + hd->part[minor].nr_sects = 2; } } /* @@ -456,13 +470,22 @@ struct gendisk *p; int nr=0; + chr_dev_init(); + blk_dev_init(); + sti(); +#ifdef CONFIG_SCSI + scsi_dev_init(); +#endif +#ifdef CONFIG_INET + net_dev_init(); +#endif console_map_init(); for (p = gendisk_head ; p ; p=p->next) { setup_dev(p); nr += p->nr_real; } - + if (ramdisk_size) rd_load(); } diff -u --recursive --new-file v1.3.32/linux/drivers/block/gscd.c linux/drivers/block/gscd.c --- v1.3.32/linux/drivers/block/gscd.c Mon Sep 18 14:53:49 1995 +++ linux/drivers/block/gscd.c Tue Oct 10 11:04:33 1995 @@ -121,7 +121,7 @@ /* common GoldStar Initialization */ -static long my_gscd_init (unsigned long , unsigned long); +static int my_gscd_init (void); /* lo-level cmd-Funktionen */ @@ -969,12 +969,12 @@ long err; - /* call the GoldStar-init with dummys */ - err = my_gscd_init ( 10, 20 ); + /* call the GoldStar-init */ + err = my_gscd_init ( ); if ( err < 0 ) { - return -EIO; + return err; } else { @@ -1006,18 +1006,15 @@ /* Test for presence of drive and initialize it. Called only at boot time. */ -unsigned long gscd_init (unsigned long mem_start, unsigned long mem_end) +int gscd_init (void) { -unsigned long err; - - err = my_gscd_init ( mem_start, mem_end ); - return ( labs(err)); + return my_gscd_init (); } /* This is the common initalisation for the GoldStar drive. */ /* It is called at boot time AND for module init. */ -long my_gscd_init (unsigned long mem_start, unsigned long mem_end) +int my_gscd_init (void) { int i; int result; @@ -1028,7 +1025,7 @@ if (check_region(gscd_port, 4)) { printk("GSCD: Init failed, I/O port (%X) already in use.\n", gscd_port); - return -mem_start; + return -EIO; } @@ -1037,7 +1034,7 @@ if ( result == 0x09 ) { printk ("GSCD: DMA kann ich noch nicht!\n" ); - return -mem_start; + return -EIO; } if ( result == 0x0b ) @@ -1047,14 +1044,14 @@ if ( i == 0 ) { printk ( "GSCD: GoldStar CD-ROM Drive is not found.\n" ); - return -mem_start; + return -EIO; } } if ( (result != 0x0b) && (result != 0x09) ) { printk ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n" ); - return -mem_start; + return -EIO; } /* reset all drives */ @@ -1072,7 +1069,7 @@ { printk("GSCD: Unable to get major %d for GoldStar CD-ROM\n", MAJOR_NR); - return -mem_start; + return -EIO; } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; @@ -1084,7 +1081,7 @@ request_region(gscd_port, 4, "gscd"); printk ( "GSCD: GoldStar CD-ROM Drive found.\n" ); - return mem_start; + return 0; } static void gscd_hsg2msf (long hsg, struct msf *msf) diff -u --recursive --new-file v1.3.32/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v1.3.32/linux/drivers/block/hd.c Mon Sep 18 14:53:49 1995 +++ linux/drivers/block/hd.c Tue Oct 10 11:08:09 1995 @@ -1047,18 +1047,18 @@ block_fsync /* fsync */ }; -unsigned long hd_init(unsigned long mem_start, unsigned long mem_end) +int hd_init(void) { if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { printk("hd: unable to get major %d for harddisk\n",MAJOR_NR); - return mem_start; + return -1; } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ hd_gendisk.next = gendisk_head; gendisk_head = &hd_gendisk; timer_table[HD_TIMER].fn = hd_times_out; - return mem_start; + return 0; } #define DEVICE_BUSY busy[target] diff -u --recursive --new-file v1.3.32/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v1.3.32/linux/drivers/block/ide.c Wed Oct 4 14:14:29 1995 +++ linux/drivers/block/ide.c Tue Oct 10 13:39:57 1995 @@ -171,6 +171,8 @@ #include #include #include +#include + #include #include #include @@ -458,6 +460,10 @@ for (unit = 0; unit < gd->nr_real; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; +#ifdef CONFIG_BLK_DEV_IDECD + if (drive->present && drive->media == cdrom) + ide_cdrom_setup(drive); +#endif /* CONFIG_BLK_DEV_IDECD */ drive->part[0].nr_sects = current_capacity(drive); if (!drive->present || drive->media != disk) { drive->part[0].start_sect = -1; /* skip partition check */ @@ -473,33 +479,6 @@ } /* - * ide_alloc(): memory allocation for use *only* during driver initialization. - * If "within_area" is non-zero, the memory will be allocated such that - * it lies entirely within a "within_area" sized area (eg. 4096). This is - * needed for DMA stuff. "within_area" must be a power of two (not validated). - * All allocations are longword aligned. - */ -static unsigned long ide_mem_start = 0uL; /* used by ide_alloc() */ - -void *ide_alloc (unsigned long bytecount, unsigned long within_area) -{ - const unsigned long longsize_m1 = (sizeof(long) - 1); - void *p; - - if (!ide_mem_start) - panic("ide: ide_alloc() not valid now\n"); - ide_mem_start = (ide_mem_start + longsize_m1) & ~longsize_m1; - if (within_area) { - unsigned long fraction = within_area - (ide_mem_start & (within_area - 1)); - if (fraction < bytecount) - ide_mem_start += fraction; /* realign to a new page */ - } - p = (void *) ide_mem_start; - ide_mem_start += (bytecount + longsize_m1) & ~longsize_m1; - return p; -} - -/* * init_gendisk() (as opposed to ide_geninit) is called for each major device, * after probing for drives, to allocate partition tables and other data * structures needed for the routines in genhd.c. ide_geninit() gets called @@ -517,10 +496,10 @@ break; } minors = units * (1<sizes = ide_alloc (minors * sizeof(int), 0); - gd->part = ide_alloc (minors * sizeof(struct hd_struct), 0); - bs = ide_alloc (minors*sizeof(int), 0); + gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL); + gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL); + gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL); + bs = kmalloc (minors*sizeof(int), GFP_KERNEL); /* cdroms and msdos f/s are examples of non-1024 blocksizes */ blksize_size[hwif->major] = bs; @@ -1980,7 +1959,7 @@ struct hd_driveid *id; unsigned long capacity, check; - id = drive->id = ide_alloc (SECTOR_WORDS*4, 0); + id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_KERNEL); ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */ sti(); @@ -2311,10 +2290,6 @@ for (unit = 0; unit < 2; ++unit) { /* note the hardcoded '2' */ ide_drive_t *drive = &hwif->drives[unit]; (void) probe_for_drive (drive); -#ifdef CONFIG_BLK_DEV_IDECD - if (drive->present && drive->media == cdrom) - ide_cdrom_setup(drive); -#endif /* CONFIG_BLK_DEV_IDECD */ } for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; @@ -2771,7 +2746,7 @@ * Got the irq, now set everything else up */ if ((hwgroup = irq_to_hwgroup[hwif->irq]) == NULL) { - hwgroup = ide_alloc (sizeof(ide_hwgroup_t), 0); + hwgroup = kmalloc (sizeof(ide_hwgroup_t), GFP_KERNEL); irq_to_hwgroup[hwif->irq] = hwgroup; hwgroup->hwif = hwif->next = hwif; hwgroup->rq = NULL; @@ -2941,11 +2916,10 @@ /* * This is gets invoked once during initialization, to set *everything* up */ -unsigned long ide_init (unsigned long mem_start, unsigned long mem_end) +int ide_init (void) { int h; - ide_mem_start = mem_start; /* for ide_alloc () */ init_ide_data (); /* * First, we determine what hardware is present @@ -3025,7 +2999,5 @@ hwif->present = 1; /* success */ } } - mem_start = ide_mem_start; - ide_mem_start = 0uL; /* prevent further use of ide_alloc() */ - return mem_start; + return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v1.3.32/linux/drivers/block/ll_rw_blk.c Mon Sep 18 14:53:50 1995 +++ linux/drivers/block/ll_rw_blk.c Tue Oct 10 10:18:45 1995 @@ -585,7 +585,7 @@ } } -long blk_dev_init(long mem_start, long mem_end) +int blk_dev_init(void) { struct request * req; @@ -596,13 +596,13 @@ } memset(ro_bits,0,sizeof(ro_bits)); #ifdef CONFIG_BLK_DEV_IDE - mem_start = ide_init(mem_start,mem_end); /* this MUST preceed hd_init */ + ide_init(); /* this MUST preceed hd_init */ #endif #ifdef CONFIG_BLK_DEV_HD - mem_start = hd_init(mem_start,mem_end); + hd_init(); #endif #ifdef CONFIG_BLK_DEV_XD - mem_start = xd_init(mem_start,mem_end); + xd_init(); #endif #ifdef CONFIG_BLK_DEV_FD floppy_init(); @@ -610,36 +610,34 @@ outb_p(0xc, 0x3f2); #endif #ifdef CONFIG_CDU31A - mem_start = cdu31a_init(mem_start,mem_end); + cdu31a_init(); #endif CONFIG_CDU31A #ifdef CONFIG_MCD - mem_start = mcd_init(mem_start,mem_end); + mcd_init(); #endif CONFIG_MCD #ifdef CONFIG_MCDX - mem_start = mcdx_init(mem_start,mem_end); + mcdx_init(); #endif CONFIG_MCDX #ifdef CONFIG_SBPCD - mem_start = sbpcd_init(mem_start, mem_end); + sbpcd_init(); #endif CONFIG_SBPCD #ifdef CONFIG_AZTCD - mem_start = aztcd_init(mem_start,mem_end); + aztcd_init(); #endif CONFIG_AZTCD #ifdef CONFIG_CDU535 - mem_start = sony535_init(mem_start,mem_end); + sony535_init(); #endif CONFIG_CDU535 #ifdef CONFIG_GSCD - mem_start = gscd_init(mem_start, mem_end); + gscd_init(); #endif CONFIG_GSCD #ifdef CONFIG_CM206 - mem_start = cm206_init(mem_start, mem_end); + cm206_init(); #endif #ifdef CONFIG_OPTCD - mem_start = optcd_init(mem_start,mem_end); + optcd_init(); #endif CONFIG_OPTCD #ifdef CONFIG_SJCD - mem_start = sjcd_init(mem_start,mem_end); + sjcd_init(); #endif CONFIG_SJCD - if (ramdisk_size) - mem_start += rd_init(mem_start, ramdisk_size*1024); - return mem_start; + return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/block/mcd.c linux/drivers/block/mcd.c --- v1.3.32/linux/drivers/block/mcd.c Mon Sep 18 14:53:50 1995 +++ linux/drivers/block/mcd.c Tue Oct 10 11:17:48 1995 @@ -70,6 +70,7 @@ # ifndef CONFIG_MODVERSIONS char kernel_version[]= UTS_RELEASE; # endif +#define mcd_init init_module #else # define MOD_INC_USE_COUNT # define MOD_DEC_USE_COUNT @@ -1169,23 +1170,15 @@ * Test for presence of drive and initialize it. Called at boot time. */ -#ifndef MODULE -unsigned long -mcd_init(unsigned long mem_start, unsigned long mem_end) -#else -int init_module(void) -#endif +int +mcd_init(void) { int count; unsigned char result[3]; if (mcd_port <= 0 || mcd_irq <= 0) { printk("skip mcd_init\n"); -#ifndef MODULE - return mem_start; -#else return -EIO; -#endif } printk("mcd=0x%x,%d: ", mcd_port, mcd_irq); @@ -1194,22 +1187,13 @@ { printk("Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR); -#ifndef MODULE - return mem_start; -#else return -EIO; -#endif - } if (check_region(mcd_port, 4)) { printk("Init failed, I/O port (%X) already in use\n", mcd_port); -#ifndef MODULE - return mem_start; -#else return -EIO; -#endif } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; @@ -1229,11 +1213,7 @@ if (count >= 2000000) { printk("Init failed. No mcd device at 0x%x irq %d\n", mcd_port, mcd_irq); -#ifndef MODULE - return mem_start; -#else return -EIO; -#endif } count = inb(MCDPORT(0)); /* pick up the status */ @@ -1242,19 +1222,11 @@ if(getValue(result+count)) { printk("mitsumi get version failed at 0x%d\n", mcd_port); -#ifndef MODULE - return mem_start; -#else return -EIO; -#endif } if (result[0] == result[1] && result[1] == result[2]) -#ifndef MODULE - return mem_start; -#else return -EIO; -#endif printk("Mitsumi status, type and version : %02X %c %x ", result[0],result[1],result[2]); @@ -1276,11 +1248,7 @@ if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD")) { printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq); -#ifndef MODULE - return mem_start; -#else return -EIO; -#endif } request_region(mcd_port, 4,"mcd"); @@ -1296,11 +1264,7 @@ mcd_invalidate_buffers(); mcdPresent = 1; -#ifndef MODULE - return mem_start; -#else return 0; -#endif } diff -u --recursive --new-file v1.3.32/linux/drivers/block/mcdx.c linux/drivers/block/mcdx.c --- v1.3.32/linux/drivers/block/mcdx.c Mon Sep 18 14:53:50 1995 +++ linux/drivers/block/mcdx.c Tue Oct 10 14:33:52 1995 @@ -191,7 +191,7 @@ changed elsewhere. */ /* declared in blk.h */ -unsigned long mcdx_init(unsigned long mem_start, unsigned long mem_end); +int mcdx_init(void); void do_mcdx_request(void); int check_mcdx_media_change(kdev_t); @@ -275,12 +275,6 @@ /* KERNEL INTERFACE FUNCTIONS **************************************/ -#ifdef MODULE -#define free(x, y) kfree((x)) -#else -#define free(x, y) (mem_start -= y) -#endif - static int mcdx_ioctl( struct inode* ip, struct file* fp, @@ -955,7 +949,7 @@ int i; int drives = 0; - mcdx_init(0, 0); + mcdx_init(); for (i = 0; i < MCDX_NDRIVES; i++) { if (mcdx_stuffp[i]) { TRACE((INIT, "init_module() drive %d stuff @ %p\n", @@ -1026,7 +1020,7 @@ } -unsigned long mcdx_init(unsigned long mem_start, unsigned long mem_end) +int mcdx_init(void) { int drive; @@ -1047,17 +1041,11 @@ TRACE((INIT, "init() try drive %d\n", drive)); -#ifdef MODULE TRACE((MALLOC, "init() malloc %d bytes\n", size)); if (!(stuffp = kmalloc(size, GFP_KERNEL))) { WARN(("init() malloc failed\n")); break; } -#else - TRACE((INIT, "adjust mem_start\n")); - stuffp = (struct s_drive_stuff *) mem_start; - mem_start += size; -#endif TRACE((INIT, "init() got %d bytes for drive stuff @ %p\n", sizeof(*stuffp), stuffp)); @@ -1084,7 +1072,7 @@ stuffp->wreg_data, stuffp->wreg_data + MCDX_IO_SIZE - 1)); TRACE((MALLOC, "init() free stuffp @ %p\n", stuffp)); - free(stuffp, size); + kfree(stuffp); TRACE((INIT, "init() continue at next drive\n")); continue; /* next drive */ } @@ -1101,7 +1089,7 @@ MCDX, stuffp->wreg_data, stuffp->irq)); TRACE((MALLOC, "init() free stuffp @ %p\n", stuffp)); - free(stuffp, size); + kfree(stuffp); TRACE((INIT, "init() continue at next drive\n")); continue; } @@ -1129,7 +1117,7 @@ if (!stuffp->present) { WARN(("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n", MCDX, stuffp->wreg_data, stuffp->irq)); - free(stuffp, size); + kfree(stuffp); continue; /* next drive */ } @@ -1138,7 +1126,7 @@ WARN(("%s=0x%3p,%d: Init failed. Can't get major %d.\n", MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR)); - free(stuffp, size); + kfree(stuffp); continue; /* next drive */ } @@ -1156,7 +1144,7 @@ MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq)); stuffp->irq = 0; - free(stuffp, size); + kfree(stuffp); continue; } request_region((unsigned int) stuffp->wreg_data, @@ -1188,7 +1176,7 @@ TRACE((INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp)); } - return mem_start; + return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/block/optcd.c linux/drivers/block/optcd.c --- v1.3.32/linux/drivers/block/optcd.c Sun Sep 3 12:26:51 1995 +++ linux/drivers/block/optcd.c Tue Oct 10 11:07:25 1995 @@ -58,6 +58,7 @@ # ifndef CONFIG_MODVERSIONS char kernel_version[]= UTS_RELEASE; # endif +#define optcd_init init_module #else # define MOD_INC_USE_COUNT # define MOD_DEC_USE_COUNT @@ -1402,28 +1403,19 @@ optcd_port = ints[1]; } -#ifndef MODULE -#define RETURN_EIO return mem_start -#else -#define RETURN_EIO return -EIO -#endif - /* * Test for presence of drive and initialize it. Called at boot time. */ -#ifndef MODULE -unsigned long optcd_init(unsigned long mem_start, unsigned long mem_end) { -#else -int init_module(void) { -#endif + +int optcd_init(void) { if (optcd_port <= 0) { printk("optcd: no Optics Storage CDROM Initialization\n"); - RETURN_EIO; + return -EIO; } if (check_region(optcd_port, 4)) { printk("optcd: conflict, I/O port 0x%x already used\n", optcd_port); - RETURN_EIO; + return -EIO; } if (!check_region(ISP16_DRIVE_SET_PORT, 5)) { @@ -1443,38 +1435,34 @@ if ( isp16_config( optcd_port, ISP16_SONY, 0, 0 ) < 0 ) { printk( "ISP16 cdrom interface has not been properly configured.\n" ); - RETURN_EIO; + return -EIO; } } } if (!optResetDrive()) { printk("optcd: drive at 0x%x not ready\n", optcd_port); - RETURN_EIO; + return -EIO; } if (!version_ok()) { printk("optcd: unknown drive detected; aborting\n"); - RETURN_EIO; + return -EIO; } if (optCmd(COMINITDOUBLE) < 0) { printk("optcd: cannot init double speed mode\n"); - RETURN_EIO; + return -EIO; } if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) { printk("optcd: unable to get major %d\n", MAJOR_NR); - RETURN_EIO; + return -EIO; } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = 4; request_region(optcd_port, 4, "optcd"); optPresent = 1; printk("optcd: 8000 AT CDROM at 0x%x\n", optcd_port); -#ifndef MODULE - return mem_start; -#else return 0; -#endif } #ifdef MODULE diff -u --recursive --new-file v1.3.32/linux/drivers/block/sbpcd.c linux/drivers/block/sbpcd.c --- v1.3.32/linux/drivers/block/sbpcd.c Mon Sep 18 14:53:51 1995 +++ linux/drivers/block/sbpcd.c Tue Oct 10 14:44:44 1995 @@ -314,19 +314,19 @@ */ #if !(SBPCD_ISSUE-1) #define DO_SBPCD_REQUEST(a) do_sbpcd_request(a) -#define SBPCD_INIT(a,b) sbpcd_init(a,b) +#define SBPCD_INIT(a) sbpcd_init(a) #endif #if !(SBPCD_ISSUE-2) #define DO_SBPCD_REQUEST(a) do_sbpcd2_request(a) -#define SBPCD_INIT(a,b) sbpcd2_init(a,b) +#define SBPCD_INIT(a) sbpcd2_init(a) #endif #if !(SBPCD_ISSUE-3) #define DO_SBPCD_REQUEST(a) do_sbpcd3_request(a) -#define SBPCD_INIT(a,b) sbpcd3_init(a,b) +#define SBPCD_INIT(a) sbpcd3_init(a) #endif #if !(SBPCD_ISSUE-4) #define DO_SBPCD_REQUEST(a) do_sbpcd4_request(a) -#define SBPCD_INIT(a,b) sbpcd4_init(a,b) +#define SBPCD_INIT(a) sbpcd4_init(a) #endif /*==========================================================================*/ #if SBPCD_DIS_IRQ @@ -406,13 +406,13 @@ */ #if !(SBPCD_ISSUE-1) #ifdef CONFIG_SBPCD2 -extern unsigned long sbpcd2_init(unsigned long, unsigned long); +extern int sbpcd2_init(void); #endif #ifdef CONFIG_SBPCD3 -extern unsigned long sbpcd3_init(unsigned long, unsigned long); +extern int sbpcd3_init(void); #endif #ifdef CONFIG_SBPCD4 -extern unsigned long sbpcd4_init(unsigned long, unsigned long); +extern int sbpcd4_init(void); #endif #endif @@ -5096,7 +5096,7 @@ #ifdef MODULE int init_module(void) #else - unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) +int SBPCD_INIT(void) #endif MODULE { int i=0, j=0; @@ -5279,7 +5279,6 @@ D_S[j].sbp_bufsiz=SBP_BUFFER_FRAMES; if (D_S[j].drv_type&drv_fam1) if (READ_AUDIO>0) D_S[j].sbp_audsiz=READ_AUDIO; -#ifdef MODULE D_S[j].sbp_buf=(u_char *) vmalloc(D_S[j].sbp_bufsiz*CD_FRAMESIZE); if (D_S[j].sbp_buf==NULL) { @@ -5293,15 +5292,6 @@ if (D_S[j].aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",D_S[j].sbp_audsiz); else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[j].sbp_audsiz); } -#else - D_S[j].sbp_buf=(u_char *)mem_start; - mem_start += D_S[j].sbp_bufsiz*CD_FRAMESIZE; - if (D_S[j].sbp_audsiz>0) - { - D_S[j].aud_buf=(u_char *)mem_start; - mem_start += D_S[j].sbp_audsiz*CD_FRAMESIZE_RAW; - } -#endif MODULE /* * set the block size */ @@ -5315,16 +5305,16 @@ init_done: #if !(SBPCD_ISSUE-1) #ifdef CONFIG_SBPCD2 - mem_start=sbpcd2_init(mem_start, mem_end); + sbpcd2_init(); #endif #ifdef CONFIG_SBPCD3 - mem_start=sbpcd3_init(mem_start, mem_end); + sbpcd3_init(); #endif #ifdef CONFIG_SBPCD4 - mem_start=sbpcd4_init(mem_start, mem_end); + sbpcd4_init(); #endif #endif - return (mem_start); + return 0; #endif MODULE } /*==========================================================================*/ diff -u --recursive --new-file v1.3.32/linux/drivers/block/sjcd.c linux/drivers/block/sjcd.c --- v1.3.32/linux/drivers/block/sjcd.c Mon Sep 18 14:53:51 1995 +++ linux/drivers/block/sjcd.c Tue Oct 10 10:49:56 1995 @@ -1353,7 +1353,7 @@ * Test for presence of drive and initialize it. Called at boot time. * Probe cdrom, find out version and status. */ -unsigned long sjcd_init( unsigned long mem_start, unsigned long mem_end ){ +int sjcd_init( void ){ int i; if ( (isp16_type=isp16_detect()) < 0 ) @@ -1368,13 +1368,13 @@ if ( isp16_config( sjcd_port, expected_drive, sjcd_irq, sjcd_dma ) < 0 ) { printk( "ISP16 cdrom interface has not been properly configured.\n" ); - return(mem_start); + return -1; } } if( register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){ printk( "Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR ); - return( mem_start ); + return -1; } blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST; @@ -1383,7 +1383,7 @@ if( check_region( sjcd_port, 4 ) ){ printk( "Init failed, I/O port (%X) is already in use\n", sjcd_port ); - return( mem_start ); + return -1; } printk( "Sanyo CDR-H94A:" ); @@ -1395,7 +1395,7 @@ if( !( inb( SJCDPORT( 1 ) ) & 0x04 ) ) break; if( i == 0 ){ printk( " No device at 0x%x found.\n", sjcd_port ); - return( mem_start ); + return -1; } sjcd_send_cmd( SCMD_RESET ); @@ -1412,7 +1412,7 @@ ( int )sjcd_version.minor ); } else { printk( " Read version failed.\n" ); - return( mem_start ); + return -1; } /* @@ -1427,7 +1427,7 @@ sjcd_port, sjcd_irq ); sjcd_present++; - return( mem_start ); + return 0; } /* diff -u --recursive --new-file v1.3.32/linux/drivers/block/sonycd535.c linux/drivers/block/sonycd535.c --- v1.3.32/linux/drivers/block/sonycd535.c Mon Sep 18 14:53:51 1995 +++ linux/drivers/block/sonycd535.c Tue Oct 10 14:50:30 1995 @@ -111,11 +111,11 @@ #ifdef MODULE # include -# include # include # ifndef CONFIG_MODVERSIONS char kernel_version[]= UTS_RELEASE; # endif +#define sony535_init init_module #else # define MOD_INC_USE_COUNT # define MOD_DEC_USE_COUNT @@ -131,6 +131,7 @@ #include #include #include +#include #define REALLY_SLOW_IO #include @@ -225,33 +226,31 @@ static int initialized = 0; /* Has the drive been initialized? */ static int sony_disc_changed = 1; /* Has the disk been changed - since the last check? */ + since the last check? */ static int sony_toc_read = 0; /* Has the table of contents been - read? */ + read? */ static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead - buffer. */ + buffer. */ static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of - the read-ahead buffer. */ + the read-ahead buffer. */ static unsigned int sony_usage = 0; /* How many processes have the - drive open. */ + drive open. */ static int sony_first_block = -1; /* First OS block (512 byte) in - the read-ahead buffer */ + the read-ahead buffer */ static int sony_last_block = -1; /* Last OS block (512 byte) in - the read-ahead buffer */ + the read-ahead buffer */ static struct s535_sony_toc *sony_toc; /* Points to the table of - contents. */ + contents. */ + static struct s535_sony_subcode *last_sony_subcode; /* Points to the last - subcode address read */ -#ifndef MODULE -static Byte *sony_buffer; /* Points to the read-ahead buffer */ -#else + subcode address read */ static Byte **sony_buffer; /* Points to the pointers - to the sector buffers */ -#endif + to the sector buffers */ + static int sony_inuse = 0; /* is the drive in use? Only one - open at a time allowed */ + open at a time allowed */ /* * The audio status uses the values from read subchannel data as specified @@ -607,25 +606,16 @@ * it returns one of the standard error returns. ***************************************************************************/ static int -#ifndef MODULE -seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2], - Byte * data_buff, int buf_size) -#else seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2], Byte **buff, int buf_size) -#endif { const int block_size = 2048; Byte cmd_buff[7]; int i; int read_status; int retry_count; -#ifndef MODULE - Byte *start_pos = data_buff; -#else Byte *data_buff; int sector_count = 0; -#endif if (buf_size < ((long)block_size) * n_blocks) return NO_ROOM; @@ -651,9 +641,7 @@ } if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) { /* data is ready, read it */ -#ifdef MODULE data_buff = buff[sector_count++]; -#endif for (i = 0; i < block_size; i++) *data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */ break; /* exit the timeout loop */ @@ -667,11 +655,7 @@ /* read all the data, now read the status */ if ((i = read_exec_status(status)) != 0) return i; -#ifndef MODULE - return data_buff - start_pos; -#else return block_size * sector_count; -#endif } /* seek_and_read_N_blocks() */ /**************************************************************************** @@ -938,14 +922,9 @@ * The data is in memory now, copy it to the buffer and advance to the * next block to read. */ -#ifndef MODULE - copyoff = (block - sony_first_block) * 512; - memcpy(CURRENT->buffer, sony_buffer + copyoff, 512); -#else copyoff = block - sony_first_block; memcpy(CURRENT->buffer, sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512); -#endif block += 1; nsect -= 1; @@ -1519,13 +1498,8 @@ /* * Initialize the driver. */ -#ifndef MODULE -unsigned long -sony535_init(unsigned long mem_start, unsigned long mem_end) -#else int -init_module(void) -#endif +sony535_init(void) { struct s535_sony_drive_config drive_config; Byte cmd_buff[3]; @@ -1533,13 +1507,11 @@ Byte status[2]; int retry_count; int tmp_irq; -#ifdef MODULE int i; -#endif /* Setting the base I/O address to 0 will disable it. */ if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0)) - goto bail; + return 0; /* Set up all the register locations */ result_reg = sony535_cd_base_io; @@ -1561,11 +1533,7 @@ #endif if (check_region(sony535_cd_base_io,4)) { printk(CDU535_MESSAGE_NAME ": my base address is not free!\n"); -#ifndef MODULE - return mem_start; -#else return -EIO; -#endif } /* look for the CD-ROM, follows the procedure in the DOS driver */ inb(select_unit_reg); @@ -1639,24 +1607,11 @@ if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { printk("Unable to get major %d for %s\n", MAJOR_NR, CDU535_MESSAGE_NAME); -#ifndef MODULE - return mem_start; -#else return -EIO; -#endif } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */ -#ifndef MODULE - sony_toc = (struct s535_sony_toc *)mem_start; - mem_start += sizeof *sony_toc; - last_sony_subcode = (struct s535_sony_subcode *)mem_start; - mem_start += sizeof *last_sony_subcode; - sony_buffer = (Byte *)mem_start; - mem_start += sony_buffer_size; - -#else /* MODULE */ sony_toc = (struct s535_sony_toc *) kmalloc(sizeof *sony_toc, GFP_KERNEL); if (sony_toc == NULL) @@ -1685,7 +1640,6 @@ return -ENOMEM; } } -#endif /* MODULE */ initialized = 1; } } @@ -1693,18 +1647,10 @@ if (!initialized) { printk("Did not find a " CDU535_MESSAGE_NAME " drive\n"); -#ifdef MODULE return -EIO; -#endif - } else { - request_region(sony535_cd_base_io, 4, CDU535_HANDLE); } -bail: -#ifndef MODULE - return mem_start; -#else + request_region(sony535_cd_base_io, 4, CDU535_HANDLE); return 0; -#endif } #ifndef MODULE diff -u --recursive --new-file v1.3.32/linux/drivers/block/triton.c linux/drivers/block/triton.c --- v1.3.32/linux/drivers/block/triton.c Wed Oct 4 14:14:29 1995 +++ linux/drivers/block/triton.c Tue Oct 10 12:02:16 1995 @@ -85,7 +85,9 @@ #include #include #include + #include +#include #include "ide.h" @@ -352,9 +354,9 @@ unsigned long *table; request_region(base, 8, hwif->name); hwif->dma_base = base; - table = ide_alloc(2 * PRD_ENTRIES * sizeof(long), 4096); + table = (void *) __get_dma_pages(GFP_KERNEL, 0); hwif->dmatable = table; - outl((unsigned long) table, base + 4); + outl(virt_to_bus(table), base + 4); hwif->dmaproc = &triton_dmaproc; } printk("\n %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d\n", diff -u --recursive --new-file v1.3.32/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v1.3.32/linux/drivers/block/xd.c Mon Sep 18 14:53:51 1995 +++ linux/drivers/block/xd.c Tue Oct 10 10:50:23 1995 @@ -115,18 +115,18 @@ static u_short xd_iobase = 0; /* xd_init: register the block device number and set up pointer tables */ -u_long xd_init (u_long mem_start,u_long mem_end) +int xd_init (void) { if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) { printk("xd_init: unable to get major number %d\n",MAJOR_NR); - return (mem_start); + return -1; } blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */ xd_gendisk.next = gendisk_head; gendisk_head = &xd_gendisk; - return mem_start; + return 0; } /* xd_detect: scan the possible BIOS ROM locations for the signature strings */ diff -u --recursive --new-file v1.3.32/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c --- v1.3.32/linux/drivers/char/atixlmouse.c Fri Sep 15 11:13:00 1995 +++ linux/drivers/char/atixlmouse.c Tue Oct 10 10:43:02 1995 @@ -13,6 +13,9 @@ #ifdef MODULE #include #include + +char kernel_version[] = UTS_RELEASE; +#define atixl_busmouse_init init_module #else #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT @@ -109,29 +112,31 @@ static void release_mouse(struct inode * inode, struct file * file) { + fasync_mouse(inode, file, 0); + if (--mouse.active) + return; ATIXL_MSE_INT_OFF(); /* Interrupts are really shut down here */ - mouse.active = 0; mouse.ready = 0; free_irq(ATIXL_MOUSE_IRQ); - fasync_mouse(inode, file, 0); + MOD_DEC_USE_COUNT; } static int open_mouse(struct inode * inode, struct file * file) { if (!mouse.present) return -EINVAL; - if (mouse.active) + if (mouse.active++) + return 0; + if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse")) { + mouse.active--; return -EBUSY; - mouse.active = 1; + } mouse.ready = 0; mouse.dx = 0; mouse.dy = 0; mouse.buttons = mouse.latch_buttons = 0; - if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse")) { - mouse.active = 0; - return -EBUSY; - } ATIXL_MSE_INT_ON(); /* Interrupts are really enabled here */ + MOD_INC_USE_COUNT; return 0; } @@ -200,13 +205,8 @@ ATIXL_BUSMOUSE, "atixl", &atixl_busmouse_fops }; -#ifdef MODULE -char kernel_version[] = UTS_RELEASE; -int init_module(void) -#else -unsigned long atixl_busmouse_init(unsigned long kmem_start) -#endif +int atixl_busmouse_init(void) { unsigned char a,b,c; @@ -217,11 +217,7 @@ printk("\nATI Inport "); else{ mouse.present = 0; -#ifdef MODULE return -EIO; -#else - return kmem_start; -#endif } outb(0x80, ATIXL_MSE_CONTROL_PORT); /* Reset the Inport device */ outb(0x07, ATIXL_MSE_CONTROL_PORT); /* Select Internal Register 7 */ @@ -234,18 +230,16 @@ mouse.wait = NULL; printk("Bus mouse detected and installed.\n"); mouse_register(&atixl_mouse); -#ifdef MODULE return 0; -#else - return kmem_start; -#endif } #ifdef MODULE void cleanup_module(void) { - if (MOD_IN_USE) + if (MOD_IN_USE) { printk("atixlmouse: in use, remove delayed\n"); + return; + } mouse_deregister(&atixl_mouse); } #endif diff -u --recursive --new-file v1.3.32/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c --- v1.3.32/linux/drivers/char/busmouse.c Fri Sep 15 11:13:00 1995 +++ linux/drivers/char/busmouse.c Tue Oct 10 10:43:54 1995 @@ -31,6 +31,9 @@ #ifdef MODULE #include #include + +char kernel_version[] = UTS_RELEASE; +#define bus_mouse_init init_module #else #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT @@ -113,37 +116,38 @@ } /* - * close access to the mouse (can deal with multiple - * opens if allowed in the future) + * close access to the mouse */ static void close_mouse(struct inode * inode, struct file * file) { - if (--mouse.active == 0) { - MSE_INT_OFF(); - free_irq(mouse_irq); - } fasync_mouse(inode, file, 0); + if (--mouse.active) + return; + MSE_INT_OFF(); + free_irq(mouse_irq); + MOD_DEC_USE_COUNT; } /* - * open access to the mouse, currently only one open is - * allowed. + * open access to the mouse */ static int open_mouse(struct inode * inode, struct file * file) { if (!mouse.present) return -EINVAL; - if (mouse.active) + if (mouse.active++) + return 0; + if (request_irq(mouse_irq, mouse_interrupt, 0, "Busmouse")) { + mouse.active--; return -EBUSY; + } mouse.ready = 0; mouse.dx = 0; mouse.dy = 0; mouse.buttons = 0x87; - if (request_irq(mouse_irq, mouse_interrupt, 0, "Busmouse")) - return -EBUSY; - mouse.active = 1; + MOD_INC_USE_COUNT; MSE_INT_ON(); return 0; } @@ -208,26 +212,16 @@ } /* - * select for mouse input, must disable the mouse interrupt while checking - * mouse.ready/select_wait() to avoid race condition (though in reality - * such a condition is not fatal to the proper operation of the mouse since - * multiple interrupts generally occur). + * select for mouse input */ - static int mouse_select(struct inode *inode, struct file *file, int sel_type, select_table * wait) { - int r = 0; - - if (sel_type == SEL_IN) { - MSE_INT_OFF(); - if (mouse.ready) { - r = 1; - } else { - select_wait(&mouse.wait, wait); + if (sel_type == SEL_IN) { + if (mouse.ready) + return 1; + select_wait(&mouse.wait, wait); } - MSE_INT_ON(); - } - return(r); + return 0; } struct file_operations bus_mouse_fops = { @@ -248,13 +242,7 @@ LOGITECH_BUSMOUSE, "busmouse", &bus_mouse_fops }; -#ifdef MODULE -char kernel_version[] = UTS_RELEASE; - -int init_module(void) -#else -unsigned long bus_mouse_init(unsigned long kmem_start) -#endif +int bus_mouse_init(void) { int i; @@ -264,11 +252,7 @@ /* busy loop */; if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) { mouse.present = 0; -#ifdef MODULE return -EIO; -#else - return kmem_start; -#endif } outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT); MSE_INT_OFF(); @@ -282,11 +266,7 @@ printk("Logitech Bus mouse detected and installed with IRQ %d.\n", mouse_irq); mouse_register(&bus_mouse); -#ifdef MODULE return 0; -#else - return kmem_start; -#endif } #ifdef MODULE diff -u --recursive --new-file v1.3.32/linux/drivers/char/console.c linux/drivers/char/console.c --- v1.3.32/linux/drivers/char/console.c Wed Sep 27 15:59:57 1995 +++ linux/drivers/char/console.c Tue Oct 10 12:19:12 1995 @@ -16,7 +16,7 @@ * 'int vc_resize(unsigned long lines, unsigned long cols)' * 'void vc_disallocate(unsigned int currcons)' * - * 'long con_init(long)' + * 'unsigned long con_init(unsigned long)' * 'int con_open(struct tty_struct *tty, struct file * filp)' * 'void con_write(struct tty_struct * tty)' * 'void console_print(const char * b)' @@ -1369,6 +1369,7 @@ clr_kbd(kbdapplic); clr_kbd(lnm); kbd_table[currcons].lockstate = 0; + kbd_table[currcons].slockstate = 0; kbd_table[currcons].ledmode = LED_SHOW_FLAGS; kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate; set_leds(); @@ -1990,7 +1991,7 @@ } /* - * long con_init(long); + * unsigned long con_init(unsigned long); * * This routine initializes console interrupts, and does nothing * else. If you want the screen to clear, call tty_write with @@ -1999,7 +2000,7 @@ * Reads the information preserved by setup.s to determine the current display * type and sets everything accordingly. */ -long con_init(long kmem_start) +unsigned long con_init(unsigned long kmem_start) { const char *display_desc = "????"; int currcons = 0; diff -u --recursive --new-file v1.3.32/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v1.3.32/linux/drivers/char/cyclades.c Mon Sep 18 14:53:52 1995 +++ linux/drivers/char/cyclades.c Tue Oct 10 10:41:02 1995 @@ -20,8 +20,8 @@ * This version does not support shared irq's. * * This module exports the following rs232 io functions: - * long cy_init(long); - * int cy_open(struct tty_struct *tty, struct file *filp); + * int cy_init(void); + * int cy_open(struct tty_struct *tty, struct file *filp); * * $Log: cyclades.c,v $ * Revision 1.36.3.2 1995/09/08 22:07:14 bentson @@ -2729,8 +2729,8 @@ If there are more cards with more ports than have been statically allocated above, a warning is printed and the extra ports are ignored. */ -long -cy_init(long kmem_start) +int +cy_init(void) { struct cyclades_port *info; struct cyclades_card *cinfo; @@ -2873,7 +2873,7 @@ /* info->timeout */ } } - return kmem_start; + return 0; } /* cy_init */ diff -u --recursive --new-file v1.3.32/linux/drivers/char/istallion.c linux/drivers/char/istallion.c --- v1.3.32/linux/drivers/char/istallion.c Fri Sep 15 11:13:00 1995 +++ linux/drivers/char/istallion.c Tue Oct 10 10:39:37 1995 @@ -226,14 +226,6 @@ INIT_C_CC }; -/* - * Memory allocation vars. These keep track of what memory allocation - * we can currently use. They help deal with memory in a consistent - * way, whether during init or run-time. - */ -static int stli_meminited = 0; -static long stli_memend; - /*****************************************************************************/ /* @@ -587,13 +579,10 @@ #ifdef MODULE int init_module(void); void cleanup_module(void); -#else -static void stli_meminit(long base); -static long stli_memhalt(void); #endif static void *stli_memalloc(int len); -long stli_init(long kmem_start); +int stli_init(void); static int stli_open(struct tty_struct *tty, struct file *filp); static void stli_close(struct tty_struct *tty, struct file *filp); static int stli_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count); @@ -738,7 +727,7 @@ save_flags(flags); cli(); - stli_init(0); + stli_init(); restore_flags(flags); return(0); @@ -824,33 +813,9 @@ * which are tightly controlled. */ -#ifndef MODULE - -static void stli_meminit(long base) -{ - stli_memend = base; - stli_meminited = 1; -} - -static long stli_memhalt() -{ - stli_meminited = 0; - return(stli_memend); -} - -#endif - static void *stli_memalloc(int len) { - void *mem; - - if (stli_meminited) { - mem = (void *) stli_memend; - stli_memend += len; - } else { - mem = (void *) kmalloc(len, GFP_KERNEL); - } - return(mem); + return (void *) kmalloc(len, GFP_KERNEL); } /*****************************************************************************/ @@ -4015,14 +3980,10 @@ /*****************************************************************************/ -long stli_init(long kmem_start) +int stli_init(void) { printk("%s: version %s\n", stli_drvname, stli_drvversion); -#ifndef MODULE - stli_meminit(kmem_start); -#endif - stli_brdinit(); /* @@ -4087,10 +4048,7 @@ if (tty_register_driver(&stli_callout)) printk("STALLION: failed to register callout driver\n"); -#ifndef MODULE - kmem_start = stli_memhalt(); -#endif - return(kmem_start); + return 0; } /*****************************************************************************/ diff -u --recursive --new-file v1.3.32/linux/drivers/char/kbd_kern.h linux/drivers/char/kbd_kern.h --- v1.3.32/linux/drivers/char/kbd_kern.h Wed Feb 15 10:50:55 1995 +++ linux/drivers/char/kbd_kern.h Tue Oct 10 12:00:39 1995 @@ -33,6 +33,7 @@ #define VC_SHIFTRLOCK KG_SHIFTR /* shiftr lock mode */ #define VC_CTRLLLOCK KG_CTRLL /* ctrll lock mode */ #define VC_CTRLRLOCK KG_CTRLR /* ctrlr lock mode */ + unsigned char slockstate; /* for `sticky' Shift, Ctrl, etc. */ unsigned char ledmode:2; /* one 2-bit value */ #define LED_SHOW_FLAGS 0 /* traditional state */ @@ -61,7 +62,7 @@ extern struct kbd_struct kbd_table[]; -extern unsigned long kbd_init(unsigned long); +extern int kbd_init(void); extern unsigned char getledstate(void); extern void setledstate(struct kbd_struct *kbd, unsigned int led); @@ -104,6 +105,11 @@ extern inline void chg_vc_kbd_lock(struct kbd_struct * kbd, int flag) { kbd->lockstate ^= 1 << flag; +} + +extern inline void chg_vc_kbd_slock(struct kbd_struct * kbd, int flag) +{ + kbd->slockstate ^= 1 << flag; } extern inline void chg_vc_kbd_mode(struct kbd_struct * kbd, int flag) diff -u --recursive --new-file v1.3.32/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v1.3.32/linux/drivers/char/keyboard.c Wed Oct 4 14:14:29 1995 +++ linux/drivers/char/keyboard.c Tue Oct 10 10:20:31 1995 @@ -13,6 +13,7 @@ * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993 * Added decr/incr_console, dynamic keymaps, Unicode support, * dynamic function/string keys, led setting, Sept 1994 + * `Sticky' modifier keys, 951006. * */ @@ -124,12 +125,12 @@ static k_handfn do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, - do_meta, do_ascii, do_lock, do_lowercase, do_ignore; + do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_ignore; static k_hand key_handler[16] = { do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, - do_meta, do_ascii, do_lock, do_lowercase, - do_ignore, do_ignore, do_ignore, do_ignore + do_meta, do_ascii, do_lock, do_lowercase, do_slock, + do_ignore, do_ignore, do_ignore }; typedef void (*void_fnp)(void); @@ -151,7 +152,8 @@ const int max_vals[] = { 255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1, NR_DEAD - 1, 255, 3, NR_SHIFT - 1, - 255, NR_ASCII - 1, NR_LOCK - 1, 255 + 255, NR_ASCII - 1, NR_LOCK - 1, 255, + NR_LOCK - 1 }; const int NR_TYPES = SIZE(max_vals); @@ -530,7 +532,7 @@ u_char type; /* the XOR below used to be an OR */ - int shift_final = shift_state ^ kbd->lockstate; + int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate; ushort *key_map = key_maps[shift_final]; if (key_map != NULL) { @@ -548,6 +550,8 @@ } } (*key_handler[type])(keysym & 0xff, up_flag); + if (type != KT_SLOCK) + kbd->slockstate = 0; } else { /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */ if (!up_flag) @@ -1028,6 +1032,13 @@ chg_vc_kbd_lock(kbd, value); } +static void do_slock(unsigned char value, char up_flag) +{ + if (up_flag || rep) + return; + chg_vc_kbd_slock(kbd, value); +} + /* * send_data sends a character to the keyboard and waits * for a acknowledge, possibly retrying if asked to. Returns @@ -1165,7 +1176,7 @@ sti(); } -unsigned long kbd_init(unsigned long kmem_start) +int kbd_init(void) { int i; struct kbd_struct kbd0; @@ -1174,6 +1185,7 @@ kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS; kbd0.ledmode = LED_SHOW_FLAGS; kbd0.lockstate = KBD_DEFLOCK; + kbd0.slockstate = 0; kbd0.modeflags = KBD_DEFMODE; kbd0.kbdmode = VC_XLATE; @@ -1202,5 +1214,5 @@ #endif mark_bh(KEYBOARD_BH); enable_bh(KEYBOARD_BH); - return kmem_start; + return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v1.3.32/linux/drivers/char/lp.c Mon Sep 18 14:53:53 1995 +++ linux/drivers/char/lp.c Tue Oct 10 10:42:01 1995 @@ -559,22 +559,17 @@ char kernel_version[]=UTS_RELEASE; int io[] = {0, 0, 0}; int irq[] = {0, 0, 0}; - -int init_module(void) -#else -long lp_init(long kmem_start) +#define lp_init init_module #endif + +int lp_init(void) { int offset = 0; int count = 0; if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) { printk("lp: unable to get major %d\n", LP_MAJOR); -#ifdef MODULE return -EIO; -#else - return kmem_start; -#endif } #ifdef MODULE /* When user feeds parameters, use them */ @@ -610,11 +605,7 @@ if (count == 0) printk("lp: Driver configured but no interfaces found.\n"); -#ifdef MODULE return 0; -#else - return kmem_start; -#endif } #ifdef MODULE diff -u --recursive --new-file v1.3.32/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v1.3.32/linux/drivers/char/mem.c Wed Oct 4 14:14:29 1995 +++ linux/drivers/char/mem.c Tue Oct 10 10:13:39 1995 @@ -23,7 +23,7 @@ #include #ifdef CONFIG_SOUND -extern long soundcard_init(long mem_start); +int soundcard_init(void); #endif static int read_ram(struct inode * inode, struct file * file, char * buf, int count) @@ -403,41 +403,27 @@ NULL /* fsync */ }; -#ifdef CONFIG_FTAPE -char* ftape_big_buffer; -#endif - -long chr_dev_init(long mem_start, long mem_end) +int chr_dev_init(void) { if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) printk("unable to get major %d for memory devs\n", MEM_MAJOR); #ifdef CONFIG_RANDOM rand_initialize(); #endif - mem_start = tty_init(mem_start); + tty_init(); #ifdef CONFIG_PRINTER - mem_start = lp_init(mem_start); + lp_init(); #endif #if defined (CONFIG_BUSMOUSE) || defined (CONFIG_82C710_MOUSE) || \ defined (CONFIG_PSMOUSE) || defined (CONFIG_MS_BUSMOUSE) || \ defined (CONFIG_ATIXL_BUSMOUSE) - mem_start = mouse_init(mem_start); + mouse_init(); #endif #ifdef CONFIG_SOUND - mem_start = soundcard_init(mem_start); + soundcard_init(); #endif #if CONFIG_QIC02_TAPE - mem_start = qic02_tape_init(mem_start); + qic02_tape_init(); #endif -/* - * Rude way to allocate kernel memory buffer for tape device - */ -#ifdef CONFIG_FTAPE - /* allocate NR_FTAPE_BUFFERS 32Kb buffers at aligned address */ - ftape_big_buffer= (char*) ((mem_start + 0x7fff) & ~0x7fff); - printk( "ftape: allocated %d buffers aligned at: %p\n", - NR_FTAPE_BUFFERS, ftape_big_buffer); - mem_start = (long) ftape_big_buffer + NR_FTAPE_BUFFERS * 0x8000; -#endif - return mem_start; + return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/char/mouse.c linux/drivers/char/mouse.c --- v1.3.32/linux/drivers/char/mouse.c Fri Sep 15 11:13:00 1995 +++ linux/drivers/char/mouse.c Tue Oct 10 10:23:09 1995 @@ -38,10 +38,10 @@ static struct mouse mouse_list = { 0, "head", NULL, &mouse_list, &mouse_list }; #ifndef MODULE -extern unsigned long bus_mouse_init(unsigned long); -extern unsigned long psaux_init(unsigned long); -extern unsigned long ms_bus_mouse_init(unsigned long); -extern unsigned long atixl_busmouse_init(unsigned long); +extern int bus_mouse_init(void); +extern int psaux_init(void); +extern int ms_bus_mouse_init(void); +extern int atixl_busmouse_init(void); #endif static int mouse_open(struct inode * inode, struct file * file) @@ -79,6 +79,7 @@ { if (mouse->next || mouse->prev) return -EBUSY; + MOD_INC_USE_COUNT; mouse->next = &mouse_list; mouse->prev = mouse_list.prev; mouse->prev->next = mouse; @@ -90,6 +91,7 @@ { if (!mouse->next || !mouse->prev) return -EINVAL; + MOD_DEC_USE_COUNT; mouse->prev->next = mouse->next; mouse->next->prev = mouse->prev; mouse->next = NULL; @@ -99,53 +101,40 @@ #ifdef MODULE char kernel_version[] = UTS_RELEASE; - -int init_module(void) -#else -unsigned long mouse_init(unsigned long kmem_start) +#define mouse_init init_module #endif + +int mouse_init(void) { #ifndef MODULE #ifdef CONFIG_BUSMOUSE - kmem_start = bus_mouse_init(kmem_start); + bus_mouse_init(); #endif #if defined CONFIG_PSMOUSE || defined CONFIG_82C710_MOUSE - kmem_start = psaux_init(kmem_start); + psaux_init(); #endif #ifdef CONFIG_MS_BUSMOUSE - kmem_start = ms_bus_mouse_init(kmem_start); + ms_bus_mouse_init(); #endif #ifdef CONFIG_ATIXL_BUSMOUSE - kmem_start = atixl_busmouse_init(kmem_start); + atixl_busmouse_init(); #endif #endif /* !MODULE */ if (register_chrdev(MOUSE_MAJOR,"mouse",&mouse_fops)) { printk("unable to get major %d for mouse devices\n", MOUSE_MAJOR); -#ifdef MODULE return -EIO; -#endif } -#ifdef MODULE return 0; -#else - return kmem_start; -#endif } #ifdef MODULE void cleanup_module(void) { - mouse_data *c = mouse_list, *n; if (MOD_IN_USE) { printk("mouse: in use, remove delayed\n"); return; } unregister_chrdev(MOUSE_MAJOR, "mouse"); - while (c) { - n = c->next; - kfree(c); - c = n; - } } #endif diff -u --recursive --new-file v1.3.32/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c --- v1.3.32/linux/drivers/char/msbusmouse.c Wed Oct 4 14:14:30 1995 +++ linux/drivers/char/msbusmouse.c Tue Oct 10 10:29:30 1995 @@ -33,6 +33,9 @@ #ifdef MODULE #include #include + +char kernel_version[] = UTS_RELEASE; +#define ms_bus_mouse_init init_module #else #define MOD_INC_USE_COUNT #define MOD_DEC_USE_COUNT @@ -96,26 +99,29 @@ static void release_mouse(struct inode * inode, struct file * file) { + fasync_mouse(inode, file, 0); + if (--mouse.active) + return; MS_MSE_INT_OFF(); - mouse.active = mouse.ready = 0; + mouse.ready = 0; free_irq(MOUSE_IRQ); - fasync_mouse(inode, file, 0); + MOD_DEC_USE_COUNT; } static int open_mouse(struct inode * inode, struct file * file) { if (!mouse.present) return -EINVAL; - if (mouse.active) - return -EBUSY; - mouse.active = 1; - mouse.ready = mouse.dx = mouse.dy = 0; - mouse.buttons = 0x80; + if (mouse.active++) + return 0; if (request_irq(MOUSE_IRQ, ms_mouse_interrupt, 0, "MS Busmouse")) { - mouse.active = 0; + mouse.active--; return -EBUSY; } + mouse.ready = mouse.dx = mouse.dy = 0; + mouse.buttons = 0x80; outb(MS_MSE_START, MS_MSE_CONTROL_PORT); + MOD_INC_USE_COUNT; MS_MSE_INT_ON(); return 0; } @@ -175,13 +181,7 @@ MICROSOFT_BUSMOUSE, "msbusmouse", &ms_bus_mouse_fops }; -#ifdef MODULE -char kernel_version[] = UTS_RELEASE; - -int init_module(void) -#else -unsigned long ms_bus_mouse_init(unsigned long kmem_start) -#endif +int ms_bus_mouse_init(void) { int mse_byte, i; @@ -207,33 +207,24 @@ mouse.present = 0; } } - if (mouse.present == 0) { -#ifdef MODULE - return -EIO; -#else - return kmem_start; -#endif - } + if (mouse.present == 0) + return -EIO; MS_MSE_INT_OFF(); request_region(MS_MSE_CONTROL_PORT, 0x04, "MS Busmouse"); printk("Microsoft BusMouse detected and installed.\n"); mouse_register(&ms_bus_mouse); -#ifdef MODULE return 0; -#else - return kmem_start; -#endif } #ifdef MODULE void cleanup_module(void) { - if (MOD_IN_USE) + if (MOD_IN_USE) { printk("msbusmouse: in use, remove delayed\n"); - else { - mouse_deregister(&ms_bus_mouse); - release_region(MS_MSE_CONTROL_PORT, 0x04); + return; } + mouse_deregister(&ms_bus_mouse); + release_region(MS_MSE_CONTROL_PORT, 0x04); } #endif diff -u --recursive --new-file v1.3.32/linux/drivers/char/psaux.c linux/drivers/char/psaux.c --- v1.3.32/linux/drivers/char/psaux.c Wed Oct 4 14:14:30 1995 +++ linux/drivers/char/psaux.c Tue Oct 10 10:25:26 1995 @@ -123,7 +123,7 @@ static struct aux_queue *queue; static int aux_ready = 0; -static int aux_busy = 0; +static int aux_count = 0; static int aux_present = 0; static int poll_aux_status(void); static int poll_aux_status_nosleep(void); @@ -131,7 +131,7 @@ #ifdef CONFIG_82C710_MOUSE static int qp_present = 0; -static int qp_busy = 0; +static int qp_count = 0; static int qp_data = QP_DATA; static int qp_status = QP_STATUS; @@ -260,13 +260,15 @@ static void release_aux(struct inode * inode, struct file * file) { + fasync_aux(inode, file, 0); + if (--aux_count) + return; aux_write_cmd(AUX_INTS_OFF); /* disable controller ints */ poll_aux_status(); outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */ poll_aux_status(); free_irq(AUX_IRQ); - fasync_aux(inode, file, 0); - aux_busy = 0; + MOD_DEC_USE_COUNT; } #ifdef CONFIG_82C710_MOUSE @@ -274,6 +276,9 @@ { unsigned char status; + fasync_aux(inode, file, 0); + if (--qp_count) + return; if (!poll_qp_status()) printk("Warning: Mouse device busy in release_qp()\n"); status = inb_p(qp_status); @@ -281,8 +286,7 @@ if (!poll_qp_status()) printk("Warning: Mouse device busy in release_qp()\n"); free_irq(QP_IRQ); - fasync_aux(inode, file, 0); - qp_busy = 0; + MOD_DEC_USE_COUNT; } #endif @@ -304,15 +308,16 @@ static int open_aux(struct inode * inode, struct file * file) { if (!aux_present) - return -EINVAL; - if (aux_busy) - return -EBUSY; - if (!poll_aux_status()) + return -ENODEV; + if (aux_count++) + return 0; + if (!poll_aux_status()) { + aux_count--; return -EBUSY; - aux_busy = 1; + } queue->head = queue->tail = 0; /* Flush input queue */ if (request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse")) { - aux_busy = 0; + aux_count--; return -EBUSY; } poll_aux_status(); @@ -321,14 +326,14 @@ aux_write_cmd(AUX_INTS_ON); /* enable controller ints */ poll_aux_status(); aux_ready = 0; + MOD_INC_USE_COUNT; return 0; } #ifdef CONFIG_82C710_MOUSE /* * Install interrupt handler. - * Enable the device, enable interrupts. Set qp_busy - * (allow only one opener at a time.) + * Enable the device, enable interrupts. */ static int open_qp(struct inode * inode, struct file * file) @@ -338,13 +343,13 @@ if (!qp_present) return -EINVAL; - if (qp_busy) - return -EBUSY; + if (qp_count++) + return 0; - if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse")) + if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse")) { + qp_count--; return -EBUSY; - - qp_busy = 1; + } status = inb_p(qp_status); status |= (QP_ENABLE|QP_RESET); @@ -358,11 +363,15 @@ while (!poll_qp_status()) { printk("Error: Mouse device busy in open_qp()\n"); + qp_count--; + status &= ~(QP_ENABLE|QP_INTS_ON); + outb_p(status, qp_status); + free_irq(QP_IRQ); return -EBUSY; } outb_p(AUX_ENABLE_DEV, qp_data); /* Wake up mouse */ - + MOD_INC_USE_COUNT; return 0; } #endif @@ -481,7 +490,7 @@ PSMOUSE_MINOR, "ps2aux", &psaux_fops }; -unsigned long psaux_init(unsigned long kmem_start) +int psaux_init(void) { int qp_found = 0; @@ -500,15 +509,10 @@ aux_present = 1; kbd_read_mask = AUX_OBUF_FULL; } else { -#ifdef MODULE return -EIO; -#else - return kmem_start; /* No mouse at all */ -#endif } mouse_register(&psaux_mouse); - queue = (struct aux_queue *) kmem_start; - kmem_start += sizeof (struct aux_queue); + queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); memset(queue, 0, sizeof(*queue)); queue->head = queue->tail = 0; queue->proc_list = NULL; @@ -528,11 +532,7 @@ poll_aux_status_nosleep(); /* Disable interrupts */ outb_p(AUX_INTS_OFF, AUX_OUTPUT_PORT); /* on the controller */ } -#ifdef MODULE return 0; -#else - return kmem_start; -#endif } #ifdef MODULE diff -u --recursive --new-file v1.3.32/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v1.3.32/linux/drivers/char/pty.c Wed Aug 2 13:21:00 1995 +++ linux/drivers/char/pty.c Tue Oct 10 10:30:00 1995 @@ -211,7 +211,7 @@ return 0; } -long pty_init(long kmem_start) +int pty_init(void) { memset(&pty_state, 0, sizeof(pty_state)); memset(&pty_driver, 0, sizeof(struct tty_driver)); @@ -260,5 +260,5 @@ if (tty_register_driver(&pty_slave_driver)) panic("Couldn't register pty slave driver"); - return kmem_start; + return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/char/scc.c linux/drivers/char/scc.c --- v1.3.32/linux/drivers/char/scc.c Mon Sep 18 14:53:53 1995 +++ linux/drivers/char/scc.c Tue Oct 10 10:37:06 1995 @@ -158,7 +158,7 @@ #define Z8530_MAJOR 34 #endif -long scc_init(long kmem_start); +int scc_init(void); int scc_open(struct tty_struct *tty, struct file *filp); static void scc_close(struct tty_struct *tty, struct file *filp); @@ -2298,7 +2298,7 @@ /* * Init SCC driver * */ /* ******************************************************************** */ -long scc_init (long kmem_start) +int scc_init (void) { int chip, chan; register io_port ctrl; @@ -2418,6 +2418,6 @@ #endif - return kmem_start; + return 0; } #endif diff -u --recursive --new-file v1.3.32/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v1.3.32/linux/drivers/char/serial.c Mon Sep 18 14:53:53 1995 +++ linux/drivers/char/serial.c Tue Oct 10 10:37:50 1995 @@ -13,8 +13,8 @@ * * This module exports the following rs232 io functions: * - * long rs_init(long); - * int rs_open(struct tty_struct * tty, struct file * filp) + * int rs_init(void); + * int rs_open(struct tty_struct * tty, struct file * filp) */ #include @@ -2572,7 +2572,7 @@ /* * The serial driver boot-time initialization code! */ -long rs_init(long kmem_start) +int rs_init(void) { int i; struct async_struct * info; @@ -2695,7 +2695,7 @@ break; } } - return kmem_start; + return 0; } /* diff -u --recursive --new-file v1.3.32/linux/drivers/char/stallion.c linux/drivers/char/stallion.c --- v1.3.32/linux/drivers/char/stallion.c Fri Sep 15 11:13:01 1995 +++ linux/drivers/char/stallion.c Tue Oct 10 10:36:02 1995 @@ -438,16 +438,6 @@ /*****************************************************************************/ /* - * Memory allocation vars. These keep track of what memory allocation - * we can currently use. They help deal with memory in a consistent - * way, whether during init or run-time. - */ -static int stl_meminited = 0; -static long stl_memend; - -/*****************************************************************************/ - -/* * Define some handy local macros... */ #ifndef MIN @@ -463,13 +453,10 @@ #ifdef MODULE int init_module(void); void cleanup_module(void); -#else -static void stl_meminit(long base); -static long stl_memhalt(void); #endif static void *stl_memalloc(int len); -long stl_init(long kmem_start); +int stl_init(void); static int stl_open(struct tty_struct *tty, struct file *filp); static void stl_close(struct tty_struct *tty, struct file *filp); static int stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count); @@ -533,7 +520,7 @@ save_flags(flags); cli(); - stl_init(0); + stl_init(); restore_flags(flags); return(0); @@ -628,33 +615,9 @@ * memory and it will do the right thing. */ -#ifndef MODULE - -static void stl_meminit(long base) -{ - stl_memend = base; - stl_meminited = 1; -} - -static long stl_memhalt() -{ - stl_meminited = 0; - return(stl_memend); -} - -#endif - static void *stl_memalloc(int len) { - void *mem; - - if (stl_meminited) { - mem = (void *) stl_memend; - stl_memend += len; - } else { - mem = (void *) kmalloc(len, GFP_KERNEL); - } - return(mem); + return (void *) kmalloc(len, GFP_KERNEL); } /*****************************************************************************/ @@ -2902,14 +2865,10 @@ /*****************************************************************************/ -long stl_init(long kmem_start) +int stl_init(void) { printk("%s: version %s\n", stl_drvname, stl_drvversion); -#ifndef MODULE - stl_meminit(kmem_start); -#endif - stl_initbrds(); /* @@ -2964,10 +2923,7 @@ if (tty_register_driver(&stl_callout)) printk("STALLION: failed to register callout driver\n"); -#ifndef MODULE - kmem_start = stl_memhalt(); -#endif - return(kmem_start); + return 0; } /*****************************************************************************/ diff -u --recursive --new-file v1.3.32/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c --- v1.3.32/linux/drivers/char/tpqic02.c Mon Sep 18 14:53:53 1995 +++ linux/drivers/char/tpqic02.c Tue Oct 10 10:32:05 1995 @@ -2870,17 +2870,17 @@ } /* qic02_get_resources */ -long qic02_tape_init(long kmem_start) +int qic02_tape_init(void) /* Shouldn't this be a caddr_t ? */ { if (TPSTATSIZE != 6) { printk(TPQIC02_NAME ": internal error: tpstatus struct incorrect!\n"); - return kmem_start; + return -ENODEV; } if ((TPQBUF_SIZE<512) || (TPQBUF_SIZE>=0x10000)) { printk(TPQIC02_NAME ": internal error: DMA buffer size out of range\n"); - return kmem_start; + return -ENODEV; } QIC02_TAPE_DEBUG = TPQD_DEFAULT_FLAGS; @@ -2901,7 +2901,7 @@ # endif rcs_revision, rcs_date); if (qic02_get_resources()) - return kmem_start; + return -ENODEV; #else printk(TPQIC02_NAME ": Runtime config, %s, %s\n", rcs_revision, rcs_date); @@ -2921,7 +2921,7 @@ #ifndef CONFIG_MAX_16M if (buffaddr+TPQBUF_SIZE>=0x1000000) { printk(TPQIC02_NAME ": DMA buffer *must* be in lower 16MB\n"); - return kmem_start; + return -ENODEV; } #endif @@ -2932,7 +2932,7 @@ free_irq(QIC02_TAPE_IRQ); free_dma(QIC02_TAPE_DMA); #endif - return kmem_start; + return -ENODEV; } /* prepare timer */ @@ -2948,7 +2948,7 @@ free_irq(QIC02_TAPE_IRQ); free_dma(QIC02_TAPE_DMA); unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME); - return kmem_start; + return -ENODEV; } else { if (is_exception()) { tpqputs(TPQD_ALWAYS, "exception detected\n"); @@ -2967,6 +2967,6 @@ ioctl_status.mt_fileno = 0; /* number of current file on tape */ ioctl_status.mt_blkno = 0; /* number of current (logical) block */ - return kmem_start; + return 0; } /* qic02_tape_init */ diff -u --recursive --new-file v1.3.32/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v1.3.32/linux/drivers/char/tty_io.c Mon Sep 18 14:53:53 1995 +++ linux/drivers/char/tty_io.c Tue Oct 10 10:27:28 1995 @@ -1777,7 +1777,7 @@ * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */ -long tty_init(long kmem_start) +int tty_init(void) { if (sizeof(struct tty_struct) > PAGE_SIZE) panic("size of tty structure > PAGE_SIZE!"); @@ -1786,21 +1786,21 @@ if (register_chrdev(TTYAUX_MAJOR,"cua",&tty_fops)) panic("unable to get major %d for tty device", TTYAUX_MAJOR); - kmem_start = kbd_init(kmem_start); - kmem_start = rs_init(kmem_start); + kbd_init(); + rs_init(); #ifdef CONFIG_SCC - kmem_start = scc_init(kmem_start); + scc_init(); #endif #ifdef CONFIG_CYCLADES - kmem_start = cy_init(kmem_start); + cy_init(); #endif #ifdef CONFIG_STALLION - kmem_start = stl_init(kmem_start); + stl_init(); #endif #ifdef CONFIG_ISTALLION - kmem_start = stli_init(kmem_start); + stli_init(); #endif - kmem_start = pty_init(kmem_start); - kmem_start = vcs_init(kmem_start); - return kmem_start; + pty_init(); + vcs_init(); + return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c --- v1.3.32/linux/drivers/char/vc_screen.c Wed Aug 2 13:21:01 1995 +++ linux/drivers/char/vc_screen.c Tue Oct 10 10:31:02 1995 @@ -204,9 +204,12 @@ NULL /* fsync */ }; -long vcs_init(long kmem_start) +int vcs_init(void) { - if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops)) + int error; + + error = register_chrdev(VCS_MAJOR, "vcs", &vcs_fops); + if (error) printk("unable to get major %d for vcs device", VCS_MAJOR); - return kmem_start; + return error; } diff -u --recursive --new-file v1.3.32/linux/drivers/net/3c503.c linux/drivers/net/3c503.c --- v1.3.32/linux/drivers/net/3c503.c Wed Oct 4 14:14:30 1995 +++ linux/drivers/net/3c503.c Tue Oct 10 14:03:45 1995 @@ -183,7 +183,7 @@ request_region(ioaddr, EL2_IO_EXTENT,"3c503"); if (dev == NULL) - dev = init_etherdev(0, sizeof(struct ei_device), 0); + dev = init_etherdev(0, sizeof(struct ei_device)); if (ei_debug && version_printed++ == 0) printk(version); diff -u --recursive --new-file v1.3.32/linux/drivers/net/3c505.c linux/drivers/net/3c505.c --- v1.3.32/linux/drivers/net/3c505.c Sat Sep 9 15:26:52 1995 +++ linux/drivers/net/3c505.c Tue Oct 10 15:04:54 1995 @@ -1258,7 +1258,7 @@ adapter = (elp_device *)(dev->priv = kmalloc(sizeof(elp_device), GFP_KERNEL)); CHECK_NULL(adapter); if (adapter == NULL) - return -ENOMEM; + return; memset(&(adapter->stats), 0, sizeof(struct enet_statistics)); /* diff -u --recursive --new-file v1.3.32/linux/drivers/net/3c507.c linux/drivers/net/3c507.c --- v1.3.32/linux/drivers/net/3c507.c Fri Oct 6 14:35:15 1995 +++ linux/drivers/net/3c507.c Tue Oct 10 15:45:26 1995 @@ -354,7 +354,7 @@ /* Allocate a new 'dev' if needed. */ if (dev == NULL) - dev = init_etherdev(0, sizeof(struct net_local), 0); + dev = init_etherdev(0, sizeof(struct net_local)); if (net_debug && version_printed++ == 0) printk(version); @@ -427,6 +427,8 @@ dev->get_stats = el16_get_stats; ether_setup(dev); /* Generic ethernet behaviour */ + + dev->flags&=~IFF_MULTICAST; /* Multicast doesn't work */ return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v1.3.32/linux/drivers/net/Makefile Sat Sep 9 15:26:52 1995 +++ linux/drivers/net/Makefile Mon Oct 9 09:17:53 1995 @@ -139,6 +139,10 @@ endif endif +ifneq ($(CONFIG_PPP),n) + M_OBJS += bsd_comp.o +endif + ifeq ($(CONFIG_SLIP),y) L_OBJS += slip.o CONFIG_SLHC_BUILTIN = y diff -u --recursive --new-file v1.3.32/linux/drivers/net/README.multicast linux/drivers/net/README.multicast --- v1.3.32/linux/drivers/net/README.multicast Thu Jan 1 02:00:00 1970 +++ linux/drivers/net/README.multicast Tue Oct 10 15:45:26 1995 @@ -0,0 +1,58 @@ +Behaviour of cards under Multicast. This is how they currently +behave not what the hardware can do. In paticular all the 8390 based +cards don't use the onboard hash filter, and the lance driver doesn't +use its filter, even though the code for loading it is in the DEC +lance based driver. + +The following multicast requirements are needed +----------------------------------------------- +Appletalk Multicast hardware filtering not important but + avoid cards only doing promisc +IP-Multicast Multicast hardware filters really help +IP-MRoute AllMulti hardware filters are of no help + + +Board Multicast AllMulti Promisc Filter +------------------------------------------------------------------------ +3c501 YES YES YES Software +3c503 YES YES YES Software(#) +3c505 YES NO YES Hardware +3c507 NO NO NO N/A +3c509 YES YES YES Software +ac3200 YES YES YES Software(#) +apricot YES PROMISC YES Hardware +arcnet NO NO NO N/A +at1700 **** PROMISC YES Software +atp **** PROMISC YES Software +de4x5 YES NO YES Hardware +de600 NO NO NO N/A +de620 **** PROMISC YES Software +depca YES PROMISC YES Hardware +e2100 YES YES YES Software(#) +eepro YES(*) PROMISC YES Hardware +eexpress NO NO NO N/A +ewrk3 YES PROMISC YES Hardware +hp-plus YES YES YES Software(#) +hp YES YES YES Software(#) +hp100 YES YES YES Software(#) +ibmtr NO NO NO N/A +lance YES YES YES Software(#) +ne YES YES YES Software(#) +ni52 +ni65 NO NO NO N/A +seeq NO NO NO N/A +sk_g16 NO NO YES N/A +smc-ultra YES YES YES Software(#) +tulip YES YES YES Hardware +wavelan --------Buggy-------- YES N/A +wd YES YES YES Software(#) +znet YES YES YES Software + + +**** = This driver would take down your entire network if you use it in a + multicast kernel with IP forwarding enabled (patches sent to Linus) +YES(*) = As above but only if >64 addresses are activated. +PROMISC = All multicasts mode is in fact promiscuous mode. +(#) = Hardware multicast support is not used yet. + + diff -u --recursive --new-file v1.3.32/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v1.3.32/linux/drivers/net/Space.c Tue Aug 8 12:31:34 1995 +++ linux/drivers/net/Space.c Mon Oct 9 09:17:54 1995 @@ -252,34 +252,10 @@ #if defined(CONFIG_PPP) extern int ppp_init(struct device *); -#ifdef CONFIG_PPP_LOTS - - static struct device ppp15_dev={"ppp15",0,0,0,0,15,0,0,0,0,NEXT_DEV,ppp_init}; - static struct device ppp14_dev={"ppp14",0,0,0,0,14,0,0,0,0,&ppp15_dev,ppp_init}; - static struct device ppp13_dev={"ppp13",0,0,0,0,13,0,0,0,0,&ppp14_dev,ppp_init}; - static struct device ppp12_dev={"ppp12",0,0,0,0,12,0,0,0,0,&ppp13_dev,ppp_init}; - static struct device ppp11_dev={"ppp11",0,0,0,0,11,0,0,0,0,&ppp12_dev,ppp_init}; - static struct device ppp10_dev={"ppp10",0,0,0,0,10,0,0,0,0,&ppp11_dev,ppp_init}; - static struct device ppp9_dev={"ppp9",0,0,0,0,9,0,0,0,0,&ppp10_dev,ppp_init}; - static struct device ppp8_dev={"ppp8",0,0,0,0,8,0,0,0,0,&ppp9_dev,ppp_init}; - static struct device ppp7_dev={"ppp7",0,0,0,0,7,0,0,0,0,&ppp8_dev,ppp_init}; - static struct device ppp6_dev={"ppp6",0,0,0,0,6,0,0,0,0,&ppp7_dev,ppp_init}; - static struct device ppp5_dev={"ppp5",0,0,0,0,5,0,0,0,0,&ppp6_dev,ppp_init}; - static struct device ppp4_dev={"ppp4",0,0,0,0,4,0,0,0,0,&ppp5_dev,ppp_init}; -# undef NEXT_DEV -# define NEXT_DEV (&ppp4_dev) -#endif /* CONFIG_PPP_LOTS */ - -static struct device ppp3_dev = { - "ppp3", 0x0, 0x0, 0x0, 0x0, 3, 0, 0, 0, 0, NEXT_DEV, ppp_init, }; -static struct device ppp2_dev = { - "ppp2", 0x0, 0x0, 0x0, 0x0, 2, 0, 0, 0, 0, &ppp3_dev, ppp_init, }; -static struct device ppp1_dev = { - "ppp1", 0x0, 0x0, 0x0, 0x0, 1, 0, 0, 0, 0, &ppp2_dev, ppp_init, }; -static struct device ppp0_dev = { - "ppp0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, &ppp1_dev, ppp_init, }; +static struct device ppp_bootstrap = { + "ppp_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, ppp_init, }; #undef NEXT_DEV -#define NEXT_DEV (&ppp0_dev) +#define NEXT_DEV (&ppp_bootstrap) #endif /* PPP */ #ifdef CONFIG_DUMMY diff -u --recursive --new-file v1.3.32/linux/drivers/net/at1700.c linux/drivers/net/at1700.c --- v1.3.32/linux/drivers/net/at1700.c Fri Oct 6 14:35:15 1995 +++ linux/drivers/net/at1700.c Tue Oct 10 15:45:26 1995 @@ -205,7 +205,7 @@ /* Allocate a new 'dev' if needed. */ if (dev == NULL) - dev = init_etherdev(0, sizeof(struct net_local), 0); + dev = init_etherdev(0, sizeof(struct net_local)); /* Grab the region so that we can find another board if the IRQ request fails. */ @@ -623,9 +623,18 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs) { short ioaddr = dev->base_addr; - if (num_addrs) { + if (num_addrs) + { + /* + * We must make the kernel realise we had to move + * into promisc mode or we start all out war on + * the cable. - AC + */ + dev->flags|=IFF_PROMISC; + outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */ - } else + } + else outb(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */ } #ifdef MODULE diff -u --recursive --new-file v1.3.32/linux/drivers/net/atp.c linux/drivers/net/atp.c --- v1.3.32/linux/drivers/net/atp.c Sat Sep 9 15:26:52 1995 +++ linux/drivers/net/atp.c Tue Oct 10 15:45:26 1995 @@ -765,6 +765,13 @@ { struct net_local *lp = (struct net_local *)dev->priv; short ioaddr = dev->base_addr; + /* + * We must make the kernel realise we had to move + * into promisc mode or we start all out war on + * the cable. - AC + */ + if(num_addrs) + dev->flags|=IFF_PROMISC; lp->addr_mode = num_addrs ? CMR2h_PROMISC : CMR2h_Normal; write_reg_high(ioaddr, CMR2, lp->addr_mode); } diff -u --recursive --new-file v1.3.32/linux/drivers/net/bsd_comp.c linux/drivers/net/bsd_comp.c --- v1.3.32/linux/drivers/net/bsd_comp.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/net/bsd_comp.c Mon Oct 9 09:17:54 1995 @@ -0,0 +1,1207 @@ +/* Because this code is derived from the 4.3BSD compress source: + * + * Copyright (c) 1985, 1986 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * James A. Woods, derived from original work by Spencer Thomas + * and Joseph Orost. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This version is for use with contigious buffers on Linux-derived systems. + * + * ==FILEVERSION 4== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, increment the number above. + * bsd_comp.c is shipped with a PPP distribution as well as with + * the kernel; if everyone increases the FILEVERSION number above, + * then scripts can do the right thing when deciding whether to + * install a new bsd_comp.c file. Don't change the format of that + * line otherwise, so the installation script can recognize it. + * + * $Id: bsd_comp.c,v 1.1 1994/12/08 01:59:58 paulus Exp $ + */ + +#ifndef MODULE +#error This file must be compiled as a module. +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* to get the struct task_struct */ +#include /* used in new tty drivers */ +#include /* used in new tty drivers */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef NEW_SKBUFF +#include +#endif + +#include +#include +#include + +#undef PACKETPTR +#define PACKETPTR 1 +#include +#undef PACKETPTR + +/* + * PPP "BSD compress" compression + * The differences between this compression and the classic BSD LZW + * source are obvious from the requirement that the classic code worked + * with files while this handles arbitrarily long streams that + * are broken into packets. They are: + * + * When the code size expands, a block of junk is not emitted by + * the compressor and not expected by the decompressor. + * + * New codes are not necessarily assigned every time an old + * code is output by the compressor. This is because a packet + * end forces a code to be emitted, but does not imply that a + * new sequence has been seen. + * + * The compression ratio is checked at the first end of a packet + * after the appropriate gap. Besides simplifying and speeding + * things up, this makes it more likely that the transmitter + * and receiver will agree when the dictionary is cleared when + * compression is not going well. + */ + +/* + * Macros to extract protocol version and number of bits + * from the third byte of the BSD Compress CCP configuration option. + */ + +#define BSD_VERSION(x) ((x) >> 5) +#define BSD_NBITS(x) ((x) & 0x1F) + +#define BSD_CURRENT_VERSION 1 + +/* + * A dictionary for doing BSD compress. + */ + +struct bsd_dict { + union { /* hash value */ + unsigned long fcode; + struct { +#ifndef BIG_ENDIAN_BITFIELD /* Little endian order */ + unsigned short prefix; /* preceding code */ + unsigned char suffix; /* last character of new code */ + unsigned char pad; +#else /* Big endian order */ + unsigned char pad; + unsigned char suffix; /* last character of new code */ + unsigned short prefix; /* preceding code */ +#endif + } hs; + } f; + unsigned short codem1; /* output of hash table -1 */ + unsigned short cptr; /* map code to hash table entry */ +}; + +struct bsd_db { + int totlen; /* length of this structure */ + unsigned int hsize; /* size of the hash table */ + unsigned char hshift; /* used in hash function */ + unsigned char n_bits; /* current bits/code */ + unsigned char maxbits; /* maximum bits/code */ + unsigned char debug; /* non-zero if debug desired */ + unsigned char unit; /* ppp unit number */ + unsigned short seqno; /* sequence # of next packet */ + unsigned int mru; /* size of receive (decompress) bufr */ + unsigned int maxmaxcode; /* largest valid code */ + unsigned int max_ent; /* largest code in use */ + unsigned int in_count; /* uncompressed bytes, aged */ + unsigned int bytes_out; /* compressed bytes, aged */ + unsigned int ratio; /* recent compression ratio */ + unsigned int checkpoint; /* when to next check the ratio */ + unsigned int clear_count; /* times dictionary cleared */ + unsigned int incomp_count; /* incompressible packets */ + unsigned int incomp_bytes; /* incompressible bytes */ + unsigned int uncomp_count; /* uncompressed packets */ + unsigned int uncomp_bytes; /* uncompressed bytes */ + unsigned int comp_count; /* compressed packets */ + unsigned int comp_bytes; /* compressed bytes */ + unsigned short *lens; /* array of lengths of codes */ + struct bsd_dict *dict; /* dictionary */ +}; + +#define BSD_OVHD 2 /* BSD compress overhead/packet */ +#define MIN_BSD_BITS 9 +#define BSD_INIT_BITS MIN_BSD_BITS +#define MAX_BSD_BITS 15 + +static void bsd_free (void *state); +static void *bsd_alloc(unsigned char *options, int opt_len, int decomp); +static void *bsd_comp_alloc (unsigned char *options, int opt_len); +static void *bsd_decomp_alloc (unsigned char *options, int opt_len); + +static int bsd_init (void *db, unsigned char *options, + int opt_len, int unit, int debug, int decomp); +static int bsd_comp_init (void *state, unsigned char *options, + int opt_len, int unit, int opthdr, int debug); +static int bsd_decomp_init (void *state, unsigned char *options, + int opt_len, int unit, int opthdr, int mru, + int debug); + +static void bsd_reset (void *state); +static void bsd_comp_stats (void *state, struct compstat *stats); + +static int bsd_compress (void *state, unsigned char *rptr, + unsigned char *obuf, int isize, int osize); +static void bsd_incomp (void *state, unsigned char *ibuf, int icnt); + +static int bsd_decompress (void *state, unsigned char *ibuf, int isize, + unsigned char *obuf, int osize); + +/* These are in ppp.c */ +extern int ppp_register_compressor (struct compressor *cp); +extern void ppp_unregister_compressor (struct compressor *cp); + +/* + * the next two codes should not be changed lightly, as they must not + * lie within the contiguous general code space. + */ +#define CLEAR 256 /* table clear output code */ +#define FIRST 257 /* first free entry */ +#define LAST 255 + +#define MAXCODE(b) ((1 << (b)) - 1) +#define BADCODEM1 MAXCODE(MAX_BSD_BITS); + +#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \ + ^ (unsigned long)(prefix)) +#define BSD_KEY(prefix,suffix) ((((unsigned long)(suffix)) << 16) \ + + (unsigned long)(prefix)) + +#define CHECK_GAP 10000 /* Ratio check interval */ + +#define RATIO_SCALE_LOG 8 +#define RATIO_SCALE (1<>RATIO_SCALE_LOG) + +/* + * clear the dictionary + */ + +static void +bsd_clear(struct bsd_db *db) +{ + db->clear_count++; + db->max_ent = FIRST-1; + db->n_bits = BSD_INIT_BITS; + db->bytes_out = 0; + db->in_count = 0; + db->incomp_count = 0; + db->ratio = 0; + db->checkpoint = CHECK_GAP; +} + +/* + * If the dictionary is full, then see if it is time to reset it. + * + * Compute the compression ratio using fixed-point arithmetic + * with 8 fractional bits. + * + * Since we have an infinite stream instead of a single file, + * watch only the local compression ratio. + * + * Since both peers must reset the dictionary at the same time even in + * the absence of CLEAR codes (while packets are incompressible), they + * must compute the same ratio. + */ + +static int bsd_check (struct bsd_db *db) /* 1=output CLEAR */ + { + unsigned int new_ratio; + + if (db->in_count >= db->checkpoint) + { + /* age the ratio by limiting the size of the counts */ + if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX) + { + db->in_count -= (db->in_count >> 2); + db->bytes_out -= (db->bytes_out >> 2); + } + + db->checkpoint = db->in_count + CHECK_GAP; + + if (db->max_ent >= db->maxmaxcode) + { + /* Reset the dictionary only if the ratio is worse, + * or if it looks as if it has been poisoned + * by incompressible data. + * + * This does not overflow, because + * db->in_count <= RATIO_MAX. + */ + + new_ratio = db->in_count << RATIO_SCALE_LOG; + if (db->bytes_out != 0) + { + new_ratio /= db->bytes_out; + } + + if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) + { + bsd_clear (db); + return 1; + } + db->ratio = new_ratio; + } + } + return 0; + } + +/* + * Return statistics. + */ + +static void bsd_comp_stats (void *state, struct compstat *stats) + { + struct bsd_db *db = (struct bsd_db *) state; + + stats->unc_bytes = db->uncomp_bytes; + stats->unc_packets = db->uncomp_count; + stats->comp_bytes = db->comp_bytes; + stats->comp_packets = db->comp_count; + stats->inc_bytes = db->incomp_bytes; + stats->inc_packets = db->incomp_count; + stats->in_count = db->in_count; + stats->bytes_out = db->bytes_out; + } + +/* + * Reset state, as on a CCP ResetReq. + */ + +static void bsd_reset (void *state) + { + struct bsd_db *db = (struct bsd_db *) state; + + bsd_clear(db); + + db->seqno = 0; + db->clear_count = 0; + } + +/* + * Release the compression structure + */ + +static void bsd_free (void *state) + { + struct bsd_db *db = (struct bsd_db *) state; + + if (db) + { +/* + * Release the dictionary + */ + if (db->dict) + { + vfree (db->dict); + db->dict = NULL; + } +/* + * Release the string buffer + */ + if (db->lens) + { + vfree (db->lens); + db->lens = NULL; + } +/* + * Finally release the structure itself. + */ + kfree (db); + MOD_DEC_USE_COUNT; + } + } + +/* + * Allocate space for a (de) compressor. + */ + +static void *bsd_alloc (unsigned char *options, int opt_len, int decomp) + { + int bits; + unsigned int hsize, hshift, maxmaxcode; + struct bsd_db *db; + + if (opt_len != 3 || options[0] != CI_BSD_COMPRESS || options[1] != 3 + || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION) + { + return NULL; + } + + bits = BSD_NBITS(options[2]); + + switch (bits) + { + case 9: /* needs 82152 for both directions */ + case 10: /* needs 84144 */ + case 11: /* needs 88240 */ + case 12: /* needs 96432 */ + hsize = 5003; + hshift = 4; + break; + case 13: /* needs 176784 */ + hsize = 9001; + hshift = 5; + break; + case 14: /* needs 353744 */ + hsize = 18013; + hshift = 6; + break; + case 15: /* needs 691440 */ + hsize = 35023; + hshift = 7; + break; + case 16: /* needs 1366160--far too much, */ + /* hsize = 69001; */ /* and 69001 is too big for cptr */ + /* hshift = 8; */ /* in struct bsd_db */ + /* break; */ + default: + return NULL; + } +/* + * Allocate the main control structure for this instance. + */ + maxmaxcode = MAXCODE(bits); + db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db), + GFP_KERNEL); + if (!db) + { + return NULL; + } + + memset (db, 0, sizeof(struct bsd_db)); +/* + * Allocate space for the dictionary. This may be more than one page in + * length. + */ + db->dict = (struct bsd_dict *) vmalloc (hsize * + sizeof (struct bsd_dict)); + if (!db->dict) + { + bsd_free (db); + return NULL; + } + + MOD_INC_USE_COUNT; +/* + * If this is the compression buffer then there is no length data. + */ + if (!decomp) + { + db->lens = NULL; + } +/* + * For decompression, the length information is needed as well. + */ + else + { + db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) * + sizeof (db->lens[0])); + if (!db->lens) + { + bsd_free (db); + return (NULL); + } + } +/* + * Initialize the data information for the compression code + */ + db->totlen = sizeof (struct bsd_db) + + (sizeof (struct bsd_dict) * hsize); + + db->hsize = hsize; + db->hshift = hshift; + db->maxmaxcode = maxmaxcode; + db->maxbits = bits; + + return (void *) db; + } + +static void *bsd_comp_alloc (unsigned char *options, int opt_len) + { + return bsd_alloc (options, opt_len, 0); + } + +static void *bsd_decomp_alloc (unsigned char *options, int opt_len) + { + return bsd_alloc (options, opt_len, 1); + } + +/* + * Initialize the database. + */ + +static int bsd_init (void *state, unsigned char *options, + int opt_len, int unit, int debug, int decomp) + { + struct bsd_db *db = state; + int indx; + + if ((opt_len != 3) || (options[0] != CI_BSD_COMPRESS) || (options[1] != 3) + || (BSD_VERSION(options[2]) != BSD_CURRENT_VERSION) + || (BSD_NBITS(options[2]) != db->maxbits) + || (decomp && db->lens == NULL)) + { + return 0; + } + + if (decomp) + { + indx = LAST; + do + { + db->lens[indx] = 1; + } + while (indx-- > 0); + } + + indx = db->hsize; + while (indx-- != 0) + { + db->dict[indx].codem1 = BADCODEM1; + db->dict[indx].cptr = 0; + } + + db->unit = unit; + db->mru = 0; +#ifndef DEBUG + if (debug) +#endif + db->debug = 1; + + bsd_reset(db); + + return 1; + } + +static int bsd_comp_init (void *state, unsigned char *options, + int opt_len, int unit, int opthdr, int debug) + { + return bsd_init (state, options, opt_len, unit, debug, 0); + } + +static int bsd_decomp_init (void *state, unsigned char *options, + int opt_len, int unit, int opthdr, int mru, + int debug) + { + return bsd_init (state, options, opt_len, unit, debug, 1); + } + +/* + * Obtain pointers to the various structures in the compression tables + */ + +#define dict_ptrx(p,idx) &(p->dict[idx]) +#define lens_ptrx(p,idx) &(p->lens[idx]) + +#ifdef DEBUG +static unsigned short *lens_ptr(struct bsd_db *db, int idx) + { + if ((unsigned int) idx > (unsigned int) db->maxmaxcode) + { + printk ("<9>ppp: lens_ptr(%d) > max\n", idx); + idx = 0; + } + return lens_ptrx (db, idx); + } + +static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx) + { + if ((unsigned int) idx >= (unsigned int) db->hsize) + { + printk ("<9>ppp: dict_ptr(%d) > max\n", idx); + idx = 0; + } + return dict_ptrx (db, idx); + } + +#else +#define lens_ptr(db,idx) lens_ptrx(db,idx) +#define dict_ptr(db,idx) dict_ptrx(db,idx) +#endif + +/* + * compress a packet + * + * The result of this function is the size of the compressed + * packet. A zero is returned if the packet was not compressed + * for some reason, such as the size being larger than uncompressed. + * + * One change from the BSD compress command is that when the + * code size expands, we do not output a bunch of padding. + */ + +static int bsd_compress (void *state, unsigned char *rptr, unsigned char *obuf, + int isize, int osize) + { + struct bsd_db *db; + int hshift; + unsigned int max_ent; + unsigned int n_bits; + unsigned int bitno; + unsigned long accm; + int ent; + unsigned long fcode; + struct bsd_dict *dictp; + unsigned char c; + int hval; + int disp; + int ilen; + int mxcode; + unsigned char *wptr; + int olen; + +#define PUTBYTE(v) \ + { \ + ++olen; \ + if (wptr) \ + { \ + *wptr++ = (unsigned char) (v); \ + if (olen >= osize) \ + { \ + wptr = NULL; \ + } \ + } \ + } + +#define OUTPUT(ent) \ + { \ + bitno -= n_bits; \ + accm |= ((ent) << bitno); \ + do \ + { \ + PUTBYTE(accm >> 24); \ + accm <<= 8; \ + bitno += 8; \ + } \ + while (bitno <= 24); \ + } + + /* + * If the protocol is not in the range we're interested in, + * just return without compressing the packet. If it is, + * the protocol becomes the first byte to compress. + */ + + ent = PPP_PROTOCOL(rptr); + if (ent < 0x21 || ent > 0xf9) + { + return 0; + } + + db = (struct bsd_db *) state; + hshift = db->hshift; + max_ent = db->max_ent; + n_bits = db->n_bits; + bitno = 32; + accm = 0; + mxcode = MAXCODE (n_bits); + + /* Initialize the output pointers */ + wptr = obuf; + olen = PPP_HDRLEN + BSD_OVHD; + + if (osize > isize) + { + osize = isize; + } + + /* This is the PPP header information */ + if (wptr) + { + *wptr++ = PPP_ADDRESS(rptr); + *wptr++ = PPP_CONTROL(rptr); + *wptr++ = 0; + *wptr++ = PPP_COMP; + *wptr++ = db->seqno >> 8; + *wptr++ = db->seqno; + } + + /* Skip the input header */ + rptr += PPP_HDRLEN; + isize -= PPP_HDRLEN; + ilen = ++isize; /* This is off by one, but that is what is in draft! */ + + while (--ilen > 0) + { + c = *rptr++; + fcode = BSD_KEY (ent, c); + hval = BSD_HASH (ent, c, hshift); + dictp = dict_ptr (db, hval); + + /* Validate and then check the entry. */ + if (dictp->codem1 >= max_ent) + { + goto nomatch; + } + + if (dictp->f.fcode == fcode) + { + ent = dictp->codem1 + 1; + continue; /* found (prefix,suffix) */ + } + + /* continue probing until a match or invalid entry */ + disp = (hval == 0) ? 1 : hval; + + do + { + hval += disp; + if (hval >= db->hsize) + { + hval -= db->hsize; + } + dictp = dict_ptr (db, hval); + if (dictp->codem1 >= max_ent) + { + goto nomatch; + } + } + while (dictp->f.fcode != fcode); + + ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */ + continue; + +nomatch: + OUTPUT(ent); /* output the prefix */ + + /* code -> hashtable */ + if (max_ent < db->maxmaxcode) + { + struct bsd_dict *dictp2; + struct bsd_dict *dictp3; + int indx; + + /* expand code size if needed */ + if (max_ent >= mxcode) + { + db->n_bits = ++n_bits; + mxcode = MAXCODE (n_bits); + } + + /* Invalidate old hash table entry using + * this code, and then take it over. + */ + + dictp2 = dict_ptr (db, max_ent + 1); + indx = dictp2->cptr; + dictp3 = dict_ptr (db, indx); + + if (dictp3->codem1 == max_ent) + { + dictp3->codem1 = BADCODEM1; + } + + dictp2->cptr = hval; + dictp->codem1 = max_ent; + dictp->f.fcode = fcode; + db->max_ent = ++max_ent; + + if (db->lens) + { + unsigned short *len1 = lens_ptr (db, max_ent); + unsigned short *len2 = lens_ptr (db, ent); + *len1 = *len2 + 1; + } + } + ent = c; + } + + OUTPUT(ent); /* output the last code */ + + db->bytes_out += olen; /* Do not count bytes from here */ + db->uncomp_bytes += isize; + db->in_count += isize; + ++db->uncomp_count; + ++db->seqno; + + if (bitno < 32) + { + ++db->bytes_out; /* must be set before calling bsd_check */ + } + + /* + * Generate the clear command if needed + */ + + if (bsd_check(db)) + { + OUTPUT (CLEAR); + } + + /* + * Pad dribble bits of last code with ones. + * Do not emit a completely useless byte of ones. + */ + + if (bitno != 32) + { + PUTBYTE((accm | (0xff << (bitno-8))) >> 24); + } + + /* + * Increase code size if we would have without the packet + * boundary because the decompressor will do so. + */ + + if (max_ent >= mxcode && max_ent < db->maxmaxcode) + { + db->n_bits++; + } + + /* If output length is too large then this is an incomplete frame. */ + if (wptr == NULL) + { + ++db->incomp_count; + db->incomp_bytes += isize; + olen = 0; + } + else /* Count the number of compressed frames */ + { + ++db->comp_count; + db->comp_bytes += olen; + } + + /* Return the resulting output length */ + return olen; +#undef OUTPUT +#undef PUTBYTE + } + +/* + * Update the "BSD Compress" dictionary on the receiver for + * incompressible data by pretending to compress the incoming data. + */ + +static void bsd_incomp (void *state, unsigned char *ibuf, int icnt) + { + (void) bsd_compress (state, ibuf, (char *) 0, icnt, 0); + } + +/* + * Decompress "BSD Compress". + * + * Because of patent problems, we return DECOMP_ERROR for errors + * found by inspecting the input data and for system problems, but + * DECOMP_FATALERROR for any errors which could possibly be said to + * be being detected "after" decompression. For DECOMP_ERROR, + * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be + * infringing a patent of Motorola's if we do, so we take CCP down + * instead. + * + * Given that the frame has the correct sequence number and a good FCS, + * errors such as invalid codes in the input most likely indicate a + * bug, so we return DECOMP_FATALERROR for them in order to turn off + * compression, even though they are detected by inspecting the input. + */ + +static int bsd_decompress (void *state, unsigned char *ibuf, int isize, + unsigned char *obuf, int osize) + { + struct bsd_db *db; + unsigned int max_ent; + unsigned long accm; + unsigned int bitno; /* 1st valid bit in accm */ + unsigned int n_bits; + unsigned int tgtbitno; /* bitno when we have a code */ + struct bsd_dict *dictp; + int explen; + int seq; + unsigned int incode; + unsigned int oldcode; + unsigned int finchar; + unsigned char *p; + unsigned char *wptr; + int adrs; + int ctrl; + int ilen; + int codelen; + int extra; + + db = (struct bsd_db *) state; + max_ent = db->max_ent; + accm = 0; + bitno = 32; /* 1st valid bit in accm */ + n_bits = db->n_bits; + tgtbitno = 32 - n_bits; /* bitno when we have a code */ + + /* + * Save the address/control from the PPP header + * and then get the sequence number. + */ + + adrs = PPP_ADDRESS (ibuf); + ctrl = PPP_CONTROL (ibuf); + + seq = (ibuf[4] << 8) + ibuf[5]; + + ibuf += (PPP_HDRLEN + 2); + ilen = isize - (PPP_HDRLEN + 2); + + /* + * Check the sequence number and give up if it differs from + * the value we're expecting. + */ + + if (seq != db->seqno) + { + if (db->debug) + { + printk("bsd_decomp%d: bad sequence # %d, expected %d\n", + db->unit, seq, db->seqno - 1); + } + return DECOMP_ERROR; + } + + ++db->seqno; + db->bytes_out += ilen; + + /* + * Fill in the ppp header, but not the last byte of the protocol + * (that comes from the decompressed data). + */ + + wptr = obuf; + *wptr++ = adrs; + *wptr++ = ctrl; + *wptr++ = 0; + + oldcode = CLEAR; + explen = 3; + + /* + * Keep the checkpoint correctly so that incompressible packets + * clear the dictionary at the proper times. + */ + + for (;;) + { + if (ilen-- <= 0) + { + db->in_count += (explen - 3); /* don't count the header */ + break; + } + + /* + * Accumulate bytes until we have a complete code. + * Then get the next code, relying on the 32-bit, + * unsigned accm to mask the result. + */ + + bitno -= 8; + accm |= *ibuf++ << bitno; + if (tgtbitno < bitno) + { + continue; + } + + incode = accm >> tgtbitno; + accm <<= n_bits; + bitno += n_bits; + + /* + * The dictionary must only be cleared at the end of a packet. + */ + + if (incode == CLEAR) + { + if (ilen > 0) + { + if (db->debug) + { + printk("bsd_decomp%d: bad CLEAR\n", db->unit); + } + return DECOMP_FATALERROR; /* probably a bug */ + } + + bsd_clear(db); + break; + } + + if ((incode > max_ent + 2) || (incode > db->maxmaxcode) + || (incode > max_ent && oldcode == CLEAR)) + { + if (db->debug) + { + printk("bsd_decomp%d: bad code 0x%x oldcode=0x%x ", + db->unit, incode, oldcode); + printk("max_ent=0x%x explen=%d seqno=%d\n", + max_ent, explen, db->seqno); + } + return DECOMP_FATALERROR; /* probably a bug */ + } + + /* Special case for KwKwK string. */ + if (incode > max_ent) + { + finchar = oldcode; + extra = 1; + } + else + { + finchar = incode; + extra = 0; + } + + codelen = *(lens_ptr (db, finchar)); + explen += codelen + extra; + if (explen > osize) + { + if (db->debug) + { + printk("bsd_decomp%d: ran out of mru\n", db->unit); +#ifdef DEBUG + printk(" len=%d, finchar=0x%x, codelen=%d, explen=%d\n", + ilen, finchar, codelen, explen); +#endif + } + return DECOMP_FATALERROR; + } + + /* + * Decode this code and install it in the decompressed buffer. + */ + + wptr += codelen; + p = wptr; + while (finchar > LAST) + { + struct bsd_dict *dictp2 = dict_ptr (db, finchar); + + dictp = dict_ptr (db, dictp2->cptr); +#ifdef DEBUG + if (--codelen <= 0 || dictp->codem1 != finchar-1) + { + if (codelen <= 0) + { + printk("bsd_decomp%d: fell off end of chain ", db->unit); + printk("0x%x at 0x%x by 0x%x, max_ent=0x%x\n", + incode, finchar, dictp2->cptr, max_ent); + } + else + { + if (dictp->codem1 != finchar-1) + { + printk("bsd_decomp%d: bad code chain 0x%x " + "finchar=0x%x ", + db->unit, incode, finchar); + + printk("oldcode=0x%x cptr=0x%x codem1=0x%x\n", + oldcode, dictp2->cptr, dictp->codem1); + } + } + return DECOMP_FATALERROR; + } +#endif + *--p = dictp->f.hs.suffix; + finchar = dictp->f.hs.prefix; + } + *--p = finchar; + +#ifdef DEBUG + if (--codelen != 0) + { + printk("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n", + db->unit, codelen, incode, max_ent); + } +#endif + + if (extra) /* the KwKwK case again */ + { + *wptr++ = finchar; + } + + /* + * If not first code in a packet, and + * if not out of code space, then allocate a new code. + * + * Keep the hash table correct so it can be used + * with uncompressed packets. + */ + + if (oldcode != CLEAR && max_ent < db->maxmaxcode) + { + struct bsd_dict *dictp2, *dictp3; + unsigned short *lens1, *lens2; + unsigned long fcode; + int hval, disp, indx; + + fcode = BSD_KEY(oldcode,finchar); + hval = BSD_HASH(oldcode,finchar,db->hshift); + dictp = dict_ptr (db, hval); + + /* look for a free hash table entry */ + if (dictp->codem1 < max_ent) + { + disp = (hval == 0) ? 1 : hval; + do + { + hval += disp; + if (hval >= db->hsize) + { + hval -= db->hsize; + } + dictp = dict_ptr (db, hval); + } + while (dictp->codem1 < max_ent); + } + + /* + * Invalidate previous hash table entry + * assigned this code, and then take it over + */ + + dictp2 = dict_ptr (db, max_ent + 1); + indx = dictp2->cptr; + dictp3 = dict_ptr (db, indx); + + if (dictp3->codem1 == max_ent) + { + dictp3->codem1 = BADCODEM1; + } + + dictp2->cptr = hval; + dictp->codem1 = max_ent; + dictp->f.fcode = fcode; + db->max_ent = ++max_ent; + + /* Update the length of this string. */ + lens1 = lens_ptr (db, max_ent); + lens2 = lens_ptr (db, oldcode); + *lens1 = *lens2 + 1; + + /* Expand code size if needed. */ + if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) + { + db->n_bits = ++n_bits; + tgtbitno = 32-n_bits; + } + } + oldcode = incode; + } + + ++db->comp_count; + ++db->uncomp_count; + db->comp_bytes += isize - BSD_OVHD - PPP_HDRLEN; + db->uncomp_bytes += explen; + + if (bsd_check(db)) + { + if (db->debug) + { + printk("bsd_decomp%d: peer should have cleared dictionary on %d\n", + db->unit, db->seqno - 1); + } + } + return explen; + } + +/************************************************************* + * Table of addresses for the BSD compression module + *************************************************************/ + +static struct compressor ppp_bsd_compress = { + CI_BSD_COMPRESS, /* compress_proto */ + bsd_comp_alloc, /* comp_alloc */ + bsd_free, /* comp_free */ + bsd_comp_init, /* comp_init */ + bsd_reset, /* comp_reset */ + bsd_compress, /* compress */ + bsd_comp_stats, /* comp_stat */ + bsd_decomp_alloc, /* decomp_alloc */ + bsd_free, /* decomp_free */ + bsd_decomp_init, /* decomp_init */ + bsd_reset, /* decomp_reset */ + bsd_decompress, /* decompress */ + bsd_incomp, /* incomp */ + bsd_comp_stats /* decomp_stat */ +}; + +/************************************************************* + * Module support routines + *************************************************************/ + +char kernel_version[] = UTS_RELEASE; + +int +init_module(void) +{ + int answer = ppp_register_compressor (&ppp_bsd_compress); + if (answer == 0) + printk (KERN_INFO "PPP BSD Compression module registered\n"); + return answer; +} + +void +cleanup_module(void) +{ + if (MOD_IN_USE) + printk("ppp_bsd_comp: device busy, remove delayed\n"); + else + ppp_unregister_compressor (&ppp_bsd_compress); +} diff -u --recursive --new-file v1.3.32/linux/drivers/net/de600.c linux/drivers/net/de600.c --- v1.3.32/linux/drivers/net/de600.c Sun Sep 3 12:26:54 1995 +++ linux/drivers/net/de600.c Tue Oct 10 15:45:26 1995 @@ -715,6 +715,8 @@ ether_setup(dev); + dev->flags&=~IFF_MULTICAST; + select_prn(); return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/net/de620.c linux/drivers/net/de620.c --- v1.3.32/linux/drivers/net/de620.c Wed Aug 9 14:55:40 1995 +++ linux/drivers/net/de620.c Tue Oct 10 15:45:27 1995 @@ -468,7 +468,15 @@ static void de620_set_multicast_list(struct device *dev, int num_addrs, void *addrs) { - if (num_addrs) { /* Enable promiscuous mode */ + if (num_addrs) + { /* Enable promiscuous mode */ + /* + * We must make the kernel realise we had to move + * into promisc mode or we start all out war on + * the cable. - AC + */ + dev->flags|=IFF_PROMISC; + de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL); } else { /* Disable promiscuous mode, use normal mode */ diff -u --recursive --new-file v1.3.32/linux/drivers/net/eepro.c linux/drivers/net/eepro.c --- v1.3.32/linux/drivers/net/eepro.c Sat Sep 9 15:26:52 1995 +++ linux/drivers/net/eepro.c Tue Oct 10 15:45:27 1995 @@ -792,7 +792,15 @@ short ioaddr = dev->base_addr; unsigned short mode; - if (num_addrs < -1 || num_addrs > 63) { + if (num_addrs <= -1 || num_addrs > 63) { + /* + * We must make the kernel realise we had to move + * into promisc mode or we start all out war on + * the cable. If it was a promisc rewquest the + * flag is already set. If not we assert it. + */ + dev->flags|=IFF_PROMISC; + outb(BANK2_SELECT, ioaddr); /* be CAREFULL, BANK 2 now */ mode = inb(ioaddr + REG2); outb(mode | PRMSC_Mode, ioaddr + REG2); diff -u --recursive --new-file v1.3.32/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c --- v1.3.32/linux/drivers/net/eexpress.c Fri Oct 6 14:35:15 1995 +++ linux/drivers/net/eexpress.c Tue Oct 10 15:45:27 1995 @@ -414,6 +414,8 @@ ether_setup(dev); + dev->flags&=~IFF_MULTICAST; + return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- v1.3.32/linux/drivers/net/ewrk3.c Fri Oct 6 14:35:15 1995 +++ linux/drivers/net/ewrk3.c Mon Oct 9 09:24:26 1995 @@ -1885,7 +1885,7 @@ } else { release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE); unregister_netdev(&thisEthwrk); - free(thisEthwrk.priv); + kfree(thisEthwrk.priv); thisEthwrk.priv = NULL; } } diff -u --recursive --new-file v1.3.32/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c --- v1.3.32/linux/drivers/net/hp-plus.c Wed Oct 4 14:14:31 1995 +++ linux/drivers/net/hp-plus.c Tue Oct 10 14:03:45 1995 @@ -160,7 +160,7 @@ return ENODEV; if (dev == NULL) - dev = init_etherdev(0, sizeof(struct ei_device), 0); + dev = init_etherdev(0, sizeof(struct ei_device)); printk("%s: %s at %#3x,", dev->name, name, ioaddr); diff -u --recursive --new-file v1.3.32/linux/drivers/net/hp.c linux/drivers/net/hp.c --- v1.3.32/linux/drivers/net/hp.c Wed Oct 4 14:14:31 1995 +++ linux/drivers/net/hp.c Tue Oct 10 14:03:45 1995 @@ -129,7 +129,7 @@ } if (dev == NULL) - dev = init_etherdev(0, sizeof(struct ei_device), 0); + dev = init_etherdev(0, sizeof(struct ei_device)); printk("%s: %s (ID %02x) at %#3x,", dev->name, name, board_id, ioaddr); diff -u --recursive --new-file v1.3.32/linux/drivers/net/hp100.c linux/drivers/net/hp100.c --- v1.3.32/linux/drivers/net/hp100.c Tue Aug 15 20:39:03 1995 +++ linux/drivers/net/hp100.c Tue Oct 10 15:45:27 1995 @@ -876,13 +876,13 @@ hp100_page( MAC_CTRL ); hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 ); /* stop rx/tx */ - if ( num_addrs < 0 ) + if ( num_addrs == -1 ) { lp -> mac2_mode = HP100_MAC2MODE6; /* promiscuous mode, all good */ lp -> mac1_mode = HP100_MAC1MODE6; /* packets on the net */ } else - if ( num_addrs > 0 ) + if ( num_addrs != 0 ) { lp -> mac2_mode = HP100_MAC2MODE5; /* multicast mode, packets for me */ lp -> mac1_mode = HP100_MAC1MODE5; /* broadcasts and all multicasts */ diff -u --recursive --new-file v1.3.32/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v1.3.32/linux/drivers/net/lance.c Sun Sep 3 16:12:49 1995 +++ linux/drivers/net/lance.c Tue Oct 10 15:45:27 1995 @@ -37,7 +37,7 @@ #include static unsigned int lance_portlist[] = {0x300, 0x320, 0x340, 0x360, 0}; -unsigned long lance_probe1(int ioaddr, unsigned long mem_start); +void lance_probe1(int ioaddr); #ifdef HAVE_DEVLIST struct netdev_entry lance_drv = @@ -187,8 +187,7 @@ struct lance_private { /* The Tx and Rx ring entries must be aligned on 8-byte boundaries. - This is accomplished by allocating 7 extra bytes for the struct - and adjusting the start of the struct to be 8-byte aligned. */ + This is always true for kmalloc'ed memory */ struct lance_rx_head rx_ring[RX_RING_SIZE]; struct lance_tx_head tx_ring[TX_RING_SIZE]; struct lance_init_block init_block; @@ -270,11 +269,11 @@ before the memory management system is started, and thus well before the other probes. */ -unsigned long lance_init(unsigned long mem_start, unsigned long mem_end) +int lance_init(void) { int *port; - if (mem_end <= 16*1024*1024) + if (high_memory <= 16*1024*1024) lance_need_isa_bounce_buffers = 0; #if defined(CONFIG_PCI) @@ -308,9 +307,9 @@ pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND, pci_command); } - printk("Found PCnet/PCI at %#x, irq %d (mem_start is %#lx).\n", - pci_ioaddr, pci_irq_line, mem_start); - mem_start = lance_probe1(pci_ioaddr, mem_start); + printk("Found PCnet/PCI at %#x, irq %d.\n", + pci_ioaddr, pci_irq_line); + lance_probe1(pci_ioaddr); pci_irq_line = 0; } } @@ -326,14 +325,14 @@ if ((offset14 == 0x52 || offset14 == 0x57) && ((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44)) - mem_start = lance_probe1(ioaddr, mem_start); + lance_probe1(ioaddr); } } - return mem_start; + return 0; } -unsigned long lance_probe1(int ioaddr, unsigned long mem_start) +void lance_probe1(int ioaddr) { struct device *dev; struct lance_private *lp; @@ -372,7 +371,7 @@ outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */ if (inw(ioaddr+LANCE_DATA) != 0x0004) - return mem_start; + return; /* Get the version of the chip. */ outw(88, ioaddr+LANCE_ADDR); @@ -385,7 +384,7 @@ if (lance_debug > 2) printk(" LANCE chip version is %#x.\n", chip_version); if ((chip_version & 0xfff) != 0x003) - return mem_start; + return; chip_version = (chip_version >> 12) & 0xffff; for (lance_version = 1; chip_table[lance_version].id_number; lance_version++) { if (chip_table[lance_version].id_number == chip_version) @@ -393,14 +392,7 @@ } } - dev = init_etherdev(0, 7 - + ((sizeof(struct lance_private) + 7) & ~7) - + PKT_BUF_SZ*RX_RING_SIZE - + (lance_need_isa_bounce_buffers - ? PKT_BUF_SZ*TX_RING_SIZE - : 0), - &mem_start); - + dev = init_etherdev(0, 0); chipname = chip_table[lance_version].name; printk("%s: %s at %#3x,", dev->name, chipname, ioaddr); @@ -412,13 +404,14 @@ dev->base_addr = ioaddr; request_region(ioaddr, LANCE_TOTAL_SIZE, chip_table[lance_version].name); - /* Make certain the data structures used by the LANCE are aligned. */ - dev->priv = (void *)(((int)dev->priv + 7) & ~7); - lp = (struct lance_private *)dev->priv; + /* Make certain the data structures used by the LANCE are aligned and DMAble. */ + lp = (struct lance_private *) kmalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL); + dev->priv = lp; lp->name = chipname; - lp->rx_buffs = (long)lp + ((sizeof(struct lance_private) + 7) & ~7); - lp->tx_bounce_buffs = (char (*)[PKT_BUF_SZ]) - (lp->rx_buffs + PKT_BUF_SZ*RX_RING_SIZE); + lp->rx_buffs = (unsigned long) kmalloc(PKT_BUF_SZ*RX_RING_SIZE, GFP_DMA | GFP_KERNEL); + lp->tx_bounce_buffs = NULL; + if (lance_need_isa_bounce_buffers) + lp->tx_bounce_buffs = kmalloc(PKT_BUF_SZ*TX_RING_SIZE, GFP_DMA | GFP_KERNEL); lp->chip_version = lance_version; @@ -490,7 +483,7 @@ printk(", probed IRQ %d", dev->irq); else { printk(", failed to detect IRQ line.\n"); - return mem_start; + return; } /* Check for the initialization done bit, 0x0100, which means @@ -504,7 +497,7 @@ } else if (dev->dma) { if (request_dma(dev->dma, chipname)) { printk("DMA %d allocation failed.\n", dev->dma); - return mem_start; + return; } else printk(", assigned DMA %d.\n", dev->dma); } else { /* OK, we have to auto-DMA. */ @@ -539,7 +532,7 @@ } if (i == 4) { /* Failure: bail. */ printk("DMA detection failed.\n"); - return mem_start; + return; } } @@ -560,7 +553,7 @@ dev->get_stats = &lance_get_stats; dev->set_multicast_list = &set_multicast_list; - return mem_start; + return; } @@ -1082,6 +1075,7 @@ } /* Set or clear the multicast filter for this adaptor. + num_addrs == -2 All multicasts num_addrs == -1 Promiscuous mode, receive all packets num_addrs == 0 Normal mode, clear multicast list num_addrs > 0 Multicast mode, receive normal and MC packets, and do @@ -1095,7 +1089,7 @@ outw(0, ioaddr+LANCE_ADDR); outw(0x0004, ioaddr+LANCE_DATA); /* Temporarily stop the lance. */ - if (num_addrs >= 0) { + if (num_addrs >= 0 || num_addrs==-2) { short multicast_table[4]; int i; /* We don't use the multicast table, but rely on upper-layer filtering. */ diff -u --recursive --new-file v1.3.32/linux/drivers/net/loopback.c linux/drivers/net/loopback.c --- v1.3.32/linux/drivers/net/loopback.c Wed Oct 4 14:14:31 1995 +++ linux/drivers/net/loopback.c Tue Oct 10 15:45:27 1995 @@ -125,8 +125,11 @@ int loopback_init(struct device *dev) { int i; - - dev->mtu = 2000; /* MTU */ +#ifdef CONFIG_SKB_LARGE + dev->mtu = 7900; /* MTU */ +#else + dev->mtu = 3800; +#endif dev->tbusy = 0; dev->hard_start_xmit = loopback_xmit; dev->open = NULL; @@ -140,7 +143,7 @@ dev->family = AF_INET; #ifdef CONFIG_INET dev->pa_addr = in_aton("127.0.0.1"); - dev->pa_brdaddr = in_aton("127.255.255.255"); + dev->pa_brdaddr = in_aton("127.255.255.255"); dev->pa_mask = in_aton("255.0.0.0"); dev->pa_alen = 4; #endif diff -u --recursive --new-file v1.3.32/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v1.3.32/linux/drivers/net/ne.c Wed Oct 4 14:14:31 1995 +++ linux/drivers/net/ne.c Tue Oct 10 14:03:45 1995 @@ -284,7 +284,7 @@ if (dev == NULL) - dev = init_etherdev(0, sizeof(struct ei_device), 0); + dev = init_etherdev(0, sizeof(struct ei_device)); if (dev->irq < 2) { autoirq_setup(0); diff -u --recursive --new-file v1.3.32/linux/drivers/net/net_init.c linux/drivers/net/net_init.c --- v1.3.32/linux/drivers/net/net_init.c Thu Sep 7 17:17:17 1995 +++ linux/drivers/net/net_init.c Tue Oct 10 14:01:01 1995 @@ -54,34 +54,6 @@ #define MAX_ETH_CARDS 16 /* same as the number if irq's in irq2dev[] */ static struct device *ethdev_index[MAX_ETH_CARDS]; -unsigned long lance_init(unsigned long mem_start, unsigned long mem_end); -unsigned long pi_init(unsigned long mem_start, unsigned long mem_end); -unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end); -unsigned long dec21040_init(unsigned long mem_start, unsigned long mem_end); - -/* - net_dev_init() is our network device initialization routine. - It's called from init/main.c with the start and end of free memory, - and returns the new start of free memory. - */ - -unsigned long net_dev_init (unsigned long mem_start, unsigned long mem_end) -{ - - /* Network device initialization for devices that must allocate - low-memory or contiguous DMA buffers. - */ -#if defined(CONFIG_LANCE) - mem_start = lance_init(mem_start, mem_end); -#endif -#if defined(CONFIG_PI) - mem_start = pi_init(mem_start, mem_end); -#endif -#if defined(CONFIG_DEC_ELCP) - mem_start = dec21040_init(mem_start, mem_end); -#endif - return mem_start; -} /* Fill in the fields of the device structure with ethernet-generic values. @@ -94,7 +66,7 @@ */ struct device * -init_etherdev(struct device *dev, int sizeof_priv, unsigned long *mem_startp) +init_etherdev(struct device *dev, int sizeof_priv) { int new_device = 0; int i; @@ -114,11 +86,7 @@ dev = cur_dev; dev->init = NULL; sizeof_priv = (sizeof_priv + 3) & ~3; - if (mem_startp && *mem_startp ) { - dev->priv = (void*) *mem_startp; - *mem_startp += sizeof_priv; - } else - dev->priv = sizeof_priv + dev->priv = sizeof_priv ? kmalloc(sizeof_priv, GFP_KERNEL) : NULL; if (dev->priv) memset(dev->priv, 0, sizeof_priv); @@ -128,11 +96,7 @@ alloc_size &= ~3; /* Round to dword boundary. */ - if (mem_startp && *mem_startp ) { - dev = (struct device *)*mem_startp; - *mem_startp += alloc_size; - } else - dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL); + dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL); memset(dev, 0, alloc_size); if (sizeof_priv) dev->priv = (void *) (dev + 1); diff -u --recursive --new-file v1.3.32/linux/drivers/net/ni65.c linux/drivers/net/ni65.c --- v1.3.32/linux/drivers/net/ni65.c Sat Sep 9 15:26:52 1995 +++ linux/drivers/net/ni65.c Tue Oct 10 15:45:27 1995 @@ -256,6 +256,7 @@ ether_setup(dev); + dev->flags &= ~IFF_MULTICAST; dev->interrupt = 0; dev->tbusy = 0; dev->start = 0; diff -u --recursive --new-file v1.3.32/linux/drivers/net/pi2.c linux/drivers/net/pi2.c --- v1.3.32/linux/drivers/net/pi2.c Tue Aug 15 20:39:03 1995 +++ linux/drivers/net/pi2.c Tue Oct 10 14:18:20 1995 @@ -79,9 +79,6 @@ #define DEF_B_SQUELDELAY 3 /* 30 mS */ #define DEF_B_CLOCKMODE 0 /* Normal clock mode */ -struct device *init_etherdev(struct device *dev, int sizeof_private, - unsigned long *mem_startp); - static const char *version = "PI: V0.8 ALPHA April 23 1995 David Perry (dp@hydra.carleton.ca)\n"; @@ -1207,7 +1204,7 @@ } -unsigned long pi_init(unsigned long mem_start, unsigned long mem_end) +int pi_init(void) { int *port; int ioaddr = 0; @@ -1236,7 +1233,7 @@ break; default: printk("PI: ERROR: No card found\n"); - return mem_start; + return -EIO; } /* Link a couple of device structures into the chain */ @@ -1247,9 +1244,7 @@ */ register_netdev(&pi0a); - pi0a.priv=(void *)mem_start; - mem_start+=sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4 - + 8; /* for alignment */ + pi0a.priv = kmalloc(sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA); pi0a.dma = PI_DMA; pi0a.base_addr = ioaddr + 2; @@ -1259,9 +1254,7 @@ register_netdev(&pi0b); pi0b.base_addr = ioaddr; pi0b.irq = 0; - pi0b.priv=(void *)mem_start; - mem_start+=sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4 - + 8; /* for alignment */ + pi0b.priv = kmalloc(sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA); /* Now initialize them */ pi_probe(&pi0a, card_type); @@ -1269,7 +1262,7 @@ pi0b.irq = pi0a.irq; /* IRQ is shared */ - return mem_start; + return 0; } static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize) diff -u --recursive --new-file v1.3.32/linux/drivers/net/ppp.c linux/drivers/net/ppp.c --- v1.3.32/linux/drivers/net/ppp.c Wed Oct 4 14:14:31 1995 +++ linux/drivers/net/ppp.c Tue Oct 10 15:11:32 1995 @@ -1,5 +1,21 @@ -/* PPP for Linux -*/ +/* PPP for Linux + * + * Michael Callahan + * Al Longyear + * + * Dynamic PPP devices by Jim Freeman . + * ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid + * + * ==FILEVERSION 4== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, increment the number above. + * ppp.c is shipped with a PPP distribution as well as with the kernel; + * if everyone increases the FILEVERSION number above, then scripts + * can do the right thing when deciding whether to install a new ppp.c + * file. Don't change the format of that line otherwise, so the + * installation script can recognize it. + */ /* Sources: @@ -15,29 +31,51 @@ Flags for this module (any combination is acceptable for testing.): - NET02D - Define if using Net-2-Debugged in kernels earlier - than v1.1.4. - - NEW_TTY_DRIVERS - Define if using new Ted Ts'o's alpha TTY drivers - from tsx-11.mit.edu. From Ted Ts'o. - - OPTIMIZE_FLAG_TIME - Number of jiffies to force sending of leading flag + OPTIMIZE_FLAG_TIME - Number of jiffies to force sending of leading flag character. This is normally set to ((HZ * 3) / 2). - This is 1.5 seconds. If not defined then the leading - flag is always sent. + This is 1.5 seconds. If zero then the leading + flag is always sent. + + CHECK_CHARACTERS - Enable the checking on all received characters for + 8 data bits, no parity. This adds a small amount of + processing for each received character. + + NEW_SKBUFF - Use NET3.020 sk_buff's */ -/* #define NET02D -* */ -#define NEW_TTY_DRIVERS /* */ -#define OPTIMIZE_FLAG_TIME ((HZ * 3)/2) /* */ -#define CHECK_CHARACTERS +/* #define NEW_SKBUFF 1 */ +#define OPTIMIZE_FLAG_TIME ((HZ * 3)/2) + +#define CHECK_CHARACTERS 1 +#define PPP_COMPRESS 1 +#define USE_SKB_PROTOCOL 1 /* Set by the installation program! */ + +#ifdef NEW_SKBUFF +#undef USE_SKB_PROTOCOL +#define USE_SKB_PROTOCOL 2 +#endif + +#ifndef PPP_MAX_DEV +#define PPP_MAX_DEV 256 +#endif + +/* $Id: ppp.c,v 1.5 1995/06/12 11:36:53 paulus Exp $ + * Added dynamic allocation of channels to eliminate + * compiled-in limits on the number of channels. + * + * Dynamic channel allocation code Copyright 1995 Caldera, Inc., + * released under the GNU General Public License Version 2. + */ -#include -#ifdef MODULE #include +#ifdef MODULE #include -#endif +#define STATIC +#else +#define STATIC static +#endif /* def MODULE */ +#include #include #include #include @@ -49,2111 +87,3529 @@ #include #include #include -#include /* to get the struct task_struct */ -#include /* used in new tty drivers */ -#include /* used in new tty drivers */ +#include /* to get the struct task_struct */ +#include /* used in new tty drivers */ +#include /* used in new tty drivers */ #include #include #include - -#ifdef NET02D /* v1.1.4 net code and earlier */ -#include -#include -#include -#define skb_queue_head_init(buf) *(buf) = NULL -#else /* v1.1.5 and later */ +#include +#include #include #include #include +#include + +#ifdef NEW_SKBUFF +#include +#else +typedef struct sk_buff sk_buff; +#define skb_data(skb) ((unsigned char *) (skb)->data) #endif +#include +#include +#include +#include "slhc.h" +#include +#include #include +#include -#include -#include +#undef PACKETPTR +#define PACKETPTR 1 +#include +#undef PACKETPTR -#include "slhc.h" +#define bsd_decompress (*ppp->sc_rcomp->decompress) +#define bsd_compress (*ppp->sc_xcomp->compress) -#include -#ifndef ARPHRD_PPP -#define ARPHRD_PPP 0 +#ifndef PPP_IPX +#define PPP_IPX 0x2b /* IPX protocol over PPP */ #endif -#define PRINTK(p) printk p ; -#define ASSERT(p) if (!p) PRINTK ((KERN_CRIT "assertion failed: " # p)) -#define PRINTKN(n,p) {if (ppp_debug >= n) PRINTK (p)} -#define CHECK_PPP(a) if (!ppp->inuse) { PRINTK ((ppp_warning, __LINE__)) return a;} -#define CHECK_PPP_VOID() if (!ppp->inuse) { PRINTK ((ppp_warning, __LINE__)) return;} - -#define in_xmap(ppp,c) (ppp->xmit_async_map[(c) >> 5] & (1 << ((c) & 0x1f))) -#define in_rmap(ppp,c) ((((unsigned int) (unsigned char) (c)) < 0x20) && \ - ppp->recv_async_map & (1 << (c))) - -#define bset(p,b) ((p)[(b) >> 5] |= (1 << ((b) & 0x1f))) - -int ppp_debug = 2; -int ppp_debug_netpackets = 0; - -/* Define this string only once for all macro invocations */ -static char ppp_warning[] = KERN_WARNING "PPP: ALERT! not INUSE! %d\n"; - -int ppp_init(struct device *); -static void ppp_init_ctrl_blk(struct ppp *); -static int ppp_dev_open(struct device *); -static int ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd); -static int ppp_dev_close(struct device *); -static void ppp_kick_tty(struct ppp *); - -#ifdef NEW_TTY_DRIVERS -#define ppp_find(tty) ((struct ppp *) tty->disc_data) -#else -static void ppp_output_done(void *); -static void ppp_unesc(struct ppp *ppp, unsigned char *c, int n); -static struct ppp *ppp_find(struct tty_struct *); -#endif - -static void ppp_doframe(struct ppp *); -static int ppp_do_ip(struct ppp *, unsigned short, unsigned char *, int); -static int ppp_us_queue(struct ppp *, unsigned short, unsigned char *, int); -static int ppp_xmit(struct sk_buff *, struct device *); - -#ifdef NET02D -static int ppp_header(unsigned char *buff, struct device *dev, - unsigned short type, unsigned long daddr, - unsigned long saddr, unsigned len); -static int ppp_rebuild_header(void *buff, struct device *dev); -static void ppp_add_arp(unsigned long addr, struct sk_buff *skb, - struct device *dev); -#else -static int ppp_header(struct sk_buff *, struct device *, unsigned short, - void *, void *, unsigned); -static int ppp_rebuild_header(void *, struct device *, unsigned long, - struct sk_buff *); -#endif - -static struct enet_statistics *ppp_get_stats (struct device *); -static struct ppp *ppp_alloc(void); -static int ppp_lock(struct ppp *); -static void ppp_unlock(struct ppp *); -static void ppp_add_fcs(struct ppp *); -static int ppp_check_fcs(struct ppp *); -static void ppp_print_buffer(const char *,const char *,int,int); - -static int ppp_read(struct tty_struct *, struct file *, unsigned char *, - unsigned int); -static int ppp_write(struct tty_struct *, struct file *, const unsigned char *, - unsigned int); -static int ppp_ioctl(struct tty_struct *, struct file *, unsigned int, - unsigned long); -static int ppp_select(struct tty_struct *tty, struct inode * inode, - struct file * filp, int sel_type, select_table * wait); -static int ppp_open(struct tty_struct *); -static void ppp_close(struct tty_struct *); - -#ifdef NEW_TTY_DRIVERS -static int ppp_receive_room(struct tty_struct *tty); -static void ppp_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count); -static void ppp_write_wakeup(struct tty_struct *tty); -#else -static void ppp_tty_input_ready(struct tty_struct *); +#ifndef PPP_LQR +#define PPP_LQR 0xc025 /* Link Quality Reporting Protocol */ #endif -/* FCS table from RFC1331 */ +STATIC int ppp_register_compressor (struct compressor *cp); +STATIC void ppp_unregister_compressor (struct compressor *cp); -static unsigned short fcstab[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 - }; - -struct tty_ldisc ppp_ldisc; - -static struct ppp ppp_ctrl[PPP_NRUNIT]; - -/************************************************************* - * INITIALIZATION - *************************************************************/ +/* + * Local functions + */ -static int first_time = 1; +static struct compressor *find_compressor (int type); +static void ppp_init_ctrl_blk (register struct ppp *); +static void ppp_kick_tty (struct ppp *, struct ppp_buffer *bfr); +static int ppp_doframe (struct ppp *); +static struct ppp *ppp_alloc (void); +static void ppp_print_buffer (const u_char *, const u_char *, int); +extern inline void ppp_stuff_char (struct ppp *ppp, + register struct ppp_buffer *buf, + register u_char chr); +extern inline int lock_buffer (register struct ppp_buffer *buf); + +static int rcv_proto_ip (struct ppp *, u_short, u_char *, int); +static int rcv_proto_ipx (struct ppp *, u_short, u_char *, int); +static int rcv_proto_vjc_comp (struct ppp *, u_short, u_char *, int); +static int rcv_proto_vjc_uncomp (struct ppp *, u_short, u_char *, int); +static int rcv_proto_unknown (struct ppp *, u_short, u_char *, int); +static int rcv_proto_lqr (struct ppp *, u_short, u_char *, int); +static void ppp_doframe_lower (struct ppp *, u_char *, int); +static int ppp_doframe (struct ppp *); + +extern int ppp_bsd_compressor_init(void); +static void ppp_proto_ccp (struct ppp *ppp, u_char *dp, int len, int rcvd); +static int rcv_proto_ccp (struct ppp *, u_short, u_char *, int); -/* called at boot time for each ppp device */ +#define ins_char(pbuf,c) (buf_base(pbuf) [(pbuf)->count++] = (u_char)(c)) -int -ppp_init(struct device *dev) -{ - struct ppp *ppp; - int i; +#ifndef OPTIMIZE_FLAG_TIME +#define OPTIMIZE_FLAG_TIME 0 +#endif - ppp = &ppp_ctrl[dev->base_addr]; +#ifndef PPP_MAX_DEV +#define PPP_MAX_DEV 256 +#endif - if (first_time) { - first_time = 0; +/* + * Parameters which may be changed via insmod. + */ - printk (KERN_INFO "PPP: version %s (%d channels)" -#ifdef NET02D - " NET02D" -#endif -#ifdef NEW_TTY_DRIVERS - " NEW_TTY_DRIVERS" -#endif -#ifdef OPTIMIZE_FLAG_TIME - " OPTIMIZE_FLAGS" -#endif - "\n", PPP_VERSION, PPP_NRUNIT); +STATIC int flag_time = OPTIMIZE_FLAG_TIME; +STATIC int max_dev = PPP_MAX_DEV; - printk (KERN_INFO - "TCP compression code copyright 1989 Regents of the " - "University of California\n"); +/* + * The "main" procedure to the ppp device + */ - (void) memset(&ppp_ldisc, 0, sizeof(ppp_ldisc)); - ppp_ldisc.open = ppp_open; - ppp_ldisc.close = ppp_close; - ppp_ldisc.read = ppp_read; - ppp_ldisc.write = ppp_write; - ppp_ldisc.ioctl = ppp_ioctl; - ppp_ldisc.select = ppp_select; +int ppp_init (struct device *); -#ifdef NEW_TTY_DRIVERS - ppp_ldisc.magic = TTY_LDISC_MAGIC; - ppp_ldisc.receive_room = ppp_receive_room; - ppp_ldisc.receive_buf = ppp_receive_buf; - ppp_ldisc.write_wakeup = ppp_write_wakeup; -#else - ppp_ldisc.handler = ppp_tty_input_ready; -#endif +/* + * Network device driver callback routines + */ - if ((i = tty_register_ldisc(N_PPP, &ppp_ldisc)) == 0) - printk(KERN_INFO "PPP line discipline registered.\n"); - else - printk(KERN_ERR "error registering line discipline: %d\n", i); - } - - /* initialize PPP control block */ - ppp_init_ctrl_blk (ppp); - ppp->inuse = 0; - ppp->line = dev->base_addr; - ppp->tty = NULL; - ppp->dev = dev; - - /* clear statistics */ - memset (&ppp->stats, '\0', sizeof (struct ppp_stats)); - - /* device INFO */ - dev->mtu = PPP_MTU; - dev->hard_start_xmit = ppp_xmit; - dev->open = ppp_dev_open; - dev->stop = ppp_dev_close; - dev->get_stats = ppp_get_stats; - dev->hard_header = ppp_header; - dev->rebuild_header = ppp_rebuild_header; - dev->hard_header_len = 0; - dev->addr_len = 0; - dev->type = ARPHRD_PPP; - -#ifdef NET02D - dev->add_arp = ppp_add_arp; - dev->queue_xmit = dev_queue_xmit; +static int ppp_dev_open (struct device *); +static int ppp_dev_ioctl (struct device *dev, struct ifreq *ifr, int cmd); +static int ppp_dev_close (struct device *); +static int ppp_dev_xmit (sk_buff *, struct device *); +static struct enet_statistics *ppp_dev_stats (struct device *); + +#if USE_SKB_PROTOCOL == 0 /* The 1.2.x kernel is here */ +#define dev_alloc_skb(count) alloc_skb(count, GFP_ATOMIC) +#define skb_put(skb,count) skb_data(skb) +#define get_long_user(addr) get_user_long((void *) addr) +#define get_int_user(addr) ((int) get_user_long((void *) addr)) +#define put_byte_user(val,addr) put_fs_byte(val,((u_char *) (addr))) +#define put_long_user(val,addr) put_fs_long((val),((void *) (addr))) + +static unsigned short ppp_dev_type (sk_buff *, struct device *); +static int ppp_dev_header (unsigned char *buff, struct device *dev, + unsigned short type, void *daddr, void *saddr, + unsigned len, struct sk_buff *skb); + +#else /* The 1.3.x kernel is here */ +#define get_long_user(addr) get_user(((long *) addr)) +#define get_int_user(addr) ((int) get_user(((int *) addr))) +#define put_byte_user(val,addr) put_user((val),((u_char *) (addr))) +#define put_long_user(val,addr) put_user((val),((long *) (addr))) + +static int ppp_dev_header (sk_buff *, struct device *, unsigned short, + void *, void *, unsigned); +#endif + +#ifdef NEW_SKBUFF +static int ppp_dev_input (struct protocol *self, struct protocol *lower, + sk_buff *skb, void *saddr, void *daddr); +static int ppp_dev_output (struct protocol *self, sk_buff *skb, int type, + int subid, void *saddr, void *daddr, void *opt); +static int ppp_dev_getkey(int protocol, int subid, unsigned char *key); #else - dev->do_ioctl = ppp_dev_ioctl; +static int ppp_dev_rebuild (void *, struct device *, unsigned long, + sk_buff *); #endif - for (i = 0; i < DEV_NUMBUFFS; i++) - skb_queue_head_init(&dev->buffs[i]); /* = NULL if NET02D */ - - /* New-style flags */ - dev->flags = IFF_POINTOPOINT; - dev->family = AF_INET; - dev->pa_addr = 0; - dev->pa_brdaddr = 0; - dev->pa_mask = 0; - dev->pa_alen = 4; - - return 0; -} +/* + * TTY callbacks + */ -static void -ppp_init_ctrl_blk(struct ppp *ppp) -{ - ppp->magic = PPP_MAGIC; - ppp->sending = 0; - ppp->toss = 0xFE; - ppp->escape = 0; - - ppp->flags = 0; - ppp->mtu = PPP_MTU; - ppp->mru = PPP_MRU; - ppp->fcs = 0; - - memset (ppp->xmit_async_map, 0, sizeof (ppp->xmit_async_map)); - ppp->xmit_async_map[0] = 0xffffffff; - ppp->xmit_async_map[3] = 0x60000000; - ppp->recv_async_map = 0x00000000; - - ppp->slcomp = NULL; - ppp->rbuff = NULL; - ppp->xbuff = NULL; - ppp->cbuff = NULL; - - ppp->rhead = NULL; - ppp->rend = NULL; - ppp->rcount = 0; - ppp->xhead = NULL; - ppp->xtail = NULL; - - ppp->us_rbuff = NULL; - ppp->us_rbuff_end = NULL; - ppp->us_rbuff_head = NULL; - ppp->us_rbuff_tail = NULL; - ppp->read_wait = NULL; - ppp->write_wait = NULL; - ppp->us_rbuff_lock = 0; - ppp->inp_sig = 0; - ppp->inp_sig_pid = 0; +static int ppp_tty_read (struct tty_struct *, struct file *, u_char *, + unsigned int); +static int ppp_tty_write (struct tty_struct *, struct file *, const u_char *, + unsigned int); +static int ppp_tty_ioctl (struct tty_struct *, struct file *, unsigned int, + unsigned long); +static int ppp_tty_select (struct tty_struct *tty, struct inode *inode, + struct file *filp, int sel_type, select_table * wait); +static int ppp_tty_open (struct tty_struct *); +static void ppp_tty_close (struct tty_struct *); +static int ppp_tty_room (struct tty_struct *tty); +static void ppp_tty_receive (struct tty_struct *tty, const u_char * cp, + char *fp, int count); +static void ppp_tty_wakeup (struct tty_struct *tty); -#ifdef OPTIMIZE_FLAG_TIME /* ensure flag will always be sent first time */ - ppp->last_xmit = jiffies - OPTIMIZE_FLAG_TIME; -#else - ppp->last_xmit = 0; -#endif +#define CHECK_PPP(a) if (!ppp->inuse) { printk (ppp_warning, __LINE__); return a;} +#define CHECK_PPP_VOID() if (!ppp->inuse) { printk (ppp_warning, __LINE__); return;} - /* clear statistics */ - memset (&ppp->stats, '\0', sizeof (struct ppp_stats)); +#define in_xmap(ppp,c) (ppp->xmit_async_map[(c) >> 5] & (1 << ((c) & 0x1f))) +#define in_rmap(ppp,c) ((((unsigned int) (u_char) (c)) < 0x20) && \ + ppp->recv_async_map & (1 << (c))) - /* Reset the demand dial information */ - ppp->ddinfo.ip_sjiffies = - ppp->ddinfo.ip_rjiffies = - ppp->ddinfo.nip_sjiffies = - ppp->ddinfo.nip_rjiffies = jiffies; -} +#define bset(p,b) ((p)[(b) >> 5] |= (1 << ((b) & 0x1f))) -/* - * MTU has been changed by the IP layer. Unfortunately we are not told - * about this, but we spot it ourselves and fix things up. We could be - * in an upcall from the tty driver, or in an ip packet queue. - */ - -static void -ppp_changedmtu (struct ppp *ppp, int new_mtu, int new_mru) -{ - struct device *dev; - unsigned char *new_rbuff, *new_xbuff, *new_cbuff; - unsigned char *old_rbuff, *old_xbuff, *old_cbuff; - int mtu, mru; -/* - * Allocate the buffer from the kernel for the data - */ - dev = ppp->dev; - mru = new_mru; - mtu = new_mtu; - - /* RFC 1331, section 7.2 says the minimum value is 1500 bytes */ - if (mru < PPP_MRU) - mru = PPP_MRU; +#define tty2ppp(tty) ((struct ppp *) (tty->disc_data)) +#define dev2ppp(dev) ((struct ppp *) (dev->priv)) +#define ppp2tty(ppp) ((struct tty_struct *) ppp->tty) +#define ppp2dev(ppp) ((struct device *) ppp->dev) + +struct ppp_hdr { + unsigned char address; + unsigned char control; + unsigned char protocol[2]; +}; - mtu = (mtu * 2) + 20; - mru = (mru * 2) + 20; +#define PPP_HARD_HDR_LEN (sizeof (struct ppp_hdr)) - PRINTKN (2,(KERN_INFO "ppp: channel %s mtu = %d, mru = %d\n", - dev->name, new_mtu, new_mru)); - - new_xbuff = (unsigned char *) kmalloc(mtu + 4, GFP_ATOMIC); - new_rbuff = (unsigned char *) kmalloc(mru + 4, GFP_ATOMIC); - new_cbuff = (unsigned char *) kmalloc(mru + 4, GFP_ATOMIC); -/* - * If the buffers failed to allocate then complain. - */ - if (new_xbuff == NULL || new_rbuff == NULL || new_cbuff == NULL) - { - PRINTKN (2,(KERN_ERR "ppp: failed to allocate new buffers\n")); -/* - * Release new buffer pointers if the updates were not performed - */ - if (new_rbuff != NULL) - kfree (new_rbuff); +typedef struct ppp_ctrl { + struct ppp_ctrl *next; /* Next structure in the list */ + char name [8]; /* Name of the device */ + struct ppp ppp; /* PPP control table */ + struct device dev; /* Device information table */ +} ppp_ctrl_t; + +static ppp_ctrl_t *ppp_list = NULL; + +#define ctl2ppp(ctl) (struct ppp *) &ctl->ppp +#define ctl2dev(ctl) (struct device *) &ctl->dev +#undef PPP_NRUNIT + +/* Buffer types */ +#define BUFFER_TYPE_DEV_RD 0 /* ppp read buffer */ +#define BUFFER_TYPE_TTY_WR 1 /* tty write buffer */ +#define BUFFER_TYPE_DEV_WR 2 /* ppp write buffer */ +#define BUFFER_TYPE_TTY_RD 3 /* tty read buffer */ +#define BUFFER_TYPE_VJ 4 /* vj compression buffer */ - if (new_xbuff != NULL) - kfree (new_xbuff); +/* Define this string only once for all macro envocations */ +static char ppp_warning[] = KERN_WARNING "PPP: ALERT! not INUSE! %d\n"; - if (new_cbuff != NULL) - kfree (new_cbuff); - } -/* - * Update the pointers to the new buffer structures. - */ - else - { - cli(); - old_xbuff = ppp->xbuff; - old_rbuff = ppp->rbuff; - old_cbuff = ppp->cbuff; - - ppp->xbuff = new_xbuff; - ppp->rbuff = new_rbuff; - ppp->cbuff = new_cbuff; - - dev->mem_start = (unsigned long) new_xbuff; - dev->mem_end = (unsigned long) (dev->mem_start + mtu); - - dev->rmem_start = (unsigned long) new_rbuff; - ppp->rend = (unsigned char *) - dev->rmem_end = (unsigned long) (dev->rmem_start + mru); +static char szVersion[] = PPP_VERSION; + +#ifdef NEW_SKBUFF +static struct protocol proto_ppp; +#endif - ppp->rhead = new_rbuff; /* - * Update the parameters for the new buffer sizes + * Information for the protocol decoder */ - ppp->toss = 0xFE; - ppp->escape = 0; - ppp->sending = 0; - ppp->rcount = 0; - ppp->mru = new_mru; +typedef int (*pfn_proto) (struct ppp *, u_short, u_char *, int); - ppp->mtu = - dev->mtu = new_mtu; +typedef struct ppp_proto_struct { + int proto; + pfn_proto func; +} ppp_proto_type; + +static +ppp_proto_type proto_list[] = { + { PPP_IP, rcv_proto_ip }, + { PPP_IPX, rcv_proto_ipx }, + { PPP_VJC_COMP, rcv_proto_vjc_comp }, + { PPP_VJC_UNCOMP, rcv_proto_vjc_uncomp }, + { PPP_LQR, rcv_proto_lqr }, + { PPP_CCP, rcv_proto_ccp }, + { 0, rcv_proto_unknown } /* !!! MUST BE LAST !!! */ +}; - sti(); /* - * Release old buffer pointers + * Values for FCS calculations. */ - if (old_rbuff != NULL) - kfree (old_rbuff); - - if (old_xbuff != NULL) - kfree (old_xbuff); - - if (old_cbuff != NULL) - kfree (old_cbuff); - } -} -/* called when we abandon the PPP line discipline */ +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ +#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_crc16_table[((fcs) ^ (c)) & 0xff]) + +unsigned short ppp_crc16_table[256] = +{ + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; -static void -ppp_release(struct ppp *ppp) +#ifdef CHECK_CHARACTERS +static unsigned paritytab[8] = { -#ifdef NEW_TTY_DRIVERS - if (ppp->tty != NULL && ppp->tty->disc_data == ppp) - ppp->tty->disc_data = NULL; /* Break the tty->ppp link */ -#endif - - if (ppp->dev) { - dev_close (ppp->dev); - ppp->dev->flags = 0; - } - - kfree (ppp->xbuff); - kfree (ppp->cbuff); - kfree (ppp->rbuff); - kfree (ppp->us_rbuff); - - ppp->xbuff = - ppp->cbuff = - ppp->rbuff = - ppp->us_rbuff = NULL; - - if (ppp->slcomp) { - slhc_free(ppp->slcomp); - ppp->slcomp = NULL; - } + 0x96696996, 0x69969669, 0x69969669, 0x96696996, + 0x69969669, 0x96696996, 0x96696996, 0x69969669 +}; +#endif - ppp->inuse = 0; - ppp->tty = NULL; +/* local function to store a value into the LQR frame */ +extern inline u_char * store_long (register u_char *p, register int value) { + *p++ = (u_char) (value >> 24); + *p++ = (u_char) (value >> 16); + *p++ = (u_char) (value >> 8); + *p++ = (u_char) value; + return p; } -static void -ppp_close(struct tty_struct *tty) -{ - struct ppp *ppp = ppp_find(tty); - - if (ppp == NULL || ppp->magic != PPP_MAGIC) { - PRINTKN (1,(KERN_WARNING "ppp: trying to close unopened tty!\n")); - } else { - CHECK_PPP_VOID(); - ppp_release (ppp); +/************************************************************* + * INITIALIZATION + *************************************************************/ - PRINTKN (2,(KERN_INFO "ppp: channel %s closing.\n", ppp->dev->name)); -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - } -} +/* This procedure is called once and once only to define who we are to + * the operating system and the various procedures that it may use in + * accessing the ppp protocol. + */ -/* called when PPP line discipline is selected on a tty */ static int -ppp_open(struct tty_struct *tty) +ppp_first_time (void) { - struct ppp *ppp = ppp_find(tty); - - if (ppp) { - PRINTKN (1,(KERN_ERR "ppp_open: gack! tty already associated to %s!\n", - ppp->magic == PPP_MAGIC ? ppp->dev->name : "unknown")); - return -EEXIST; - } - - ppp = ppp_alloc(); - if (ppp == NULL) { - PRINTKN (1,(KERN_ERR "ppp_open: couldn't allocate ppp channel\n")); - return -ENFILE; - } - - /* make sure the channel is actually open */ - ppp_init_ctrl_blk (ppp); - - ppp->tty = tty; + static struct tty_ldisc ppp_ldisc; + int status; -#ifdef NEW_TTY_DRIVERS - tty->disc_data = ppp; - if (tty->driver.flush_buffer) - tty->driver.flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); -#else - tty_read_flush (tty); - tty_write_flush (tty); + printk (KERN_INFO + "PPP: version %s (dynamic channel allocation)" +#ifdef NEW_SKBUFF + " NEW_SKBUFF" +#endif + "\n", szVersion); + +#ifndef MODULE /* slhc module logic has its own copyright announcment */ + printk (KERN_INFO + "TCP compression code copyright 1989 Regents of the " + "University of California\n"); #endif + + printk (KERN_INFO + "PPP Dynamic channel allocation code copyright 1995 " + "Caldera, Inc.\n"); +/* + * Register the protocol for the device + */ - if ((ppp->slcomp = slhc_init(16, 16)) == NULL) { - PRINTKN (1,(KERN_ERR "ppp: no space for compression buffers!\n")); - ppp_release (ppp); - return -ENOMEM; - } - - /* Define the buffers for operation */ - ppp_changedmtu (ppp, ppp->dev->mtu, ppp->mru); - if (ppp->rbuff == NULL) { - ppp_release (ppp); - return -ENOMEM; - } - - /* Allocate a user-level receive buffer */ - ppp->us_rbuff = (unsigned char *) kmalloc (RBUFSIZE, GFP_KERNEL); - if (ppp->us_rbuff == NULL) { - PRINTKN (1,(KERN_ERR "ppp: no space for user receive buffer\n")); - ppp_release (ppp); - return -ENOMEM; - } - - ppp->us_rbuff_head = - ppp->us_rbuff_tail = ppp->us_rbuff; - ppp->us_rbuff_end = ppp->us_rbuff + RBUFSIZE; +#ifdef NEW_SKBUFF + memset (&proto_ppp, 0, sizeof (proto_ppp)); - PRINTKN (2,(KERN_INFO "ppp: channel %s open\n", ppp->dev->name)); + proto_ppp.name = "PPP"; + proto_ppp.output = ppp_dev_output; + proto_ppp.input = ppp_dev_input; + proto_ppp.bh_input = ppp_dev_input; + proto_ppp.control_event = default_protocol_control; + proto_ppp.get_binding = ppp_dev_getkey; + proto_ppp.header_space = 0; /* PPP_HARD_HDR_LEN; */ -#ifdef MODULE - MOD_INC_USE_COUNT; + protocol_register(&proto_ppp); #endif - return (ppp->line); +/* + * Register the tty dicipline + */ + (void) memset (&ppp_ldisc, 0, sizeof (ppp_ldisc)); + ppp_ldisc.magic = TTY_LDISC_MAGIC; + ppp_ldisc.open = ppp_tty_open; + ppp_ldisc.close = ppp_tty_close; + ppp_ldisc.read = ppp_tty_read; + ppp_ldisc.write = ppp_tty_write; + ppp_ldisc.ioctl = ppp_tty_ioctl; + ppp_ldisc.select = ppp_tty_select; + ppp_ldisc.receive_room = ppp_tty_room; + ppp_ldisc.receive_buf = ppp_tty_receive; + ppp_ldisc.write_wakeup = ppp_tty_wakeup; + + status = tty_register_ldisc (N_PPP, &ppp_ldisc); + if (status == 0) + printk (KERN_INFO "PPP line discipline registered.\n"); + else + printk (KERN_ERR "error registering line discipline: %d\n", + status); + return status; } -/* called when ppp interface goes "up". here this just means we start - passing IP packets */ -static int -ppp_dev_open(struct device *dev) -{ - struct ppp *ppp = &ppp_ctrl[dev->base_addr]; - - /* reset POINTOPOINT every time, since dev_close zaps it! */ - dev->flags |= IFF_POINTOPOINT; - - if (ppp->tty == NULL) { - PRINTKN (1,(KERN_ERR "ppp: %s not connected to a TTY! can't go open!\n", - dev->name)); - return -ENXIO; - } - - PRINTKN (2,(KERN_INFO "ppp: channel %s going up for IP packets!\n", - dev->name)); +/************************************************************* + * INITIALIZATION + *************************************************************/ - CHECK_PPP(-ENXIO); - return 0; -} +/* called when the device is actually created */ static int -ppp_dev_close(struct device *dev) +ppp_init_dev (struct device *dev) { - struct ppp *ppp = &ppp_ctrl[dev->base_addr]; - - if (ppp->tty == NULL) { - PRINTKN (1,(KERN_ERR "ppp: %s not connected to a TTY! can't go down!\n", - dev->name)); - return -ENXIO; - } + int indx; +#ifdef NEW_SKBUFF + dev->default_protocol = &proto_ppp; /* Our protocol layer is PPP */ +#else + dev->hard_header = ppp_dev_header; +#if USE_SKB_PROTOCOL == 0 + dev->type_trans = ppp_dev_type; +#endif + dev->rebuild_header = ppp_dev_rebuild; + dev->hard_header_len = 0; /* PPP_HARD_HDR_LEN; */ +#endif + + /* device INFO */ + dev->mtu = PPP_MTU; + dev->hard_start_xmit = ppp_dev_xmit; + dev->open = ppp_dev_open; + dev->stop = ppp_dev_close; + dev->get_stats = ppp_dev_stats; + dev->do_ioctl = ppp_dev_ioctl; + dev->addr_len = 0; + dev->type = ARPHRD_PPP; + + for (indx = 0; indx < DEV_NUMBUFFS; indx++) + skb_queue_head_init (&dev->buffs[indx]); + + /* New-style flags */ + dev->flags = IFF_POINTOPOINT; + dev->family = AF_INET; + dev->pa_addr = 0; + dev->pa_brdaddr = 0; + dev->pa_mask = 0; + dev->pa_alen = 4; /* sizeof (unsigned long) */ - PRINTKN (2,(KERN_INFO "ppp: channel %s going down for IP packets!\n", - dev->name)); - CHECK_PPP(-ENXIO); - return 0; + return 0; } -#ifndef NET02D -static int ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd) -{ - struct ppp *ppp = &ppp_ctrl[dev->base_addr]; - int error; +/* + * Local procedure to initialize the ppp structure + */ - struct stats - { - struct ppp_stats ppp_stats; - struct slcompress slhc; - } *result; +static void +ppp_init_ctrl_blk (register struct ppp *ppp) +{ + ppp->magic = PPP_MAGIC; + ppp->toss = 0xE0; + ppp->escape = 0; - error = verify_area (VERIFY_WRITE, - ifr->ifr_ifru.ifru_data, - sizeof (struct stats)); + ppp->flags = 0; + ppp->mtu = PPP_MTU; + ppp->mru = PPP_MRU; + + memset (ppp->xmit_async_map, 0, sizeof (ppp->xmit_async_map)); + ppp->xmit_async_map[0] = 0xffffffff; + ppp->xmit_async_map[3] = 0x60000000; + ppp->recv_async_map = 0x00000000; + + ppp->rbuf = NULL; + ppp->wbuf = NULL; + ppp->ubuf = NULL; + ppp->cbuf = NULL; + ppp->slcomp = NULL; + ppp->read_wait = NULL; + ppp->write_wait = NULL; + ppp->last_xmit = jiffies - flag_time; + + /* clear statistics */ + memset (&ppp->stats, '\0', sizeof (struct pppstat)); + + /* Reset the demand dial information */ + ppp->ddinfo.xmit_idle= /* time since last NP packet sent */ + ppp->ddinfo.recv_idle=jiffies; /* time since last NP packet received */ + + /* PPP compression data */ + ppp->sc_xc_state = + ppp->sc_rc_state = NULL; +} - if (error == 0) { - result = (struct stats *) ifr->ifr_ifru.ifru_data; +/* called at boot/load time for each ppp device defined in the kernel */ - memcpy_tofs (&result->ppp_stats, &ppp->stats, sizeof (struct ppp_stats)); - if (ppp->slcomp) - memcpy_tofs (&result->slhc, ppp->slcomp, sizeof (struct slcompress)); - } +#ifndef MODULE +int +ppp_init (struct device *dev) +{ + static int first_time = 1; + int answer = 0; - return error; + if (first_time) { + static struct symbol_table ppp_syms = { +#include + X(ppp_register_compressor), + X(ppp_unregister_compressor), + X(ppp_crc16_table), +#include + }; + + first_time = 0; + answer = ppp_first_time(); + if (answer == 0) + (void) register_symtab (&ppp_syms); + } +/* + * Un-register the devices defined at the start of the system. They will + * be added when they are needed again. The first device just gets us into + * this code to register the handlers. + */ + unregister_netdev (dev); + return answer; } #endif -/************************************************************* - * TTY OUTPUT - * The following function delivers a fully-formed PPP - * frame in ppp->xbuff to the TTY for output. - *************************************************************/ +/* + * Routine to allocate a buffer for later use by the driver. + */ -#ifdef NEW_TTY_DRIVERS -static inline void -#else -static void -#endif -ppp_output_done (void *ppp) +static struct ppp_buffer * +ppp_alloc_buf (int size, int type) { - /* unlock the transmitter queue */ - ppp_unlock ((struct ppp *) ppp); + struct ppp_buffer *buf; - /* If the device is still up then enable the transmitter of the - next frame. */ - if (((struct ppp *) ppp)->dev->flags & IFF_UP) -#ifndef NET02D - mark_bh (NET_BH); -#else - dev_tint (((struct ppp *) ppp)->dev); -#endif + buf = (struct ppp_buffer *) kmalloc (size + sizeof (struct ppp_buffer), + GFP_ATOMIC); - /* enable any blocked process pending transmission */ - wake_up_interruptible (&((struct ppp *) ppp)->write_wait); + if (buf != NULL) { + buf->size = size - 1; /* Mask for the buffer size */ + buf->type = type; + buf->locked = 0; + buf->count = 0; + buf->head = 0; + buf->tail = 0; + buf->fcs = PPP_INITFCS; + } + return (buf); } -#ifndef NEW_TTY_DRIVERS +/* + * Routine to release the allocated buffer. + */ + static void -ppp_kick_tty (struct ppp *ppp) +ppp_free_buf (struct ppp_buffer *ptr) { - register int count = ppp->xhead - ppp->xbuff; - register int answer; - - ppp->stats.sbytes += count; - - answer = tty_write_data (ppp->tty, - ppp->xbuff, - count, - ppp_output_done, - (void *) ppp); - - if (answer == 0) - ppp_output_done (ppp); /* Should not happen */ - else - if (answer < 0) { - ppp->stats.serrors++; - ppp_output_done (ppp); /* unlock the transmitter */ - } + if (ptr != NULL) + kfree (ptr); } -#else +/* + * Lock the indicated transmit buffer + */ -static void -ppp_kick_tty (struct ppp *ppp) +extern inline int +lock_buffer (register struct ppp_buffer *buf) { - register int count, actual; - - count = ppp->xhead - ppp->xbuff; - - actual = ppp->tty->driver.write(ppp->tty, 0, ppp->xbuff, count); - ppp->stats.sbytes += actual; - if (actual == count) { - ppp_output_done(ppp); - } else { - ppp->xtail = ppp->xbuff + actual; - ppp->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); - } + register int state; + int flags; +/* + * Save the current state and if free then set it to the "busy" state + */ + save_flags (flags); + cli (); + state = buf->locked; + if (state == 0) + buf->locked = 2; +/* + * Restore the flags and return the previous state. 0 implies success. + */ + restore_flags (flags); + return (state); } -static void ppp_write_wakeup(struct tty_struct *tty) +/* + * MTU has been changed by the IP layer. Unfortunately we are not told + * about this, but we spot it ourselves and fix things up. We could be + * in an upcall from the tty driver, or in an ip packet queue. + */ + +static int +ppp_changedmtu (struct ppp *ppp, int new_mtu, int new_mru) { - register int count, actual; - struct ppp *ppp = ppp_find(tty); + struct device *dev; - if (!ppp || ppp->magic != PPP_MAGIC) { - PRINTKN (1, - (KERN_ERR "PPP: write_wakeup called but couldn't " - "find PPP struct.\n")); - return; - } + struct ppp_buffer *new_rbuf; + struct ppp_buffer *new_wbuf; + struct ppp_buffer *new_cbuf; + struct ppp_buffer *new_tbuf; + + struct ppp_buffer *old_rbuf; + struct ppp_buffer *old_wbuf; + struct ppp_buffer *old_cbuf; + struct ppp_buffer *old_tbuf; - if (!ppp->xtail) - return; + int mtu, mru; +/* + * Allocate the buffer from the kernel for the data + */ + dev = ppp2dev (ppp); + mru = new_mru; + /* allow for possible escapement of every character */ + mtu = (new_mtu * 2) + 20; + + /* RFC 1331, section 7.2 says the minimum value is 1500 bytes */ + if (mru < PPP_MRU) + mru = PPP_MRU; - cli(); - if (ppp->flags & SC_XMIT_BUSY) { - sti(); - return; - } - ppp->flags |= SC_XMIT_BUSY; - sti(); + mru += 10; - count = ppp->xhead - ppp->xtail; - - actual = tty->driver.write(tty, 0, ppp->xtail, count); - ppp->stats.sbytes += actual; - if (actual == count) { - ppp->xtail = 0; - tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); - - ppp_output_done(ppp); - } else { - ppp->xtail += actual; + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO "ppp: channel %s mtu = %d, mru = %d\n", + dev->name, new_mtu, new_mru); + + new_wbuf = ppp_alloc_buf (mtu+PPP_HARD_HDR_LEN, BUFFER_TYPE_DEV_WR); + new_tbuf = ppp_alloc_buf ((PPP_MTU * 2) + 24, BUFFER_TYPE_TTY_WR); + new_rbuf = ppp_alloc_buf (mru + 84, BUFFER_TYPE_DEV_RD); + new_cbuf = ppp_alloc_buf (mru+PPP_HARD_HDR_LEN, BUFFER_TYPE_VJ); +/* + * If the buffers failed to allocate then complain and release the partial + * allocations. + */ + if (new_wbuf == NULL || new_tbuf == NULL || + new_rbuf == NULL || new_cbuf == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp: failed to allocate new buffers\n"); + + ppp_free_buf (new_wbuf); + ppp_free_buf (new_tbuf); + ppp_free_buf (new_rbuf); + ppp_free_buf (new_cbuf); + return 0; } - ppp->flags &= ~SC_XMIT_BUSY; -} -#endif +/* + * Update the pointers to the new buffer structures. + */ + cli (); + old_wbuf = ppp->wbuf; + old_rbuf = ppp->rbuf; + old_cbuf = ppp->cbuf; + old_tbuf = ppp->tbuf; + + ppp->wbuf = new_wbuf; + ppp->rbuf = new_rbuf; + ppp->cbuf = new_cbuf; + ppp->tbuf = new_tbuf; + + ppp->rbuf->size -= 80; /* reserve space for vj header expansion */ + + dev->mem_start = (unsigned long) buf_base (new_wbuf); + dev->mem_end = (unsigned long) (dev->mem_start + mtu); + dev->rmem_start = (unsigned long) buf_base (new_rbuf); + dev->rmem_end = (unsigned long) (dev->rmem_start + mru); +/* + * Update the parameters for the new buffer sizes + */ + ppp->toss = 0xE0; /* To ignore characters until new FLAG */ + ppp->escape = 0; /* No pending escape character */ -/************************************************************* - * TTY INPUT - * The following functions handle input that arrives from - * the TTY. It recognizes PPP frames and either hands them - * to the network layer or queues them for delivery to a - * user process reading this TTY. - *************************************************************/ + dev->mtu = + ppp->mtu = new_mtu; + ppp->mru = new_mru; -/* stuff a single character into the receive buffer */ + ppp->s1buf = NULL; + ppp->s2buf = NULL; + ppp->xbuf = NULL; -static inline void -ppp_enqueue(struct ppp *ppp, unsigned char c) -{ - unsigned long flags; + ppp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + ppp->flags &= ~SC_XMIT_BUSY; - save_flags(flags); - cli(); - if (ppp->rhead < ppp->rend) { - *ppp->rhead = c; - ppp->rhead++; - ppp->rcount++; - } else - ppp->stats.roverrun++; - restore_flags(flags); + sti (); +/* + * Release old buffer pointers + */ + ppp_free_buf (old_rbuf); + ppp_free_buf (old_wbuf); + ppp_free_buf (old_cbuf); + ppp_free_buf (old_tbuf); + return 1; } -#ifdef CHECK_CHARACTERS -static unsigned paritytab[8] = { - 0x96696996, 0x69969669, 0x69969669, 0x96696996, - 0x69969669, 0x96696996, 0x96696996, 0x69969669 -}; -#endif - -#ifndef NEW_TTY_DRIVERS -static void -ppp_dump_inqueue(struct tty_struct *tty) -{ - int head = tty->read_q.head, - tail = tty->read_q.tail, - i, count; - char buffer[8]; - - PRINTK ((KERN_DEBUG "INQUEUE: head %d tail %d imode %x:\n", head, tail, - (unsigned int) tty->termios->c_iflag)) - - i = tail; - count = 0; - - while (i != head) { - buffer [count] = tty->read_q.buf[i]; - if (++count == 8) { - ppp_print_buffer (NULL, buffer, 8, KERNEL_DS); - count = 0; - } - i = (i + 1) & (TTY_BUF_SIZE - 1); - } - ppp_print_buffer (NULL, buffer, count, KERNEL_DS); -} - -/* called by lower levels of TTY driver when data becomes available. - all incoming data comes through this function. */ - -void ppp_tty_input_ready(struct tty_struct *tty) -{ - struct ppp *ppp = ppp_find(tty); - int n, error; - unsigned char buff[128]; - -/* PRINTK( (KERN_DEBUG "PPP: handler called.\n") ) */ - if (!ppp || ppp->magic != PPP_MAGIC) { - PRINTKN (1, - (KERN_ERR "PPP: handler called but couldn't find PPP struct.\n")); - return; - } - - CHECK_PPP_VOID(); - - /* ZZZ */ - if (ppp_debug >= 5) - ppp_dump_inqueue(ppp->tty); - - do { - n = tty_read_raw_data(tty, buff, 128); - if ( n == 0 ) /* nothing there */ - break; - - if (ppp_debug >= 5) - ppp_print_buffer ("receive buffer", buff, n > 0 ? n : -n, KERNEL_DS); - - if ( n < 0 ) { - /* Last character is error flag. - Process the previous characters, then set toss flag. */ - n = (-n) - 1; - error = buff[n]; - } else error = 0; - ppp->stats.rbytes += n; - ppp_unesc(ppp,buff,n); - if (error) - ppp->toss = error; - } while (1); -} - -/* recover frame by undoing PPP escape mechanism; - copies N chars of input data from C into PPP->rbuff - calls ppp_doframe to dispose of any frames it finds -*/ +/* + * CCP is down; free (de)compressor state if necessary. + */ static void -ppp_unesc(struct ppp *ppp, unsigned char *c, int n) +ppp_ccp_closed (struct ppp *ppp) { - int i; - - for (i = 0; i < n; i++, c++) { - PRINTKN (6,(KERN_DEBUG "(%x)", (unsigned int) *c)); - -#ifdef CHECK_CHARACTERS - if (*c & 0x80) - sc->sc_flags |= SC_RCV_B7_1; - else - sc->sc_flags |= SC_RCV_B7_0; - - if (paritytab[*c >> 5] & (1 << (*c & 0x1F))) - sc->sc_flags |= SC_RCV_ODDP; - else - sc->sc_flags |= SC_RCV_EVNP; -#endif - - switch (*c) { - case PPP_ESC: /* PPP_ESC: invert 0x20 in next character */ - ppp->escape = PPP_TRANS; - break; - - case PPP_FLAG: /* PPP_FLAG: end of frame */ - if (ppp->escape) /* PPP_ESC just before PPP_FLAG is illegal */ - ppp->toss = 0xFF; - - if ((ppp->toss & 0x80) == 0) - ppp_doframe(ppp); /* pass frame on to next layers */ - - ppp->rcount = 0; - ppp->rhead = ppp->rbuff; - ppp->escape = 0; - ppp->toss = 0; - break; - - default: /* regular character */ - if (!in_rmap (ppp, *c)) { - if (ppp->toss == 0) - ppp_enqueue (ppp, *c ^ ppp->escape); - ppp->escape = 0; - } - break; - } - } -} + if (ppp->sc_xc_state) { + (*ppp->sc_xcomp->comp_free) (ppp->sc_xc_state); + ppp->sc_xc_state = NULL; + } -#else -static int ppp_receive_room(struct tty_struct *tty) -{ - return 65536; /* We can handle an infinite amount of data. :-) */ + if (ppp->sc_rc_state) { + (*ppp->sc_rcomp->decomp_free) (ppp->sc_rc_state); + ppp->sc_rc_state = NULL; + } } +/* + * Called to release all of the information in the current PPP structure. + * + * It is called when the ppp device goes down or if it is unable to go + * up. + */ -static void ppp_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static void +ppp_release (struct ppp *ppp) { - register struct ppp *ppp = ppp_find (tty); - unsigned char c; - -/* PRINTK( ("PPP: handler called.\n") ); */ + struct tty_struct *tty; + struct device *dev; - if (!ppp || ppp->magic != PPP_MAGIC) { - PRINTKN (1,("PPP: handler called but couldn't find " - "PPP struct.\n")); - return; - } + tty = ppp2tty (ppp); + dev = ppp2dev (ppp); - CHECK_PPP_VOID(); - - if (ppp_debug >= 5) { - ppp_print_buffer ("receive buffer", cp, count, KERNEL_DS); - } + ppp_ccp_closed (ppp); - ppp->stats.rbytes += count; - - while (count-- > 0) { - c = *cp++; + if (tty != NULL && tty->disc_data == ppp) + tty->disc_data = NULL; /* Break the tty->ppp link */ + + if (dev && dev->flags & IFF_UP) { + dev_close (dev); /* close the device properly */ + dev->flags = 0; /* prevent recursion */ + } - if (fp) { - if (*fp && ppp->toss == 0) - ppp->toss = *fp; - fp++; - } + ppp_free_buf (ppp->rbuf); + ppp_free_buf (ppp->wbuf); + ppp_free_buf (ppp->cbuf); + ppp_free_buf (ppp->ubuf); + ppp_free_buf (ppp->tbuf); + + ppp->rbuf = + ppp->wbuf = + ppp->cbuf = + ppp->tbuf = + ppp->xbuf = + ppp->s1buf = + ppp->s2buf = + ppp->ubuf = NULL; + + if (ppp->slcomp) { + slhc_free (ppp->slcomp); + ppp->slcomp = NULL; + } -#ifdef CHECK_CHARACTERS - if (c & 0x80) - ppp->flags |= SC_RCV_B7_1; - else - ppp->flags |= SC_RCV_B7_0; - - if (paritytab[c >> 5] & (1 << (c & 0x1F))) - ppp->flags |= SC_RCV_ODDP; - else - ppp->flags |= SC_RCV_EVNP; -#endif - - switch (c) { - case PPP_ESC: /* PPP_ESC: invert 0x20 in next character */ - ppp->escape = PPP_TRANS; - break; - - case PPP_FLAG: /* PPP_FLAG: end of frame */ - if (ppp->escape) /* PPP_ESC just before PPP_FLAG is "cancel"*/ - ppp->toss = 0xFF; - - if ((ppp->toss & 0x80) == 0) - ppp_doframe(ppp); /* pass frame on to next layers */ - - ppp->rcount = 0; - ppp->rhead = ppp->rbuff; - ppp->escape = 0; - ppp->toss = 0; - break; - - default: /* regular character */ - if (!in_rmap (ppp, c)) { - if (ppp->toss == 0) - ppp_enqueue (ppp, c ^ ppp->escape); - ppp->escape = 0; - } - } - } + ppp->inuse = 0; + ppp->tty = NULL; } + +/* + * Device callback. + * + * Called when the PPP device goes down in response to an ifconfig request. + */ + +static void +ppp_tty_close (struct tty_struct *tty) +{ + struct ppp *ppp = tty2ppp (tty); + + if (ppp != NULL) { + if (ppp->magic != PPP_MAGIC) { + if (ppp->flags & SC_DEBUG) + printk (KERN_WARNING + "ppp: trying to close unopened tty!\n"); + } else { + CHECK_PPP_VOID(); + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO "ppp: channel %s closing.\n", + ppp2dev(ppp) -> name); + ppp_release (ppp); + MOD_DEC_USE_COUNT; + } + } +} + +/* + * TTY callback. + * + * Called when the tty discipline is switched to PPP. + */ + +static int +ppp_tty_open (struct tty_struct *tty) +{ + struct ppp *ppp = tty2ppp (tty); +/* + * There should not be an existing table for this slot. + */ + if (ppp) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_tty_open: gack! tty already associated to %s!\n", + ppp->magic == PPP_MAGIC ? ppp2dev(ppp)->name + : "unknown"); + return -EEXIST; + } +/* + * Allocate the structure from the system + */ + ppp = ppp_alloc(); + if (ppp == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_tty_open: couldn't allocate ppp channel\n"); + return -ENFILE; + } +/* + * Initialize the control block + */ + ppp_init_ctrl_blk (ppp); + ppp->tty = tty; + tty->disc_data = ppp; +/* + * Flush any pending characters in the driver and discipline. + */ + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer (tty); + + if (tty->driver.flush_buffer) + tty->driver.flush_buffer (tty); +/* + * Allocate space for the default VJ header compression slots + */ + ppp->slcomp = slhc_init (16, 16); + if (ppp->slcomp == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_tty_open: no space for compression buffers!\n"); + ppp_release (ppp); + return -ENOMEM; + } +/* + * Allocate space for the MTU and MRU buffers + */ + if (ppp_changedmtu (ppp, ppp2dev(ppp)->mtu, ppp->mru) == 0) { + ppp_release (ppp); + return -ENOMEM; + } +/* + * Allocate space for a user level buffer + */ + ppp->ubuf = ppp_alloc_buf (RBUFSIZE, BUFFER_TYPE_TTY_RD); + if (ppp->ubuf == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_tty_open: no space for user receive buffer\n"); + ppp_release (ppp); + return -ENOMEM; + } + + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO "ppp: channel %s open\n", + ppp2dev(ppp)->name); + + MOD_INC_USE_COUNT; + return (ppp->line); +} + +/* + * Local function to send the next portion of the buffer. + * + * Called by the tty driver's tty_wakeup function should it be entered + * because the partial buffer was transmitted. + * + * Called by kick_tty to send the initial portion of the buffer. + * + * Completion processing of the buffer transmission is handled here. + */ + +static void +ppp_tty_wakeup_code (struct ppp *ppp, struct tty_struct *tty, + struct ppp_buffer *xbuf) +{ + register int count, actual; +/* + * Prevent re-entrancy by ensuring that this routine is called only once. + */ + cli (); + if (ppp->flags & SC_XMIT_BUSY) { + sti (); + return; + } + ppp->flags |= SC_XMIT_BUSY; + sti (); +/* + * Send the next block of data to the modem + */ + count = xbuf->count - xbuf->tail; + actual = tty->driver.write (tty, 0, + buf_base (xbuf) + xbuf->tail, count); +/* + * Terminate transmission of any block which may have an error. + * This could occur should the carrier drop. + */ + if (actual < 0) { + ppp->stats.ppp_oerrors++; + actual = count; + } else + ppp->bytes_sent += actual; +/* + * If the buffer has been transmitted then clear the indicators. + */ + xbuf->tail += actual; + if (actual == count) { + xbuf = NULL; + ppp->flags &= ~SC_XMIT_BUSY; +/* + * Complete the transmission on the current buffer. + */ + xbuf = ppp->xbuf; + if (xbuf != NULL) { + tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + xbuf->locked = 0; + ppp->xbuf = NULL; +/* + * If the completed buffer came from the device write, then complete the + * transmission block. + */ + if (ppp2dev (ppp) -> flags & IFF_UP) { + if (xbuf->type == BUFFER_TYPE_DEV_WR) + ppp2dev (ppp)->tbusy = 0; + mark_bh (NET_BH); + } +/* + * Wake up the transmission queue for all completion events. + */ + wake_up_interruptible (&ppp->write_wait); +/* + * Look at the priorities. Choose a daemon write over the device driver. + */ + cli(); + xbuf = ppp->s1buf; + ppp->s1buf = NULL; + if (xbuf == NULL) { + xbuf = ppp->s2buf; + ppp->s2buf = NULL; + } + sti(); +/* + * If there is a pending buffer then transmit it now. + */ + if (xbuf != NULL) { + ppp->flags &= ~SC_XMIT_BUSY; + ppp_kick_tty (ppp, xbuf); + return; + } + } + } +/* + * Clear the re-entry flag + */ + ppp->flags &= ~SC_XMIT_BUSY; +} + +/* + * This function is called by the tty driver when the transmit buffer has + * additional space. It is used by the ppp code to continue to transmit + * the current buffer should the buffer have been partially sent. + * + * In addition, it is used to send the first part of the buffer since the + * logic and the inter-locking would be identical. + */ + +static void +ppp_tty_wakeup (struct tty_struct *tty) +{ + struct ppp_buffer *xbuf; + struct ppp *ppp = tty2ppp (tty); + + if (!ppp) + return; + + if (ppp->magic != PPP_MAGIC) + return; +/* + * Ensure that there is a transmission pending. Clear the re-entry flag if + * there is no pending buffer. Otherwise, send the buffer. + */ + xbuf = ppp->xbuf; + if (xbuf == NULL) + tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + else + ppp_tty_wakeup_code (ppp, tty, xbuf); +} + +/* + * This function is called to transmit a buffer to the remote. The buffer + * is placed on the pending queue if there is presently a buffer being + * sent or it is transmitted with the aid of ppp_tty_wakeup. + */ + +static void +ppp_kick_tty (struct ppp *ppp, struct ppp_buffer *xbuf) +{ + register int flags; +/* + * Hold interrupts. + */ + save_flags (flags); + cli (); +/* + * Control the flags which are best performed with the interrupts masked. + */ + xbuf->locked = 1; + xbuf->tail = 0; +/* + * If the transmitter is busy then place the buffer on the appropriate + * priority queue. + */ + if (ppp->xbuf != NULL) { + if (xbuf->type == BUFFER_TYPE_TTY_WR) + ppp->s1buf = xbuf; + else + ppp->s2buf = xbuf; + restore_flags (flags); + return; + } +/* + * If the transmitter is not busy then this is the highest priority frame + */ + ppp->flags &= ~SC_XMIT_BUSY; + ppp->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); + ppp->xbuf = xbuf; + restore_flags (flags); +/* + * Do the "tty wakeup_code" to actually send this buffer. + */ + ppp_tty_wakeup_code (ppp, ppp2tty (ppp), xbuf); +} + +/************************************************************* + * TTY INPUT + * The following functions handle input that arrives from + * the TTY. It recognizes PPP frames and either hands them + * to the network layer or queues them for delivery to a + * user process reading this TTY. + *************************************************************/ + +/* + * Callback function from tty driver. Return the amount of space left + * in the receiver's buffer to decide if remote transmitter is to be + * throttled. + */ + +static int +ppp_tty_room (struct tty_struct *tty) +{ + return 65536; /* We can handle an infinite amount of data. :-) */ +} + +/* + * Callback function when data is available at the tty driver. + */ + +static void +ppp_tty_receive (struct tty_struct *tty, const u_char * data, + char *flags, int count) +{ + register struct ppp *ppp = tty2ppp (tty); + register struct ppp_buffer *buf = NULL; + u_char chr; +/* + * Fetch the pointer to the buffer. Be careful about race conditions. + */ + if (ppp != NULL) + buf = ppp->rbuf; + + if (buf == NULL) + return; +/* + * Verify the table pointer and ensure that the line is + * still in PPP discipline. + */ + if (ppp->magic != PPP_MAGIC) { + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "PPP: handler called but couldn't find " + "PPP struct.\n"); + return; + } + CHECK_PPP_VOID (); +/* + * Print the buffer if desired + */ + if (ppp->flags & SC_LOG_RAWIN) + ppp_print_buffer ("receive buffer", data, count); +/* + * Collect the character and error condition for the character. Set the toss + * flag for the first character error. + */ + while (count-- > 0) { + ppp->bytes_rcvd++; + chr = *data++; + if (flags) { + if (*flags && ppp->toss == 0) + ppp->toss = *flags; + ++flags; + } +/* + * Set the flags for 8 data bits and no parity. + * + * Actually, it sets the flags for d7 being 0/1 and parity being even/odd + * so that the normal processing would have all flags set at the end of the + * session. A missing flag bit would denote an error condition. + */ + +#ifdef CHECK_CHARACTERS + if (chr & 0x80) + ppp->flags |= SC_RCV_B7_1; + else + ppp->flags |= SC_RCV_B7_0; + + if (paritytab[chr >> 5] & (1 << (chr & 0x1F))) + ppp->flags |= SC_RCV_ODDP; + else + ppp->flags |= SC_RCV_EVNP; +#endif +/* + * Branch on the character. Process the escape character. The sequence ESC ESC + * is defined to be ESC. + */ + switch (chr) { + case PPP_ESCAPE: /* PPP_ESCAPE: invert bit in next character */ + ppp->escape = PPP_TRANS; + break; +/* + * FLAG. This is the end of the block. If the block terminated by ESC FLAG, + * then the block is to be ignored. In addition, characters before the very + * first FLAG are also tossed by this procedure. + */ + case PPP_FLAG: /* PPP_FLAG: end of frame */ + ppp->stats.ppp_ibytes += ppp->rbuf->count; + if (ppp->escape) + ppp->toss |= 0x80; +/* + * Process frames which are not to be ignored. If the processing failed, + * then clean up the VJ tables. + */ + if ((ppp->toss & 0x80) != 0 || + ppp_doframe (ppp) == 0) { + slhc_toss (ppp->slcomp); + } +/* + * Reset all indicators for the new frame to follow. + */ + buf->count = 0; + buf->fcs = PPP_INITFCS; + ppp->escape = 0; + ppp->toss = 0; + break; +/* + * All other characters in the data come here. If the character is in the + * receive mask then ignore the character. + */ + default: + if (in_rmap (ppp, chr)) + break; +/* + * Adjust the character and if the frame is to be discarded then simply + * ignore the character until the ending FLAG is received. + */ + chr ^= ppp->escape; + ppp->escape = 0; + + if (ppp->toss != 0) + break; +/* + * If the count sent is within reason then store the character, bump the + * count, and update the FCS for the character. + */ + if (buf->count < buf->size) { + buf_base (buf)[buf->count++] = chr; + buf->fcs = PPP_FCS (buf->fcs, chr); + break; + } +/* + * The peer sent too much data. Set the flags to discard the current frame + * and wait for the re-synchronization FLAG to be sent. + */ + ppp->stats.ppp_ierrors++; + ppp->toss |= 0xC0; + break; + } + } +} + +/* + * Put the input frame into the networking system for the indicated protocol + */ + +static int +ppp_rcv_rx (struct ppp *ppp, unsigned short proto, u_char * data, int count) +{ + sk_buff *skb = dev_alloc_skb (count); +/* + * Generate a skb buffer for the new frame. + */ + if (skb == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_do_ip: packet dropped on %s (no memory)!\n", + ppp2dev (ppp)->name); + return 0; + } +/* + * Move the received data from the input buffer to the skb buffer. + */ + skb->dev = ppp2dev (ppp); /* We are the device */ +#if USE_SKB_PROTOCOL == 0 + skb->len = count; +#else + skb->protocol = proto; + skb->mac.raw = skb_data(skb); +#endif + memcpy (skb_put(skb,count), data, count); /* move data */ +/* + * Tag the frame and kick it to the proper receive routine + */ + skb->free = 1; + ppp->ddinfo.recv_idle = jiffies; + netif_rx (skb); + return 1; +} + +/* + * Process the receipt of an IP frame + */ + +static int +rcv_proto_ip (struct ppp *ppp, unsigned short proto, u_char * data, int count) +{ + if (ppp2dev (ppp)->flags & IFF_UP) { + if (count > 0) + return ppp_rcv_rx (ppp, htons (ETH_P_IP), data, count); + } + return 0; +} + +/* + * Process the receipt of an IPX frame + */ + +static int +rcv_proto_ipx (struct ppp *ppp, unsigned short proto, u_char * data, int count) +{ +#ifdef NEW_SKBUFF + if (ppp2dev (ppp)->flags & IFF_UP) { + if (count > 0) + return ppp_rcv_rx (ppp, htons (ETH_P_IPX), data, count); + } else +#endif + return 0; +} + +/* + * Process the receipt of an VJ Compressed frame + */ + +static int +rcv_proto_vjc_comp (struct ppp *ppp, unsigned short proto, + u_char *data, int count) +{ + if ((ppp->flags & SC_REJ_COMP_TCP) == 0) { + int new_count = slhc_uncompress (ppp->slcomp, data, count); + if (new_count >= 0) { + return rcv_proto_ip (ppp, PPP_IP, data, new_count); + } + if (ppp->flags & SC_DEBUG) + printk (KERN_NOTICE + "ppp: error in VJ decompression\n"); + } + return 0; +} + +/* + * Process the receipt of an VJ Un-compressed frame + */ + +static int +rcv_proto_vjc_uncomp (struct ppp *ppp, unsigned short proto, + u_char *data, int count) +{ + if ((ppp->flags & SC_REJ_COMP_TCP) == 0) { + if (slhc_remember (ppp->slcomp, data, count) > 0) { + return rcv_proto_ip (ppp, PPP_IP, data, count); + } + if (ppp->flags & SC_DEBUG) + printk (KERN_NOTICE + "ppp: error in VJ memorizing\n"); + } + return 0; +} + +/* + * Receive all unclassified protocols. + */ + +static int +rcv_proto_unknown (struct ppp *ppp, unsigned short proto, + u_char *data, int len) +{ + int totlen; + register int current_idx; + +#define PUTC(c) \ +{ \ + buf_base (ppp->ubuf) [current_idx++] = (u_char) (c); \ + current_idx &= ppp->ubuf->size; \ + if (current_idx == ppp->ubuf->tail) \ + goto failure; \ +} + +/* + * The total length includes the protocol data. + * Lock the user information buffer. + */ + if (set_bit (0, &ppp->ubuf->locked)) { + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "ppp_us_queue: can't get lock\n"); + } else { + current_idx = ppp->ubuf->head; +/* + * Insert the buffer length (not counted), the protocol, and the data + */ + totlen = len + 2; + PUTC (totlen >> 8); + PUTC (totlen); + + PUTC (proto >> 8); + PUTC (proto); + + totlen -= 2; + while (totlen-- > 0) { + PUTC (*data++); + } +#undef PUTC +/* + * The frame is complete. Update the head pointer and wakeup the pppd + * process. + */ + ppp->ubuf->head = current_idx; + + clear_bit (0, &ppp->ubuf->locked); + wake_up_interruptible (&ppp->read_wait); + if (ppp->tty->fasync != NULL) + kill_fasync (ppp->tty->fasync, SIGIO); + + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp: successfully queued %d bytes, flags = %x\n", + len + 2, ppp->flags); + + return 1; +/* + * The buffer is full. Unlock the header + */ +failure: + clear_bit (0, &ppp->ubuf->locked); + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_us_queue: ran out of buffer space.\n"); + } +/* + * Discard the frame. There are no takers for this protocol. + */ + if (ppp->flags & SC_DEBUG) + printk (KERN_WARNING + "ppp: dropping packet on the floor.\n"); + slhc_toss (ppp->slcomp); + return 0; +} + +/* + * Handle a CCP packet. + * + * The CCP packet is passed along to the pppd process just like any + * other PPP frame. The difference is that some processing needs to be + * immediate or the compressors will become confused on the peer. + */ + +static void ppp_proto_ccp (struct ppp *ppp, u_char *dp, int len, int rcvd) +{ + int slen = CCP_LENGTH(dp); + u_char *opt = dp + CCP_HDRLEN; + int opt_len = slen - CCP_HDRLEN; + + if (slen > len) + return; + + switch (CCP_CODE(dp)) { + case CCP_CONFREQ: + case CCP_TERMREQ: + case CCP_TERMACK: +/* + * CCP must be going down - disable compression + */ + if (ppp->flags & SC_CCP_UP) { + ppp->flags &= ~(SC_CCP_UP | + SC_COMP_RUN | + SC_DECOMP_RUN); + } + break; + + case CCP_CONFACK: + if ((ppp->flags & SC_CCP_OPEN) == 0) + break; + if (ppp->flags & SC_CCP_UP) + break; + if (slen < (CCP_HDRLEN + CCP_OPT_MINLEN)) + break; + if (slen < (CCP_OPT_LENGTH (opt) + CCP_HDRLEN)) + break; +/* + * we're agreeing to send compressed packets. + */ + if (!rcvd) { + if (ppp->sc_xc_state == NULL) + break; + + if ((*ppp->sc_xcomp->comp_init) + (ppp->sc_xc_state, + opt, + opt_len, + ppp2dev (ppp)->base_addr, + 0, + ppp->flags & SC_DEBUG)) + ppp->flags |= SC_COMP_RUN; + break; + } +/* + * peer is agreeing to send compressed packets. + */ + if (ppp->sc_rc_state == NULL) + break; + + if ((*ppp->sc_rcomp->decomp_init) + (ppp->sc_rc_state, + opt, + opt_len, + ppp2dev (ppp)->base_addr, + 0, + ppp->mru, + ppp->flags & SC_DEBUG)) { + ppp->flags |= SC_DECOMP_RUN; + ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR); + } + break; +/* + * The protocol sequence is complete at this end + */ + case CCP_RESETACK: + if ((ppp->flags & SC_CCP_UP) == 0) + break; + + if (!rcvd) { + if (ppp->sc_xc_state && (ppp->flags & SC_COMP_RUN)) + (*ppp->sc_xcomp->comp_reset)(ppp->sc_xc_state); + } else { + if (ppp->sc_rc_state && (ppp->flags & SC_DECOMP_RUN)) { + (*ppp->sc_rcomp->decomp_reset)(ppp->sc_rc_state); + ppp->flags &= ~SC_DC_ERROR; + } + } + break; + } +} + +static int +rcv_proto_ccp (struct ppp *ppp, unsigned short proto, u_char *dp, int len) +{ + ppp_proto_ccp (ppp, dp, len, 1); + return rcv_proto_unknown (ppp, proto, dp, len); +} + +/* + * Handle a LQR packet. + * + * The LQR packet is passed along to the pppd process just like any + * other PPP frame. The difference is that some processing needs to be + * performed to append the current data to the end of the frame. + */ + +static int +rcv_proto_lqr (struct ppp *ppp, unsigned short proto, u_char * data, int len) +{ +#if 0 /* until support is in the pppd process don't corrupt the reject. */ + register u_char *p; + if (len > 8) { + if (len < 48) + memset (&data [len], '\0', 48 - len); +/* + * Fill in the fields from the driver data + */ + p = &data [48]; + p = store_long (p, ++ppp->stats.ppp_ilqrs); + p = store_long (p, ppp->stats.ppp_ipackets); + p = store_long (p, ppp->stats.ppp_discards); + p = store_long (p, ppp->stats.ppp_ierrors); + p = store_long (p, ppp->stats.ppp_ioctects + len); + + len = 68; + } +#endif +/* + * Pass the frame to the pppd daemon. + */ + return rcv_proto_unknown (ppp, proto, data, len); +} + +/* on entry, a received frame is in ppp->rbuf.bufr + check it and dispose as appropriate */ + +static void ppp_doframe_lower (struct ppp *ppp, u_char *data, int count) +{ + u_short proto = PPP_PROTOCOL (data); + ppp_proto_type *proto_ptr; +/* + * Ignore empty frames + */ + if (count <= 4) + return; +/* + * Count the frame and print it + */ + ++ppp->stats.ppp_ipackets; + if (ppp->flags & SC_LOG_INPKT) + ppp_print_buffer ("receive frame", data, count); +/* + * Find the procedure to handle this protocol. The last one is marked + * as a protocol 0 which is the 'catch-all' to feed it to the pppd daemon. + */ + proto_ptr = proto_list; + while (proto_ptr->proto != 0 && proto_ptr->proto != proto) + ++proto_ptr; +/* + * Update the appropriate statistic counter. + */ + if ((*proto_ptr->func) (ppp, proto, + &data[PPP_HARD_HDR_LEN], + count - PPP_HARD_HDR_LEN)) + ppp->stats.ppp_ioctects += count; + else + ++ppp->stats.ppp_discards; +} + +/* on entry, a received frame is in ppp->rbuf.bufr + check it and dispose as appropriate */ + +static int +ppp_doframe (struct ppp *ppp) +{ + u_char *data = buf_base (ppp->rbuf); + int count = ppp->rbuf->count; + int addr, ctrl, proto; + int new_count; + u_char *new_data; +/* + * If there is a pending error from the receiver then log it and discard + * the damaged frame. + */ + if (ppp->toss) { + if (ppp->flags & SC_DEBUG) + printk (KERN_WARNING + "ppp_toss: tossing frame, reason = %d\n", + ppp->toss); + ppp->stats.ppp_ierrors++; + return 0; + } +/* + * An empty frame is ignored. This occurs if the FLAG sequence precedes and + * follows each frame. + */ + if (count == 0) + return 1; +/* + * Generate an error if the frame is too small. + */ + if (count < PPP_HARD_HDR_LEN) { + if (ppp->flags & SC_DEBUG) + printk (KERN_WARNING + "ppp: got runt ppp frame, %d chars\n", count); + slhc_toss (ppp->slcomp); + ppp->stats.ppp_ierrors++; + return 1; + } +/* + * Verify the CRC of the frame and discard the CRC characters from the + * end of the buffer. + */ + if (ppp->rbuf->fcs != PPP_GOODFCS) { + if (ppp->flags & SC_DEBUG) + printk (KERN_WARNING + "ppp: frame with bad fcs, excess = %x\n", + ppp->rbuf->fcs ^ PPP_GOODFCS); + ppp->stats.ppp_ierrors++; + return 0; + } + count -= 2; /* ignore the fcs characters */ +/* + * Ignore the leading ADDRESS and CONTROL fields in the frame. + */ + addr = PPP_ALLSTATIONS; + ctrl = PPP_UI; + + if ((data[0] == PPP_ALLSTATIONS) && (data[1] == PPP_UI)) { + data += 2; + count -= 2; + } +/* + * Obtain the protocol from the frame + */ + proto = (u_short) *data++; + if ((proto & 1) == 0) { + proto = (proto << 8) | (u_short) *data++; + --count; + } +/* + * Rewrite the header with the full information. This may encroach upon + * the 'filler' area in the buffer header. This is the purpose for the + * filler. + */ + *(--data) = proto; + *(--data) = proto >> 8; + *(--data) = ctrl; + *(--data) = addr; + count += 3; +/* + * Process the active decompressor. + */ + if ((ppp->sc_rc_state != (void *) 0) && + (ppp->flags & SC_DECOMP_RUN) && + ((ppp->flags & (SC_DC_FERROR | SC_DC_ERROR)) == 0)) { + if (proto == PPP_COMP) { +/* + * If the frame is compressed then decompress it. + */ + new_data = kmalloc (ppp->mru + 4, GFP_ATOMIC); + if (new_data == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_doframe: no memory\n"); + slhc_toss (ppp->slcomp); + (*ppp->sc_rcomp->incomp) (ppp->sc_rc_state, + data, + count); + return 1; + } +/* + * Decompress the frame + */ + new_count = bsd_decompress (ppp->sc_rc_state, + data, + count, + new_data, + ppp->mru + 4); + switch (new_count) { + default: + ppp_doframe_lower (ppp, new_data, new_count); + kfree (new_data); + return 1; + + case DECOMP_OK: + break; + + case DECOMP_ERROR: + ppp->flags |= SC_DC_ERROR; + break; + + case DECOMP_FATALERROR: + ppp->flags |= SC_DC_FERROR; + break; + } +/* + * Log the error condition and discard the frame. + */ + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_proto_comp: " + "decompress err %d\n", new_count); + kfree (new_data); + slhc_toss (ppp->slcomp); + return 1; + } +/* + * The frame is not special. Pass it through the compressor without + * actually compressing the data + */ + (*ppp->sc_rcomp->incomp) (ppp->sc_rc_state, + data, + count); + } +/* + * Process the uncompressed frame. + */ + ppp_doframe_lower (ppp, data, count); + return 1; +} + +/************************************************************* + * LINE DISCIPLINE SUPPORT + * The following functions form support user programs + * which read and write data on a TTY with the PPP line + * discipline. Reading is done from a circular queue, + * filled by the lower TTY levels. + *************************************************************/ + +/* read a PPP frame from the us_rbuff circular buffer, + waiting if necessary +*/ + +static int +ppp_tty_read (struct tty_struct *tty, struct file *file, u_char * buf, + unsigned int nr) +{ + struct ppp *ppp = tty2ppp (tty); + u_char c; + int len, indx; + +#define GETC(c) \ +{ \ + c = buf_base (ppp->ubuf) [ppp->ubuf->tail++]; \ + ppp->ubuf->tail &= ppp->ubuf->size; \ +} + +/* + * Validate the pointer to the PPP structure + */ + if (!ppp) + return -EIO; + + if (ppp->magic != PPP_MAGIC) + return -EIO; + + CHECK_PPP (-ENXIO); + + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "ppp_tty_read: called buf=%p nr=%u\n", + buf, nr); +/* + * Acquire the read lock. + */ + for (;;) { + ppp = tty2ppp (tty); + if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse) + return 0; + + if (set_bit (0, &ppp->ubuf->locked) != 0) { + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "ppp_tty_read: sleeping(ubuf)\n"); + + current->timeout = 0; + current->state = TASK_INTERRUPTIBLE; + schedule (); + + if (current->signal & ~current->blocked) + return -EINTR; + continue; + } +/* + * Before we attempt to write the frame to the user, ensure that the + * user has access to the pages for the total buffer length. + */ + indx = verify_area (VERIFY_WRITE, buf, nr); + if (indx != 0) + return (indx); +/* + * Fetch the length of the buffer from the first two bytes. + */ + if (ppp->ubuf->head == ppp->ubuf->tail) + len = 0; + else { + GETC (c); + len = c << 8; + GETC (c); + len += c; + } +/* + * If there is no length then wait for the data to arrive. + */ + if (len == 0) { + /* no data */ + clear_bit (0, &ppp->ubuf->locked); + if (file->f_flags & O_NONBLOCK) { + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "ppp_tty_read: no data " + "(EWOULDBLOCK)\n"); + return -EWOULDBLOCK; + } + current->timeout = 0; + + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "ppp_tty_read: sleeping(read_wait)\n"); + + interruptible_sleep_on (&ppp->read_wait); + if (current->signal & ~current->blocked) + return -EINTR; + continue; + } +/* + * Reset the time of the last read operation. + */ + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG "ppp_tty_read: len = %d\n", len); +/* + * Ensure that the frame will fit within the caller's buffer. If not, then + * discard the frame from the input buffer and return an error to the caller. + */ + if (len + 2 > nr) { + /* Can't copy it, update us_rbuff_head */ + + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "ppp: read of %u bytes too small for %d " + "frame\n", nr, len + 2); + ppp->ubuf->tail += len; + ppp->ubuf->tail &= ppp->ubuf->size; + clear_bit (0, &ppp->ubuf->locked); + ppp->stats.ppp_ierrors++; + return -EOVERFLOW; + } +/* + * Before we attempt to write the frame to the user, ensure that the + * page tables are proper. + */ + indx = verify_area (VERIFY_WRITE, buf, len + 2); + if (indx != 0) { + ppp->ubuf->tail += len; + ppp->ubuf->tail &= ppp->ubuf->size; + clear_bit (0, &ppp->ubuf->locked); + return (indx); + } +/* + * Fake the insertion of the ADDRESS and CONTROL information because these + * were not saved in the buffer. + */ + put_byte_user (PPP_ALLSTATIONS, buf++); + put_byte_user (PPP_UI, buf++); + + indx = len; +/* + * Copy the received data from the buffer to the caller's area. + */ + while (indx-- > 0) { + GETC (c); + put_byte_user (c, buf); + ++buf; + } +/* + * Release the lock and return the character count in the buffer area. + */ + clear_bit (0, &ppp->ubuf->locked); + len += 2; /* Account for ADDRESS and CONTROL bytes */ + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "ppp_tty_read: passing %d bytes up\n", len); + return len; + } +#undef GETC +} + +/* stuff a character into the transmit buffer, using PPP's way of escaping + special characters. + also, update fcs to take account of new character */ + +extern inline void +ppp_stuff_char (struct ppp *ppp, register struct ppp_buffer *buf, + register u_char chr) +{ +/* + * The buffer should not be full. + */ + if (ppp->flags & SC_DEBUG) { + if ((buf->count < 0) || (buf->count > 3000)) + printk (KERN_DEBUG "ppp_stuff_char: %x %d\n", + (unsigned int) buf->count, + (unsigned int) chr); + } +/* + * Update the FCS and if the character needs to be escaped, do it. + */ + buf->fcs = PPP_FCS (buf->fcs, chr); + if (in_xmap (ppp, chr)) { + chr ^= PPP_TRANS; + ins_char (buf, PPP_ESCAPE); + } +/* + * Add the character to the buffer. + */ + ins_char (buf, chr); +} + +/* + * Procedure to encode the data with the proper escapement and send the + * data to the remote system. + */ + +static void +ppp_dev_xmit_lower (struct ppp *ppp, struct ppp_buffer *buf, + u_char *data, int count, int non_ip) +{ + unsigned short int write_fcs; + int address, control; + int proto; +/* + * Insert the leading FLAG character + */ + buf->count = 0; + + if (non_ip || flag_time == 0) + ins_char (buf, PPP_FLAG); + else { + if (jiffies - ppp->last_xmit > flag_time) + ins_char (buf, PPP_FLAG); + } + ppp->last_xmit = jiffies; + buf->fcs = PPP_INITFCS; +/* + * Emit the address/control information if needed + */ + address = PPP_ADDRESS (data); + control = PPP_CONTROL (data); + proto = PPP_PROTOCOL (data); + + if (address != PPP_ALLSTATIONS || + control != PPP_UI || + (ppp->flags & SC_COMP_AC) == 0) { + ppp_stuff_char (ppp, buf, address); + ppp_stuff_char (ppp, buf, control); + } +/* + * Emit the protocol (compressed if possible) + */ + if ((ppp->flags & SC_COMP_PROT) == 0 || (proto & 0xFF00)) + ppp_stuff_char (ppp, buf, proto >> 8); + + ppp_stuff_char (ppp, buf, proto); +/* + * Insert the data + */ + data += 4; + count -= 4; + + while (count-- > 0) + ppp_stuff_char (ppp, buf, *data++); +/* + * Add the trailing CRC and the final flag character + */ + write_fcs = buf->fcs ^ 0xFFFF; + ppp_stuff_char (ppp, buf, write_fcs); + ppp_stuff_char (ppp, buf, write_fcs >> 8); + + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG "ppp_dev_xmit_lower: fcs is %hx\n", + write_fcs); +/* + * Add the trailing flag character + */ + ins_char (buf, PPP_FLAG); +/* + * Print the buffer + */ + if (ppp->flags & SC_LOG_FLUSH) + ppp_print_buffer ("ppp flush", buf_base (buf), + buf->count); + else { + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "ppp_dev_xmit: writing %d chars\n", + buf->count); + } +/* + * Send the block to the tty driver. + */ + ppp->stats.ppp_obytes += buf->count; + ppp_kick_tty (ppp, buf); +} + +/* + * Send an frame to the remote with the proper bsd compression. + * + * Return 0 if frame was queued for transmission. + * 1 if frame must be re-queued for later driver support. + */ + +static int +ppp_dev_xmit_frame (struct ppp *ppp, struct ppp_buffer *buf, + u_char *data, int count) +{ + int proto; + int address, control; + u_char *new_data; + int new_count; +/* + * Print the buffer + */ + if (ppp->flags & SC_LOG_OUTPKT) + ppp_print_buffer ("write frame", data, count); +/* + * Determine if the frame may be compressed. Attempt to compress the + * frame if possible. + */ + proto = PPP_PROTOCOL (data); + address = PPP_ADDRESS (data); + control = PPP_CONTROL (data); + + if (((ppp->flags & SC_COMP_RUN) != 0) && + (ppp->sc_xc_state != (void *) 0) && + (address == PPP_ALLSTATIONS) && + (control == PPP_UI) && + (proto != PPP_LCP) && + (proto != PPP_CCP)) { + new_data = kmalloc (count, GFP_ATOMIC); + if (new_data == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_dev_xmit_frame: no memory\n"); + return 1; + } + + new_count = bsd_compress (ppp->sc_xc_state, + data, + new_data, + count, + count); + + if (new_count > 0) { + ++ppp->stats.ppp_opackets; + ppp->stats.ppp_ooctects += new_count; + + ppp_dev_xmit_lower (ppp, buf, new_data, + new_count, 0); + kfree (new_data); + return 0; + } +/* + * The frame could not be compressed. + */ + kfree (new_data); + } +/* + * The frame may not be compressed. Update the statistics before the + * count field is destroyed. The frame will be transmitted. + */ + ++ppp->stats.ppp_opackets; + ppp->stats.ppp_ooctects += count; +/* + * Go to the escape encoding + */ + ppp_dev_xmit_lower (ppp, buf, data, count, !!(proto & 0xFF00)); + return 0; +} + +/* + * Revise the tty frame for specific protocols. + */ + +static int +send_revise_frame (register struct ppp *ppp, u_char *data, int len) +{ + u_char *p; + + switch (PPP_PROTOCOL (data)) { +/* + * Update the LQR frame with the current MIB information. This saves having + * the daemon read old MIB data from the driver. + */ + case PPP_LQR: + len = 48; /* total size of this frame */ + p = (u_char *) &data [40]; /* Point to last two items. */ + p = store_long (p, ppp->stats.ppp_opackets + 1); + p = store_long (p, ppp->stats.ppp_ooctects + len); + break; +/* + * Outbound compression frames + */ + case PPP_CCP: + ppp_proto_ccp (ppp, + data + PPP_HARD_HDR_LEN, + len - PPP_HARD_HDR_LEN, + 0); + break; +/* + * All other frame types + */ + default: + break; + } + + return len; +} + +/* + * write a frame with NR chars from BUF to TTY + * we have to put the FCS field on ourselves + */ + +static int +ppp_tty_write (struct tty_struct *tty, struct file *file, const u_char * data, + unsigned int count) +{ + struct ppp *ppp = tty2ppp (tty); + u_char *new_data; + int status; +/* + * Verify the pointer to the PPP data and that the tty is still in PPP mode. + */ + if (!ppp) + return -EIO; + + if (ppp->magic != PPP_MAGIC) + return -EIO; + + CHECK_PPP (-ENXIO); +/* + * Ensure that the caller does not wish to send too much. + */ + if (count > PPP_MTU) { + if (ppp->flags & SC_DEBUG) + printk (KERN_WARNING + "ppp_tty_write: truncating user packet " + "from %u to mtu %d\n", count, PPP_MTU); + count = PPP_MTU; + } +/* + * Allocate a buffer for the data and fetch it from the user space. + */ + new_data = kmalloc (count, GFP_KERNEL); + if (new_data == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_tty_write: no memory\n"); + return 0; + } +/* + * lock this PPP unit so we will be the only writer; + * sleep if necessary + */ + while (lock_buffer (ppp->tbuf) != 0) { + current->timeout = 0; + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG "ppp_tty_write: sleeping\n"); + interruptible_sleep_on (&ppp->write_wait); + + ppp = tty2ppp (tty); + if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse) { + kfree (new_data); + return 0; + } + + if (current->signal & ~current->blocked) { + kfree (new_data); + return -EINTR; + } + } +/* + * Ensure that the caller's buffer is valid. + */ + status = verify_area (VERIFY_READ, data, count); + if (status != 0) { + kfree (new_data); + ppp->tbuf->locked = 0; + return status; + } + + memcpy_fromfs (new_data, data, count); +/* + * Change the LQR frame + */ + count = send_revise_frame (ppp, new_data, count); +/* + * Send the data + */ + ppp_dev_xmit_frame (ppp, ppp->tbuf, new_data, count); + kfree (new_data); + return (int) count; +} + +/* + * Process the BSD compression IOCTL event for the tty device. + */ + +static int +ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp) +{ + struct compressor *cp; + struct ppp_option_data data; + int error; + int nb; + u_char *ptr; + u_char ccp_option[CCP_MAX_OPTION_LENGTH]; +/* + * Fetch the compression parameters + */ + error = verify_area (VERIFY_READ, odp, sizeof (data)); + if (error == 0) { + memcpy_fromfs (&data, odp, sizeof (data)); + nb = data.length; + ptr = data.ptr; + if ((unsigned long) nb >= (unsigned long)CCP_MAX_OPTION_LENGTH) + nb = CCP_MAX_OPTION_LENGTH; + + error = verify_area (VERIFY_READ, ptr, nb); + } + + if (error != 0) + return error; + + memcpy_fromfs (ccp_option, ptr, nb); + + if (ccp_option[1] < 2) /* preliminary check on the length byte */ + return (-EINVAL); + + cp = find_compressor ((int) (unsigned) (unsigned char) ccp_option[0]); + if (cp != (struct compressor *) 0) { + /* + * Found a handler for the protocol - try to allocate + * a compressor or decompressor. + */ + error = 0; + if (data.transmit) { + if (ppp->sc_xc_state != NULL) + (*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state); + + ppp->sc_xcomp = cp; + ppp->sc_xc_state = cp->comp_alloc(ccp_option, nb); + + if (ppp->sc_xc_state == NULL) { + if (ppp->flags & SC_DEBUG) + printk("ppp%ld: comp_alloc failed\n", + ppp2dev (ppp)->base_addr); + error = -ENOBUFS; + } + ppp->flags &= ~SC_COMP_RUN; + } else { + if (ppp->sc_rc_state != NULL) + (*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state); + ppp->sc_rcomp = cp; + ppp->sc_rc_state = cp->decomp_alloc(ccp_option, nb); + if (ppp->sc_rc_state == NULL) { + if (ppp->flags & SC_DEBUG) + printk("ppp%ld: decomp_alloc failed\n", + ppp2dev (ppp)->base_addr); + error = ENOBUFS; + } + ppp->flags &= ~SC_DECOMP_RUN; + } + return (error); + } + + if (ppp->flags & SC_DEBUG) + printk(KERN_DEBUG "ppp%ld: no compressor for [%x %x %x], %x\n", + ppp2dev (ppp)->base_addr, ccp_option[0], ccp_option[1], + ccp_option[2], nb); + return (-EINVAL); /* no handler found */ +} + +/* + * Process the IOCTL event for the tty device. + */ + +static int +ppp_tty_ioctl (struct tty_struct *tty, struct file *file, unsigned int param2, + unsigned long param3) +{ + struct ppp *ppp = tty2ppp (tty); + register int temp_i = 0; + int error; +/* + * Verify the status of the PPP device. + */ + if (!ppp) + return -EBADF; + + if (ppp->magic != PPP_MAGIC) + return -EBADF; + + CHECK_PPP (-ENXIO); +/* + * The user must have an euid of root to do these requests. + */ + if (!suser ()) + return -EPERM; +/* + * Set the MRU value + */ + switch (param2) { + case PPPIOCSMRU: + error = verify_area (VERIFY_READ, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + temp_i = get_int_user ((int *) param3); + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: set mru to %x\n", temp_i); + + if (ppp->mru != temp_i) + ppp_changedmtu (ppp, ppp2dev (ppp)->mtu, temp_i); + } + break; +/* + * Fetch the flags + */ + case PPPIOCGFLAGS: + error = verify_area (VERIFY_WRITE, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + temp_i = (ppp->flags & SC_MASK); +#ifndef CHECK_CHARACTERS /* Don't generate errors if we don't check chars. */ + temp_i |= SC_RCV_B7_1 | SC_RCV_B7_0 | + SC_RCV_ODDP | SC_RCV_EVNP; #endif + put_long_user ((long) temp_i, param3); + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG + "ppp_tty_ioctl: get flags: addr %lx flags " + "%x\n", param3, temp_i); + } + break; +/* + * Set the flags for the various options + */ + case PPPIOCSFLAGS: + error = verify_area (VERIFY_READ, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + temp_i = get_int_user (param3) & SC_MASK; + temp_i |= (ppp->flags & ~SC_MASK); + + if ((ppp->flags & SC_CCP_OPEN) && + (temp_i & SC_CCP_OPEN) == 0) + ppp_ccp_closed (ppp); + + if ((ppp->flags | temp_i) & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: set flags to %x\n", temp_i); + ppp->flags = temp_i; + } + break; +/* + * Set the compression mode + */ + case PPPIOCSCOMPRESS: + error = ppp_set_compression (ppp, + (struct ppp_option_data *) param3); + break; +/* + * Retrieve the transmit async map + */ + case PPPIOCGASYNCMAP: + error = verify_area (VERIFY_WRITE, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + put_long_user (ppp->xmit_async_map[0], param3); + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: get asyncmap: addr " + "%lx asyncmap %lx\n", + param3, + (unsigned long) ppp->xmit_async_map[0]); + } + break; +/* + * Set the transmit async map + */ + case PPPIOCSASYNCMAP: + error = verify_area (VERIFY_READ, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + ppp->xmit_async_map[0] = get_long_user (param3); + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: set xmit asyncmap %lx\n", + (unsigned long) ppp->xmit_async_map[0]); + } + break; +/* + * Set the receive async map + */ + case PPPIOCSRASYNCMAP: + error = verify_area (VERIFY_READ, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + ppp->recv_async_map = get_long_user (param3); + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: set rcv asyncmap %lx\n", + (unsigned long) ppp->recv_async_map); + } + break; +/* + * Obtain the unit number for this device. + */ + case PPPIOCGUNIT: + error = verify_area (VERIFY_WRITE, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + put_long_user (ppp2dev (ppp)->base_addr, param3); + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: get unit: %ld", + ppp2dev (ppp)->base_addr); + } + break; +/* + * Set the debug level + */ + case PPPIOCSDEBUG: + error = verify_area (VERIFY_READ, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + temp_i = (get_int_user (param3) & 0x1F) << 16; + temp_i |= (ppp->flags & ~0x1F0000); + + if ((ppp->flags | temp_i) & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: set flags to %x\n", temp_i); + ppp->flags = temp_i; + } + break; +/* + * Get the debug level + */ + case PPPIOCGDEBUG: + error = verify_area (VERIFY_WRITE, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + temp_i = (ppp->flags >> 16) & 0x1F; + put_long_user ((long) temp_i, param3); + + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: get debug level %d\n", + temp_i); + } + break; +/* + * Get the times since the last send/receive frame operation + */ + case PPPIOCGIDLE: + error = verify_area (VERIFY_WRITE, (void *) param3, + sizeof (struct ppp_idle)); + if (error == 0) { + struct ppp_idle cur_ddinfo; + unsigned long cur_jiffies = jiffies; + + /* change absolute times to relative times. */ + cur_ddinfo.xmit_idle = (cur_jiffies - ppp->ddinfo.xmit_idle) / HZ; + cur_ddinfo.recv_idle = (cur_jiffies - ppp->ddinfo.recv_idle) / HZ; + memcpy_tofs ((void *) param3, &cur_ddinfo, + sizeof (cur_ddinfo)); + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: read demand dial info\n"); + } + break; +/* + * Retrieve the extended async map + */ + case PPPIOCGXASYNCMAP: + error = verify_area (VERIFY_WRITE, + (void *) param3, + sizeof (ppp->xmit_async_map)); + if (error == 0) { + memcpy_tofs ((void *) param3, + ppp->xmit_async_map, + sizeof (ppp->xmit_async_map)); + + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: get xasyncmap: addr %lx\n", + param3); + } + break; +/* + * Set the async extended map + */ + case PPPIOCSXASYNCMAP: + error = verify_area (VERIFY_READ, (void *) param3, + sizeof (ppp->xmit_async_map)); + if (error == 0) { + __u32 temp_tbl[8]; + + memcpy_fromfs (temp_tbl, (void *) param3, + sizeof (ppp->xmit_async_map)); + temp_tbl[1] = 0x00000000; + temp_tbl[2] &= ~0x40000000; + temp_tbl[3] |= 0x60000000; + + if ((temp_tbl[2] & temp_tbl[3]) != 0 || + (temp_tbl[4] & temp_tbl[5]) != 0 || + (temp_tbl[6] & temp_tbl[7]) != 0) + error = -EINVAL; + else { + memcpy (ppp->xmit_async_map, temp_tbl, + sizeof (ppp->xmit_async_map)); + + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: set xasyncmap\n"); + } + } + break; +/* + * Set the maximum VJ header compression slot number. + */ + case PPPIOCSMAXCID: + error = verify_area (VERIFY_READ, (void *) param3, + sizeof (temp_i)); + if (error == 0) { + temp_i = get_int_user (param3) + 1; + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp_tty_ioctl: set maxcid to %d\n", + temp_i); + if (ppp->slcomp != NULL) + slhc_free (ppp->slcomp); + ppp->slcomp = slhc_init (16, temp_i); + + if (ppp->slcomp == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp: no space for compression buffers!\n"); + ppp_release (ppp); + error = -ENOMEM; + } + } + break; +/* + * Allow users to read, but not set, the serial port parameters + */ + case TCGETS: + case TCGETA: + error = n_tty_ioctl (tty, file, param2, param3); + break; +/* + * All other ioctl() events will come here. + */ + default: + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_tty_ioctl: invalid ioctl: %x, addr %lx\n", + param2, + param3); + + error = -ENOIOCTLCMD; + break; + } + return error; +} + +/* + * TTY callback. + * + * Process the select() statement for the PPP device. + */ + +static int +ppp_tty_select (struct tty_struct *tty, struct inode *inode, + struct file *filp, int sel_type, select_table * wait) +{ + struct ppp *ppp = tty2ppp (tty); + int result = 1; +/* + * Verify the status of the PPP device. + */ + if (!ppp) + return -EBADF; + + if (ppp->magic != PPP_MAGIC) + return -EBADF; + + CHECK_PPP (0); +/* + * Branch on the type of select mode. A read request must lock the user + * buffer area. + */ + switch (sel_type) { + case SEL_IN: + if (set_bit (0, &ppp->ubuf->locked) == 0) { + /* Test for the presence of data in the queue */ + if (ppp->ubuf->head != ppp->ubuf->tail) { + clear_bit (0, &ppp->ubuf->locked); + break; + } + clear_bit (0, &ppp->ubuf->locked); + } /* fall through */ + /* + * Exceptions or read errors. + */ + case SEL_EX: + /* Is this a pty link and the remote disconnected? */ + if (tty->flags & (1 << TTY_SLAVE_CLOSED)) + break; + + /* Is this a local link and the modem disconnected? */ + if (tty_hung_up_p (filp)) + break; + + select_wait (&ppp->read_wait, wait); + result = 0; + break; +/* + * Write mode. A write is allowed if there is no current transmission. + */ + case SEL_OUT: + if (ppp->tbuf->locked != 0) { + select_wait (&ppp->write_wait, wait); + result = 0; + } + break; + } + return result; +} + +/************************************************************* + * NETWORK OUTPUT + * This routine accepts requests from the network layer + * and attempts to deliver the packets. + * It also includes various routines we are compelled to + * have to make the network layer work (arp, etc...). + *************************************************************/ + +/* + * Callback from the network layer when the device goes up. + */ + +static int +ppp_dev_open (struct device *dev) +{ + struct ppp *ppp = dev2ppp (dev); + + /* reset POINTOPOINT every time, since dev_close zaps it! */ + dev->flags |= IFF_POINTOPOINT; + + if (ppp2tty (ppp) == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp: %s not connected to a TTY! can't go open!\n", + dev->name); + return -ENXIO; + } + + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp: channel %s going up for IP packets!\n", + dev->name); + + CHECK_PPP (-ENXIO); + return 0; +} + +/* + * Callback from the network layer when the ppp device goes down. + */ + +static int +ppp_dev_close (struct device *dev) +{ + struct ppp *ppp = dev2ppp (dev); + + if (ppp2tty (ppp) == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp: %s not connected to a TTY! can't go down!\n", + dev->name); + return -ENXIO; + } +/* + * We don't do anything about the device going down. It is not important + * for us. + */ + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO + "ppp: channel %s going down for IP packets!\n", + dev->name); + CHECK_PPP (-ENXIO); + return 0; +} + +/* + * IOCTL operation to read the version of the driver. + */ + +static int +ppp_dev_ioctl_version (struct ppp *ppp, struct ifreq *ifr) +{ + int error; + int len; + char *result; +/* + * Must have write access to the buffer. + */ + result = (char *) ifr->ifr_ifru.ifru_data; + len = strlen (szVersion) + 1; + error = verify_area (VERIFY_WRITE, result, len); +/* + * Move the version data + */ + if (error == 0) + memcpy_tofs (result, szVersion, len); + + return error; +} + +/* + * IOCTL to read the statistics for the pppstats program. + */ + +static int +ppp_dev_ioctl_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev) +{ + struct ppp_stats *result, temp; + int error; +/* + * Must have write access to the buffer. + */ + result = (struct ppp_stats *) ifr->ifr_ifru.ifru_data; + error = verify_area (VERIFY_WRITE, + result, + sizeof (temp)); +/* + * Supply the information for the caller. First move the version data + * then move the ppp stats; and finally the vj stats. + */ + memset (&temp, 0, sizeof(temp)); + if (error == 0 && dev->flags & IFF_UP) { + memcpy (&temp.p, &ppp->stats, sizeof (struct pppstat)); + if (ppp->slcomp != NULL) { + temp.vj.vjs_packets = ppp->slcomp->sls_o_compressed+ + ppp->slcomp->sls_o_uncompressed; + temp.vj.vjs_compressed = ppp->slcomp->sls_o_compressed; + temp.vj.vjs_searches = ppp->slcomp->sls_o_searches; + temp.vj.vjs_misses = ppp->slcomp->sls_o_misses; + temp.vj.vjs_errorin = ppp->slcomp->sls_i_error; + temp.vj.vjs_tossed = ppp->slcomp->sls_i_tossed; + temp.vj.vjs_uncompressedin = ppp->slcomp->sls_i_uncompressed; + temp.vj.vjs_compressedin = ppp->slcomp->sls_i_compressed; + } + } +/* + * Move the data to the caller's buffer + */ + if (error == 0) + memcpy_tofs (result, &temp, sizeof (temp)); + return error; +} -/* on entry, a received frame is in ppp->rbuff - check it and dispose as appropriate */ -static void -ppp_doframe(struct ppp *ppp) -{ - u_char *c = ppp->rbuff; - u_short proto; - int count = ppp->rcount; - - /* forget it if we've already noticed an error */ - if (ppp->toss) { - PRINTKN (1, (KERN_WARNING "ppp_toss: tossing frame, reason = %d\n", - ppp->toss)); - slhc_toss (ppp->slcomp); - ppp->stats.rerrors++; - return; - } - - /* do this before printing buffer to avoid generating copious output */ - if (count == 0) - return; - - if (ppp_debug >= 3) - ppp_print_buffer ("receive frame", c, count, KERNEL_DS); - - if (count < 4) { - PRINTKN (1,(KERN_WARNING "ppp: got runt ppp frame, %d chars\n", count)); - slhc_toss (ppp->slcomp); - ppp->stats.runts++; - return; - } - - /* check PPP error detection field */ - if (!ppp_check_fcs(ppp)) { - PRINTKN (1,(KERN_WARNING "ppp: frame with bad fcs\n")); - slhc_toss (ppp->slcomp); - ppp->stats.rerrors++; - return; - } - - count -= 2; /* ignore last two characters */ - - /* now we have a good frame */ - /* figure out the protocol field */ - if ((c[0] == PPP_ADDRESS) && (c[1] == PPP_CONTROL)) { - c = c + 2; /* ADDR/CTRL not compressed, so skip */ - count -= 2; - } - - proto = (u_short) *c++; /* PROTO compressed */ - if (proto & 1) { - count--; - } else { - proto = (proto << 8) | (u_short) *c++; /* PROTO uncompressed */ - count -= 2; - } - - /* Send the frame to the network if the ppp device is up */ - if ((ppp->dev->flags & IFF_UP) && ppp_do_ip(ppp, proto, c, count)) { - ppp->ddinfo.ip_rjiffies = jiffies; - return; - } - - /* If we got here, it has to go to a user process doing a read, - so queue it. - - User process expects to get whole frame (for some reason), so - use count+2 so as to include FCS field. */ - - if (ppp_us_queue (ppp, proto, c, count+2)) { - ppp->ddinfo.nip_rjiffies = jiffies; - ppp->stats.rothers++; - return; - } - - /* couldn't cope. */ - PRINTKN (1,(KERN_WARNING - "ppp: dropping packet on the floor: nobody could take it.\n")); - slhc_toss (ppp->slcomp); - ppp->stats.tossed++; -} - -/* Examine packet at C, attempt to pass up to net layer. - PROTO is the protocol field from the PPP frame. - Return 1 if could handle it, 0 otherwise. */ - -static int -ppp_do_ip (struct ppp *ppp, unsigned short proto, unsigned char *c, - int count) -{ - int flags, done; - struct sk_buff *skb; - - PRINTKN (4,(KERN_DEBUG "ppp_do_ip: proto %x len %d first byte %x\n", - (int) proto, count, c[0])); - - if (ppp_debug_netpackets) { - PRINTK (("KERN_DEBUG %s <-- proto %x len %d\n", ppp->dev->name, - (int) proto, count)); - } - - if (proto == PROTO_IP) { - ppp->stats.runcomp++; - goto sendit; - } - - if ((proto == PROTO_VJCOMP) && !(ppp->flags & SC_REJ_COMP_TCP)) { - /* get space for uncompressing the header */ - done = 0; - save_flags (flags); - cli(); - if ((ppp->rhead + 80) < ppp->rend) { - ppp->rhead += 80; - ppp->rcount += 80; - done = 1; - } - restore_flags(flags); - - if (! done) { - PRINTKN (1,(KERN_NOTICE - "ppp: no space to decompress VJ compressed TCP header.\n")); - ppp->stats.roverrun++; - slhc_toss (ppp->slcomp); - return 1; - } - - count = slhc_uncompress(ppp->slcomp, c, count); - if (count <= 0) { - ppp->stats.rerrors++; - PRINTKN (1,(KERN_NOTICE "ppp: error in VJ decompression\n")); - slhc_toss (ppp->slcomp); - return 1; - } - ppp->stats.rcomp++; - goto sendit; - } - - if ((proto == PROTO_VJUNCOMP) && !(ppp->flags & SC_REJ_COMP_TCP)) { - if (slhc_remember(ppp->slcomp, c, count) <= 0) { - ppp->stats.rerrors++; - PRINTKN (1,(KERN_NOTICE "ppp: error in VJ memorizing\n")); - slhc_toss (ppp->slcomp); - return 1; - } - ppp->stats.runcomp++; - goto sendit; - } - - /* not ours */ - return 0; - - sendit: - if (ppp_debug_netpackets) { - struct iphdr *iph = (struct iphdr *) c; - PRINTK ((KERN_INFO "%s <-- src %x dst %x len %d\n", ppp->dev->name, - iph->saddr, iph->daddr, count)) - } +/* + * IOCTL to read the compression statistics for the pppstats program. + */ - /* receive the frame through the network software */ - - skb=dev_alloc_skb(count); - if(skb) - { - skb->mac.raw=skb->data; - memcpy(skb_put(skb,count), c,count); - skb->protocol=htons(ETH_P_IP); - skb->dev=ppp->dev; - netif_rx(skb); - } - return 1; -} - -/* stuff packet at BUF, length LEN, into the us_rbuff buffer - prepend PROTO information */ - -#define PUTC(c,label) *ppp->us_rbuff_head++ = c; \ - if (ppp->us_rbuff_head == ppp->us_rbuff_end) \ - ppp->us_rbuff_head = ppp->us_rbuff; \ - if (ppp->us_rbuff_head == ppp->us_rbuff_tail) \ - goto label; -#define GETC(c) c = *ppp->us_rbuff_tail++; \ - if (ppp->us_rbuff_tail == ppp->us_rbuff_end) \ - ppp->us_rbuff_tail = ppp->us_rbuff; - -static int -ppp_us_queue(struct ppp *ppp, unsigned short proto, - unsigned char *buf, int len) -{ - int totlen; - unsigned char *saved_head; - - totlen = len+2; /* including protocol */ - - if (set_bit(1, &ppp->us_rbuff_lock)) { - PRINTKN (1, (KERN_NOTICE "ppp_us_queue: can't get lock\n")); - return 0; - } - saved_head = ppp->us_rbuff_head; - - PUTC((totlen & 0xff00) >> 8, failure); - PUTC(totlen & 0x00ff, failure); - PUTC((proto & 0xff00) >> 8, failure); - PUTC(proto & 0x00ff, failure); - - while (len-- > 0) { - PUTC(*buf++, failure); - } - - PRINTKN (3, (KERN_INFO "ppp: successfully queued %d bytes\n", totlen)); - clear_bit(1, &ppp->us_rbuff_lock); - wake_up_interruptible (&ppp->read_wait); - -#ifdef NEW_TTY_DRIVERS - kill_fasync(ppp->tty->fasync, SIGIO); -#endif - - if (ppp->inp_sig && ppp->inp_sig_pid) - if (kill_proc (ppp->inp_sig_pid, ppp->inp_sig, 1) != 0) { - /* process is gone */ - PRINTKN (2,(KERN_NOTICE - "ppp: process that requested notification is gone\n")); - ppp->inp_sig = 0; - ppp->inp_sig_pid = 0; - } - return 1; - - failure: - ppp->us_rbuff_head = saved_head; - clear_bit(1, &ppp->us_rbuff_lock); +static int +ppp_dev_ioctl_comp_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev) +{ + struct ppp_comp_stats *result, temp; + int error; +/* + * Must have write access to the buffer. + */ + result = (struct ppp_comp_stats *) ifr->ifr_ifru.ifru_data; + error = verify_area (VERIFY_WRITE, + result, + sizeof (temp)); +/* + * Supply the information for the caller. + */ + memset (&temp, 0, sizeof(temp)); + if (error == 0 && dev->flags & IFF_UP) { + if (ppp->sc_xc_state != NULL) + (*ppp->sc_xcomp->comp_stat) (ppp->sc_xc_state, + &temp.c); + + if (ppp->sc_rc_state != NULL) + (*ppp->sc_rcomp->decomp_stat) (ppp->sc_rc_state, + &temp.d); + } +/* + * Move the data to the caller's buffer + */ + if (error == 0) + memcpy_tofs (result, &temp, sizeof (temp)); + return error; +} - PRINTKN (1, (KERN_NOTICE "ppp_us_queue: ran out of buffer space.\n")); +/* + * Callback from the network layer to process the sockioctl functions. + */ - return 0; +static int +ppp_dev_ioctl (struct device *dev, struct ifreq *ifr, int cmd) +{ + struct ppp *ppp = dev2ppp (dev); + int error; +/* + * Process the requests + */ + switch (cmd) { + case SIOCGPPPSTATS: + error = ppp_dev_ioctl_stats (ppp, ifr, dev); + break; + + case SIOCGPPPCSTATS: + error = ppp_dev_ioctl_comp_stats (ppp, ifr, dev); + break; + + case SIOCGPPPVER: + error = ppp_dev_ioctl_version (ppp, ifr); + break; + + default: + error = -EINVAL; + break; + } + return error; } -/************************************************************* - * LINE DISCIPLINE SUPPORT - * The following functions form support user programs - * which read and write data on a TTY with the PPP line - * discipline. Reading is done from a circular queue, - * filled by the lower TTY levels. - *************************************************************/ - -/* read a PPP frame from the us_rbuff circular buffer, - waiting if necessary -*/ +/* + * Send an IP frame to the remote with vj header compression. + * + * Return 0 if frame was queued for transmission. + * 1 if frame must be re-queued for later driver support. + */ static int -ppp_read(struct tty_struct *tty, struct file *file, unsigned char *buf, unsigned int nr) +ppp_dev_xmit_ip1 (struct device *dev, struct ppp *ppp, u_char *data) { - struct ppp *ppp = ppp_find(tty); - unsigned char c; - int len, i; - - if (!ppp || ppp->magic != PPP_MAGIC) { - PRINTKN (1,(KERN_ERR "ppp_read: cannot find ppp channel\n")); - return -EIO; - } - - CHECK_PPP(-ENXIO); - - PRINTKN (4,(KERN_DEBUG "ppp_read: called %p num %u\n", - buf, nr)); - - do { - /* try to acquire read lock */ - if (set_bit(0, &ppp->us_rbuff_lock) == 0) { - /* got lock */ - if (ppp->us_rbuff_head == ppp->us_rbuff_tail) { - /* no data */ - PRINTKN (4,(KERN_DEBUG "ppp_read: no data\n")); - clear_bit(0, &ppp->us_rbuff_lock); - if (ppp->inp_sig) { - PRINTKN (4,(KERN_DEBUG "ppp_read: EWOULDBLOCK\n")); - return -EWOULDBLOCK; - } else goto wait; - } - - i = verify_area (VERIFY_WRITE,buf,nr); - if (i != 0) { - ppp->us_rbuff_lock = 0; - return i; - } - - /* reset the time of the last read operation */ - ppp->ddinfo.nip_rjiffies = jiffies; - - GETC (c); len = c << 8; GETC (c); len += c; - - PRINTKN (4,(KERN_DEBUG "ppp_read: len = %d\n", len)); - - if (len + 2 > nr) { - /* frame too big; can't copy it, but do update us_rbuff_head */ - PRINTKN (1,(KERN_DEBUG - "ppp: read of %u bytes too small for %d frame\n", - nr, len+2)); - ppp->us_rbuff_head += len; - if (ppp->us_rbuff_head > ppp->us_rbuff_end) - ppp->us_rbuff_head += - (ppp->us_rbuff_end - ppp->us_rbuff); - clear_bit(0, &ppp->us_rbuff_lock); - wake_up_interruptible (&ppp->read_wait); - ppp->stats.rgiants++; - return -EOVERFLOW; /* ZZZ; HACK! */ - } else { - /* have the space: copy the packet, faking the first two bytes */ - put_user (PPP_ADDRESS, buf++); - put_user (PPP_CONTROL, buf++); - i = len; - while (i-- > 0) { - GETC (c); - put_user (c, buf++); - } - } - - clear_bit(0, &ppp->us_rbuff_lock); - PRINTKN (3,(KERN_DEBUG "ppp_read: passing %d bytes up\n", len + 2)); - ppp->stats.rothers++; - return len + 2; - } - - /* need to wait */ - wait: - current->timeout = 0; - PRINTKN (3,(KERN_DEBUG "ppp_read: sleeping\n")); - interruptible_sleep_on (&ppp->read_wait); - - /* Ensure that the ppp device is still attached. */ - ppp = ppp_find(tty); - if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse) - return 0; - - if (current->signal & ~current->blocked) - return -EINTR; - } while (1); -} + int proto = PPP_IP; + int len; + struct ppp_hdr *hdr; + struct tty_struct *tty = ppp2tty (ppp); +/* + * Obtain the length from the IP header. + */ + len = ((struct iphdr *)data) -> tot_len; + len = ntohs (len); +/* + * Validate the tty interface + */ + if (tty == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_dev_xmit: %s not connected to a TTY!\n", + dev->name); + return 0; + } +/* + * Ensure that the PPP device is still up + */ + if (!(dev->flags & IFF_UP)) { + if (ppp->flags & SC_DEBUG) + printk (KERN_WARNING + "ppp_dev_xmit: packet sent on interface %s," + " which is down for IP\n", + dev->name); + return 0; + } +/* + * Detect a change in the transfer size + */ + if (ppp->mtu != ppp2dev (ppp)->mtu) { + ppp_changedmtu (ppp, + ppp2dev (ppp)->mtu, + ppp->mru); + } +/* + * Acquire the lock on the transmission buffer. If the buffer was busy then + * mark the device as busy and return "failure to send, try back later" error. + */ + if (lock_buffer (ppp->wbuf) != 0) { + dev->tbusy = 1; + return 1; + } +/* + * Print the frame being sent + */ + if (ppp->flags & SC_LOG_OUTPKT) + ppp_print_buffer ("ppp outpkt", data, len); +/* + * At this point, the buffer will be transmitted. There is no other exit. + * + * Try to compress the header. + */ + if (ppp->flags & SC_COMP_TCP) { + len = slhc_compress (ppp->slcomp, data, len, + buf_base (ppp->cbuf) + PPP_HARD_HDR_LEN, + &data, + (ppp->flags & SC_NO_TCP_CCID) == 0); + + if (data[0] & SL_TYPE_COMPRESSED_TCP) { + proto = PPP_VJC_COMP; + data[0] ^= SL_TYPE_COMPRESSED_TCP; + } else { + if (data[0] >= SL_TYPE_UNCOMPRESSED_TCP) + proto = PPP_VJC_UNCOMP; + data[0] = (data[0] & 0x0f) | 0x40; + } + } +/* + * Send the frame + */ + len += PPP_HARD_HDR_LEN; + hdr = &((struct ppp_hdr *) data)[-1]; -/* stuff a character into the transmit buffer, using PPP's way of escaping - special characters. - also, update ppp->fcs to take account of new character */ -static inline void -ppp_stuff_char(struct ppp *ppp, unsigned char c) -{ - int curpt = ppp->xhead - ppp->xbuff; - if ((curpt < 0) || (curpt > 3000)) { - PRINTK ((KERN_DEBUG "ppp_stuff_char: %p %p %d\n", - ppp->xbuff, ppp->xhead, curpt)) - } - if (in_xmap (ppp, c)) { - *ppp->xhead++ = PPP_ESC; - *ppp->xhead++ = c ^ PPP_TRANS; - } else - *ppp->xhead++ = c; - ppp->fcs = (ppp->fcs >> 8) ^ fcstab[(ppp->fcs ^ c) & 0xff]; + hdr->address = PPP_ALLSTATIONS; + hdr->control = PPP_UI; + hdr->protocol[0] = 0; + hdr->protocol[1] = proto; + + return ppp_dev_xmit_frame (ppp, ppp->wbuf, (u_char *) hdr, len); } -/* write a frame with NR chars from BUF to TTY - we have to put the FCS field on ourselves -*/ +/* + * This is just an interum solution until the 1.3 kernel's networking is + * available. The 1.2 kernel has problems with device headers before the + * buffers. + * + * This routine should be deleted, and the ppp_dev_xmit_ip1 routine called + * by this name. + */ static int -ppp_write(struct tty_struct *tty, struct file *file, const unsigned char *buf, unsigned int nr) +ppp_dev_xmit_ip (struct device *dev, struct ppp *ppp, u_char *data) { - struct ppp *ppp = ppp_find(tty); - int i; + struct ppp_hdr *hdr; + int len; + int answer; + + len = ((struct iphdr *)data) -> tot_len; + len = ntohs (len); + + hdr = (struct ppp_hdr *) kmalloc (len + sizeof (struct ppp_hdr), + GFP_ATOMIC); + + if (hdr == NULL) + answer = 1; + else { + memcpy (&hdr[1], data, len); + answer = ppp_dev_xmit_ip1 (dev, ppp, (u_char *) &hdr[1]); + kfree (hdr); + } - if (!ppp || ppp->magic != PPP_MAGIC) { - PRINTKN (1,(KERN_ERR "ppp_write: cannot find ppp unit\n")); - return -EIO; - } + return answer; +} - CHECK_PPP(-ENXIO); - - if (ppp->mtu != ppp->dev->mtu) /* Someone has been ifconfigging */ - ppp_changedmtu (ppp, ppp->dev->mtu, ppp->mru); +/* + * Send an IPX (or any other non-IP) frame to the remote. + * + * Return 0 if frame was queued for transmission. + * 1 if frame must be re-queued for later driver support. + */ - if (nr > ppp->mtu) { - PRINTKN (1,(KERN_WARNING - "ppp_write: truncating user packet from %u to mtu %d\n", - nr, ppp->mtu)); - nr = ppp->mtu; - } - - i = verify_area (VERIFY_READ,buf,nr); - if (i != 0) - return i; - - if (ppp_debug >= 3) - ppp_print_buffer ("write frame", buf, nr, USER_DS); - - /* lock this PPP unit so we will be the only writer; - sleep if necessary */ - while ((ppp->sending == 1) || !ppp_lock(ppp)) { - current->timeout = 0; - PRINTKN (3,(KERN_DEBUG "ppp_write: sleeping\n")); - interruptible_sleep_on(&ppp->write_wait); - - /* Ensure that the ppp device is still attached. */ - ppp = ppp_find(tty); - if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse) - return 0; - - if (current->signal & ~current->blocked) - return -EINTR; - } - - /* OK, locked. Stuff the given bytes into the buffer. */ - - PRINTKN(4,(KERN_DEBUG "ppp_write: acquired write lock\n")); - ppp->xhead = ppp->xbuff; - -#ifdef OPTIMIZE_FLAG_TIME - if (jiffies - ppp->last_xmit > OPTIMIZE_FLAG_TIME) - *ppp->xhead++ = PPP_FLAG; - ppp->last_xmit = jiffies; -#else - *ppp->xhead++ = PPP_FLAG; -#endif - - ppp->fcs = PPP_FCS_INIT; - i = nr; - while (i-- > 0) - ppp_stuff_char(ppp,get_user(buf++)); +#ifdef NEW_SKBUFF +static int +ppp_dev_xmit_ipx1 (struct device *dev, struct ppp *ppp, + u_char *data, int len, int proto) +{ + struct tty_struct *tty = ppp2tty (ppp); + struct ppp_hdr *hdr; +/* + * Validate the tty interface + */ + if (tty == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_dev_xmit: %s not connected to a TTY!\n", + dev->name); + return 0; + } +/* + * Ensure that the PPP device is still up + */ + if (!(dev->flags & IFF_UP)) { + if (ppp->flags & SC_DEBUG) + printk (KERN_WARNING + "ppp_dev_xmit: packet sent on interface %s," + " which is down\n", + dev->name); + return 0; + } +/* + * Detect a change in the transfer size + */ + if (ppp->mtu != ppp2dev (ppp)->mtu) { + ppp_changedmtu (ppp, + ppp2dev (ppp)->mtu, + ppp->mru); + } +/* + * Acquire the lock on the transmission buffer. If the buffer was busy then + * mark the device as busy and return "failure to send, try back later" error. + */ + if (lock_buffer (ppp->wbuf) != 0) { + dev->tbusy = 1; + return 1; + } +/* + * Print the frame being sent + */ + if (ppp->flags & SC_LOG_OUTPKT) + ppp_print_buffer ("ppp outpkt", data, len); +/* + * Send the frame + */ + len += PPP_HARD_HDR_LEN; + hdr = &((struct ppp_hdr *) data)[-1]; - ppp_add_fcs(ppp); /* concatenate FCS at end */ + hdr->address = PPP_ALLSTATIONS; + hdr->control = PPP_UI; + hdr->protocol[0] = proto >> 8; + hdr->protocol[1] = proto; - *ppp->xhead++ = PPP_FLAG; - - /* reset the time of the last write operation */ - ppp->ddinfo.nip_sjiffies = jiffies; + return ppp_dev_xmit_frame (ppp, ppp->wbuf, (u_char *) hdr, len); +} - if (ppp_debug >= 6) - ppp_print_buffer ("xmit buffer", ppp->xbuff, ppp->xhead - ppp->xbuff, KERNEL_DS); - else { - PRINTKN (4,(KERN_DEBUG "ppp_write: writing %d chars\n", - (int) (ppp->xhead - ppp->xbuff))); - } - - /* packet is ready-to-go */ - ++ppp->stats.sothers; - ppp_kick_tty(ppp); +/* + * This is just an interum solution until the 1.3 kernel's networking is + * available. The 1.2 kernel has problems with device headers before the + * buffers. + * + * This routine should be deleted, and the ppp_dev_xmit_ipx1 routine called + * by this name. + */ - return((int)nr); -} - static int -ppp_ioctl(struct tty_struct *tty, struct file *file, unsigned int i, - unsigned long l) +ppp_dev_xmit_ipx (struct device *dev, struct ppp *ppp, + u_char *data, int len, int proto) { - struct ppp *ppp = ppp_find(tty); - register int temp_i = 0; - int error; - - if (!ppp || ppp->magic != PPP_MAGIC) { - PRINTK ((KERN_ERR "ppp_ioctl: can't find PPP block from tty!\n")) - return -EBADF; - } - - CHECK_PPP(-ENXIO); - - /* This must be root user */ - if (!suser()) - return -EPERM; - - switch (i) { - case PPPIOCSMRU: - error = verify_area (VERIFY_READ, (void *) l, sizeof (temp_i)); - if (error == 0) { - temp_i = get_user ((int *) l); - PRINTKN (3,(KERN_INFO "ppp_ioctl: set mru to %d\n", temp_i)); - if (ppp->mru != temp_i) - ppp_changedmtu (ppp, ppp->dev->mtu, temp_i); - } - break; - - case PPPIOCGFLAGS: - error = verify_area (VERIFY_WRITE, (void *) l, sizeof (temp_i)); - if (error == 0) { - temp_i = (ppp->flags & SC_MASK); -#ifndef CHECK_CHARACTERS /* Don't generate errors if we don't check chars. */ - temp_i |= SC_RCV_B7_1 | SC_RCV_B7_0 | SC_RCV_ODDP | SC_RCV_EVNP; -#endif - put_user (temp_i, (int *) l); - PRINTKN (3,(KERN_DEBUG "ppp_ioctl: get flags: addr %lx flags %x\n", - l, - temp_i)); - } - break; - - case PPPIOCSFLAGS: - error = verify_area (VERIFY_READ, (void *) l, sizeof (temp_i)); - if (error == 0) { - temp_i = get_user ((int *) l); - ppp->flags ^= ((ppp->flags ^ temp_i) & SC_MASK); - PRINTKN (3,(KERN_INFO "ppp_ioctl: set flags to %x\n", temp_i)); - } - break; - - case PPPIOCGASYNCMAP: - error = verify_area (VERIFY_WRITE, (void *) l, sizeof (temp_i)); - if (error == 0) { - put_user (ppp->xmit_async_map[0], (int *) l); - PRINTKN (3,(KERN_INFO "ppp_ioctl: get asyncmap: addr %lx asyncmap %lx\n", - l, (unsigned long) ppp->xmit_async_map[0])); - } - break; - - case PPPIOCSASYNCMAP: - error = verify_area (VERIFY_READ, (void *) l, sizeof (temp_i)); - if (error == 0) { - ppp->xmit_async_map[0] = get_user ((int *) l); - bset (ppp->xmit_async_map, PPP_FLAG); - bset (ppp->xmit_async_map, PPP_ESC); - PRINTKN (3,(KERN_INFO "ppp_ioctl: set xmit asyncmap %lx\n", - (unsigned long) ppp->xmit_async_map[0])); - } - break; - - case PPPIOCRASYNCMAP: - error = verify_area (VERIFY_READ, (void *) l, sizeof (temp_i)); - if (error == 0) { - ppp->recv_async_map = get_user ((int *) l); - PRINTKN (3,(KERN_INFO "ppp_ioctl: set recv asyncmap %lx\n", - (unsigned long) ppp->recv_async_map)); - } - break; - - case PPPIOCGUNIT: - error = verify_area (VERIFY_WRITE, (void *) l, sizeof (temp_i)); - if (error == 0) { - put_user (ppp->dev->base_addr, (int *) l); - PRINTKN (3,(KERN_INFO "ppp_ioctl: get unit: %ld", ppp->dev->base_addr)); - } - break; - - case PPPIOCSINPSIG: - error = verify_area (VERIFY_READ, (void *) l, sizeof (temp_i)); - if (error == 0) { - ppp->inp_sig = get_user ((int *) l); - ppp->inp_sig_pid = current->pid; - PRINTKN (3,(KERN_INFO "ppp_ioctl: set input signal %d\n", ppp->inp_sig)); - } - break; - - case PPPIOCSDEBUG: - error = verify_area (VERIFY_READ, (void *) l, sizeof (temp_i)); - if (error == 0) { - ppp_debug = get_user ((int *) l); - ppp_debug_netpackets = (ppp_debug & 0xff00) >> 8; - ppp_debug &= 0xff; - PRINTKN (1, (KERN_INFO "ppp_ioctl: set debug level %d, netpacket %d\n", - ppp_debug, ppp_debug_netpackets)); - } - break; - - case PPPIOCGDEBUG: - error = verify_area (VERIFY_WRITE, (void *) l, sizeof (temp_i)); - if (error == 0) { - put_user ((long) (ppp_debug | (ppp_debug_netpackets << 8)), (int *) l); - PRINTKN (3,(KERN_INFO "ppp_ioctl: get debug level %d\n", - ppp_debug | (ppp_debug_netpackets << 8))); - } - break; - - case PPPIOCGSTAT: - error = verify_area (VERIFY_WRITE, (void *) l, sizeof (struct ppp_stats)); - if (error == 0) { - memcpy_tofs ((void *) l, &ppp->stats, sizeof (struct ppp_stats)); - PRINTKN (3,(KERN_INFO "ppp_ioctl: read statistics\n")); - } - break; - - case PPPIOCGTIME: - error = verify_area (VERIFY_WRITE, (void *) l, sizeof (struct ppp_ddinfo)); - if (error == 0) { - struct ppp_ddinfo cur_ddinfo; - unsigned long cur_jiffies = jiffies; - - /* change absolute times to relative times. */ - cur_ddinfo.ip_sjiffies = cur_jiffies - ppp->ddinfo.ip_sjiffies; - cur_ddinfo.ip_rjiffies = cur_jiffies - ppp->ddinfo.ip_rjiffies; - cur_ddinfo.nip_sjiffies = cur_jiffies - ppp->ddinfo.nip_sjiffies; - cur_ddinfo.nip_rjiffies = cur_jiffies - ppp->ddinfo.nip_rjiffies; - - memcpy_tofs ((void *) l, &cur_ddinfo, sizeof (struct ppp_ddinfo)); - PRINTKN (3,(KERN_INFO "ppp_ioctl: read demand dial info\n")); - } - break; - - case PPPIOCGXASYNCMAP: - error = verify_area (VERIFY_WRITE, - (void *) l, - sizeof (ppp->xmit_async_map)); - if (error == 0) { - memcpy_tofs ((void *) l, - ppp->xmit_async_map, - sizeof (ppp->xmit_async_map)); - PRINTKN (3,(KERN_INFO "ppp_ioctl: get xasyncmap: addr %lx\n", l)); - } - break; - - case PPPIOCSXASYNCMAP: - error = verify_area (VERIFY_READ, (void *) l, - sizeof (ppp->xmit_async_map)); - if (error == 0) { - __u32 temp_tbl [8]; - - memcpy_fromfs (temp_tbl, (void *) l, sizeof (ppp->xmit_async_map)); - temp_tbl[1] = 0x00000000; /* must not escape 0x20 - 0x3f */ - temp_tbl[2] &= ~0x40000000; /* must not escape 0x5e */ - temp_tbl[3] |= 0x60000000; /* must escape 0x7d and 0x7e */ - - if ((temp_tbl[2] & temp_tbl[3]) != 0 || - (temp_tbl[4] & temp_tbl[5]) != 0 || - (temp_tbl[6] & temp_tbl[7]) != 0) - error = -EINVAL; - else { - memcpy (ppp->xmit_async_map, temp_tbl, sizeof (ppp->xmit_async_map)); - PRINTKN (3,(KERN_INFO "ppp_ioctl: set xasyncmap\n")); - } - } - break; - - case PPPIOCSMAXCID: - error = verify_area (VERIFY_READ, (void *) l, sizeof (temp_i)); - if (error == 0) { - temp_i = get_user ((int *) l) + 1; - PRINTKN (3,(KERN_INFO "ppp_ioctl: set maxcid to %d\n", temp_i)); - if (ppp->slcomp != NULL) - slhc_free (ppp->slcomp); - - ppp->slcomp = slhc_init (temp_i, temp_i); - - if (ppp->slcomp == NULL) { - PRINTKN (1,(KERN_ERR "ppp: no space for compression buffers!\n")); - ppp_release (ppp); - error = -ENOMEM; - } - } - break; - -#ifdef NEW_TTY_DRIVERS - /* Allow stty to read, but not set, the serial port */ - case TCGETS: - case TCGETA: - error = n_tty_ioctl(tty, file, i, l); - break; + struct ppp_hdr *hdr; + int answer; + + hdr = (struct ppp_hdr *) kmalloc (len + sizeof (struct ppp_hdr), + GFP_ATOMIC); + if (hdr == NULL) + answer = 1; + else { + memcpy (&hdr[1], data, len); + answer = ppp_dev_xmit_ipx1 (dev, ppp, (u_char *) &hdr[1], + len, proto); + kfree (hdr); + } + + return answer; +} #endif /* - * All other ioctl() events will come here. + * Send a frame to the remote. + */ + +static int +ppp_dev_xmit (sk_buff *skb, struct device *dev) +{ + int answer, len; + u_char *data; + struct ppp *ppp = dev2ppp (dev); + struct tty_struct *tty = ppp2tty (ppp); +/* + * just a little sanity check. + */ + if (skb == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_WARNING "ppp_dev_xmit: null packet!\n"); + return 0; + } +/* + * Avoid timing problem should tty hangup while data is queued to be sent + */ + if (!ppp->inuse) { + dev_kfree_skb (skb, FREE_WRITE); + dev_close (dev); + return 0; + } +/* + * Validate the tty linkage + */ + if (ppp->flags & SC_DEBUG) + printk (KERN_DEBUG "ppp_dev_xmit [%s]: skb %X\n", + dev->name, (int) skb); +/* + * Validate the tty interface + */ + if (tty == NULL) { + if (ppp->flags & SC_DEBUG) + printk (KERN_ERR + "ppp_dev_xmit: %s not connected to a TTY!\n", + dev->name); + dev_kfree_skb (skb, FREE_WRITE); + return 0; + } +/* + * Fetch the pointer to the data + */ + len = skb->len; + data = skb_data(skb); +/* + * Look at the protocol in the skb to determine the difference between + * an IP frame and an IPX frame. */ - default: - PRINTKN (1,(KERN_ERR "ppp_ioctl: invalid ioctl: %x, addr %lx\n", - i, - l)); -#ifdef NEW_TTY_DRIVERS - error = -ENOIOCTLCMD; +#ifdef NEW_SKBUFF + switch (skb->protocol) { + case htons (ETH_P_IPX): + answer = ppp_dev_xmit_ipx (dev, ppp, data, len, PPP_IPX); + break; + + case htons (ETH_P_IP): + answer = ppp_dev_xmit_ip (dev, ppp, data); + break; + + default: /* All others have no support at this time. */ + dev_kfree_skb (skb, FREE_WRITE); + return 0; + } #else - error = -EINVAL; + answer = ppp_dev_xmit_ip (dev, ppp, data); #endif - break; - } - return error; + +/* + * This is the end of the transmission. Release the buffer if it was sent. + */ + if (answer == 0) { + dev_kfree_skb (skb, FREE_WRITE); + ppp->ddinfo.xmit_idle = jiffies; + } + return answer; } -static int -ppp_select (struct tty_struct *tty, struct inode * inode, - struct file * filp, int sel_type, select_table * wait) +/* + * Generate the statistic information for the /proc/net/dev listing. + */ + +static struct enet_statistics * +ppp_dev_stats (struct device *dev) { - struct ppp *ppp = ppp_find (tty); - - if (!ppp || ppp->magic != PPP_MAGIC) { - PRINTK ((KERN_ERR "ppp_select: can't find PPP block from tty!\n")) - return -EBADF; - } - - /* If the PPP protocol is no longer active, return false */ - CHECK_PPP (0); - - /* Process the request based upon the type desired */ - switch (sel_type) { - case SEL_IN: - if (set_bit(0, &ppp->us_rbuff_lock) == 0) { - /* Test for the presence of data in the queue */ - if (ppp->us_rbuff_head != ppp->us_rbuff_tail) { - clear_bit (0, &ppp->us_rbuff_lock); - return 1; - } - clear_bit (0, &ppp->us_rbuff_lock); - } /* fall through */ - - case SEL_EX: - /* Is there a pending error condition? */ - if (tty->packet && tty->link->ctrl_status) - return 1; - - /* closed? */ - if (tty->flags & (1 << TTY_SLAVE_CLOSED)) - return 1; - - /* If the tty is disconnected, then this is an exception too */ - if (tty_hung_up_p(filp)) - return 1; + struct ppp *ppp = dev2ppp (dev); + static struct enet_statistics ppp_stats; - select_wait (&ppp->read_wait, wait); - break; - - case SEL_OUT: - if (ppp_lock (ppp)) { - if (ppp->sending == 0) { - ppp_unlock (ppp); - return 1; - } - ppp_unlock (ppp); - } - select_wait (&ppp->write_wait, wait); - break; - } - return 0; + ppp_stats.rx_packets = ppp->stats.ppp_ipackets; + ppp_stats.rx_errors = ppp->stats.ppp_ierrors; + ppp_stats.rx_dropped = ppp->stats.ppp_ierrors; + ppp_stats.rx_fifo_errors = 0; + ppp_stats.rx_length_errors = 0; + ppp_stats.rx_over_errors = 0; + ppp_stats.rx_crc_errors = 0; + ppp_stats.rx_frame_errors = 0; + ppp_stats.tx_packets = ppp->stats.ppp_opackets; + ppp_stats.tx_errors = ppp->stats.ppp_oerrors; + ppp_stats.tx_dropped = 0; + ppp_stats.tx_fifo_errors = 0; + ppp_stats.collisions = 0; + ppp_stats.tx_carrier_errors = 0; + ppp_stats.tx_aborted_errors = 0; + ppp_stats.tx_window_errors = 0; + ppp_stats.tx_heartbeat_errors = 0; + + if (ppp->flags & SC_DEBUG) + printk (KERN_INFO "ppp_dev_stats called"); + return &ppp_stats; } -/************************************************************* - * NETWORK OUTPUT - * This routine accepts requests from the network layer - * and attempts to deliver the packets. - * It also includes various routines we are compelled to - * have to make the network layer work (arp, etc...). - *************************************************************/ +#ifdef NEW_SKBUFF +/* + * The PPP protocol is currently pure IP (no IPX yet). This defines + * the protocol layer which is blank since the driver does all the + * cooking. + */ -int -ppp_xmit(struct sk_buff *skb, struct device *dev) -{ - struct tty_struct *tty; - struct ppp *ppp; - unsigned char *p; - unsigned short proto; - int len; - - /* just a little sanity check. */ - if (skb == NULL) { - PRINTKN(3,(KERN_WARNING "ppp_xmit: null packet!\n")); - return 0; - } - - /* Get pointers to the various components */ - ppp = &ppp_ctrl[dev->base_addr]; - tty = ppp->tty; - p = skb->data; - len = skb->len; - proto = PROTO_IP; - - PRINTKN(4,(KERN_DEBUG "ppp_xmit [%s]: skb %lX busy %d\n", dev->name, - (unsigned long int) skb, ppp->sending)); - - /* avoid race conditions when the link fails */ - if (!ppp->inuse) { - dev_kfree_skb(skb, FREE_WRITE); - dev_close (dev); - return 0; - } - - if (tty == NULL) { - PRINTKN(1,(KERN_ERR "ppp_xmit: %s not connected to a TTY!\n", dev->name)); - goto done; - } - - if (!(dev->flags & IFF_UP)) { - PRINTKN(1,(KERN_WARNING - "ppp_xmit: packet sent on interface %s, which is down for IP\n", - dev->name)); - goto done; - } - -#ifdef CURED_AGES_AGO - /* get length from IP header as per Alan Cox bugfix for slip.c */ - if (len < sizeof(struct iphdr)) { - PRINTKN(0,(KERN_ERR "ppp_xmit: given runt packet, ignoring\n")); - goto done; - } - len = ntohs( ((struct iphdr *)(skb->data)) -> tot_len ); -#endif - - /* If doing demand dial then divert the first frame to pppd. */ - if (ppp->flags & SC_IP_DOWN) { - if ((ppp->flags & SC_IP_FLUSH) == 0) { - if (ppp_us_queue (ppp, proto, p, len)) - ppp->flags |= SC_IP_FLUSH; - } - goto done; - } - - /* Attempt to acquire send lock */ - if (ppp->sending || !ppp_lock(ppp)) { - PRINTKN(3,(KERN_WARNING "ppp_xmit: busy\n")); - ppp->stats.sbusy++; - return 1; - } - - ppp->xhead = ppp->xbuff; - - /* try to compress, if VJ compression mode is on */ - if (ppp->flags & SC_COMP_TCP) { - len = slhc_compress(ppp->slcomp, p, len, ppp->cbuff, &p, - !(ppp->flags & SC_NO_TCP_CCID)); - if (p[0] & SL_TYPE_COMPRESSED_TCP) - proto = PROTO_VJCOMP; - else { - if (p[0] >= SL_TYPE_UNCOMPRESSED_TCP) { - proto = PROTO_VJUNCOMP; - p[0] = (p[0] & 0x0f) | 0x40; - } - } - } - - /* increment appropriate counter */ - if (proto == PROTO_VJCOMP) - ++ppp->stats.scomp; - else - ++ppp->stats.suncomp; - - if (ppp_debug_netpackets) { - struct iphdr *iph = (struct iphdr *)skb->data; - PRINTK ((KERN_DEBUG "%s ==> proto %x len %d src %x dst %x proto %d\n", - dev->name, (int) proto, (int) len, (int) iph->saddr, - (int) iph->daddr, (int) iph->protocol)) - } - - /* start of frame: FLAG ALL_STATIONS CONTROL */ -#ifdef OPTIMIZE_FLAG_TIME - if (jiffies - ppp->last_xmit > OPTIMIZE_FLAG_TIME) - *ppp->xhead++ = PPP_FLAG; - ppp->last_xmit = jiffies; -#else - *ppp->xhead++ = PPP_FLAG; -#endif - - ppp->fcs = PPP_FCS_INIT; - if (!(ppp->flags & SC_COMP_AC)) { - ppp_stuff_char(ppp, PPP_ADDRESS); - ppp_stuff_char(ppp, PPP_CONTROL); - } - - if (!(ppp->flags & SC_COMP_PROT) || (proto & 0xff00)) - ppp_stuff_char(ppp, proto>>8); - ppp_stuff_char(ppp, proto&0xff); - - /* data part */ - while (len-- > 0) - ppp_stuff_char(ppp, *p++); - - /* fcs and flag */ - ppp_add_fcs(ppp); - *ppp->xhead++ = PPP_FLAG; - - /* update the time for demand dial function */ - ppp->ddinfo.ip_sjiffies = jiffies; - - /* send it! */ - if (ppp_debug >= 6) - ppp_print_buffer ("xmit buffer", ppp->xbuff, ppp->xhead - ppp->xbuff, KERNEL_DS); - else { - PRINTKN (4,(KERN_DEBUG "ppp_write: writing %d chars\n", - (int) (ppp->xhead - ppp->xbuff))); - } - - ppp_kick_tty(ppp); - - done: - dev_kfree_skb(skb, FREE_WRITE); - return 0; -} - -#ifdef NET02D -static int -ppp_header(unsigned char *buff, struct device *dev, unsigned short type, - unsigned long daddr, unsigned long saddr, unsigned len) +static int ppp_dev_input (struct protocol *self, struct protocol *lower, + sk_buff *skb, void *saddr, void *daddr) { - return(0); + return protocol_pass_demultiplex(self, NULL, skb, NULL, NULL); } -static int -ppp_rebuild_header(void *buff, struct device *dev) +static int ppp_dev_output (struct protocol *self, sk_buff *skb, int type, + int subid, void *saddr, void *daddr, void *opt) { - return(0); + if(skb->dev==NULL) + { + printk("ppp_dev_output: No device.\n"); + kfree_skb(skb, FREE_WRITE); + return -1; + } + dev_queue_xmit(skb, skb->dev, skb->priority); + return 0; } -static void -ppp_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev) +static int ppp_dev_getkey(int protocol, int subid, unsigned char *key) { + switch (protocol) + { + case htons (ETH_P_IP): + case htons (ETH_P_IPX): + return 0; + + default: + break; + } + + return -EAFNOSUPPORT; } #else -static int -ppp_header(struct sk_buff *skb, struct device *dev, unsigned short type, - void *daddr, void *saddr, unsigned len) -{ - return(0); -} +#if USE_SKB_PROTOCOL == 0 +/* + * Called to enquire about the type of the frame in the buffer. Return + * ETH_P_IP for an IP frame, ETH_P_IPX for an IPX frame. + */ -static int -ppp_rebuild_header(void *buff, struct device *dev, unsigned long raddr, - struct sk_buff *skb) +static unsigned short +ppp_dev_type (sk_buff *skb, struct device *dev) { - return(0); + return (htons (ETH_P_IP)); } #endif -static struct enet_statistics * -ppp_get_stats (struct device *dev) +#if USE_SKB_PROTOCOL == 0 +static int ppp_dev_header (unsigned char *buff, struct device *dev, + unsigned short type, void *daddr, void *saddr, + unsigned len, struct sk_buff *skb) +#else +static int ppp_dev_header (sk_buff *skb, struct device *dev, + unsigned short type, void *daddr, + void *saddr, unsigned len) +#endif { - struct ppp *ppp = &ppp_ctrl[dev->base_addr]; - static struct enet_statistics ppp_stats; - - ppp_stats.rx_packets = ppp->stats.rcomp + ppp->stats.runcomp; - ppp_stats.rx_errors = ppp->stats.rerrors; - ppp_stats.rx_dropped = ppp->stats.tossed; - ppp_stats.rx_fifo_errors = 0; - ppp_stats.rx_length_errors = ppp->stats.runts; - ppp_stats.rx_over_errors = ppp->stats.roverrun; - ppp_stats.rx_crc_errors = 0; - ppp_stats.rx_frame_errors = 0; - ppp_stats.tx_packets = ppp->stats.scomp + ppp->stats.suncomp; - ppp_stats.tx_errors = ppp->stats.serrors; - ppp_stats.tx_dropped = 0; - ppp_stats.tx_fifo_errors = 0; - ppp_stats.collisions = ppp->stats.sbusy; - ppp_stats.tx_carrier_errors = 0; - ppp_stats.tx_aborted_errors = 0; - ppp_stats.tx_window_errors = 0; - ppp_stats.tx_heartbeat_errors = 0; + return (0); +} - PRINTKN (3, (KERN_INFO "ppp_get_stats called")); - return &ppp_stats; +static int +ppp_dev_rebuild (void *buff, struct device *dev, unsigned long raddr, + sk_buff *skb) +{ + return (0); } +#endif /************************************************************* * UTILITIES * Miscellany called by various functions above. *************************************************************/ -#ifndef NEW_TTY_DRIVERS -/* find a PPP channel given a TTY */ -struct ppp * -ppp_find(struct tty_struct *tty) -{ - int i; - for (i = 0; i < PPP_NRUNIT; i++) - if (ppp_ctrl[i].inuse && (ppp_ctrl[i].tty == tty)) return &ppp_ctrl[i]; - - return NULL; -} -#endif - -/* allocate a PPP channel */ +/* allocate or create a PPP channel */ static struct ppp * -ppp_alloc(void) +ppp_alloc (void) { - int i; - for (i = 0; i < PPP_NRUNIT; i++) - if (!set_bit(0, &ppp_ctrl[i].inuse)) return &ppp_ctrl[i]; - - return NULL; -} + int if_num; + int status; + ppp_ctrl_t *ctl; + struct device *dev; + struct ppp *ppp; + + /* try to find an free device */ + ctl = ppp_list; + if_num = 0; + + while (ctl) { + ppp = ctl2ppp (ctl); + if (!set_bit(0, &ppp->inuse)) + return (ppp); + ctl = ctl->next; + if (++if_num == max_dev) + return (NULL); + } +/* + * There are no available items. Allocate a device from the system pool + */ + ctl = (ppp_ctrl_t *) kmalloc (sizeof(ppp_ctrl_t), GFP_KERNEL); + if (ctl) { + (void) memset(ctl, 0, sizeof(ppp_ctrl_t)); + ppp = ctl2ppp (ctl); + dev = ctl2dev (ctl); + + /* initialize channel control data */ + set_bit(0, &ppp->inuse); + + ppp->line = if_num; + ppp->tty = NULL; + ppp->dev = dev; + + dev->next = NULL; + dev->init = ppp_init_dev; + dev->name = ctl->name; + dev->base_addr = (unsigned long) if_num; + dev->priv = (void *) ppp; -/* marks a PPP interface 'busy'. user processes will wait, if - they try to write, and the network code will refrain from sending - return nonzero if succeeded in acquiring lock -*/ + sprintf (dev->name, "ppp%d", if_num); + + /* link in the new channel */ + ctl->next = ppp_list; + ppp_list = ctl; + +/* register device so that we can be ifconfig'd */ +/* ppp_init_dev() will be called as a side-effect */ + + status = register_netdev (dev); + if (status == 0) { + printk ("registered device %s\n", dev->name); + return (ppp); + } -static int -ppp_lock(struct ppp *ppp) -{ - int flags, locked; - save_flags(flags); - cli(); - locked = ppp->sending; - ppp->sending = 1; - if (ppp->dev->flags & IFF_UP) - ppp->dev->tbusy = 1; - restore_flags(flags); - return locked == 0; + printk (KERN_ERR + "ppp_alloc - register_netdev(%s) = %d failure.\n", + dev->name, status); + /* This one will forever be busy as it is not initialized */ + } + return (NULL); } +/* + * Utility procedures to print a buffer in hex/ascii + */ + static void -ppp_unlock(struct ppp *ppp) +ppp_print_hex (register u_char * out, const u_char * in, int count) { - int flags; - save_flags(flags); - cli(); - ppp->sending = 0; - if (ppp->dev->flags & IFF_UP) - ppp->dev->tbusy = 0; - restore_flags(flags); -} + register u_char next_ch; + static char hex[] = "0123456789ABCDEF"; -/* FCS support functions */ + while (count-- > 0) { + next_ch = *in++; + *out++ = hex[(next_ch >> 4) & 0x0F]; + *out++ = hex[next_ch & 0x0F]; + ++out; + } +} static void -ppp_add_fcs(struct ppp *ppp) +ppp_print_char (register u_char * out, const u_char * in, int count) { - unsigned short fcs = ppp->fcs; + register u_char next_ch; + + while (count-- > 0) { + next_ch = *in++; - fcs ^= 0xffff; - ppp_stuff_char(ppp, fcs & 0x00ff); - ppp_stuff_char(ppp, (fcs & 0xff00) >> 8); - ASSERT (ppp->fcs == PPP_FCS_GOOD); - PRINTKN (4,(KERN_DEBUG "ppp_add_fcs: fcs is %lx\n", - (long) (unsigned long) fcs)); + if (next_ch < 0x20 || next_ch > 0x7e) + *out++ = '.'; + else { + *out++ = next_ch; + if (next_ch == '%') /* printk/syslogd has a bug !! */ + *out++ = '%'; + } + } + *out = '\0'; } -static int -ppp_check_fcs(struct ppp *ppp) +static void +ppp_print_buffer (const u_char * name, const u_char * buf, int count) { - unsigned short fcs = PPP_FCS_INIT, msgfcs; - unsigned char *c = ppp->rbuff; - int i; + u_char line[44]; - for (i = 0; i < ppp->rcount - 2; i++, c++) - fcs = (fcs >> 8) ^ fcstab[(fcs ^ *c) & 0xff]; + if (name != (u_char *) NULL) + printk (KERN_DEBUG "ppp: %s, count = %d\n", name, count); + + while (count > 8) { + memset (line, 32, 44); + ppp_print_hex (line, buf, 8); + ppp_print_char (&line[8 * 3], buf, 8); + printk (KERN_DEBUG "%s\n", line); + count -= 8; + buf += 8; + } - fcs ^= 0xffff; - msgfcs = (c[1] << 8) + c[0]; - PRINTKN (4,(KERN_INFO "ppp_check_fcs: got %lx want %lx\n", - (unsigned long) msgfcs, (unsigned long) fcs)); - return fcs == msgfcs; + if (count > 0) { + memset (line, 32, 44); + ppp_print_hex (line, buf, count); + ppp_print_char (&line[8 * 3], buf, count); + printk (KERN_DEBUG "%s\n", line); + } } -static char hex[] = "0123456789ABCDEF"; +/************************************************************* + * Compressor module interface + *************************************************************/ + +struct compressor_link { + struct compressor_link *next; + struct compressor *comp; +}; + +static struct compressor_link *ppp_compressors = (struct compressor_link *) 0; -static inline void ppp_print_hex (register char *out, const char *in, int count) +static struct compressor *find_compressor (int type) { - register unsigned char next_ch; + struct compressor_link *lnk; + unsigned long flags; + + save_flags(flags); + cli(); - while (count-- > 0) { - next_ch = (unsigned char) get_user (in); + lnk = ppp_compressors; + while (lnk != (struct compressor_link *) 0) { + if ((int) (unsigned char) lnk->comp->compress_proto == type) { + restore_flags(flags); + return lnk->comp; + } + lnk = lnk->next; + } - *out++ = hex[(next_ch >> 4) & 0x0F]; - *out++ = hex[next_ch & 0x0F]; - ++out; - ++in; - } + restore_flags(flags); + return (struct compressor *) 0; } -static inline void ppp_print_char (register char *out, const char *in, int count) +STATIC int ppp_register_compressor (struct compressor *cp) { - register unsigned char next_ch; + struct compressor_link *new; + unsigned long flags; - while (count-- > 0) { - next_ch = (unsigned char) get_user (in); + new = (struct compressor_link *) kmalloc (sizeof (struct compressor_link), GFP_KERNEL); - if (next_ch < 0x20 || next_ch > 0x7e) - *out++ = '.'; - else { - *out++ = next_ch; - if (next_ch == '%') /* printk/syslogd has a bug !! */ - *out++ = '%'; - } - ++in; - } - *out = '\0'; -} + if (new == (struct compressor_link *) 0) + return 1; -static void ppp_print_buffer(const char *name, const char *buf, int count, int seg) -{ - char line [44]; - int old_fs = get_fs(); + save_flags(flags); + cli(); + + if (find_compressor (cp->compress_proto)) { + restore_flags(flags); + kfree (new); + return 0; + } - set_fs (seg); + new->next = ppp_compressors; + new->comp = cp; + ppp_compressors = new; - if (name != NULL) - PRINTK ((KERN_DEBUG "ppp: %s, count = %d\n", name, count)); + restore_flags(flags); + return 0; +} - while (count > 8) { - memset (line, ' ', sizeof (line)); - ppp_print_hex (line, buf, 8); - ppp_print_char (&line[8 * 3], buf, 8); - PRINTK ((KERN_DEBUG "%s\n", line)); - count -= 8; - buf += 8; - } +STATIC void ppp_unregister_compressor (struct compressor *cp) +{ + struct compressor_link *prev = (struct compressor_link *) 0; + struct compressor_link *lnk; + unsigned long flags; - if (count > 0) { - memset (line, ' ', sizeof (line)); - ppp_print_hex (line, buf, count); - ppp_print_char (&line[8 * 3], buf, count); - PRINTK ((KERN_DEBUG "%s\n", line)); - } + save_flags(flags); + cli(); - set_fs (old_fs); + lnk = ppp_compressors; + while (lnk != (struct compressor_link *) 0) { + if (lnk->comp == cp) { + if (prev) + prev->next = lnk->next; + else + ppp_compressors = lnk->next; + kfree (lnk); + break; + } + prev = lnk; + lnk = lnk->next; + } + restore_flags(flags); } +/************************************************************* + * Module support routines + *************************************************************/ + #ifdef MODULE char kernel_version[] = UTS_RELEASE; -static struct device dev_ppp[PPP_NRUNIT] = { - { - "ppp0", /* ppp */ - 0, 0, 0, 0, /* memory */ - 0, 0, /* base, irq */ - 0, 0, 0, NULL, ppp_init, - } - , { "ppp1" , 0, 0, 0, 0, 1, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp2" , 0, 0, 0, 0, 2, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp3" , 0, 0, 0, 0, 3, 0, 0, 0, 0, NULL, ppp_init } - -#ifdef PPP_PPP_LOTS - , { "ppp4" , 0, 0, 0, 0, 4, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp5" , 0, 0, 0, 0, 5, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp6" , 0, 0, 0, 0, 6, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp7" , 0, 0, 0, 0, 7, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp8" , 0, 0, 0, 0, 8, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp9" , 0, 0, 0, 0, 9, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp10" , 0, 0, 0, 0, 10, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp11" , 0, 0, 0, 0, 11, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp12" , 0, 0, 0, 0, 12, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp13" , 0, 0, 0, 0, 13, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp14" , 0, 0, 0, 0, 14, 0, 0, 0, 0, NULL, ppp_init } - , { "ppp15" , 0, 0, 0, 0, 15, 0, 0, 0, 0, NULL, ppp_init } -#endif -}; - int init_module(void) { - int err; - int i,j; + int status; - for (i = 0; i < PPP_NRUNIT; i++) { - if ((err = register_netdev(&dev_ppp[i]))) { - if (err == -EEXIST) { - printk("PPP: devices already present. Module not loaded.\n"); - /* we must unregister already registered units */ - if(i>0) { - for(j = 0; j < i ; j++) - unregister_netdev(&dev_ppp[j]); - if ((j = tty_register_ldisc(N_PPP, NULL))) { - printk("PPP: can't unregister line discipline (err = %d)\n", j); - } - } - } - return err; - } - } - return 0; + /* register our line disciplines */ + status = ppp_first_time(); + if (status != 0) + printk (KERN_INFO + "PPP: ppp_init() failure %d\n", status); + return (status); } void cleanup_module(void) { - int i; + int status; + ppp_ctrl_t *ctl, *next_ctl; + struct device *dev; + struct ppp *ppp; + int busy_flag = MOD_IN_USE; +/* + * Ensure that the devices are not in operation. + */ + if (!busy_flag) { + ctl = ppp_list; + while (ctl) { + ppp = ctl2ppp (ctl); + if (ppp->inuse && ppp->tty != NULL) { + busy_flag = 1; + break; + } - if (MOD_IN_USE) { - printk("PPP: device busy, remove delayed\n"); - return; + dev = ctl2dev (ctl); + if (dev->start || dev->flags & IFF_UP) { + busy_flag = 1; + break; + } + ctl = ctl->next; + } } - for (i = 0; i < PPP_NRUNIT; i++) { - unregister_netdev(&dev_ppp[i]); +/* + * Ensure that there are no compressor modules registered + */ + if (busy_flag == 0 && ppp_compressors != NULL) + busy_flag = 1; + + if (busy_flag) { + printk (KERN_INFO + "PPP: device busy, remove delayed\n"); + return; } - if ((i = tty_register_ldisc(N_PPP, NULL))) { - printk("PPP: can't unregister line discipline (err = %d)\n", i); +/* + * Release the tty registration of the line dicipline so that no new entries + * may be created. + */ + status = tty_register_ldisc (N_PPP, NULL); + if (status != 0) + printk (KERN_INFO + "PPP: Unable to unregister ppp line discipline " + "(err = %d)\n", status); + else + printk (KERN_INFO + "PPP: ppp line discipline successfully unregistered\n"); +/* + * Remove the symbol definitions + */ + (void) register_symtab ((struct symbol_table *) 0); +/* + * De-register the devices so that there is no problem with them + */ + next_ctl = ppp_list; + while (next_ctl) { + ctl = next_ctl; + next_ctl = ctl->next; + ppp = ctl2ppp (ctl); + dev = ctl2dev (ctl); + + ppp_release (ppp); + unregister_netdev (dev); + kfree (ctl); } } - #endif diff -u --recursive --new-file v1.3.32/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c --- v1.3.32/linux/drivers/net/seeq8005.c Sat Sep 9 15:26:53 1995 +++ linux/drivers/net/seeq8005.c Tue Oct 10 15:45:27 1995 @@ -54,8 +54,6 @@ #include #include #include "seeq8005.h" -extern struct device *init_etherdev(struct device *dev, int sizeof_private, - unsigned long *mem_startp); /* First, a few definitions that the brave might change. */ /* A zero-terminated list of I/O addresses to be probed. */ @@ -277,7 +275,7 @@ /* Allocate a new 'dev' if needed. */ if (dev == NULL) - dev = init_etherdev(0, sizeof(struct net_local), 0); + dev = init_etherdev(0, sizeof(struct net_local)); if (net_debug && version_printed++ == 0) printk(version); @@ -336,6 +334,8 @@ /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); + + dev->flags &= ~IFF_MULTICAST; return 0; } diff -u --recursive --new-file v1.3.32/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c --- v1.3.32/linux/drivers/net/sk_g16.c Sat Sep 9 15:26:53 1995 +++ linux/drivers/net/sk_g16.c Tue Oct 10 15:45:27 1995 @@ -807,6 +807,8 @@ /* Set the generic fields of the device structure */ ether_setup(dev); + + dev->flags &= ~IFF_MULTICAST; /* Initialize private structure */ diff -u --recursive --new-file v1.3.32/linux/drivers/net/skeleton.c linux/drivers/net/skeleton.c --- v1.3.32/linux/drivers/net/skeleton.c Tue Aug 15 20:39:03 1995 +++ linux/drivers/net/skeleton.c Tue Oct 10 14:03:45 1995 @@ -179,7 +179,7 @@ * This makes it easier to free the memory when this driver * is used as a module. */ - dev = init_etherdev(0, 0, 0); + dev = init_etherdev(0, 0); if (dev == NULL) return -ENOMEM; } diff -u --recursive --new-file v1.3.32/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c --- v1.3.32/linux/drivers/net/smc-ultra.c Wed Oct 4 14:14:31 1995 +++ linux/drivers/net/smc-ultra.c Tue Oct 10 14:03:45 1995 @@ -139,7 +139,7 @@ return ENODEV; if (dev == NULL) - dev = init_etherdev(0, sizeof(struct ei_device), 0); + dev = init_etherdev(0, sizeof(struct ei_device)); if (dev == NULL) /* Still.. */ return ENOMEM; /* Out of memory ?? */ diff -u --recursive --new-file v1.3.32/linux/drivers/net/tulip.c linux/drivers/net/tulip.c --- v1.3.32/linux/drivers/net/tulip.c Wed Oct 4 14:14:31 1995 +++ linux/drivers/net/tulip.c Tue Oct 10 14:21:31 1995 @@ -154,8 +154,7 @@ int pad0, pad1; /* Used for 8-byte alignment */ }; -static unsigned long tulip_probe1(unsigned long mem_start, int ioaddr, - int irq); +static void tulip_probe1(int ioaddr, int irq); static int tulip_open(struct device *dev); static void tulip_init_ring(struct device *dev); static int tulip_start_xmit(struct sk_buff *skb, struct device *dev); @@ -174,7 +173,7 @@ ourselves. This is done by having the initialization occur before the 'kmalloc()' memory management system is started. */ -unsigned long dec21040_init(unsigned long mem_start, unsigned long mem_end) +int dec21040_init(void) { if (pcibios_present()) { @@ -195,11 +194,11 @@ if (tulip_debug > 2) printk("Found DEC PCI Tulip at I/O %#lx, IRQ %d.\n", pci_ioaddr, pci_irq_line); - mem_start = tulip_probe1(mem_start, pci_ioaddr, pci_irq_line); + tulip_probe1(pci_ioaddr, pci_irq_line); } } - return mem_start; + return 0; } #endif #ifdef MODULE @@ -210,7 +209,7 @@ } #endif -unsigned long tulip_probe1(unsigned long mem_start, int ioaddr, int irq) +static void tulip_probe1(int ioaddr, int irq) { static int did_version = 0; /* Already printed version info. */ struct device *dev; @@ -220,9 +219,7 @@ if (tulip_debug > 0 && did_version++ == 0) printk(version); - dev = init_etherdev(0, sizeof(struct tulip_private) - + PKT_BUF_SZ*RX_RING_SIZE, - &mem_start); + dev = init_etherdev(0, 0); printk("%s: DEC 21040 Tulip at %#3x,", dev->name, ioaddr); @@ -252,9 +249,9 @@ dev->irq = irq; /* Make certain the data structures are quadword aligned. */ - dev->priv = (void *)(((int)dev->priv + 7) & ~7); - tp = (struct tulip_private *)dev->priv; - tp->rx_buffs = (long)dev->priv + sizeof(struct tulip_private); + tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA); + dev->priv = tp; + tp->rx_buffs = kmalloc(PKT_BUF_SZ*RX_RING_SIZE, GFP_KERNEL | GFP_DMA); /* The Tulip-specific entries in the device structure. */ dev->open = &tulip_open; @@ -268,7 +265,7 @@ dev->set_mac_address = &set_mac_address; #endif - return mem_start; + return; } diff -u --recursive --new-file v1.3.32/linux/drivers/net/wd.c linux/drivers/net/wd.c --- v1.3.32/linux/drivers/net/wd.c Wed Oct 4 14:14:31 1995 +++ linux/drivers/net/wd.c Tue Oct 10 14:03:45 1995 @@ -119,7 +119,7 @@ return ENODEV; if (dev == NULL) - dev = init_etherdev(0, sizeof(struct ei_device), 0); + dev = init_etherdev(0, sizeof(struct ei_device)); printk("%s: WD80x3 at %#3x, ", dev->name, ioaddr); for (i = 0; i < 6; i++) diff -u --recursive --new-file v1.3.32/linux/drivers/net/znet.c linux/drivers/net/znet.c --- v1.3.32/linux/drivers/net/znet.c Fri Oct 6 14:35:15 1995 +++ linux/drivers/net/znet.c Tue Oct 10 15:45:27 1995 @@ -640,11 +640,11 @@ { short ioaddr = dev->base_addr; - if (num_addrs < 0) { + if (num_addrs == -1) { /* Enable promiscuous mode */ i593_init[7] &= ~3; i593_init[7] |= 1; i593_init[13] &= ~8; i593_init[13] |= 8; - } else if (num_addrs > 0) { + } else if (num_addrs != 0) { /* Enable accept-all-multicast mode */ i593_init[7] &= ~3; i593_init[7] |= 0; i593_init[13] &= ~8; i593_init[13] |= 8; diff -u --recursive --new-file v1.3.32/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.3.32/linux/drivers/scsi/scsi.c Wed Sep 27 15:59:59 1995 +++ linux/drivers/scsi/scsi.c Tue Oct 10 15:22:03 1995 @@ -2258,95 +2258,47 @@ return 0; } -/* - * These are special functions that can be used to obtain memory at boot time. - * They act line a malloc function, but they simply take memory from the pool - */ - -static unsigned long scsi_init_memory_start = 0; -static unsigned long scsi_memory_lower_value = 0; -static unsigned long scsi_memory_upper_value = 0; -int scsi_loadable_module_flag; /* Set after we scan builtin drivers */ void * scsi_init_malloc(unsigned int size, int priority) { - unsigned long retval; - int order, a_size; + void * retval; - /* Use the statically allocated memory instead of kmalloc (DB) */ -#if defined(USE_STATIC_SCSI_MEMORY) - if(scsi_loadable_module_flag && !(priority & GFP_DMA)) -#else - if(scsi_loadable_module_flag) -#endif - { - /* - * For buffers used by the DMA pool, we assume page aligned - * structures. - */ - if ((size % PAGE_SIZE) == 0) { - for (order = 0, a_size = PAGE_SIZE; - a_size < size; order++, a_size <<= 1) - ; - retval = - (unsigned long) __get_dma_pages(priority & GFP_LEVEL_MASK, - order); - } - else - retval = (unsigned long) kmalloc(size, priority); - - } else { - /* - * Keep all memory aligned on 16-byte boundaries. Some host - * adaptors (e.g. BusLogic BT-445S) require DMA buffers to be - * aligned that way. - */ - size = (size + 15) & ~15; - - if(scsi_loadable_module_flag && - (scsi_init_memory_start + size) > scsi_memory_upper_value) { - retval = 0; - printk("scsi_init_malloc: no more statically allocated memory.\n"); - } - else { - retval = scsi_init_memory_start; - scsi_init_memory_start += size; - } - } + /* + * For buffers used by the DMA pool, we assume page aligned + * structures. + */ + if ((size % PAGE_SIZE) == 0) { + int order, a_size; + for (order = 0, a_size = PAGE_SIZE; + a_size < size; order++, a_size <<= 1) + ; + retval = (void *) __get_dma_pages(priority & GFP_LEVEL_MASK, + order); + } else + retval = kmalloc(size, priority); + if (retval) - memset((void *) retval, 0, size); - return (void *) retval; + memset(retval, 0, size); + return retval; } void scsi_init_free(char * ptr, unsigned int size) { - int order, a_size; + /* + * We need this special code here because the DMA pool assumes + * page aligned data. Besides, it is wasteful to allocate + * page sized chunks with kmalloc. + */ + if ((size % PAGE_SIZE) == 0) { + int order, a_size; - /* We need to compare addresses to see whether this was kmalloc'd or not */ - - if((unsigned long) ptr >= scsi_init_memory_start || - (unsigned long) ptr < scsi_memory_lower_value) { - /* - * We need this special code here because the DMA pool assumes - * page aligned data. Besides, it is wasteful to allocate - * page sized chunks with kmalloc. - */ - if ((size % PAGE_SIZE) == 0) { - for (order = 0, a_size = PAGE_SIZE; - a_size < size; order++, a_size <<= 1) - ; - free_pages((unsigned long)ptr, order); - } - else - kfree(ptr); - } else { - /* Use the same alignment as scsi_init_malloc() */ - size = (size + 15) & ~15; - - if(((unsigned long) ptr) + size == scsi_init_memory_start) - scsi_init_memory_start = (unsigned long) ptr; - } + for (order = 0, a_size = PAGE_SIZE; + a_size < size; order++, a_size <<= 1) + ; + free_pages((unsigned long)ptr, order); + } else + kfree(ptr); } void scsi_build_commandblocks(Scsi_Device * SDpnt) @@ -2382,11 +2334,10 @@ /* * scsi_dev_init() is our initialization routine, which in turn calls host - * initialization, bus scanning, and sd/st initialization routines. It - * should be called from main(). + * initialization, bus scanning, and sd/st initialization routines. */ -unsigned long scsi_dev_init (unsigned long memory_start, unsigned long memory_end) +int scsi_dev_init(void) { struct Scsi_Host * host = NULL; Scsi_Device * SDpnt; @@ -2400,13 +2351,6 @@ /* Yes we're here... */ dispatch_scsi_info_ptr = dispatch_scsi_info; - /* Init a few things so we can "malloc" memory. */ - scsi_loadable_module_flag = 0; - - /* Align everything on 16-byte boundaries. */ - scsi_init_memory_start = (memory_start + 15) & ~ 15; - scsi_memory_lower_value = scsi_init_memory_start; - timer_table[SCSI_TIMER].fn = scsi_main_timeout; timer_table[SCSI_TIMER].expires = 0; @@ -2445,7 +2389,7 @@ if (scsi_devicelist) dma_sectors = 16; /* Base value we use */ - if (memory_end-1 > ISA_DMA_THRESHOLD) + if (high_memory-1 > ISA_DMA_THRESHOLD) scsi_need_isa_bounce_buffers = 1; else scsi_need_isa_bounce_buffers = 0; @@ -2459,7 +2403,7 @@ host->cmd_per_lun; if(host->unchecked_isa_dma && - memory_end - 1 > ISA_DMA_THRESHOLD && + high_memory - 1 > ISA_DMA_THRESHOLD && SDpnt->type != TYPE_TAPE) { dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize * host->cmd_per_lun; @@ -2491,23 +2435,8 @@ for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) if(sdtpnt->finish && sdtpnt->nr_dev) (*sdtpnt->finish)(); - - scsi_loadable_module_flag = 1; - - /* This allocates statically some extra memory to be used for modules, - * until the kmalloc problem is fixed (DB) - */ - -#if defined(USE_STATIC_SCSI_MEMORY) - scsi_memory_upper_value = scsi_init_memory_start + 256 * 1024; - printk ("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n", - (scsi_memory_upper_value - scsi_memory_lower_value) / 1024, - (scsi_init_memory_start - scsi_memory_lower_value) / 1024, - (scsi_memory_upper_value - scsi_init_memory_start) / 1024); - return scsi_memory_upper_value; -#else - return scsi_init_memory_start; -#endif + + return 0; } static void print_inquiry(unsigned char *data) @@ -2577,7 +2506,7 @@ while (HBA_ptr) { #if 0 size += sprintf(buffer+len,"scsi%2d: %s\n", (int) HBA_ptr->host_no, - HBA_ptr->hostt->procname); + HBA_ptr->hostt->procname); len += size; pos = begin + len; #endif @@ -2909,10 +2838,10 @@ if(shpnt->hostt == tpnt) { if(shpnt->loaded_as_module) { pcount = next_scsi_host; - /* Remove the /proc/scsi directory entry */ + /* Remove the /proc/scsi directory entry */ #if CONFIG_PROC_FS - proc_scsi_unregister(tpnt->proc_dir, - shpnt->host_no + PROC_SCSI_FILE); + proc_scsi_unregister(tpnt->proc_dir, + shpnt->host_no + PROC_SCSI_FILE); #endif if(tpnt->release) (*tpnt->release)(shpnt); @@ -2991,7 +2920,7 @@ * init function. */ if(tpnt->init && tpnt->dev_noticed) - if ((*tpnt->init)()) return 1; + if ((*tpnt->init)()) return 1; /* * Now actually connect the devices to the new driver. diff -u --recursive --new-file v1.3.32/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h --- v1.3.32/linux/drivers/scsi/scsi.h Wed Sep 27 15:59:59 1995 +++ linux/drivers/scsi/scsi.h Tue Oct 10 15:52:46 1995 @@ -218,7 +218,7 @@ * Initializes all SCSI devices. This scans all scsi busses. */ -extern unsigned long scsi_dev_init (unsigned long, unsigned long); +extern int scsi_dev_init (void); struct scatterlist { char * address; /* Location data is to be transferred to */ diff -u --recursive --new-file v1.3.32/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- v1.3.32/linux/drivers/sound/soundcard.c Mon Sep 25 12:26:22 1995 +++ linux/drivers/sound/soundcard.c Tue Oct 10 10:15:35 1995 @@ -218,8 +218,8 @@ sound_release }; -long -soundcard_init (long mem_start) +int +soundcard_init (void) { #ifndef MODULE register_chrdev (SOUND_MAJOR, "sound", &sound_fops); @@ -227,31 +227,31 @@ soundcard_configured = 1; - mem_start = sndtable_init (mem_start); /* Initialize call tables and - * detect cards */ + sndtable_init (); /* Initialize call tables and + * detect cards */ if (!(soundcards_installed = sndtable_get_cardcount ())) - return mem_start; /* No cards detected */ + return 0; /* No cards detected */ #ifndef EXCLUDE_AUDIO if (num_audiodevs) /* Audio devices present */ { - mem_start = DMAbuf_init (mem_start); - mem_start = audio_init (mem_start); + DMAbuf_init (); + audio_init (); } #endif #ifndef EXCLUDE_MIDI if (num_midis) - mem_start = MIDIbuf_init (mem_start); + MIDIbuf_init (); #endif #ifndef EXCLUDE_SEQUENCER if (num_midis + num_synths) - mem_start = sequencer_init (mem_start); + sequencer_init (); #endif - return mem_start; + return 0; } #ifdef MODULE diff -u --recursive --new-file v1.3.32/linux/fs/exec.c linux/fs/exec.c --- v1.3.32/linux/fs/exec.c Wed Sep 13 12:45:32 1995 +++ linux/fs/exec.c Mon Oct 9 13:10:41 1995 @@ -171,6 +171,11 @@ char corefile[6+sizeof(current->comm)]; unsigned long dump_start, dump_size; struct user dump; +#ifdef __alpha__ +# define START_DATA(u) (u.start_data) +#else +# define START_DATA(u) (u.u_tsize << PAGE_SHIFT) +#endif if (!current->dumpable) return 0; @@ -211,7 +216,7 @@ goto close_coredump; has_dumped = 1; strncpy(dump.u_comm, current->comm, sizeof(current->comm)); - dump.u_ar0 = (struct pt_regs *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump))); + dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump))); dump.signal = signr; dump_thread(regs, &dump); @@ -228,7 +233,7 @@ /* make sure we actually have a data and stack area to dump */ set_fs(USER_DS); - if (verify_area(VERIFY_READ, (void *) (dump.u_tsize << PAGE_SHIFT), dump.u_dsize << PAGE_SHIFT)) + if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize << PAGE_SHIFT)) dump.u_dsize = 0; if (verify_area(VERIFY_READ, (void *) dump.start_stack, dump.u_ssize << PAGE_SHIFT)) dump.u_ssize = 0; @@ -242,7 +247,7 @@ set_fs(USER_DS); /* Dump the data area */ if (dump.u_dsize != 0) { - dump_start = dump.u_tsize << PAGE_SHIFT; + dump_start = START_DATA(dump); dump_size = dump.u_dsize << PAGE_SHIFT; DUMP_WRITE(dump_start,dump_size); } @@ -456,16 +461,12 @@ return p; } -unsigned long setup_arg_pages(unsigned long text_size,unsigned long * page) +unsigned long setup_arg_pages(unsigned long text_size, unsigned long * page) { - unsigned long code_limit,data_limit,code_base,data_base; + unsigned long data_base; int i; - code_limit = STACK_TOP; - data_limit = STACK_TOP; - code_base = data_base = 0; - current->mm->start_code = code_base; - data_base += data_limit; + data_base = STACK_TOP; for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) { data_base -= PAGE_SIZE; if (page[i]) { @@ -473,7 +474,7 @@ put_dirty_page(current,page[i],data_base); } } - return data_limit; + return STACK_TOP; } /* diff -u --recursive --new-file v1.3.32/linux/fs/proc/array.c linux/fs/proc/array.c --- v1.3.32/linux/fs/proc/array.c Mon Sep 25 12:26:23 1995 +++ linux/fs/proc/array.c Mon Oct 9 13:10:41 1995 @@ -61,10 +61,18 @@ int count1; char * pnt; struct user dump; +#ifdef __i386__ +# define FIRST_MAPPED PAGE_SIZE /* we don't have page 0 mapped on x86.. */ +#else +# define FIRST_MAPPED 0 +#endif memset(&dump, 0, sizeof(struct user)); dump.magic = CMAGIC; dump.u_dsize = MAP_NR(high_memory); +#ifdef __alpha__ + dump.start_data = PAGE_OFFSET; +#endif if (count < 0) return -EINVAL; @@ -87,14 +95,14 @@ read += count1; } - while (p < 2*PAGE_SIZE && count > 0) { + while (count > 0 && p < PAGE_SIZE + FIRST_MAPPED) { put_user(0,buf); buf++; p++; count--; read++; } - memcpy_tofs(buf,(void *) (PAGE_OFFSET + p - PAGE_SIZE),count); + memcpy_tofs(buf, (void *) (PAGE_OFFSET + p - PAGE_SIZE), count); read += count; file->f_pos += read; return read; diff -u --recursive --new-file v1.3.32/linux/include/asm-alpha/reg.h linux/include/asm-alpha/reg.h --- v1.3.32/linux/include/asm-alpha/reg.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-alpha/reg.h Mon Oct 9 13:10:41 1995 @@ -0,0 +1,52 @@ +#ifndef __reg_h__ +#define __reg_h__ + +/* + * Exception frame offsets. + */ +#define EF_V0 0 +#define EF_T0 1 +#define EF_T1 2 +#define EF_T2 3 +#define EF_T3 4 +#define EF_T4 5 +#define EF_T5 6 +#define EF_T6 7 +#define EF_T7 8 +#define EF_S0 9 +#define EF_S1 10 +#define EF_S2 11 +#define EF_S3 12 +#define EF_S4 13 +#define EF_S5 14 +#define EF_S6 15 +#define EF_A3 16 +#define EF_A4 17 +#define EF_A5 18 +#define EF_T8 19 +#define EF_T9 20 +#define EF_T10 21 +#define EF_T11 22 +#define EF_RA 23 +#define EF_T12 24 +#define EF_AT 25 +#define EF_SP 26 +#define EF_PS 27 +#define EF_PC 28 +#define EF_GP 29 +#define EF_A0 30 +#define EF_A1 31 +#define EF_A2 32 + +#define EF_SIZE (33*8) +#define HWEF_SIZE (6*8) /* size of PAL frame (PS-A2) */ + +#define EF_SSIZE (EF_SIZE - HWEF_SIZE) + +/* + * Map register number into core file offset. + */ +#define CORE_REG(reg, ubase) \ + (((unsigned long *)((unsigned long)(ubase)))[reg]) + +#endif /* __reg_h__ */ diff -u --recursive --new-file v1.3.32/linux/include/asm-alpha/signal.h linux/include/asm-alpha/signal.h --- v1.3.32/linux/include/asm-alpha/signal.h Wed Sep 27 16:00:00 1995 +++ linux/include/asm-alpha/signal.h Sat Oct 7 14:53:43 1995 @@ -43,6 +43,8 @@ #define SIGUSR2 31 #define SIGPOLL SIGIO +#define SIGPWR SIGINFO +#define SIGIOT SIGABRT /* * sa_flags values: SA_STACK is not currently supported, but will allow the diff -u --recursive --new-file v1.3.32/linux/include/asm-alpha/user.h linux/include/asm-alpha/user.h --- v1.3.32/linux/include/asm-alpha/user.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-alpha/user.h Mon Oct 9 13:10:41 1995 @@ -0,0 +1,52 @@ +#ifndef _ALPHA_USER_H +#define _ALPHA_USER_H + +#include + +#include +#include + +/* + * Core file format: The core file is written in such a way that gdb + * can understand it and provide useful information to the user (under + * linux we use the `trad-core' bfd, NOT the osf-core). The file contents + * are as follows: + * + * upage: 1 page consisting of a user struct that tells gdb + * what is present in the file. Directly after this is a + * copy of the task_struct, which is currently not used by gdb, + * but it may come in handy at some point. All of the registers + * are stored as part of the upage. The upage should always be + * only one page long. + * data: The data segment follows next. We use current->end_text to + * current->brk to pick up all of the user variables, plus any memory + * that may have been sbrk'ed. No attempt is made to determine if a + * page is demand-zero or if a page is totally unused, we just cover + * the entire range. All of the addresses are rounded in such a way + * that an integral number of pages is written. + * stack: We need the stack information in order to get a meaningful + * backtrace. We need to write the data from usp to + * current->start_stack, so we round each of these in order to be able + * to write an integer number of pages. + */ +struct user { + unsigned long regs[EF_SIZE/8+32]; /* integer and fp regs */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct regs * u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* _ALPHA_USER_H */ diff -u --recursive --new-file v1.3.32/linux/include/asm-i386/segment.h linux/include/asm-i386/segment.h --- v1.3.32/linux/include/asm-i386/segment.h Fri Jul 7 08:54:53 1995 +++ linux/include/asm-i386/segment.h Sun Oct 8 12:37:07 1995 @@ -81,7 +81,7 @@ } /* - * These are depracated.. + * These are deprecated.. */ static inline unsigned char get_user_byte(const char * addr) diff -u --recursive --new-file v1.3.32/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h --- v1.3.32/linux/include/asm-i386/unistd.h Wed Oct 4 14:14:34 1995 +++ linux/include/asm-i386/unistd.h Tue Oct 10 08:53:08 1995 @@ -271,6 +271,34 @@ return waitpid(-1,wait_stat,0); } +/* + * This is the mechanism for creating a new kernel thread. + * + * NOTE! Only a kernel-only process(ie the swapper or direct descendants + * who haven't done an "execve()") should use this: it will work within + * a system call from a "real" process, but the process memory space will + * not be free'd until both the parent and the child have exited. + */ +static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + + __asm__ __volatile__( + "int $0x80\n\t" /* Linux/i386 system call */ + "testl %0,%0\n\t" /* child or parent? */ + "jne 1f\n\t" /* parent - jump */ + "pushl %3\n\t" /* push argument */ + "call *%4\n\t" /* call fn */ + "movl %2,%0\n\t" /* exit */ + "int $0x80\n" + "1:\t" + :"=a" (retval) + :"0" (__NR_clone), "i" (__NR_exit), + "r" (arg), "r" (fn), + "b" (flags | CLONE_VM)); + return retval; +} + #endif #endif /* _ASM_I386_UNISTD_H_ */ diff -u --recursive --new-file v1.3.32/linux/include/asm-i386/user.h linux/include/asm-i386/user.h --- v1.3.32/linux/include/asm-i386/user.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-i386/user.h Mon Oct 9 13:10:41 1995 @@ -0,0 +1,78 @@ +#ifndef _I386_USER_H +#define _I386_USER_H + +#include +#include +/* Core file format: The core file is written in such a way that gdb + can understand it and provide useful information to the user (under + linux we use the 'trad-core' bfd). There are quite a number of + obstacles to being able to view the contents of the floating point + registers, and until these are solved you will not be able to view the + contents of them. Actually, you can read in the core file and look at + the contents of the user struct to find out what the floating point + registers contain. + The actual file contents are as follows: + UPAGE: 1 page consisting of a user struct that tells gdb what is present + in the file. Directly after this is a copy of the task_struct, which + is currently not used by gdb, but it may come in useful at some point. + All of the registers are stored as part of the upage. The upage should + always be only one page. + DATA: The data area is stored. We use current->end_text to + current->brk to pick up all of the user variables, plus any memory + that may have been malloced. No attempt is made to determine if a page + is demand-zero or if a page is totally unused, we just cover the entire + range. All of the addresses are rounded in such a way that an integral + number of pages is written. + STACK: We need the stack information in order to get a meaningful + backtrace. We need to write the data from (esp) to + current->start_stack, so we round each of these off in order to be able + to write an integer number of pages. + The minimum core file size is 3 pages, or 12288 bytes. +*/ + +struct user_i387_struct { + long cwd; + long swd; + long twd; + long fip; + long fcs; + long foo; + long fos; + long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ +}; + +/* When the kernel dumps core, it starts by dumping the user struct - + this will be used by gdb to figure out where the data and stack segments + are within the file, and what virtual addresses to use. */ +struct user{ +/* We start with the registers, to mimic the way that "memory" is returned + from the ptrace(3,...) function. */ + struct pt_regs regs; /* Where the registers are actually stored */ +/* ptrace does not yet supply these. Someday.... */ + int u_fpvalid; /* True if math co-processor being used. */ + /* for this mess. Not yet used. */ + struct user_i387_struct i387; /* Math Co-processor registers. */ +/* The rest of this junk is to help gdb figure out what goes where */ + unsigned long int u_tsize; /* Text segment size (pages). */ + unsigned long int u_dsize; /* Data segment size (pages). */ + unsigned long int u_ssize; /* Stack segment size (pages). */ + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack area. + This is actually the bottom of the stack, + the top of the stack is always found in the + esp register. */ + long int signal; /* Signal that caused the core dump. */ + int reserved; /* No longer used */ + struct pt_regs * u_ar0; /* Used by gdb to help find the values for */ + /* the registers. */ + struct user_i387_struct* u_fpstate; /* Math Co-processor pointer. */ + unsigned long magic; /* To uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ + int u_debugreg[8]; +}; +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* _I386_USER_H */ diff -u --recursive --new-file v1.3.32/linux/include/linux/etherdevice.h linux/include/linux/etherdevice.h --- v1.3.32/linux/include/linux/etherdevice.h Wed Aug 9 14:55:42 1995 +++ linux/include/linux/etherdevice.h Tue Oct 10 14:01:30 1995 @@ -37,7 +37,7 @@ extern void eth_header_cache(struct device *dev, struct sock *sk, unsigned long saddr, unsigned long daddr); extern void eth_copy_and_sum(struct sk_buff *dest, unsigned char *src, int length, int base); -extern struct device * init_etherdev(struct device *, int, unsigned long*); +extern struct device * init_etherdev(struct device *, int); #endif diff -u --recursive --new-file v1.3.32/linux/include/linux/genhd.h linux/include/linux/genhd.h --- v1.3.32/linux/include/linux/genhd.h Tue Aug 15 20:39:04 1995 +++ linux/include/linux/genhd.h Sun Oct 8 12:37:07 1995 @@ -14,8 +14,11 @@ #ifdef __alpha__ #define CONFIG_OSF_PARTITION 1 #endif - -#define EXTENDED_PARTITION 5 + +/* These two have identical behaviour; use the second one if DOS fdisk gets + confused about extended/logical partitions starting past cylinder 1023. */ +#define DOS_EXTENDED_PARTITION 5 +#define LINUX_EXTENDED_PARTITION 0x85 #define DM6_PARTITION 0x54 /* has DDO: use xlated geom & offset */ #define EZD_PARTITION 0x55 /* EZ-DRIVE: same as DM6 (we think) */ @@ -57,7 +60,6 @@ struct gendisk *next; }; -extern int NR_GENDISKS; /* total */ extern struct gendisk *gendisk_head; /* linked list of disks */ #endif diff -u --recursive --new-file v1.3.32/linux/include/linux/if_ppp.h linux/include/linux/if_ppp.h --- v1.3.32/linux/include/linux/if_ppp.h Tue Jul 25 18:21:23 1995 +++ linux/include/linux/if_ppp.h Mon Oct 9 09:17:54 1995 @@ -1,237 +1,143 @@ -#ifndef _LINUX_IF_PPP_H -#define _LINUX_IF_PPP_H +/* $Id: if_ppp.h,v 1.3 1995/06/12 11:36:50 paulus Exp $ */ -/* definitions for kernel PPP module - Michael Callahan - Nov. 4 1993 */ - -/* how many PPP units? */ -#ifdef CONFIG_PPP_LOTS -#define PPP_NRUNIT 16 -#else -#define PPP_NRUNIT 4 -#endif - -#define PPP_VERSION "0.2.7" +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ -/* line discipline number */ -#define N_PPP 3 +/* + * ==FILEVERSION 3== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, increment the number above. + * if_ppp.h is shipped with a PPP distribution as well as with the kernel; + * if everyone increases the FILEVERSION number above, then scripts + * can do the right thing when deciding whether to install a new if_ppp.h + * file. Don't change the format of that line otherwise, so the + * installation script can recognize it. + */ -/* Magic value for the ppp structure */ -#define PPP_MAGIC 0x5002 +#ifndef _IF_PPP_H_ +#define _IF_PPP_H_ -#define PPPIOCGFLAGS 0x5490 /* get configuration flags */ -#define PPPIOCSFLAGS 0x5491 /* set configuration flags */ -#define PPPIOCGASYNCMAP 0x5492 /* get async map */ -#define PPPIOCSASYNCMAP 0x5493 /* set async map */ -#define PPPIOCGUNIT 0x5494 /* get ppp unit number */ -#define PPPIOCSINPSIG 0x5495 /* set input ready signal */ -#define PPPIOCSDEBUG 0x5497 /* set debug level */ -#define PPPIOCGDEBUG 0x5498 /* get debug level */ -#define PPPIOCGSTAT 0x5499 /* read PPP statistic information */ -#define PPPIOCGTIME 0x549A /* read time delta information */ -#define PPPIOCGXASYNCMAP 0x549B /* get async table */ -#define PPPIOCSXASYNCMAP 0x549C /* set async table */ -#define PPPIOCSMRU 0x549D /* set receive unit size for PPP */ -#define PPPIOCRASYNCMAP 0x549E /* set receive async map */ -#define PPPIOCSMAXCID 0x549F /* set the maximum compression slot id */ - -/* special characters in the framing protocol */ -#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ -#define PPP_UI 0x03 /* Unnumbered Information */ -#define PPP_FLAG 0x7E /* frame delimiter -- marks frame boundaries */ -#define PPP_ADDRESS 0xFF /* first character of frame <-- (may be */ -#define PPP_CONTROL 0x03 /* second character of frame <-- compressed)*/ -#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ -#define PPP_ESC 0x7d /* escape character -- next character is - data, and the PPP_TRANS bit should be - toggled. PPP_ESC PPP_FLAG is illegal */ - -/* protocol numbers */ -#define PROTO_IP 0x0021 -#define PROTO_VJCOMP 0x002d -#define PROTO_VJUNCOMP 0x002f - -/* FCS support */ -#define PPP_FCS_INIT 0xffff -#define PPP_FCS_GOOD 0xf0b8 +/* + * Packet sizes + */ -/* initial MTU */ -#define PPP_MTU 1500 +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#define PPP_MAXMRU 65000 /* Largest MRU we allow */ +#define PPP_VERSION "2.2.0" +#define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */ +#define PROTO_IPX 0x002b /* protocol numbers */ -/* initial MRU */ -#define PPP_MRU PPP_MTU +/* + * Bit definitions for flags. + */ -/* flags */ #define SC_COMP_PROT 0x00000001 /* protocol compression (output) */ #define SC_COMP_AC 0x00000002 /* header compression (output) */ #define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */ #define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */ #define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */ #define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */ +#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */ +#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */ #define SC_ENABLE_IP 0x00000100 /* IP packets may be exchanged */ -#define SC_IP_DOWN 0x00000200 /* give ip frames to pppd */ -#define SC_IP_FLUSH 0x00000400 /* "next time" flag for IP_DOWN */ +#define SC_COMP_RUN 0x00001000 /* compressor has been inited */ +#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */ #define SC_DEBUG 0x00010000 /* enable debug messages */ #define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */ #define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ #define SC_LOG_RAWIN 0x00080000 /* log all chars received */ #define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ +#define SC_MASK 0x0fE0ffff /* bits that user can change */ -/* Flag bits to determine state of input characters */ -#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ -#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 0 */ -#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ -#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */ - -#define SC_MASK 0x0fffffff /* bits that user can change */ - -/* flag for doing transmitter lockout */ +/* state bits */ +#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */ +#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */ +#define SC_VJ_RESET 0x20000000 /* Need to reset the VJ decompressor */ #define SC_XMIT_BUSY 0x10000000 /* ppp_write_wakeup is active */ +#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */ +#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ +#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ +#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ +#define SC_DC_FERROR 0x00800000 /* fatal decomp error detected */ +#define SC_DC_ERROR 0x00400000 /* non-fatal decomp error detected */ /* - * This is the format of the data buffer of a LQP packet. The packet data - * is sent/received to the peer. + * Ioctl definitions. */ -struct ppp_lqp_packet_hdr { - __u32 LastOutLQRs; /* Copied from PeerOutLQRs */ - __u32 LastOutPackets; /* Copied from PeerOutPackets */ - __u32 LastOutOctets; /* Copied from PeerOutOctets */ - __u32 PeerInLQRs; /* Copied from SavedInLQRs */ - __u32 PeerInPackets; /* Copied from SavedInPackets */ - __u32 PeerInDiscards; /* Copied from SavedInDiscards */ - __u32 PeerInErrors; /* Copied from SavedInErrors */ - __u32 PeerInOctets; /* Copied from SavedInOctets */ - __u32 PeerOutLQRs; /* Copied from OutLQRs, plus 1 */ - __u32 PeerOutPackets; /* Current ifOutUniPackets, + 1 */ - __u32 PeerOutOctets; /* Current ifOutOctets + LQR */ - }; - -/* - * This data is not sent to the remote. It is updated by the driver when - * a packet is received. - */ - -struct ppp_lqp_packet_trailer { - __u32 SaveInLQRs; /* Current InLQRs on reception */ - __u32 SaveInPackets; /* Current ifInUniPackets */ - __u32 SaveInDiscards; /* Current ifInDiscards */ - __u32 SaveInErrors; /* Current ifInErrors */ - __u32 SaveInOctets; /* Current ifInOctects */ +struct npioctl { + int protocol; /* PPP procotol, e.g. PPP_IP */ + enum NPmode mode; }; -/* - * PPP LQP packet. The packet is changed by the driver immediately prior - * to transmission and updated upon reception with the current values. - * So, it must be known to the driver as well as the pppd software. - */ - -struct ppp_lpq_packet { - __u32 magic; /* current magic value */ - struct ppp_lqp_packet_hdr hdr; /* Header fields for structure */ - struct ppp_lqp_packet_trailer tail; /* Trailer fields (not sent) */ +/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */ +struct ppp_option_data { + u_char *ptr; + u_int length; + int transmit; }; -/* - * PPP interface statistics. (used by LQP / pppstats) - */ - -struct ppp_stats { - __u32 rbytes; /* bytes received */ - __u32 rcomp; /* compressed packets received */ - __u32 runcomp; /* uncompressed packets received */ - __u32 rothers; /* non-ip frames received */ - __u32 rerrors; /* received errors */ - __u32 roverrun; /* "buffer overrun" counter */ - __u32 tossed; /* packets discarded */ - __u32 runts; /* frames too short to process */ - __u32 rgiants; /* frames too large to process */ - __u32 sbytes; /* bytes sent */ - __u32 scomp; /* compressed packets sent */ - __u32 suncomp; /* uncompressed packets sent */ - __u32 sothers; /* non-ip frames sent */ - __u32 serrors; /* transmitter errors */ - __u32 sbusy; /* "transmitter busy" counter */ +struct ifpppstatsreq { + struct ifreq b; + struct ppp_stats stats; /* statistic information */ }; -/* - * Demand dial fields - */ - -struct ppp_ddinfo { - unsigned long ip_sjiffies; /* time when last IP frame sent */ - unsigned long ip_rjiffies; /* time when last IP frame recvd*/ - unsigned long nip_sjiffies; /* time when last NON-IP sent */ - unsigned long nip_rjiffies; /* time when last NON-IP recvd */ +struct ifpppcstatsreq { + struct ifreq b; + struct ppp_comp_stats stats; }; -#ifdef __KERNEL__ - -struct ppp { - int magic; /* magic value for structure */ - - /* Bitmapped flag fields. */ - char sending; /* "channel busy" indicator */ - char escape; /* 0x20 if prev char was PPP_ESC*/ - char toss; /* toss this frame */ - unsigned long inuse; /* are we allocated? */ - - unsigned int flags; /* miscellany */ - - __u32 xmit_async_map[8]; /* 1 bit means that given control - character is quoted on output*/ - - __u32 recv_async_map; /* 1 bit means that given control - character is ignored on input*/ - int mtu; /* maximum xmit frame size */ - int mru; /* maximum receive frame size */ - unsigned short fcs; /* FCS field of current frame */ - - /* Various fields. */ - int line; /* PPP channel number */ - struct tty_struct *tty; /* ptr to TTY structure */ - struct device *dev; /* easy for intr handling */ - struct slcompress *slcomp; /* for header compression */ - unsigned long last_xmit; /* time of last transmission */ - - /* These are pointers to the malloc()ed frame buffers. - These buffers are used while processing a packet. If a packet - has to hang around for the user process to read it, it lingers in - the user buffers below. */ - unsigned char *rbuff; /* receiver buffer */ - unsigned char *xbuff; /* transmitter buffer */ - unsigned char *cbuff; /* compression buffer */ - - /* These are the various pointers into the buffers. */ - unsigned char *rhead; /* RECV buffer pointer (head) */ - unsigned char *rend; /* RECV buffer pointer (end) */ - int rcount; /* PPP receive counter */ - unsigned char *xhead; /* XMIT buffer pointer (head) */ - unsigned char *xtail; /* XMIT buffer pointer (end) */ - - /* Structures for interfacing with the user process. */ -#define RBUFSIZE 4000 - unsigned char *us_rbuff; /* circular incoming packet buf.*/ - unsigned char *us_rbuff_end; /* end of allocated space */ - unsigned char *us_rbuff_head; /* head of waiting packets */ - unsigned char *us_rbuff_tail; /* tail of waiting packets */ - unsigned long us_rbuff_lock; /* lock: bit 0 head bit 1 tail */ - int inp_sig; /* input ready signal for pgrp */ - int inp_sig_pid; /* process to get notified */ - - /* items to support the select() function */ - struct wait_queue *write_wait; /* queue for reading processes */ - struct wait_queue *read_wait; /* queue for writing processes */ - - /* PPP interface statistics. */ - struct ppp_stats stats; /* statistic information */ +#define ifr__name b.ifr_ifrn.ifrn_name +#define stats_ptr b.ifr_ifru.ifru_data - /* PPP demand dial information. */ - struct ppp_ddinfo ddinfo; /* demand dial information */ -}; +/* + * Ioctl definitions. + */ -#endif /* __KERNEL__ */ -#endif /* _LINUX_PPP_H */ +#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */ +#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */ +#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */ +#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */ +#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */ +#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */ +#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */ +#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */ +#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */ +#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */ +#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */ +#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */ +#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */ +#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data) +#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */ +#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */ +#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */ +#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */ +#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */ + +#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0) +#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */ +#define SIOCGPPPCSTATS (SIOCDEVPRIVATE + 2) +#if !defined(ifr_mtu) +#define ifr_mtu ifr_ifru.ifru_metric +#endif +#endif /* _IF_PPP_H_ */ diff -u --recursive --new-file v1.3.32/linux/include/linux/if_pppvar.h linux/include/linux/if_pppvar.h --- v1.3.32/linux/include/linux/if_pppvar.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/if_pppvar.h Mon Oct 9 09:17:54 1995 @@ -0,0 +1,156 @@ +/* $Id: if_pppvar.h,v 1.2 1995/06/12 11:36:51 paulus Exp $ */ +/* + * if_pppvar.h - private structures and declarations for PPP. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + * + * Copyright (c) 1989 Carnegie Mellon University. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Carnegie Mellon University. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * ==FILEVERSION 3== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, increment the number above. + * if_pppvar.h is shipped with a PPP distribution as well as with the kernel; + * if everyone increases the FILEVERSION number above, then scripts + * can do the right thing when deciding whether to install a new if_pppvar.h + * file. Don't change the format of that line otherwise, so the + * installation script can recognize it. + */ + +/* + * Supported network protocols. These values are used for + * indexing sc_npmode. + */ + +#define NP_IP 0 /* Internet Protocol */ +#define NUM_NP 1 /* Number of NPs. */ + +/* + * Buffers for the PPP process have the following structure + */ + +#define RBUFSIZE 2048 /* MUST be a power of 2 and be <= 4095 */ + +struct ppp_buffer { + int size; /* Size of the buffer area */ + int count; /* Count of characters in bufr */ + int head; /* index to head of list */ + int tail; /* index to tail of list */ + unsigned long locked; /* Buffer is being sent */ + int type; /* Type of the buffer */ + /* =0, device read buffer */ + /* =1, device write buffer */ + /* =2, daemon write buffer */ + /* =3, daemon read buffer */ + unsigned short fcs; /* Frame Check Sequence (CRC) */ + unsigned char filler[4]; /* Extra space if needed */ +}; + +/* Given a pointer to the ppp_buffer then return base address of buffer */ +#define buf_base(buf) ((u_char *) (&buf[1])) + +/* + * Structure describing each ppp unit. + */ + +struct ppp { + int magic; /* magic value for structure */ + + /* Bitmapped flag fields. */ + char inuse; /* are we allocated? */ + char escape; /* 0x20 if prev char was PPP_ESC*/ + char toss; /* toss this frame */ + + unsigned int flags; /* miscellany */ + + ext_accm xmit_async_map; /* 1 bit means that given control + character is quoted on output*/ + + __u32 recv_async_map; /* 1 bit means that given control + character is ignored on input*/ + int mtu; /* maximum xmit frame size */ + int mru; /* maximum receive frame size */ + + /* Information about the current tty data */ + int line; /* PPP channel number */ + struct tty_struct *tty; /* ptr to TTY structure */ + int bytes_sent; /* Bytes sent on frame */ + int bytes_rcvd; /* Bytes recvd on frame */ + + /* Interface to the network layer */ + struct device *dev; /* easy for intr handling */ + + /* VJ Header compression data */ + struct slcompress *slcomp;/* for header compression */ + + /* Transmission information */ + struct ppp_buffer *xbuf; /* Buffer currently being sent */ + struct ppp_buffer *s1buf; /* Pointer to daemon buffer */ + struct ppp_buffer *s2buf; /* Pointer to device buffer */ + + __u32 last_xmit; /* time of last transmission */ + + /* These are pointers to the malloc()ed frame buffers. + These buffers are used while processing a packet. If a packet + has to hang around for the user process to read it, it lingers in + the user buffers below. */ + + struct ppp_buffer *wbuf; /* Transmission information */ + struct ppp_buffer *tbuf; /* daemon transmission buffer */ + struct ppp_buffer *rbuf; /* Receive information */ + struct ppp_buffer *ubuf; /* User buffer information */ + struct ppp_buffer *cbuf; /* compression buffer */ + + /* Queues for select() functionality */ + struct wait_queue *write_wait; /* queue for reading processes */ + struct wait_queue *read_wait; /* queue for writing processes */ + + /* Statistic information */ + struct pppstat stats; /* statistic information */ + struct ppp_idle ddinfo; /* demand dial information */ + + /* PPP compression protocol information */ + u_int sc_bytessent; /* count of octets sent */ + u_int sc_bytesrcvd; /* count of octets received */ + enum NPmode sc_npmode[NUM_NP]; /* what to do with each NP */ + struct compressor *sc_xcomp; /* transmit compressor */ + void *sc_xc_state; /* transmit compressor state */ + struct compressor *sc_rcomp; /* receive decompressor */ + void *sc_rc_state; /* receive decompressor state */ +}; diff -u --recursive --new-file v1.3.32/linux/include/linux/ip_fw.h linux/include/linux/ip_fw.h --- v1.3.32/linux/include/linux/ip_fw.h Wed Sep 13 12:45:32 1995 +++ linux/include/linux/ip_fw.h Tue Oct 10 15:59:36 1995 @@ -140,10 +140,11 @@ struct timer_list timer; /* Expiration timer */ __u16 protocol; /* Which protocol are we talking? */ __u32 src, dst; /* Source and destination IP addresses */ - __u16 sport,dport; /* Source and destoination ports */ + __u16 sport,dport; /* Source and destination ports */ __u16 mport; /* Masquaraded port */ __u32 init_seq; /* Add delta from this seq. on */ short delta; /* Delta in sequence numbers */ + short previous_delta; /* Delta in sequence numbers before last resized PORT command */ char sawfin; /* Did we saw an FIN packet? */ }; extern struct ip_masq *ip_msq_hosts; @@ -186,6 +187,7 @@ #define PORT_MASQ_BEGIN 60000 #define PORT_MASQ_END (PORT_MASQ_BEGIN+4096) +#define FTP_DPORT_TBD (PORT_MASQ_END+1) /* Avoid using hardcoded port 20 for ftp data connection */ #endif #endif /* _IP_FW_H */ diff -u --recursive --new-file v1.3.32/linux/include/linux/keyboard.h linux/include/linux/keyboard.h --- v1.3.32/linux/include/linux/keyboard.h Fri Feb 24 21:38:27 1995 +++ linux/include/linux/keyboard.h Sun Oct 8 12:37:07 1995 @@ -38,6 +38,7 @@ #define KT_META 8 #define KT_ASCII 9 #define KT_LOCK 10 +#define KT_SLOCK 12 #define K(t,v) (((t)<<8)|(v)) #define KTYP(x) ((x) >> 8) @@ -406,6 +407,15 @@ #define K_SHIFTRLOCK K(KT_LOCK,KG_SHIFTR) #define K_CTRLLLOCK K(KT_LOCK,KG_CTRLL) #define K_CTRLRLOCK K(KT_LOCK,KG_CTRLR) + +#define K_SHIFT_SLOCK K(KT_SLOCK,KG_SHIFT) +#define K_CTRL_SLOCK K(KT_SLOCK,KG_CTRL) +#define K_ALT_SLOCK K(KT_SLOCK,KG_ALT) +#define K_ALTGR_SLOCK K(KT_SLOCK,KG_ALTGR) +#define K_SHIFTL_SLOCK K(KT_SLOCK,KG_SHIFTL) +#define K_SHIFTR_SLOCK K(KT_SLOCK,KG_SHIFTR) +#define K_CTRLL_SLOCK K(KT_SLOCK,KG_CTRLL) +#define K_CTRLR_SLOCK K(KT_SLOCK,KG_CTRLR) #define NR_LOCK 8 diff -u --recursive --new-file v1.3.32/linux/include/linux/lp.h linux/include/linux/lp.h --- v1.3.32/linux/include/linux/lp.h Sun Aug 13 14:45:35 1995 +++ linux/include/linux/lp.h Tue Oct 10 11:26:05 1995 @@ -161,6 +161,6 @@ * function prototypes */ -extern long lp_init(long); +extern int lp_init(void); #endif diff -u --recursive --new-file v1.3.32/linux/include/linux/module.h linux/include/linux/module.h --- v1.3.32/linux/include/linux/module.h Mon Sep 18 14:54:09 1995 +++ linux/include/linux/module.h Tue Oct 10 15:11:16 1995 @@ -95,8 +95,14 @@ int Using_Versions; /* gcc will handle this global (used as a flag) correctly */ #endif +#ifdef MODULE #define MOD_INC_USE_COUNT mod_use_count_++ #define MOD_DEC_USE_COUNT mod_use_count_-- #define MOD_IN_USE (mod_use_count_ != 0) +#else +#define MOD_INC_USE_COUNT do { } while (0) +#define MOD_DEC_USE_COUNT do { } while (0) +#define MOD_IN_USE 1 +#endif #endif diff -u --recursive --new-file v1.3.32/linux/include/linux/mouse.h linux/include/linux/mouse.h --- v1.3.32/linux/include/linux/mouse.h Fri Sep 15 11:13:02 1995 +++ linux/include/linux/mouse.h Tue Oct 10 14:59:19 1995 @@ -6,7 +6,7 @@ #define MS_BUSMOUSE_MINOR 2 #define ATIXL_BUSMOUSE_MINOR 3 -unsigned long mouse_init(unsigned long); +extern int mouse_init(void); struct mouse { int minor; diff -u --recursive --new-file v1.3.32/linux/include/linux/ppp-comp.h linux/include/linux/ppp-comp.h --- v1.3.32/linux/include/linux/ppp-comp.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/ppp-comp.h Mon Oct 9 09:17:54 1995 @@ -0,0 +1,192 @@ +/* + * ppp-comp.h - Definitions for doing PPP packet compression. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + * + * $Id: ppp-comp.h,v 1.7 1995/05/01 01:43:37 paulus Exp $ + */ + +/* + * ==FILEVERSION 3== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, increment the number above. + * ppp-comp.h is shipped with a PPP distribution as well as with the kernel; + * if everyone increases the FILEVERSION number above, then scripts + * can do the right thing when deciding whether to install a new ppp-comp.h + * file. Don't change the format of that line otherwise, so the + * installation script can recognize it. + */ + +#ifndef _NET_PPP_COMP_H +#define _NET_PPP_COMP_H + +/* + * The following symbols control whether we include code for + * various compression methods. + */ + +#ifndef DO_BSD_COMPRESS +#define DO_BSD_COMPRESS 1 /* by default, include BSD-Compress */ +#endif + +#define DO_PREDICTOR_1 0 +#define DO_PREDICTOR_2 0 +#define DO_DEFLATE 0 + +/* + * Structure giving methods for compression/decompression. + */ + +#ifdef PACKETPTR +struct compressor { + int compress_proto; /* CCP compression protocol number */ + + /* Allocate space for a compressor (transmit side) */ + void *(*comp_alloc) (unsigned char *options, int opt_len); + + /* Free space used by a compressor */ + void (*comp_free) (void *state); + + /* Initialize a compressor */ + int (*comp_init) (void *state, unsigned char *options, + int opt_len, int unit, int opthdr, int debug); + + /* Reset a compressor */ + void (*comp_reset) (void *state); + + /* Compress a packet */ + int (*compress) (void *state, unsigned char *rptr, + unsigned char *obuf, int isize, int osize); + + /* Return compression statistics */ + void (*comp_stat) (void *state, struct compstat *stats); + + /* Allocate space for a decompressor (receive side) */ + void *(*decomp_alloc) (unsigned char *options, int opt_len); + + /* Free space used by a decompressor */ + void (*decomp_free) (void *state); + + /* Initialize a decompressor */ + int (*decomp_init) (void *state, unsigned char *options, + int opt_len, int unit, int opthdr, int mru, + int debug); + + /* Reset a decompressor */ + void (*decomp_reset) (void *state); + + /* Decompress a packet. */ + int (*decompress) (void *state, unsigned char *ibuf, int isize, + unsigned char *obuf, int osize); + + /* Update state for an incompressible packet received */ + void (*incomp) (void *state, unsigned char *ibuf, int icnt); + + /* Return decompression statistics */ + void (*decomp_stat) (void *state, struct compstat *stats); +}; +#endif /* PACKETPTR */ + +/* + * Return values for decompress routine. + * We need to make these distinctions so that we can disable certain + * useful functionality, namely sending a CCP reset-request as a result + * of an error detected after decompression. This is to avoid infringing + * a patent held by Motorola. + * Don't you just lurve software patents. + */ + +#define DECOMP_OK 0 /* everything went OK */ +#define DECOMP_ERROR 1 /* error detected before decomp. */ +#define DECOMP_FATALERROR 2 /* error detected after decomp. */ + +/* + * CCP codes. + */ + +#define CCP_CONFREQ 1 +#define CCP_CONFACK 2 +#define CCP_TERMREQ 5 +#define CCP_TERMACK 6 +#define CCP_RESETREQ 14 +#define CCP_RESETACK 15 + +/* + * Max # bytes for a CCP option + */ + +#define CCP_MAX_OPTION_LENGTH 32 + +/* + * Parts of a CCP packet. + */ + +#define CCP_CODE(dp) ((dp)[0]) +#define CCP_ID(dp) ((dp)[1]) +#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3]) +#define CCP_HDRLEN 4 + +#define CCP_OPT_CODE(dp) ((dp)[0]) +#define CCP_OPT_LENGTH(dp) ((dp)[1]) +#define CCP_OPT_MINLEN 2 + +/* + * Definitions for BSD-Compress. + */ + +#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */ +#define CILEN_BSD_COMPRESS 3 /* length of config. option */ + +/* Macros for handling the 3rd byte of the BSD-Compress config option. */ +#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */ +#define BSD_VERSION(x) ((x) >> 5) /* version of option format */ +#define BSD_CURRENT_VERSION 1 /* current version number */ +#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n)) + +#define BSD_MIN_BITS 9 /* smallest code size supported */ +#define BSD_MAX_BITS 15 /* largest code size supported */ + +/* + * Definitions for other, as yet unsupported, compression methods. + */ + +#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */ +#define CILEN_PREDICTOR_1 2 /* length of its config option */ +#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */ +#define CILEN_PREDICTOR_2 2 /* length of its config option */ + +#define CI_DEFLATE 24 /* config option for Deflate */ +#define CILEN_DEFLATE 4 /* length of its config option */ + +#define DEFLATE_MIN_SIZE 8 +#define DEFLATE_MAX_SIZE 15 +#define DEFLATE_METHOD_VAL 8 +#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE) +#define DEFLATE_METHOD(x) ((x) & 0x0F) +#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \ + + DEFLATE_METHOD_VAL) +#define DEFLATE_CHK_SEQUENCE 0 + +#endif /* _NET_PPP_COMP_H */ diff -u --recursive --new-file v1.3.32/linux/include/linux/ppp_defs.h linux/include/linux/ppp_defs.h --- v1.3.32/linux/include/linux/ppp_defs.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/ppp_defs.h Mon Oct 9 09:17:54 1995 @@ -0,0 +1,175 @@ +/* $Id: ppp_defs.h,v 1.2 1994/09/21 01:31:06 paulus Exp $ */ + +/* + * ppp_defs.h - PPP definitions. + * + * Copyright (c) 1994 The Australian National University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. The Australian National University + * makes no representations about the suitability of this software for + * any purpose. + * + * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO + * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, + * OR MODIFICATIONS. + */ + +/* + * ==FILEVERSION 4== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, increment the number above. + * ppp_defs.h is shipped with a PPP distribution as well as with the kernel; + * if everyone increases the FILEVERSION number above, then scripts + * can do the right thing when deciding whether to install a new ppp_defs.h + * file. Don't change the format of that line otherwise, so the + * installation script can recognize it. + */ + +#ifndef _PPP_DEFS_H_ +#define _PPP_DEFS_H_ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ +#define PPP_MRU 1500 /* default MRU = max length of info field */ + +#define PPP_ADDRESS(p) (((u_char *)(p))[0]) +#define PPP_CONTROL(p) (((u_char *)(p))[1]) +#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#define PPP_COMP 0xfd /* compressed packet */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ + +/* + * A 32-bit unsigned integral type. + */ +#ifndef __BIT_TYPES_DEFINED__ +#ifdef UINT32_T +typedef UINT32_T u_int32_t; +#else +typedef unsigned int u_int32_t; +#endif +#endif + +/* + * Extended asyncmap - allows any character to be escaped. + */ +typedef u_int32_t ext_accm[8]; + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Statistics for LQRP and pppstats + */ +struct pppstat { + u_int ppp_discards; /* # frames discarded */ + + u_int ppp_ibytes; /* bytes received */ + u_int ppp_ioctects; /* bytes received not in error */ + u_int ppp_ipackets; /* packets received */ + u_int ppp_ierrors; /* receive errors */ + u_int ppp_ilqrs; /* # LQR frames received */ + + u_int ppp_obytes; /* raw bytes sent */ + u_int ppp_ooctects; /* frame bytes sent */ + u_int ppp_opackets; /* packets sent */ + u_int ppp_oerrors; /* transmit errors */ + u_int ppp_olqrs; /* # LQR frames sent */ +}; + +struct vjstat { + u_int vjs_packets; /* outbound packets */ + u_int vjs_compressed; /* outbound compressed packets */ + u_int vjs_searches; /* searches for connection state */ + u_int vjs_misses; /* times couldn't find conn. state */ + u_int vjs_uncompressedin; /* inbound uncompressed packets */ + u_int vjs_compressedin; /* inbound compressed packets */ + u_int vjs_errorin; /* inbound unknown type packets */ + u_int vjs_tossed; /* inbound packets tossed because of error */ +}; + +struct compstat { + u_int unc_bytes; /* total uncompressed bytes */ + u_int unc_packets; /* total uncompressed packets */ + u_int comp_bytes; /* compressed bytes */ + u_int comp_packets; /* compressed packets */ + u_int inc_bytes; /* incompressible bytes */ + u_int inc_packets; /* incompressible packets */ + /* the compression ratio is defined as in_count / bytes_out */ + u_int in_count; /* Bytes received */ + u_int bytes_out; /* Bytes transmitted */ + double ratio; /* not computed in kernel. */ +}; + +struct ppp_stats { + struct pppstat p; /* basic PPP statistics */ + struct vjstat vj; /* VJ header compression statistics */ +}; + +struct ppp_comp_stats { + struct compstat c; /* packet compression statistics */ + struct compstat d; /* packet decompression statistics */ +}; + +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + */ +struct ppp_idle { + time_t xmit_idle; /* time since last NP packet sent */ + time_t recv_idle; /* time since last NP packet received */ +}; + +#ifndef __P +#ifdef __STDC__ +#define __P(x) x +#else +#define __P(x) () +#endif +#endif + +#endif /* _PPP_DEFS_H_ */ diff -u --recursive --new-file v1.3.32/linux/include/linux/route.h linux/include/linux/route.h --- v1.3.32/linux/include/linux/route.h Wed Sep 13 12:45:32 1995 +++ linux/include/linux/route.h Tue Oct 10 15:45:27 1995 @@ -8,6 +8,8 @@ * Version: @(#)route.h 1.0.3 05/27/93 * * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 + * for the purposes of compatibility only. + * * Fred N. van Kempen, * * This program is free software; you can redistribute it and/or @@ -22,7 +24,8 @@ /* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */ -struct rtentry { +struct rtentry +{ unsigned long rt_hash; /* hash key for lookups */ struct sockaddr rt_dst; /* target address */ struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ @@ -50,4 +53,26 @@ #define RTF_IRTT 0x0100 /* Initial round trip time */ #define RTF_REJECT 0x0200 /* Reject route */ +/* + * This structure is passed from the kernel to user space by netlink + * routing/device announcements + */ + +struct netlink_rtinfo +{ + unsigned long rtmsg_type; + struct sockaddr rtmsg_dst; + struct sockaddr rtmsg_gateway; + struct sockaddr rtmsg_genmask; + short rtmsg_flags; + short rtmsg_metric; + char rtmsg_device[16]; +}; + +#define RTMSG_NEWROUTE 0x01 +#define RTMSG_DELROUTE 0x02 +#define RTMSG_NEWDEVICE 0x11 +#define RTMSG_DELDEVICE 0x12 + #endif /* _LINUX_ROUTE_H */ + diff -u --recursive --new-file v1.3.32/linux/include/linux/scc.h linux/include/linux/scc.h --- v1.3.32/linux/include/linux/scc.h Sun Sep 3 12:27:03 1995 +++ linux/include/linux/scc.h Tue Oct 10 11:26:32 1995 @@ -557,4 +557,4 @@ /* global functions */ -extern long scc_init(long kmem_start); +extern int scc_init(void); diff -u --recursive --new-file v1.3.32/linux/include/linux/sched.h linux/include/linux/sched.h --- v1.3.32/linux/include/linux/sched.h Fri Oct 6 14:35:16 1995 +++ linux/include/linux/sched.h Tue Oct 10 15:51:58 1995 @@ -33,6 +33,7 @@ #define CLONE_FS 0x00000200 /* set if fs info shared between processes */ #define CLONE_FILES 0x00000400 /* set if open files shared between processes */ #define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */ +#define CLONE_PID 0x00001000 /* set if pid shared */ /* * These are the constant used to fake the fixed-point load-average diff -u --recursive --new-file v1.3.32/linux/include/linux/tpqic02.h linux/include/linux/tpqic02.h --- v1.3.32/linux/include/linux/tpqic02.h Fri Oct 6 14:35:16 1995 +++ linux/include/linux/tpqic02.h Tue Oct 10 15:54:40 1995 @@ -657,7 +657,7 @@ }; -extern long qic02_tape_init(long); /* for mem.c */ +extern int qic02_tape_init(void); /* for mem.c */ #endif /* CONFIG_QIC02_TAPE */ diff -u --recursive --new-file v1.3.32/linux/include/linux/tty.h linux/include/linux/tty.h --- v1.3.32/linux/include/linux/tty.h Mon Sep 18 14:54:10 1995 +++ linux/include/linux/tty.h Tue Oct 10 11:59:27 1995 @@ -272,20 +272,21 @@ extern int fg_console; extern struct wait_queue * keypress_wait; -extern long rs_init(long); -extern long lp_init(long); -extern long con_init(long); -extern long pty_init(long); -extern long tty_init(long); -extern long vcs_init(long); +extern unsigned long con_init(unsigned long); + +extern int rs_init(void); +extern int lp_init(void); +extern int pty_init(void); +extern int tty_init(void); +extern int vcs_init(void); #ifdef CONFIG_CYCLADES -extern long cy_init(long); +extern int cy_init(void); #endif #ifdef CONFIG_STALLION -extern long stl_init(long); +extern int stl_init(void); #endif #ifdef CONFIG_ISTALLION -extern long stli_init(long); +extern int stli_init(void); #endif extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device, diff -u --recursive --new-file v1.3.32/linux/include/linux/user.h linux/include/linux/user.h --- v1.3.32/linux/include/linux/user.h Mon Sep 18 14:54:10 1995 +++ linux/include/linux/user.h Mon Oct 9 13:10:41 1995 @@ -1,78 +1 @@ -#ifndef _LINUX_USER_H -#define _LINUX_USER_H - -#include -#include -/* Core file format: The core file is written in such a way that gdb - can understand it and provide useful information to the user (under - linux we use the 'trad-core' bfd). There are quite a number of - obstacles to being able to view the contents of the floating point - registers, and until these are solved you will not be able to view the - contents of them. Actually, you can read in the core file and look at - the contents of the user struct to find out what the floating point - registers contain. - The actual file contents are as follows: - UPAGE: 1 page consisting of a user struct that tells gdb what is present - in the file. Directly after this is a copy of the task_struct, which - is currently not used by gdb, but it may come in useful at some point. - All of the registers are stored as part of the upage. The upage should - always be only one page. - DATA: The data area is stored. We use current->end_text to - current->brk to pick up all of the user variables, plus any memory - that may have been malloced. No attempt is made to determine if a page - is demand-zero or if a page is totally unused, we just cover the entire - range. All of the addresses are rounded in such a way that an integral - number of pages is written. - STACK: We need the stack information in order to get a meaningful - backtrace. We need to write the data from (esp) to - current->start_stack, so we round each of these off in order to be able - to write an integer number of pages. - The minimum core file size is 3 pages, or 12288 bytes. -*/ - -struct user_i387_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ -}; - -/* When the kernel dumps core, it starts by dumping the user struct - - this will be used by gdb to figure out where the data and stack segments - are within the file, and what virtual addresses to use. */ -struct user{ -/* We start with the registers, to mimic the way that "memory" is returned - from the ptrace(3,...) function. */ - struct pt_regs regs; /* Where the registers are actually stored */ -/* ptrace does not yet supply these. Someday.... */ - int u_fpvalid; /* True if math co-processor being used. */ - /* for this mess. Not yet used. */ - struct user_i387_struct i387; /* Math Co-processor registers. */ -/* The rest of this junk is to help gdb figure out what goes where */ - unsigned long int u_tsize; /* Text segment size (pages). */ - unsigned long int u_dsize; /* Data segment size (pages). */ - unsigned long int u_ssize; /* Stack segment size (pages). */ - unsigned long start_code; /* Starting virtual address of text. */ - unsigned long start_stack; /* Starting virtual address of stack area. - This is actually the bottom of the stack, - the top of the stack is always found in the - esp register. */ - long int signal; /* Signal that caused the core dump. */ - int reserved; /* No longer used */ - struct pt_regs * u_ar0; /* Used by gdb to help find the values for */ - /* the registers. */ - struct user_i387_struct* u_fpstate; /* Math Co-processor pointer. */ - unsigned long magic; /* To uniquely identify a core file */ - char u_comm[32]; /* User command that was responsible */ - int u_debugreg[8]; -}; -#define NBPG PAGE_SIZE -#define UPAGES 1 -#define HOST_TEXT_START_ADDR (u.start_code) -#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) - -#endif +#include diff -u --recursive --new-file v1.3.32/linux/include/net/netlink.h linux/include/net/netlink.h --- v1.3.32/linux/include/net/netlink.h Wed Oct 4 14:14:34 1995 +++ linux/include/net/netlink.h Tue Oct 10 15:45:27 1995 @@ -1,8 +1,11 @@ +#ifndef __NET_NETLINK_H +#define __NET_NETLINK_H #define NET_MAJOR 18 /* Major 18 is reserved for networking */ #define MAX_LINKS 3 /* 18,0 for route updates, 18,1 for SKIP */ #define MAX_QBYTES 32768 /* Maximum bytes in the queue */ extern int netlink_attach(int unit, int (*function)(struct sk_buff *skb)); +extern int netlink_donothing(struct sk_buff *skb); extern void netlink_detach(int unit); extern int netlink_post(int unit, struct sk_buff *skb); extern void init_netlink(void); @@ -10,4 +13,11 @@ #define NETLINK_ROUTE 0 /* Routing/device hook */ #define NETLINK_SKIP 1 /* Reserved for ENskip */ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ +#define NETLINK_FIREWALL 3 /* Firewalling hook */ +#ifdef CONFIG_RTNETLINK +extern void ip_netlink_msg(unsigned long, __u32, __u32, __u32, short, short, char *); +#else +#define ip_netlink_msg(a,b,c,d,e,f,g) +#endif +#endif diff -u --recursive --new-file v1.3.32/linux/init/main.c linux/init/main.c --- v1.3.32/linux/init/main.c Wed Oct 4 14:14:34 1995 +++ linux/init/main.c Tue Oct 10 14:27:57 1995 @@ -36,16 +36,14 @@ extern int console_loglevel; -extern void init(void); +static int init(void *); + extern void init_IRQ(void); extern void init_modules(void); extern long console_init(long, long); extern long kmalloc_init(long,long); -extern long blk_dev_init(long,long); -extern long chr_dev_init(long,long); extern void sock_init(void); extern long rd_init(long mem_start, int length); -unsigned long net_dev_init(unsigned long, unsigned long); extern long pci_init(long, long); extern void bmouse_setup(char *str, int *ints); @@ -96,14 +94,11 @@ #ifdef CONFIG_SJCD extern void sjcd_setup(char *str, int *ints); #endif CONFIG_SJCD -void ramdisk_setup(char *str, int *ints); +static void ramdisk_setup(char *str, int *ints); #ifdef CONFIG_SYSVIPC extern void ipc_init(void); #endif -#ifdef CONFIG_SCSI -extern unsigned long scsi_dev_init(unsigned long, unsigned long); -#endif /* * Boot command-line arguments @@ -255,7 +250,7 @@ { 0, 0 } }; -void ramdisk_setup(char *str, int *ints) +static void ramdisk_setup(char *str, int *ints) { if (ints[0] > 0 && ints[1] >= 0) ramdisk_size = ints[1]; @@ -419,8 +414,6 @@ extern void setup_arch(char **, unsigned long *, unsigned long *); -static char init_stack[PAGE_SIZE]; - #ifdef CONFIG_SMP /* * Activate a secondary processor. @@ -435,6 +428,12 @@ idle(); } +int smp_idle(void * unused) +{ + for (;;) + idle(); +} + /* * Called by CPU#0 to activate the rest. */ @@ -445,20 +444,12 @@ smp_boot_cpus(); /* - * Create the slave init tasks. At this point - * fork will create them all ask task 0 + * Create the slave init tasks as sharing pid 0. */ for(i=1;i0) while (pid != wait(&i)) /* nothing */; @@ -636,5 +621,5 @@ printf("\n\rchild %d died with code %04x\n\r",pid,i); sync(); } - _exit(0); + return -1; } diff -u --recursive --new-file v1.3.32/linux/kernel/fork.c linux/kernel/fork.c --- v1.3.32/linux/kernel/fork.c Wed Oct 4 14:14:34 1995 +++ linux/kernel/fork.c Tue Oct 10 09:04:35 1995 @@ -29,35 +29,27 @@ int nr_tasks=1; int nr_running=1; -long last_pid=0; static int find_empty_process(void) { int i; - int this_user_tasks; struct task_struct *p; if (nr_tasks >= NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) { if (current->uid) return -EAGAIN; } -repeat: - if(smp_threads_ready) { - if ((++last_pid) & 0xffff8000) - last_pid=1; - } - this_user_tasks = 0; - for_each_task (p) { - if (p->uid == current->uid) - this_user_tasks++; - if (smp_threads_ready && (p->pid == last_pid || - p->pgrp == last_pid || - p->session == last_pid)) - goto repeat; + if (current->uid) { + long max_tasks = current->rlim[RLIMIT_NPROC].rlim_cur; + + if (max_tasks < nr_tasks) { + for_each_task (p) { + if (p->uid == current->uid) + if (--max_tasks < 0) + return -EAGAIN; + } + } } - if (this_user_tasks > current->rlim[RLIMIT_NPROC].rlim_cur) - if (current->uid) - return -EAGAIN; for (i = 0 ; i < NR_TASKS ; i++) { if (!task[i]) return i; @@ -65,6 +57,25 @@ return -EAGAIN; } +static int get_pid(unsigned long flags) +{ + static int last_pid = 0; + struct task_struct *p; + + if (flags & CLONE_PID) + return current->pid; +repeat: + if ((++last_pid) & 0xffff8000) + last_pid=1; + for_each_task (p) { + if (p->pid == last_pid || + p->pgrp == last_pid || + p->session == last_pid) + goto repeat; + } + return last_pid; +} + static int dup_mmap(struct mm_struct * mm) { struct vm_area_struct * mpnt, **p, *tmp; @@ -214,7 +225,7 @@ *(unsigned long *) p->kernel_stack_page = STACK_MAGIC; p->state = TASK_UNINTERRUPTIBLE; p->flags &= ~(PF_PTRACED|PF_TRACESYS); - p->pid = last_pid; + p->pid = get_pid(clone_flags); p->next_run = NULL; p->prev_run = NULL; p->p_pptr = p->p_opptr = current; diff -u --recursive --new-file v1.3.32/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.3.32/linux/kernel/ksyms.c Wed Oct 4 14:14:34 1995 +++ linux/kernel/ksyms.c Sun Oct 8 12:38:34 1995 @@ -349,6 +349,7 @@ X(unregister_netdev), X(ether_setup), X(eth_type_trans), + X(eth_copy_and_sum), X(alloc_skb), X(kfree_skb), X(dev_alloc_skb), diff -u --recursive --new-file v1.3.32/linux/net/Changes linux/net/Changes --- v1.3.32/linux/net/Changes Wed Oct 4 14:14:35 1995 +++ linux/net/Changes Tue Oct 10 15:45:28 1995 @@ -242,6 +242,13 @@ o IFF_ALLMULTI support for 3c501,3c509,8390 and tulip(SMC etherpower) boards [IN] +-------->>>>> 1.3.33 <<<<<<-------- + +o IFF_ALLMULTI causes an address check on ether [IN] +o Added multicast ability readme file [IN] +o Assorted driver/multicast fixes [IN] +o IP routing change errors resemble BSD more [IN] +o IP port masquerading fixes [IN] ---------- Things I thought Linus had for a while and not merged ---------------- diff -u --recursive --new-file v1.3.32/linux/net/core/dev.c linux/net/core/dev.c --- v1.3.32/linux/net/core/dev.c Wed Sep 13 12:45:34 1995 +++ linux/net/core/dev.c Tue Oct 10 15:45:28 1995 @@ -231,12 +231,6 @@ /* * Initialise multicasting status */ -#ifdef CONFIG_IP_MULTICAST - /* - * Join the all host group - */ - ip_mc_allhost(dev); -#endif dev_mc_upload(dev); notifier_call_chain(&netdev_chain, NETDEV_UP, dev); } @@ -367,7 +361,7 @@ save_flags(flags); cli(); - if (/*dev_nit && */!where) /* Always keep order. It helps other hosts + if (!where) /* Always keep order. It helps other hosts far more than it costs us */ { skb_queue_tail(dev->buffs + pri,skb); @@ -1314,12 +1308,30 @@ * present) and leaves us with a valid list of present and active devices. * */ - -void dev_init(void) +extern int lance_init(void); +extern int pi_init(void); +extern int dec21040_init(void); + +int net_dev_init(void) { struct device *dev, **dp; /* + * This is VeryUgly(tm). + * + * Some devices want to be initialized eary.. + */ +#if defined(CONFIG_LANCE) + lance_init(); +#endif +#if defined(CONFIG_PI) + pi_init(); +#endif +#if defined(CONFIG_DEC_ELCP) + dec21040_init(); +#endif + + /* * Add the devices. * If the call to dev->init fails, the dev is removed * from the chain disconnecting the device until the @@ -1346,11 +1358,16 @@ dp = &dev->next; } } + proc_net_register(&(struct proc_dir_entry) { PROC_NET_DEV, 3, "dev", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_net_inode_operations, dev_get_info }); + + bh_base[NET_BH].routine = net_bh; + enable_bh(NET_BH); + return 0; } diff -u --recursive --new-file v1.3.32/linux/net/ethernet/eth.c linux/net/ethernet/eth.c --- v1.3.32/linux/net/ethernet/eth.c Tue Aug 15 20:39:11 1995 +++ linux/net/ethernet/eth.c Tue Oct 10 15:45:28 1995 @@ -27,6 +27,8 @@ * Greg Page : 802.2 and SNAP stuff. * Alan Cox : MAC layer pointers/new format. * Paul Gortmaker : eth_copy_and_sum shouldn't csum padding. + * Alan Cox : Protect against forwarding explosions with + * older network drivers and IFF_ALLMULTI * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -184,7 +186,12 @@ skb->pkt_type=PACKET_MULTICAST; } - else if(dev->flags&IFF_PROMISC) + /* + * This ALLMULTI check should be redundant by 1.4 + * so don't forget to remove it. + */ + + else if(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) { if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN)) skb->pkt_type=PACKET_OTHERHOST; diff -u --recursive --new-file v1.3.32/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- v1.3.32/linux/net/ipv4/af_inet.c Wed Sep 27 16:00:01 1995 +++ linux/net/ipv4/af_inet.c Tue Oct 10 15:45:28 1995 @@ -1615,6 +1615,7 @@ #if defined(CONFIG_IP_MROUTE) ip_mr_init(); #endif + /* * Create all the /proc entries. */ diff -u --recursive --new-file v1.3.32/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c --- v1.3.32/linux/net/ipv4/devinet.c Sun Sep 3 12:27:05 1995 +++ linux/net/ipv4/devinet.c Tue Oct 10 15:45:28 1995 @@ -107,14 +107,14 @@ for (dev = dev_base; dev != NULL; dev = dev->next) { - if (!(dev->flags & IFF_UP)) + if ((!(dev->flags & IFF_UP)) || dev->family!=AF_INET) continue; /* * If the protocol address of the device is 0 this is special * and means we are address hunting (eg bootp). */ - if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/) + if (dev->pa_addr == 0) return IS_MYADDR; /* * Is it the exact IP address? diff -u --recursive --new-file v1.3.32/linux/net/ipv4/ip.c linux/net/ipv4/ip.c --- v1.3.32/linux/net/ipv4/ip.c Fri Oct 6 14:35:16 1995 +++ linux/net/ipv4/ip.c Tue Oct 10 15:45:28 1995 @@ -151,6 +151,7 @@ #include #include #include +#include #define CONFIG_IP_DEFRAG @@ -1682,7 +1683,7 @@ * If this fragment needs masquerading, make it so... * (Dont masquerade de-masqueraded fragments) */ - if (!(is_frag&4) && fw_res==2) + if (!(is_frag&4) && fw_res==FW_MASQUERADE) ip_fw_masquerade(&skb, dev2); #endif IS_SKB(skb); @@ -3562,14 +3563,60 @@ NULL, }; +#ifdef CONFIG_RTNETLINK + +/* + * Netlink hooks for IP + */ + +void ip_netlink_msg(unsigned long msg, __u32 daddr, __u32 gw, __u32 mask, short flags, short metric, char *name) +{ + struct sk_buff *skb=alloc_skb(sizeof(struct netlink_rtinfo), GFP_ATOMIC); + struct netlink_rtinfo *nrt; + struct sockaddr_in *s; + if(skb==NULL) + return; + nrt=(struct netlink_rtinfo *)skb_put(skb, sizeof(struct netlink_rtinfo)); + nrt->rtmsg_type=msg; + s=(struct sockaddr_in *)&nrt->rtmsg_dst; + s->sin_family=AF_INET; + s->sin_addr.s_addr=daddr; + s=(struct sockaddr_in *)&nrt->rtmsg_gateway; + s->sin_family=AF_INET; + s->sin_addr.s_addr=gw; + s=(struct sockaddr_in *)&nrt->rtmsg_genmask; + s->sin_family=AF_INET; + s->sin_addr.s_addr=mask; + nrt->rtmsg_flags=flags; + nrt->rtmsg_metric=metric; + strcpy(nrt->rtmsg_device,name); + netlink_post(NETLINK_ROUTE, skb); +} + +#endif + /* * Device notifier */ static int ip_rt_event(unsigned long event, void *ptr) { + struct device *dev=ptr; if(event==NETDEV_DOWN) - ip_rt_flush(ptr); + { + ip_netlink_msg(RTMSG_DELDEVICE, 0,0,0,0,0,dev->name); + ip_rt_flush(dev); + } +/* + * Join the intial group if multicast. + */ + if(event==NETDEV_UP) + { +#ifdef CONFIG_IP_MULTICAST + ip_mc_allhost(dev); +#endif + ip_netlink_msg(RTMSG_NEWDEVICE, 0,0,0,0,0,dev->name); + } return NOTIFY_DONE; } diff -u --recursive --new-file v1.3.32/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c --- v1.3.32/linux/net/ipv4/ip_fw.c Wed Oct 4 14:14:35 1995 +++ linux/net/ipv4/ip_fw.c Tue Oct 10 15:45:28 1995 @@ -41,6 +41,7 @@ * Thomas Quinot : Fixed port spoofing. * Alan Cox : Cleaned up retransmits in spoofing. * Alan Cox : Cleaned up length setting. + * Wouter Gadeyne : Fixed masquerading support of ftp PORT commands * * All the real work was done by ..... * @@ -586,15 +587,33 @@ struct ip_masq *ms; char buf[24]; /* xxx.xxx.xxx.xxx,ppp,ppp\000 */ int diff; + __u32 seq; /* - * Adjust seq and ack_seq with delta-offset for - * the packets AFTER this one... + * Adjust seq with delta-offset for all packets after the most recent resized PORT command + * and with previous_delta offset for all packets before most recent resized PORT */ - if (ftp->delta && after(ftp->init_seq,th->seq)) + + /* + * seq & seq_ack are in network byte order; need conversion before comparing + */ + seq=ntohl(th->seq); + if (ftp->delta || ftp->previous_delta) { - th->seq += ftp->delta; -/* th->ack_seq += ftp->delta;*/ + if(after(seq,ftp->init_seq) ) + { + th->seq = htonl(seq + ftp->delta); +#ifdef DEBUG_MASQ + printk("masq_revamp : added delta (%d) to seq\n",ftp->delta); +#endif + } + else + { + th->seq = htonl(seq + ftp->previous_delta); +#ifdef DEBUG_MASQ + printk("masq_revamp : added previous_delta (%d) to seq\n",ftp->previous_delta); +#endif + } } while (skb->len - ((unsigned char *)data - skb->h.raw) > 18) @@ -626,8 +645,9 @@ from = (p1<<24) | (p2<<16) | (p3<<8) | p4; port = (p5<<8) | p6; +#ifdef MASQ_DEBUG printk("PORT %lX:%X detected\n",from,port); - +#endif /* * Now create an masquerade entry for it */ @@ -638,7 +658,12 @@ ms->src = htonl(from); /* derived from PORT cmd */ ms->sport = htons(port); /* derived from PORT cmd */ ms->dst = iph->daddr; - ms->dport = htons(20); /* ftp-data */ + /* + * Hardcoding 20 as dport is not always correct + * At least 1 Windows ftpd uses a random port number instead of 20 + * Leave it undefined for now & wait for the first connection request to fill it out + */ + ms->dport = htons(FTP_DPORT_TBD); /* ftp-data */ ms->timer.expires = jiffies+MASQUERADE_EXPIRE_TCP_FIN; add_timer(&ms->timer); @@ -666,7 +691,6 @@ /* * simple case, just replace the old PORT cmd */ - ftp->init_seq = 0; memcpy(p,buf,strlen(buf)); return skb; } @@ -681,24 +705,27 @@ * FIXME: use ftp->init_seq_valid - 0 is a valid sequence. */ - if(!ftp->init_seq || after(ftp->init_seq,th->seq)) + if(!ftp->init_seq || after(seq,ftp->init_seq) ) + { + ftp->previous_delta=ftp->delta; ftp->delta+=diff; + ftp->init_seq = seq; + } + /* * Sizes differ, make a copy */ - printk("MASQUERADE: resizing needed for %d bytes (%ld)\n",ftp->delta, skb->len); - if (!ftp->init_seq) - ftp->init_seq = th->seq; - - skb2 = alloc_skb(MAX_HEADER + skb->len+ftp->delta, GFP_ATOMIC); +#ifdef DEBUG_MASQ + printk("MASQUERADE: resizing needed for %d bytes (%ld)\n",diff, skb->len); +#endif + skb2 = alloc_skb(MAX_HEADER + skb->len+diff, GFP_ATOMIC); if (skb2 == NULL) { printk("MASQUERADE: No memory available\n"); return skb; } skb2->free = skb->free; skb_reserve(skb2,MAX_HEADER); - skb_put(skb2,skb->len + ftp->delta); -/* skb2->h.raw = &skb2->data[skb->h.raw - skb->data];*/ + skb_put(skb2,skb->len + diff); skb2->h.raw = skb2->data + (skb->h.raw - skb->data); iph=skb2->h.iph; /* @@ -718,6 +745,12 @@ skb->len - (data-(char *)skb->data)); /* + * Update tot_len field in ip header ! + * Sequence numbers were allready modified in original packet + */ + iph->tot_len = htons(skb->len + diff); + + /* * Problem, how to replace the new skb with old one, * preferably inplace, so all the pointers in the * calling tree keep ok :( @@ -877,6 +910,7 @@ ntohl(iph->saddr), ntohs(portptr[0]), ntohl(iph->daddr), ntohs(portptr[1])); #endif + /* * reroute to original host:port if found... * @@ -891,13 +925,22 @@ { if (iph->protocol==ms->protocol && (iph->saddr==ms->dst || iph->protocol==IPPROTO_UDP) && - portptr[0]==ms->dport && + (ms->dport==htons(FTP_DPORT_TBD) || portptr[0]==ms->dport) && portptr[1]==ms->mport) { + int size = skb_ptr->len - ((unsigned char *)portptr - skb_ptr->h.raw); iph->daddr = ms->src; portptr[1] = ms->sport; + if(ms->dport==htons(FTP_DPORT_TBD)) + { + ms->dport=portptr[0]; +#ifdef DEBUG_MASQ + printk("demasq : Filled out dport entry (%d) based on initial connect attempt from FTP deamon\n",ntohs(ms->dport)); +#endif + } + /* * Yug! adjust UDP/TCP and IP checksums */ @@ -905,14 +948,32 @@ recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size); else { + __u32 ack_seq; /* - * Adjust seq and ack_seq with delta-offset for - * the packets AFTER this one... + * Adjust ack_seq with delta-offset for + * the packets AFTER most recent PORT command has caused a shift + * for packets before most recent PORT command, use previous_delta */ - if (ms->delta && after(ms->init_seq,th->ack_seq)) +#ifdef DEBUG_MASQ + printk("demasq : delta=%d ; previous_delta=%d ; init_seq=%lX ; ack_seq=%lX ; after=%d\n",ms->delta,ms->previous_delta,ntohl(ms->init_seq),ntohl(th->ack_seq),after(ntohl(th->ack_seq),ntohl(ms->init_seq))); +#endif + ack_seq=ntohl(th->ack_seq); + if (ms->delta || ms->previous_delta) { -/* th->seq += ms->delta;*/ - th->ack_seq -= ms->delta; + if(after(ack_seq,ms->init_seq)) + { + th->ack_seq = htonl(ack_seq-ms->delta); +#ifdef DEBUG_MASQ + printk("demasq : substracted delta (%d) from ack_seq\n",ms->delta); +#endif + } + else + { + th->ack_seq = htonl(ack_seq-ms->previous_delta); +#ifdef DEBUG_MASQ + printk("demasq : substracted previous_delta (%d) from ack_seq\n",ms->previous_delta); +#endif + } } tcp_send_check((struct tcphdr *)portptr,iph->saddr,iph->daddr,size,skb_ptr->sk); } @@ -1568,7 +1629,7 @@ unsigned long flags; int len=0; - len=sprintf(buffer,"Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta Expires\n"); + len=sprintf(buffer,"Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta PDelta Expires\n"); save_flags(flags); cli(); @@ -1578,12 +1639,12 @@ int timer_active = del_timer(&ms->timer); if (!timer_active) ms->timer.expires = jiffies; - len+=sprintf(buffer+len,"%s %08lX:%04X %08lX:%04X %04X %08X %5d %lu\n", + len+=sprintf(buffer+len,"%s %08lX:%04X %08lX:%04X %04X %08X %5d %5d %lu\n", strProt[ms->protocol==IPPROTO_TCP], ntohl(ms->src),ntohs(ms->sport), ntohl(ms->dst),ntohs(ms->dport), ntohs(ms->mport), - ms->init_seq,ms->delta,ms->timer.expires-jiffies); + ms->init_seq,ms->delta,ms->previous_delta,ms->timer.expires-jiffies); if (timer_active) add_timer(&ms->timer); diff -u --recursive --new-file v1.3.32/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c --- v1.3.32/linux/net/ipv4/ipmr.c Wed Oct 4 14:14:35 1995 +++ linux/net/ipv4/ipmr.c Tue Oct 10 15:45:28 1995 @@ -18,10 +18,9 @@ * Cache manager under test. Forwarding in vague test mode * Todo: * Flow control - * Tunnels - * Wipe cache on mrouted exit + * Finish Tunnels * Debug cache ttl handling properly - * Resolve IFF_ALLMULTI for most cards + * Resolve IFF_ALLMULTI for rest of cards */ #include @@ -895,7 +894,7 @@ void ip_mr_init(void) { - printk("Linux IP multicast router 0.02pre-working 8)\n"); + printk("Linux IP multicast router 0.04-might-work 8)\n"); register_netdevice_notifier(&ip_mr_notifier); proc_net_register(&(struct proc_dir_entry) { PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif", diff -u --recursive --new-file v1.3.32/linux/net/ipv4/route.c linux/net/ipv4/route.c --- v1.3.32/linux/net/ipv4/route.c Wed Sep 13 12:45:35 1995 +++ linux/net/ipv4/route.c Tue Oct 10 15:45:28 1995 @@ -32,6 +32,9 @@ * Miquel van Smoorenburg : BSD API fixes. * Miquel van Smoorenburg : Metrics. * Alan Cox : Use __u32 properly + * Alan Cox : Aligned routing errors more closely with BSD + * our system is still very different. + * Alan Cox : Faster /proc handling * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -59,6 +62,7 @@ #include #include #include +#include /* * The routing table list @@ -75,14 +79,14 @@ /* * Remove a routing table entry. - * Should we return a status value here ? */ -static void rt_del(__u32 dst, __u32 mask, +static int rt_del(__u32 dst, __u32 mask, char *devname, __u32 gtw, short rt_flags, short metric) { struct rtable *r, **rp; unsigned long flags; + int found=0; rp = &rt_base; @@ -117,11 +121,17 @@ if (rt_loopback == r) rt_loopback = NULL; + ip_netlink_msg(RTMSG_DELROUTE, dst, gtw, mask, rt_flags, metric, r->rt_dev->name); kfree_s(r, sizeof(struct rtable)); + found=1; } rt_stamp++; /* New table revision */ restore_flags(flags); + + if(found) + return 0; + return -ESRCH; } @@ -342,6 +352,7 @@ *rp = r->rt_next; if (rt_loopback == r) rt_loopback = NULL; + ip_netlink_msg(RTMSG_DELROUTE, dst,gw, mask, flags, metric, rt->rt_dev->name); kfree_s(r, sizeof(struct rtable)); } @@ -384,8 +395,9 @@ /* * Restore the interrupts and return */ - + restore_flags(cpuflags); + ip_netlink_msg(RTMSG_NEWROUTE, dst,gw, mask, flags, metric, rt->rt_dev->name); return; } @@ -429,7 +441,7 @@ dev = dev_get(devname); putname(devname); if (!dev) - return -EINVAL; + return -ENODEV; } /* @@ -541,16 +553,23 @@ * metric can become negative here if it wasn't filled in * but that's a fortunate accident; we really use that in rt_del. */ - rt_del((__u32)trg->sin_addr.s_addr, (__u32)msk->sin_addr.s_addr, devname, + err=rt_del((__u32)trg->sin_addr.s_addr, (__u32)msk->sin_addr.s_addr, devname, (__u32)gtw->sin_addr.s_addr, r->rt_flags, r->rt_metric - 1); if ( devname != NULL ) putname(devname); - return 0; + return err; } /* * Called from the PROCfs module. This outputs /proc/net/route. + * + * We preserve the old format but pad the buffers out. This means that + * we can spin over the other entries as we read them. Remember the + * gated BGP4 code could need to read 60,000+ routes on occasion (thats + * about 7Mb of data). To do that ok we will need to also cache the + * last route we got to (reads will generally be following on from + * one another without gaps). */ int rt_get_info(char *buffer, char **start, off_t offset, int length, int dummy) @@ -559,24 +578,32 @@ int len=0; off_t pos=0; off_t begin=0; - int size; + char temp[129]; - len += sprintf(buffer, - "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT\n"); - pos=len; - - /* - * This isn't quite right -- r->rt_dst is a struct! - */ - + if(offset<128) + { + sprintf(buffer,"%-127s\n","Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT"); + pos=128; + } + for (r = rt_base; r != NULL; r = r->rt_next) { - size = sprintf(buffer+len, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\t%d\t%lu\t%u\n", + /* + * Spin through entries until we are ready + */ + if(pos+128rt_dev->name, (unsigned long)r->rt_dst, (unsigned long)r->rt_gateway, r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric, (unsigned long)r->rt_mask, (int)r->rt_mss, r->rt_window, (int)r->rt_irtt); - len+=size; - pos+=size; + sprintf(buffer+len,"%-127s\n",temp); + len+=128; + pos+=128; if(poslen>MAX_QBYTES) - ret=-EWOULDBLOCK; - else + int ret=0; + if(open_map&(1<len; - ret=0; - wake_up_interruptible(&read_space_wait[MAX_LINKS]); + save_flags(flags); + cli(); + if(rdq_size[unit]+skb->len>MAX_QBYTES) + ret=-EWOULDBLOCK; + else + { + skb_queue_tail(&skb_queue_rd[unit], skb); + rdq_size[unit]+=skb->len; + ret=0; + wake_up_interruptible(&read_space_wait[unit]); + } + restore_flags(flags); } - restore_flags(flags); return ret; } @@ -213,7 +227,7 @@ int init_module(void) { int ct; - printk("Network Kernel/User communications module 0.01 ALPHA\n"); + printk("Network Kernel/User communications module 0.03\n"); if (register_chrdev(NET_MAJOR,"netlink",&netlink_fops)) { printk("netlink: unable to get major %d\n", NET_MAJOR); return -EIO; diff -u --recursive --new-file v1.3.32/linux/net/socket.c linux/net/socket.c --- v1.3.32/linux/net/socket.c Wed Oct 4 14:14:35 1995 +++ linux/net/socket.c Tue Oct 10 15:45:28 1995 @@ -1302,27 +1302,19 @@ #ifdef CONFIG_NETLINK init_netlink(); #endif - /* - * Initialize the protocols module. + * Attach the routing/device information port. */ - proto_init(); +#if defined(CONFIG_RTNETLINK) + netlink_attach(NETLINK_ROUTE, netlink_donothing); +#endif -#ifdef CONFIG_NET - /* - * Initialize the DEV module. - */ - - dev_init(); - /* - * And the bottom half handler + * Initialize the protocols module. */ - bh_base[NET_BH].routine= net_bh; - enable_bh(NET_BH); -#endif + proto_init(); } int socket_get_info(char *buffer, char **start, off_t offset, int length)