diff -u --recursive --new-file v1.1.78/linux/MAGIC linux/MAGIC --- v1.1.78/linux/MAGIC Tue Aug 9 09:32:59 1994 +++ linux/MAGIC Tue Jan 10 10:07:09 1995 @@ -25,6 +25,14 @@ structures following the array have been overwritten. Using this discipline, these cases get detected quickly and safely. +You should also register the magic number used by ioctls in the table +below. This allows ioctls on inappropriate devices to fail, rather than +doing something completely unexpected. The magic number is the first +argument to the _IO family of macros (see include/linux/ioctl.h) or +in general bits 8..15 of the ioctl number. Where ioctls are done on +devices with a major device number, it is recommended that you use the +major device number as the ioctl magic value (e.g. hd, lp). + Theodore Ts'o 31-Mar-94 @@ -39,4 +47,27 @@ SERIAL_MAGIC 0x5301 struct async_struct include/linux/serial.h SLIP_MAGIC 0x5302 struct slip drivers/net/slip.h +Ioctl Include File Comments +======================================================== +0x00 fd.h +0x03 hdreg.h +0x06 lp.h +0x12 fs.h +'C' soundcard.h +'K' kd.h +'M' soundcard.h +'P' soundcard.h +'Q' soundcard.h +'S' cdrom.h +'S' fs.h subcodes from 0x80, no conflict +'T' soundcard.h conflicts with termios.h +'T' termios.h conflicts with soundcard.h +'T' ppp.h subcodes from 0x90, no conflict +'V' vt.h +'f' ext2_fs.h +'m' mtio.h conflicts with soundcard.h +'m' soundcard.h conflicts with mtio.h +'s' pcsp.h +'v' ext2_fs.h +0x89 sockios.h diff -u --recursive --new-file v1.1.78/linux/Makefile linux/Makefile --- v1.1.78/linux/Makefile Mon Jan 9 11:24:19 1995 +++ linux/Makefile Tue Jan 10 10:09:58 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 78 +SUBLEVEL = 79 ARCH = i386 diff -u --recursive --new-file v1.1.78/linux/README linux/README --- v1.1.78/linux/README Thu Nov 3 17:08:53 1994 +++ linux/README Tue Jan 10 17:02:11 1995 @@ -179,12 +179,11 @@ see which kernel function contains the offending address. To find out the kernel function name, you'll need to find the system - binary associated with the kernel that exhibited the symptom. In the - case of compressed kernels, this will be 'linux/tools/zSystem', while - uncompressed kernels use the file 'tools/system'. To extract the - namelist and match it against the EIP from the kernel crash, do: + binary associated with the kernel that exhibited the symptom. This is + the file 'linux/vmlinux'. To extract the namelist and match it against + the EIP from the kernel crash, do: - nm tools/zSystem | sort | less + nm vmlinux | sort | less This will give you a list of kernel addresses sorted in ascending order, from which it is simple to find the function that contains the @@ -208,10 +207,10 @@ kernel with -g; edit arch/i386/Makefile appropriately, then do a "make clean". You'll also need to enable CONFIG_PROC_FS (via "make config"). - After you've rebooted with the new kernel, do "gdb tools/zSystem - /proc/kcore". You can now use all the usual gdb commands. The command to - look up the point where your system crashed is "l *0xXXXXXXXX". (Replace - the XXXes with the EIP value.) + After you've rebooted with the new kernel, do "gdb vmlinux /proc/kcore". + You can now use all the usual gdb commands. The command to look up the + point where your system crashed is "l *0xXXXXXXXX". (Replace the XXXes + with the EIP value.) gdb'ing a non-running kernel currently fails because gdb (wrongly) disregards the starting offset for which the kernel is compiled. diff -u --recursive --new-file v1.1.78/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v1.1.78/linux/arch/alpha/config.in Mon Jan 9 11:24:19 1995 +++ linux/arch/alpha/config.in Wed Jan 11 07:55:49 1995 @@ -9,7 +9,7 @@ bool 'Normal harddisk support' CONFIG_BLK_DEV_HD n bool 'XT harddisk support' CONFIG_BLK_DEV_XD n bool 'Networking support' CONFIG_NET y -bool 'System V IPC' CONFIG_SYSVIPC y +bool 'System V IPC' CONFIG_SYSVIPC n bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y if [ "$CONFIG_NET" = "y" ]; then diff -u --recursive --new-file v1.1.78/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile --- v1.1.78/linux/arch/alpha/lib/Makefile Mon Jan 9 11:24:19 1995 +++ linux/arch/alpha/lib/Makefile Wed Jan 11 07:55:49 1995 @@ -28,7 +28,6 @@ $(CC) -DREM -DINTSIZE -c -o __remlu.o divide.S dep: - $(CPP) -M *.c > .depend # # include a dependency file if one exists diff -u --recursive --new-file v1.1.78/linux/arch/alpha/lib/divide.S linux/arch/alpha/lib/divide.S --- v1.1.78/linux/arch/alpha/lib/divide.S Mon Jan 9 11:24:19 1995 +++ linux/arch/alpha/lib/divide.S Wed Jan 11 11:41:04 1995 @@ -19,27 +19,39 @@ * These are not normal C functions: instead of the normal * calling sequence, these expect their arguments in registers * $24 and $25, and return the result in $27. Register $28 may - * be clobbered (assembly temprary), anything else must be saved. + * be clobbered (assembly temporary), anything else must be saved. * - * In short: painful. I'm not going to try to be clever about it: - * let somebody else optimize it if they will. + * In short: painful. + * + * This is a rather simple bit-at-a-time algorithm: it's very good + * at dividing random 64-bit numbers, but the more usual case where + * the divisor is small is handled better by the DEC algorithm + * using lookup tables. This uses much less memory, though, and is + * nicer on the cache.. Besides, I don't know the copyright status + * of the DEC code. */ /* * My temporaries: * $0 - current bit * $1 - shifted divisor - * $2 - rest - * $3 - compare status + * $2 - modulus/quotient * * $23 - return address * $24 - dividend * $25 - divisor + * + * $27 - quotient/modulus + * $28 - compare status */ /* * Select function type and registers */ +#define mask $0 +#define divisor $1 +#define compare $28 + #ifdef DIV #define func(x) __div##x #define modulus $2 @@ -61,38 +73,44 @@ #define LONGIFY(x) #endif +.set noat .globl function .ent function function: - lda $30,-32($30) + subq $30,32,$30 stq $0, 0($30) stq $1, 8($30) stq $2,16($30) - stq $3,24($30) - bis $25,$25,$1 + + bis $25,$25,divisor bis $24,$24,modulus bis $31,$31,quotient - LONGIFY($1) + LONGIFY(divisor) LONGIFY(modulus) - beq $1, 9f /* div by zero */ - bis $31,1,$0 - blt $1, 2f /* high bit set */ -1: cmpult modulus,$1,$3 - bne $3,3f - addq $1,$1,$1 - addq $0,$0,$0 - bge $1,1b -2: cmpult modulus,$1,$3 - bne $3,3f - subq modulus,$1,modulus - addq $0,quotient,quotient -3: srl $0,1,$0 - srl $1,1,$1 - bne $0,2b + beq divisor, 9f /* div by zero */ + bis $31,1,mask + + /* shift divisor left */ +1: cmpult divisor,modulus,compare + blt divisor, 3f + addq divisor,divisor,divisor + addq mask,mask,mask + bne compare,1b + + /* ok, start to go right again.. */ +2: srl divisor,1,divisor + beq mask,9f + srl mask,1,mask +3: cmpule divisor,modulus,compare + beq compare,2b + addq quotient,mask,quotient + beq mask,9f + subq modulus,divisor,modulus + br 2b + 9: ldq $0, 0($30) ldq $1, 8($30) ldq $2, 16($30) - ldq $3, 32($30) - lda $30,32($30) + addq $30,32,$30 ret $31,($23),1 .end function diff -u --recursive --new-file v1.1.78/linux/arch/i386/config.in linux/arch/i386/config.in --- v1.1.78/linux/arch/i386/config.in Mon Jan 9 07:21:56 1995 +++ linux/arch/i386/config.in Tue Jan 10 10:07:09 1995 @@ -104,7 +104,7 @@ bool 'Dummy net driver support' CONFIG_DUMMY n bool 'SLIP (serial line) support' CONFIG_SLIP n if [ "$CONFIG_SLIP" = "y" ]; then - bool ' CSLIP compressed headers' SL_COMPRESSED y + bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y bool ' 16 channels instead of 4' SL_SLIP_LOTS n # bool ' SLIP debugging on' SL_DUMP y fi diff -u --recursive --new-file v1.1.78/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c --- v1.1.78/linux/arch/i386/kernel/bios32.c Mon Jan 9 11:24:20 1995 +++ linux/arch/i386/kernel/bios32.c Wed Jan 11 08:27:16 1995 @@ -36,9 +36,14 @@ * CHANGELOG : * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION * Revision 2.0 present on 's ASUS mainboard. + * + * Jan 10, 1995 : Modified to store the information about configured pci + * devices into a list, which can be accessed via /proc/pci by + * Curtis Varner, cvarner@cs.ucr.edu */ #include +#include #include #include #include @@ -57,6 +62,10 @@ #define PCIBIOS_WRITE_CONFIG_WORD 0xb10c #define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d +#ifdef CONFIG_PCI +extern void add_pci_resource(unsigned char, unsigned char); +#endif + /* BIOS32 signature: "_32_" */ #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) @@ -76,6 +85,15 @@ * and the PCI BIOS specification. */ +#ifdef CONFIG_PCI +typedef struct pci_resource_t +{ + unsigned char bus; + unsigned char dev_fn; + struct pci_resource_t *next; +} pci_resource_t; +#endif + union bios32 { struct { unsigned long signature; /* _32_ */ @@ -106,6 +124,12 @@ * Returns the entry point for the given service, NULL on error */ +#define PCI_LIST_SIZE 32 + +static pci_resource_t pci_list = { 0, 0, NULL }; +static int pci_index = 0; +static pci_resource_t pci_table[PCI_LIST_SIZE]; + static unsigned long bios32_service(unsigned long service) { unsigned char return_code; /* %al */ @@ -424,7 +448,7 @@ /* Returns Interrupt register */ -int interrupt_decod(unsigned char bus,unsigned char dev_fn) +int interrupt_decode(unsigned char bus,unsigned char dev_fn) { unsigned char interrupt; pcibios_read_config_byte( @@ -467,31 +491,26 @@ pcibios_read_config_dword( bus, dev_fn, (unsigned char) PCI_CLASS_REVISION, &class); class=class >> 16; - for (i=0;i> 3), - (int) (dev_fn & 7)); - info(bus,dev_fn); + add_pci_resource( bus, dev_fn); } } } +void probe_pci(void) +{ + if (pcibios_present()==0) { + printk("ProbePci PCI bios not detected.\n"); + return; + } + printk( "Probing PCI hardware.\n"); + probe_devices(0); +} + + +/* + * Function to add a resource to the pci list... + */ +void add_pci_resource(unsigned char bus, unsigned char dev_fn) +{ + pci_resource_t* new_pci; + pci_resource_t* temp; + /* + * Request and verify allocation of kernel RAM + */ + if(pci_index > 31) + { + printk("PCI resource list full.\n"); + return; + } + new_pci = &pci_table[pci_index]; + pci_index++; + /* + * Enter the new node into the list.... + * + */ + if(pci_list.next != NULL) + { + for(temp = pci_list.next; (temp->next); temp = temp->next) + /* nothing */; -void probe_pci(void) + temp->next = new_pci; + } + else + pci_list.next = new_pci; + + /* + * Set the information for the node + */ + new_pci->next = NULL; + new_pci->bus = bus; + new_pci->dev_fn = dev_fn; + + return; +} + + +int get_pci_list(char* buf) { - if (pcibios_present()==0) printk("ProbePci PCI bios not detected.\n"); - else { - printk( "Probing PCI hardware.\n"); - probe_devices(0); + int pr, length; + pci_resource_t* temp = pci_list.next; + struct pci_class_type pci_class[PCI_CLASS_NUM+1] = PCI_CLASS_TYPE; + struct pci_vendor_type pci_vendor[PCI_VENDOR_NUM+1] = PCI_VENDOR_TYPE; + struct pci_device_type pci_device[PCI_DEVICE_NUM+1] = PCI_DEVICE_TYPE; + + for (length = 0 ; (temp) && (length<4000); temp = temp->next) + { + pr=vendor_decode(temp->bus,temp->dev_fn); + + length += sprintf(buf+length, "Bus %2d Device %3d Function %2d.\n", + (int)temp->bus, + (int)((temp->dev_fn & 0xf8) >> 3), + (int) (temp->dev_fn & 7)); + + length += sprintf(buf+length, " %s : %s %s (rev %d). ", + pci_class[class_decode(temp->bus, temp->dev_fn)].class_name, + pci_vendor[pr].vendor_name, + pci_device[device_decode(temp->bus, temp->dev_fn, pci_vendor[pr].vendor_id)].device_name, + revision_decode(temp->bus, temp->dev_fn)); + + if (bist_probe(temp->bus, temp->dev_fn)) + length += sprintf(buf+length, "BIST capable. "); + + if ((pr = interrupt_decode(temp->bus, temp->dev_fn)) != 0) + length += sprintf(buf+length, "8259's interrupt %d.", pr); + + length += sprintf(buf+length, "\n"); } + + if (temp) + length += sprintf(buf+length, "4K limit reached!\n"); + + return length; } + #endif unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) @@ -638,3 +711,6 @@ #endif return memory_start; } + + + diff -u --recursive --new-file v1.1.78/linux/arch/i386/kernel/ioport.c linux/arch/i386/kernel/ioport.c --- v1.1.78/linux/arch/i386/kernel/ioport.c Mon Jan 9 11:24:20 1995 +++ linux/arch/i386/kernel/ioport.c Wed Jan 11 07:55:49 1995 @@ -12,7 +12,6 @@ #include #define IOTABLE_SIZE 32 -#define STR(x) #x typedef struct resource_entry_t { u_long from, num; @@ -202,7 +201,7 @@ } /* - * This is for compatibilty with older drivers. + * This is for compatibility with older drivers. * It can be removed when all driver call the new function. */ void snarf_region(unsigned int from, unsigned int num) diff -u --recursive --new-file v1.1.78/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v1.1.78/linux/arch/i386/kernel/traps.c Mon Jan 9 07:21:56 1995 +++ linux/arch/i386/kernel/traps.c Wed Jan 11 08:11:02 1995 @@ -82,11 +82,23 @@ asmlinkage void reserved(void); asmlinkage void alignment_check(void); +int kstack_depth_to_print = 24; + +/* + * These constants are for searching for possible module text + * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is + * a guess of how much space is likely to be vmalloced. + */ +#define VMALLOC_OFFSET (8*1024*1024) +#define MODULE_RANGE (8*1024*1024) + /*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err) { int i; unsigned long esp; unsigned short ss; + unsigned long *stack, addr, module_start, module_end; + extern char start_kernel, etext; esp = (unsigned long) ®s->esp; ss = KERNEL_DS; @@ -110,8 +122,38 @@ printk("Corrupted stack page\n"); printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ", current->comm, current->pid, 0xffff & i, current->kernel_stack_page); - for(i=0;i<5;i++) - printk("%08lx ", get_seg_long(ss,(i+(unsigned long *)esp))); + stack = (unsigned long *) esp; + for(i=0; i < kstack_depth_to_print; i++) { + if (((long) stack & 4095) == 0) + break; + if (i && ((i % 8) == 0)) + printk("\n "); + printk("%08lx ", get_seg_long(ss,stack++)); + } + printk("\nCall Trace: "); + stack = (unsigned long *) esp; + i = 1; + module_start = ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)); + module_end = module_start + MODULE_RANGE; + while (((long) stack & 4095) != 0) { + addr = get_seg_long(ss, stack++); + /* + * If the address is either in the text segment of the + * kernel, or in the region which contains vmalloc'ed + * memory, it *may* be the address of a calling + * routine; if so, print it so that someone tracing + * down the cause of the crash will be able to figure + * out the call path that was taken. + */ + if (((addr >= (unsigned long) &start_kernel) && + (addr <= (unsigned long) &etext)) || + ((addr >= module_start) && (addr <= module_end))) { + if (i && ((i % 8) == 0)) + printk("\n "); + printk("%08lx ", addr); + i++; + } + } printk("\nCode: "); for(i=0;i<20;i++) printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip))); diff -u --recursive --new-file v1.1.78/linux/arch/sparc/Makefile linux/arch/sparc/Makefile --- v1.1.78/linux/arch/sparc/Makefile Mon Jan 9 07:21:58 1995 +++ linux/arch/sparc/Makefile Wed Jan 11 09:01:16 1995 @@ -1,7 +1,7 @@ # # sparc/Makefile # -# Makefile for the architecture dependant flags and dependancies on the +# Makefile for the architecture dependent flags and dependencies on the # Sparc. # # Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) @@ -19,8 +19,8 @@ HEAD := arch/sparc/kernel/head.o -SUBDIRS := $(SUBDIRS) arch/sparc/kernel -ARCHIVES := arch/sparc/kernel/kernel.o $(ARCHIVES) +SUBDIRS := $(SUBDIRS) arch/sparc/kernel arch/sparc/lib +ARCHIVES := arch/sparc/kernel/kernel.o arch/sparc/lib/lib.a $(ARCHIVES) archclean: diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S --- v1.1.78/linux/arch/sparc/kernel/entry.S Mon Jan 9 11:24:20 1995 +++ linux/arch/sparc/kernel/entry.S Wed Jan 11 09:01:41 1995 @@ -9,6 +9,7 @@ */ #include +#include /* Here are macros for routines we do often, this allows me to inline this * without making the code look real ugly. Well, the macro looks ugly too but @@ -223,9 +224,9 @@ TRAP_WIN_CLEAN nop - or %%g0, %l3, %o0 + or %g0, %l3, %o0 call _do_hw_interrupt - or %%g0, %%g0, %o1 + or %g0, %g0, %o1 wr %l0, 0x20, %psr ! re-enable traps and reset the condition codes nop nop @@ -260,7 +261,7 @@ ld [%l6 + THREAD_WIM], %l5 and %l0, 0x1f, %l3 -/* I don't know whats worse, the extra comparison here, or an extra load +/* I don't know what's worse, the extra comparison here, or an extra load * from a lookup table, we'll see. */ cmp %l5, %l3 @@ -289,7 +290,7 @@ * was attempted and a trap occurred. Therefore the restore attempt had no * effect on window movement and the trap saved, which means it went in the * other direction. :-( We are in a trap window which is two restores away - * from the window we want to un-invalidate sorta speak and three away from + * from the window we want to un-invalidate so to speak and three away from * the one which will become invalid after this routine. There are probably * bugs already this routine. Bugs suck. */ @@ -314,14 +315,14 @@ ld [%l1 + %lo(_current)], %l1 st %l0, [%l1 + THREAD_WIM] save %g0, %g0, %g0 ! back to invalid register - ldd %l0, [%sp] ! load the window from stack - ldd %l2, [%sp + 8] - ldd %l4, [%sp + 16] - ldd %l6, [%sp + 24] - ldd %i0, [%sp + 32] - ldd %i2, [%sp + 40] - ldd %i4, [%sp + 48] - ldd %i6, [%sp + 56] + ldd [%sp], %l0 ! load the window from stack + ldd [%sp + 8], %l2 + ldd [%sp + 16], %l4 + ldd [%sp + 24], %l6 + ldd [%sp + 32], %i0 + ldd [%sp + 40], %i2 + ldd [%sp + 48], %i4 + ldd [%sp + 56], %i6 save %g0, %g0, %g0 ! to window where trap happened save %g0, %g0, %g0 ! back to trap window, so rett works wr %l0, 0x0, %psr ! load condition codes diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S --- v1.1.78/linux/arch/sparc/kernel/head.S Mon Jan 9 11:24:20 1995 +++ linux/arch/sparc/kernel/head.S Wed Jan 11 09:01:41 1995 @@ -44,6 +44,8 @@ #include #include #include +#include +#include .data @@ -52,7 +54,7 @@ .globl _intstack .globl _eintstack _intstack: - .skip 4 * PAGESIZE ! 16k = 128 128-byte stack frames + .skip 4 * PAGE_SIZE ! 16k = 128 128-byte stack frames _eintstack: @@ -77,7 +79,7 @@ */ /* Uh, actually Linus it is I who cannot spell. Too much murky - * Sparc assembly will does this to ya. + * Sparc assembly will do this to ya. */ _cputypvar: .asciz "compatability" @@ -181,8 +183,8 @@ .text .globl _msgbuf -msgbufsize = PAGESIZE ! 1 page for msg buffer -_msgbuf = PAGESIZE +msgbufsize = PAGE_SIZE ! 1 page for msg buffer +_msgbuf = PAGE_SIZE IE_reg_addr = _msgbuf + msgbufsize ! this page not used; points to IEreg @@ -191,7 +193,7 @@ /* Ok, things start to get interesting. We get linked such that 'start' is the entry symbol. However, it is real low in kernel address space and as such a nifty place to place the trap table. We achieve this goal - by just jumping to 'dostart' for the first trap's entry as the sparc + by just jumping to 'gokernel' for the first trap's entry as the sparc never receives the zero trap as it is real special (hw reset). Each trap entry point is the size of 4 sparc instructions (or 4 bytes @@ -494,7 +496,7 @@ a v0 or v2 prom. */ -gokernel: mov %o0, %g7 +gokernel: or %g0, %o0, %g7 st %o0, [_prom_vector_p] ! we will need it later rd %psr, %l2 rd %wim, %l3 @@ -502,7 +504,7 @@ or %g0, %o2, %l5 ! could be prom magic value... #if 0 /* You think I'm nutz? */ - cmp %l5, 0x0 ! check for magic SMP pointer + subcc %l5, 0x0, %g0 ! check for magic SMP pointer bne nosmp nop call %o2 ! call smp prom setup @@ -519,15 +521,15 @@ st %l3, [%l1 + %lo(_boot_wim)] sethi %hi(_boot_tbr), %l1 st %l4, [%l1 + %lo(_boot_tbr)] - sethi %hi(_boot_o_two), %l1 + sethi %hi(_boot_smp_ptr), %l1 st %l5, [%l1 + %lo(_boot_smp_ptr)] - mov %o0, %g7 + or %g0, %o0, %g7 sethi %hi(_prom_vector_p), %g5 st %o0, [%g5 + %lo(_prom_vector_p)] ! we will need it later ld [%g7 + 0x4], %o3 - cmp %o3, 2 ! a v2 prom? + subcc %o3, 0x2, %g0 ! a v2 prom? be found_v2 nop @@ -538,17 +540,19 @@ */ sethi %hi(LOAD_ADDR), %g6 - cmp %o0, %g6 ! an old sun4? - beq no_sun4_here + subcc %o0, %g6, %g0 ! an old sun4? + be no_sun4_here nop - st %g0, [_prom_iface_vers] + sethi %hi(_prom_iface_vers), %g1 + st %g0, [%g1 + %lo(_prom_iface_vers)] b not_v2 nop found_v2: - or %%g0, 0x2, %o5 - st %o5, [_prom_iface_vers] + or %g0, 0x2, %o5 + sethi %hi(_prom_iface_vers), %g1 + st %o5, [%g1 + %lo(_prom_iface_vers)] not_v2: @@ -573,29 +577,32 @@ call %l0 or %g0, %g0, %o0 ! next_node(0) = first_node - set _cputypvar, %o1 ! first node has cpu-arch - set _cputypval, %o2 ! information, the string + sethi %hi(_cputypvar), %o1 ! first node has cpu-arch + or %o1, %lo(_cputypvar), %o1 + sethi %hi(_cputypval), %o2 ! information, the string + or %o2, %lo(_cputypval), %o2 ld [%l1], %l0 ! 'compatibility' tells - ld [%l0 + 0x0c], %l0 ! that we want 'sun4x' where + ld [%l0 + 0xc], %l0 ! that we want 'sun4x' where call %l0 ! x is one of '', 'c', 'm', nop ! 'd' or 'e'. %o2 holds pointer ! to a buf where above string ! will get stored by the prom. - set _cputypval, %o2 ! better safe than sorry - ldub [%o2 + 4], %o0 - cmp %o0, 'c' ! we already know we are not - beq is_sun4c ! on a plain sun4 because of + sethi %hi(_cputypval), %o2 ! better safe than sorry + or %o2, %lo(_cputypval), %o2 + ldub [%o2 + 0x4], %o0 + subcc %o0, 'c', %g0 ! we already know we are not + be is_sun4c ! on a plain sun4 because of nop ! the check for 0x4000 in %o0 - cmp %o0, 'm' ! at start: - beq is_sun4m + subcc %o0, 'm', %g0 ! at start: + be is_sun4m nop b no_sun4d_here ! god bless the person who nop ! tried to run this on sun4d is_sun4m: is_sun4c: ! OK, this is a sun4c, yippie - mov %g7, %g6 ! load up the promvec offsets + or %g0, %g7, %g6 ! load up the promvec offsets sethi %hi(prom_magic), %g5 ! magic mushroom :> st %g6, [%g5 + %lo(prom_magic)] add %g7, 0x4, %g6 @@ -639,29 +646,39 @@ * as the prom expects. */ - set boot_msg, %o0 - ld [prom_printf], %o1 + sethi %hi(boot_msg), %o0 + or %o0, %lo(boot_msg), %o0 + sethi %hi(prom_printf), %o1 + ld [%o1 + %lo(prom_printf)], %o1 ld [%o1], %o1 call %o1 ! print boot message #1 nop -_newline: set newline, %o0 - ld [prom_printf], %o1 +_newline: sethi %hi(newline), %o0 + or %o0, %lo(newline), %o0 + sethi %hi(prom_printf), %o1 + ld [%o1 + %lo(prom_printf)], %o1 ld [%o1], %o1 call %o1 nop - set pstring1, %o0 - ld [prom_printf], %o2 + sethi %hi(pstring1), %o0 + or %o0, %lo(pstring1), %o0 + sethi %hi(prom_printf), %o2 + ld [%o2 + %lo(prom_printf)], %o2 ld [%o2], %o2 - ld [prom_magic], %o1 + sethi %hi(prom_magic), %o1 + ld [%o1 + %lo(prom_magic)], %o1 ld [%o1], %o1 call %o2 - set pstring2, %o0 - ld [prom_printf], %o2 + sethi %hi(pstring2), %o0 + or %o0, %lo(pstring2), %o0 + sethi %hi(prom_printf), %o2 + ld [%o2 + %lo(prom_printf)], %o2 ld [%o2], %o2 - ld [_prom_iface_vers], %o1 + sethi %hi(_prom_iface_vers), %o1 + ld [%o1 + %lo(_prom_iface_vers)], %o1 ld [%o1], %o1 call %o2 @@ -675,9 +692,9 @@ nop rest_of_boot: - mov PAGESHIFT_SUN4C, %g5 + or %g0, PAGE_SHIFT, %g5 - set AC_CONTEXT, %g1 ! kernel context, safe now + sethi %hi(AC_CONTEXT), %g1 ! kernel context, safe now ! the only valid context ! until we call paging_init() stba %g0, [%g1] ASI_CONTROL @@ -690,7 +707,7 @@ /* Uh, oh, interrupt time. This crap is real confusing. What I want to do is * clear all interrupts, map the interrupt enable register which in effect - * enables non-maskable interrupts (or NMI's). Actuall we take no interrupts + * enables non-maskable interrupts (or NMI's). Actually we take no interrupts * until we frob with the %tbr (trap base register) which the prom has set * to all its routines which allows some sanity during bootup. */ @@ -711,7 +728,8 @@ * show-time! */ - set 1f, %g1 + sethi %hi(1f), %g1 + or %g1, %lo(1f), %g1 jmp %g1 nop @@ -734,26 +752,31 @@ rd %psr, %g3 andn %g3, PSR_ET, %g3 - wr %g3, 0, %psr ! make sure traps are off + wr %g3, 0x0, %psr ! make sure traps are off ! before we play around - WRITE_PAUSE ! no guarentees until 3 insns + WRITE_PAUSE ! no guarantees until 3 insns - wr %g0, 0, %wim ! magical invalid window reg + wr %g0, 0x0, %wim ! magical invalid window reg WRITE_PAUSE ! see above /* I keep the timer interrupt on so that BogoMIPS works and the prom * keeps updating it's "jiffies" counter. 100HZ clock on sparcstations. */ - wr %g0, (PSR_S | PSR_PS | PSR_PIL), %psr + +/* If gas wasn't so dumb, I could use or'd macros in this next + * write. ;-( like this (PSR_PS | PSR_S | PSR_PIL)... + */ + + wr %g0, (0xfc0), %psr WRITE_PAUSE - wr %g0, 2, %wim ! window 1 invalid + wr %g0, 0x2, %wim ! window 1 invalid WRITE_PAUSE - mov 1, %g1 - sethi %hi(_task + PCB_WIM), %g2 - st %g1, [%g2 + %lo(_task + PCB_WIM)] + or %g0, 0x1, %g1 + sethi %hi(_current + THREAD_WIM), %g2 + st %g1, [%g2 + %lo(_current + THREAD_WIM)] /* I want a kernel stack NOW! */ @@ -765,7 +788,7 @@ /* - * Maybe the prom zero's out our BSS section, maybe it doesn't. I certainly + * Maybe the prom zeroes out our BSS section, maybe it doesn't. I certainly * don't know, do you? */ @@ -788,12 +811,12 @@ sub %g3, %g4, %g2 sethi %hi(_kernel_data_len), %g3 st %g2, [%g3 + %lo(_kernel_data_len)] - clr %g1 + or %g0, %g0, %g1 1: st %g0, [%o0] add %o0, 0x4, %o0 - cmp %o0, %o1 + subcc %o0, %o1, %g0 bl 1b nop @@ -812,7 +835,7 @@ or %g0, 0x0, %g3 1: srl %g1, 0x1, %g1 ! shift until highest - cmp %g1, 0x0 ! bit set + subcc %g1, 0x0, %g0 ! bit set bne 1b add %g3, 0x1, %g3 sethi %hi(_nwindows), %g4 @@ -906,7 +929,7 @@ * sequence, all sorts of bad things can happen */ -prom_abort: .skip 4 ! "L1-A" magic cookie +prom_abort: .skip 4 ! L1-A magic cookie ! must be mapped in ALL contexts /* prom_sync is a place where the kernel should place a pointer to a kernel @@ -916,7 +939,7 @@ * executed. Nice feature eh? */ -prom_sync: .skip 4 ! hook in prom for "sync" func +prom_sync: .skip 4 ! hook in prom for sync func .align 4 @@ -930,14 +953,15 @@ _nwindowsm1: .skip 4 .align 4 -/* Boot time priviledged register values, plus magic %o2 value */ +/* Boot time privileged register values, plus magic %o2 value */ .globl _boot_wim .globl _boot_psr .globl _boot_tbr - .globl _boot_o_two + .globl _boot_smp_ptr _boot_wim: .skip 4 _boot_psr: .skip 4 _boot_tbr: .skip 4 _boot_smp_ptr: .skip 4 + diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c --- v1.1.78/linux/arch/sparc/kernel/irq.c Mon Jan 9 11:24:20 1995 +++ linux/arch/sparc/kernel/irq.c Wed Jan 11 09:01:41 1995 @@ -19,6 +19,11 @@ * sa_restorer is the unused */ +#include +#include +#include +#include +#include void disable_irq(unsigned int irq_nr) { @@ -87,7 +92,7 @@ int request_irq(unsigned int irq, void (*handler)(int), unsigned long flags, const char * devname) { - return irqaction(irq,&sa); + return irqaction(irq, (struct sigaction *) 0); } void free_irq(unsigned int irq) diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v1.1.78/linux/arch/sparc/kernel/process.c Mon Jan 9 07:21:58 1995 +++ linux/arch/sparc/kernel/process.c Wed Jan 11 09:01:41 1995 @@ -30,8 +30,6 @@ */ asmlinkage int sys_idle(void) { - int i; - if (current->pid != 0) return -EPERM; @@ -54,7 +52,6 @@ { regs->sp = sp; regs->fp = fp; - regs->psr = psr; } /* @@ -75,9 +72,8 @@ struct pt_regs * childregs; childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1; - p->tss.sp = (unsigned long) childregs; + p->tss.usp = (unsigned long) childregs; *childregs = *regs; - p->tss.back_link = 0; p->tss.psr = regs->psr; /* for condition codes */ return clone_flags; } @@ -98,8 +94,8 @@ int error; char * filename; - error = do_execve(filename, (char **) regs.reg_window[0], - (char **) regs.reg_window[1], ®s); + error = do_execve(filename, (char **) regs.u_regs[0], + (char **) regs.u_regs[1], ®s); putname(filename); return error; } diff -u --recursive --new-file v1.1.78/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c --- v1.1.78/linux/arch/sparc/kernel/traps.c Mon Jan 9 07:21:58 1995 +++ linux/arch/sparc/kernel/traps.c Wed Jan 11 09:01:41 1995 @@ -8,6 +8,8 @@ * I hate traps on the sparc, grrr... */ +#include /* for jiffies */ +#include void do_hw_interrupt(unsigned long type, unsigned long vector) { @@ -23,7 +25,7 @@ return; } -extern unsigned int *trapbase; +extern unsigned long *trapbase; void trap_init(void) { diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/COPYING.LIB linux/arch/sparc/lib/COPYING.LIB --- v1.1.78/linux/arch/sparc/lib/COPYING.LIB Thu Jan 1 02:00:00 1970 +++ linux/arch/sparc/lib/COPYING.LIB Wed Jan 11 09:02:26 1995 @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile --- v1.1.78/linux/arch/sparc/lib/Makefile Thu Jan 1 02:00:00 1970 +++ linux/arch/sparc/lib/Makefile Wed Jan 11 09:02:26 1995 @@ -0,0 +1,44 @@ +# +# Makefile for Sparc library files.. +# + +.c.s: + $(CC) $(CFLAGS) -S $< +.s.o: + $(AS) -c -o $*.o $< +.c.o: + $(CC) $(CFLAGS) -c $< + +OBJS = mul.o rem.o sdiv.o udiv.o umul.o urem.o + +lib.a: $(OBJS) + $(AR) rcs lib.a $(OBJS) + sync + +mul.o: mul.S + $(CC) -c -o mul.o mul.S + +rem.o: rem.S + $(CC) -DST_DIV0=0x2 -c -o rem.o rem.S + +sdiv.o: sdiv.S + $(CC) -DST_DIV0=0x2 -c -o sdiv.o sdiv.S + +udiv.o: udiv.S + $(CC) -DST_DIV0=0x2 -c -o udiv.o udiv.S + +umul.o: umul.S + $(CC) -c -o umul.o umul.S + +urem.o: urem.S + $(CC) -DST_DIV0=0x2 -c -o urem.o urem.S + +dep: + $(CPP) -M *.S > .depend + +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/mul.S linux/arch/sparc/lib/mul.S --- v1.1.78/linux/arch/sparc/lib/mul.S Thu Jan 1 02:00:00 1970 +++ linux/arch/sparc/lib/mul.S Wed Jan 11 09:02:26 1995 @@ -0,0 +1,127 @@ +/* mul.S: This routine was taken from glibc-1.09 and is covered + * by the GNU Library General Public License Version 2. + */ + +/* + * Signed multiply, from Appendix E of the Sparc Version 8 + * Architecture Manual. + */ + +/* + * Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the upper 32 bits of + * the 64-bit product). + * + * This code optimizes short (less than 13-bit) multiplies. + */ + + .globl .mul +.mul: + mov %o0, %y ! multiplier -> Y + andncc %o0, 0xfff, %g0 ! test bits 12..31 + be Lmul_shortway ! if zero, can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product and clear N and V + + /* + * Long multiply. 32 steps, followed by a final shift step. + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %o1, %o4 ! 13 + mulscc %o4, %o1, %o4 ! 14 + mulscc %o4, %o1, %o4 ! 15 + mulscc %o4, %o1, %o4 ! 16 + mulscc %o4, %o1, %o4 ! 17 + mulscc %o4, %o1, %o4 ! 18 + mulscc %o4, %o1, %o4 ! 19 + mulscc %o4, %o1, %o4 ! 20 + mulscc %o4, %o1, %o4 ! 21 + mulscc %o4, %o1, %o4 ! 22 + mulscc %o4, %o1, %o4 ! 23 + mulscc %o4, %o1, %o4 ! 24 + mulscc %o4, %o1, %o4 ! 25 + mulscc %o4, %o1, %o4 ! 26 + mulscc %o4, %o1, %o4 ! 27 + mulscc %o4, %o1, %o4 ! 28 + mulscc %o4, %o1, %o4 ! 29 + mulscc %o4, %o1, %o4 ! 30 + mulscc %o4, %o1, %o4 ! 31 + mulscc %o4, %o1, %o4 ! 32 + mulscc %o4, %g0, %o4 ! final shift + + ! If %o0 was negative, the result is + ! (%o0 * %o1) + (%o1 << 32)) + ! We fix that here. + +#if 0 + tst %o0 + bge 1f + rd %y, %o0 + + ! %o0 was indeed negative; fix upper 32 bits of result by subtracting + ! %o1 (i.e., return %o4 - %o1 in %o1). + retl + sub %o4, %o1, %o1 + +1: + retl + mov %o4, %o1 +#else + /* Faster code adapted from tege@sics.se's code for umul.S. */ + sra %o0, 31, %o2 ! make mask from sign bit + and %o1, %o2, %o2 ! %o2 = 0 or %o1, depending on sign of %o0 + rd %y, %o0 ! get lower half of product + retl + sub %o4, %o2, %o1 ! subtract compensation + ! and put upper half in place +#endif + +Lmul_shortway: + /* + * Short multiply. 12 steps, followed by a final shift step. + * The resulting bits are off by 12 and (32-12) = 20 bit positions, + * but there is no problem with %o0 being negative (unlike above). + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %g0, %o4 ! final shift + + /* + * %o4 has 20 of the bits that should be in the low part of the + * result; %y has the bottom 12 (as %y's top 12). That is: + * + * %o4 %y + * +----------------+----------------+ + * | -12- | -20- | -12- | -20- | + * +------(---------+------)---------+ + * --hi-- ----low-part---- + * + * The upper 12 bits of %o4 should be sign-extended to form the + * high part of the product (i.e., highpart = %o4 >> 20). + */ + + rd %y, %o5 + sll %o4, 12, %o0 ! shift middle bits left 12 + srl %o5, 20, %o5 ! shift low bits right 20, zero fill at left + or %o5, %o0, %o0 ! construct low part of result + retl + sra %o4, 20, %o1 ! ... and extract high part of result diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/rem.S linux/arch/sparc/lib/rem.S --- v1.1.78/linux/arch/sparc/lib/rem.S Thu Jan 1 02:00:00 1970 +++ linux/arch/sparc/lib/rem.S Wed Jan 11 09:02:26 1995 @@ -0,0 +1,359 @@ +/* rem.S: This routine was taken from glibc-1.09 and is covered + * by the GNU Library General Public License Version 2. + */ + + +/* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .rem name of function to generate + * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1 + * true true=true => signed; true=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + .globl .rem +.rem: + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge 2f ! no, go do the divide + xor %o1, %o0, %g6 ! compute sign in any case + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge 2f ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative +2: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu Lgot_result ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu Lnot_really_big + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g7 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g7. + 2: addcc %o5, %o5, %o5 + bcc Lnot_too_big + add %g7, 1, %g7 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b Ldo_single_div + sub %g7, 1, %g7 + + Lnot_too_big: + 3: cmp %o5, %o3 + blu 2b + nop + be Ldo_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g7 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + Ldo_single_div: + subcc %g7, 1, %g7 + bl Lend_regular_divide + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b Lend_single_divloop + nop + Lsingle_divloop: + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + Lend_single_divloop: + subcc %g7, 1, %g7 + bge Lsingle_divloop + tst %o3 + b,a Lend_regular_divide + +Lnot_really_big: +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be Lgot_result + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +Ldivloop: + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl L.1.16 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl L.2.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl L.3.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl L.4.23 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +L.4.23: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +L.3.19: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl L.4.21 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +L.4.21: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +L.2.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl L.3.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl L.4.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +L.4.19: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +L.3.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl L.4.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +L.4.17: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +L.1.16: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl L.2.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl L.3.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl L.4.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +L.4.15: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +L.3.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl L.4.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +L.4.13: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +L.2.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl L.3.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl L.4.11 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +L.4.11: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +L.3.13: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl L.4.9 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +L.4.9: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +Lend_regular_divide: + subcc %o4, 1, %o4 + bge Ldivloop + tst %o3 + bl,a Lgot_result + ! non-restoring fixup here (one instruction only!) + add %o3, %o1, %o3 + + +Lgot_result: + + retl + mov %o3, %o0 diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/sdiv.S linux/arch/sparc/lib/sdiv.S --- v1.1.78/linux/arch/sparc/lib/sdiv.S Thu Jan 1 02:00:00 1970 +++ linux/arch/sparc/lib/sdiv.S Wed Jan 11 09:02:26 1995 @@ -0,0 +1,363 @@ +/* sdiv.S: This routine was taken from glibc-1.09 and is covered + * by the GNU Library General Public License Version 2. + */ + + +/* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .div name of function to generate + * div div=div => %o0 / %o1; div=rem => %o0 % %o1 + * true true=true => signed; true=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + .globl .div +.div: + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge 2f ! no, go do the divide + xor %o1, %o0, %g6 ! compute sign in any case + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge 2f ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative +2: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu Lgot_result ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu Lnot_really_big + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g7 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g7. + 2: addcc %o5, %o5, %o5 + bcc Lnot_too_big + add %g7, 1, %g7 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b Ldo_single_div + sub %g7, 1, %g7 + + Lnot_too_big: + 3: cmp %o5, %o3 + blu 2b + nop + be Ldo_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g7 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + Ldo_single_div: + subcc %g7, 1, %g7 + bl Lend_regular_divide + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b Lend_single_divloop + nop + Lsingle_divloop: + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + Lend_single_divloop: + subcc %g7, 1, %g7 + bge Lsingle_divloop + tst %o3 + b,a Lend_regular_divide + +Lnot_really_big: +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be Lgot_result + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +Ldivloop: + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl L.1.16 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl L.2.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl L.3.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl L.4.23 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +L.4.23: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +L.3.19: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl L.4.21 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +L.4.21: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +L.2.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl L.3.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl L.4.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +L.4.19: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +L.3.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl L.4.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +L.4.17: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +L.1.16: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl L.2.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl L.3.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl L.4.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +L.4.15: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +L.3.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl L.4.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +L.4.13: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +L.2.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl L.3.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl L.4.11 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +L.4.11: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +L.3.13: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl L.4.9 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +L.4.9: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +Lend_regular_divide: + subcc %o4, 1, %o4 + bge Ldivloop + tst %o3 + bl,a Lgot_result + ! non-restoring fixup here (one instruction only!) + sub %o2, 1, %o2 + + +Lgot_result: + ! check to see if answer should be < 0 + tst %g6 + bl,a 1f + sub %g0, %o2, %o2 +1: + retl + mov %o2, %o0 diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/udiv.S linux/arch/sparc/lib/udiv.S --- v1.1.78/linux/arch/sparc/lib/udiv.S Thu Jan 1 02:00:00 1970 +++ linux/arch/sparc/lib/udiv.S Wed Jan 11 09:02:26 1995 @@ -0,0 +1,346 @@ +/* udiv.S: This routine was taken from glibc-1.09 and is covered + * by the GNU Library General Public License Version 2. + */ + + +/* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .udiv name of function to generate + * div div=div => %o0 / %o1; div=rem => %o0 % %o1 + * false false=true => signed; false=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + .globl .udiv +.udiv: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu Lgot_result ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu Lnot_really_big + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g7 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g7. + 2: addcc %o5, %o5, %o5 + bcc Lnot_too_big + add %g7, 1, %g7 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b Ldo_single_div + sub %g7, 1, %g7 + + Lnot_too_big: + 3: cmp %o5, %o3 + blu 2b + nop + be Ldo_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g7 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + Ldo_single_div: + subcc %g7, 1, %g7 + bl Lend_regular_divide + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b Lend_single_divloop + nop + Lsingle_divloop: + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + Lend_single_divloop: + subcc %g7, 1, %g7 + bge Lsingle_divloop + tst %o3 + b,a Lend_regular_divide + +Lnot_really_big: +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be Lgot_result + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +Ldivloop: + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl L.1.16 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl L.2.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl L.3.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl L.4.23 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +L.4.23: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +L.3.19: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl L.4.21 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +L.4.21: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +L.2.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl L.3.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl L.4.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +L.4.19: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +L.3.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl L.4.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +L.4.17: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +L.1.16: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl L.2.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl L.3.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl L.4.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +L.4.15: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +L.3.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl L.4.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +L.4.13: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +L.2.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl L.3.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl L.4.11 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +L.4.11: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +L.3.13: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl L.4.9 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +L.4.9: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +Lend_regular_divide: + subcc %o4, 1, %o4 + bge Ldivloop + tst %o3 + bl,a Lgot_result + ! non-restoring fixup here (one instruction only!) + sub %o2, 1, %o2 + + +Lgot_result: + + retl + mov %o2, %o0 diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/umul.S linux/arch/sparc/lib/umul.S --- v1.1.78/linux/arch/sparc/lib/umul.S Thu Jan 1 02:00:00 1970 +++ linux/arch/sparc/lib/umul.S Wed Jan 11 09:02:26 1995 @@ -0,0 +1,158 @@ +/* umul.S: This routine was taken from glibc-1.09 and is covered + * by the GNU Library General Public License Version 2. + */ + + +/* + * Unsigned multiply. Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the + * upper 32 bits of the 64-bit product). + * + * This code optimizes short (less than 13-bit) multiplies. Short + * multiplies require 25 instruction cycles, and long ones require + * 45 instruction cycles. + * + * On return, overflow has occurred (%o1 is not zero) if and only if + * the Z condition code is clear, allowing, e.g., the following: + * + * call .umul + * nop + * bnz overflow (or tnz) + */ + + .globl .umul +.umul: + or %o0, %o1, %o4 + mov %o0, %y ! multiplier -> Y + andncc %o4, 0xfff, %g0 ! test bits 12..31 of *both* args + be Lmul_shortway ! if zero, can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product and clear N and V + + /* + * Long multiply. 32 steps, followed by a final shift step. + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %o1, %o4 ! 13 + mulscc %o4, %o1, %o4 ! 14 + mulscc %o4, %o1, %o4 ! 15 + mulscc %o4, %o1, %o4 ! 16 + mulscc %o4, %o1, %o4 ! 17 + mulscc %o4, %o1, %o4 ! 18 + mulscc %o4, %o1, %o4 ! 19 + mulscc %o4, %o1, %o4 ! 20 + mulscc %o4, %o1, %o4 ! 21 + mulscc %o4, %o1, %o4 ! 22 + mulscc %o4, %o1, %o4 ! 23 + mulscc %o4, %o1, %o4 ! 24 + mulscc %o4, %o1, %o4 ! 25 + mulscc %o4, %o1, %o4 ! 26 + mulscc %o4, %o1, %o4 ! 27 + mulscc %o4, %o1, %o4 ! 28 + mulscc %o4, %o1, %o4 ! 29 + mulscc %o4, %o1, %o4 ! 30 + mulscc %o4, %o1, %o4 ! 31 + mulscc %o4, %o1, %o4 ! 32 + mulscc %o4, %g0, %o4 ! final shift + + + /* + * Normally, with the shift-and-add approach, if both numbers are + * positive you get the correct result. With 32-bit two's-complement + * numbers, -x is represented as + * + * x 32 + * ( 2 - ------ ) mod 2 * 2 + * 32 + * 2 + * + * (the `mod 2' subtracts 1 from 1.bbbb). To avoid lots of 2^32s, + * we can treat this as if the radix point were just to the left + * of the sign bit (multiply by 2^32), and get + * + * -x = (2 - x) mod 2 + * + * Then, ignoring the `mod 2's for convenience: + * + * x * y = xy + * -x * y = 2y - xy + * x * -y = 2x - xy + * -x * -y = 4 - 2x - 2y + xy + * + * For signed multiplies, we subtract (x << 32) from the partial + * product to fix this problem for negative multipliers (see mul.s). + * Because of the way the shift into the partial product is calculated + * (N xor V), this term is automatically removed for the multiplicand, + * so we don't have to adjust. + * + * But for unsigned multiplies, the high order bit wasn't a sign bit, + * and the correction is wrong. So for unsigned multiplies where the + * high order bit is one, we end up with xy - (y << 32). To fix it + * we add y << 32. + */ +#if 0 + tst %o1 + bl,a 1f ! if %o1 < 0 (high order bit = 1), + add %o4, %o0, %o4 ! %o4 += %o0 (add y to upper half) +1: rd %y, %o0 ! get lower half of product + retl + addcc %o4, %g0, %o1 ! put upper half in place and set Z for %o1==0 +#else + /* Faster code from tege@sics.se. */ + sra %o1, 31, %o2 ! make mask from sign bit + and %o0, %o2, %o2 ! %o2 = 0 or %o0, depending on sign of %o1 + rd %y, %o0 ! get lower half of product + retl + addcc %o4, %o2, %o1 ! add compensation and put upper half in place +#endif + +Lmul_shortway: + /* + * Short multiply. 12 steps, followed by a final shift step. + * The resulting bits are off by 12 and (32-12) = 20 bit positions, + * but there is no problem with %o0 being negative (unlike above), + * and overflow is impossible (the answer is at most 24 bits long). + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %g0, %o4 ! final shift + + /* + * %o4 has 20 of the bits that should be in the result; %y has + * the bottom 12 (as %y's top 12). That is: + * + * %o4 %y + * +----------------+----------------+ + * | -12- | -20- | -12- | -20- | + * +------(---------+------)---------+ + * -----result----- + * + * The 12 bits of %o4 left of the `result' area are all zero; + * in fact, all top 20 bits of %o4 are zero. + */ + + rd %y, %o5 + sll %o4, 12, %o0 ! shift middle bits left 12 + srl %o5, 20, %o5 ! shift low bits right 20 + or %o5, %o0, %o0 + retl + addcc %g0, %g0, %o1 ! %o1 = zero, and set Z diff -u --recursive --new-file v1.1.78/linux/arch/sparc/lib/urem.S linux/arch/sparc/lib/urem.S --- v1.1.78/linux/arch/sparc/lib/urem.S Thu Jan 1 02:00:00 1970 +++ linux/arch/sparc/lib/urem.S Wed Jan 11 09:02:26 1995 @@ -0,0 +1,344 @@ +/* urem.S: This routine was taken from glibc-1.09 and is covered + * by the GNU Library General Public License Version 2. + */ + +/* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .urem name of function to generate + * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1 + * false false=true => signed; false=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + .globl .urem +.urem: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu Lgot_result ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu Lnot_really_big + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g7 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g7. + 2: addcc %o5, %o5, %o5 + bcc Lnot_too_big + add %g7, 1, %g7 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b Ldo_single_div + sub %g7, 1, %g7 + + Lnot_too_big: + 3: cmp %o5, %o3 + blu 2b + nop + be Ldo_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g7 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + Ldo_single_div: + subcc %g7, 1, %g7 + bl Lend_regular_divide + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b Lend_single_divloop + nop + Lsingle_divloop: + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + Lend_single_divloop: + subcc %g7, 1, %g7 + bge Lsingle_divloop + tst %o3 + b,a Lend_regular_divide + +Lnot_really_big: +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be Lgot_result + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +Ldivloop: + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl L.1.16 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl L.2.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl L.3.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl L.4.23 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +L.4.23: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +L.3.19: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl L.4.21 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +L.4.21: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +L.2.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl L.3.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl L.4.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +L.4.19: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +L.3.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl L.4.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +L.4.17: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +L.1.16: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl L.2.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl L.3.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl L.4.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +L.4.15: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +L.3.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl L.4.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +L.4.13: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +L.2.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl L.3.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl L.4.11 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +L.4.11: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +L.3.13: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl L.4.9 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +L.4.9: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +Lend_regular_divide: + subcc %o4, 1, %o4 + bge Ldivloop + tst %o3 + bl,a Lgot_result + ! non-restoring fixup here (one instruction only!) + add %o3, %o1, %o3 + + +Lgot_result: + + retl + mov %o3, %o0 diff -u --recursive --new-file v1.1.78/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v1.1.78/linux/drivers/block/floppy.c Mon Jan 9 07:22:01 1995 +++ linux/drivers/block/floppy.c Wed Jan 11 08:11:02 1995 @@ -2998,7 +2998,7 @@ } /* Allow ioctls if we have write-permissions even if read-only open */ - if ((filp->f_mode & 2) || permission(inode,2)) + if ((filp->f_mode & 2) || (permission(inode,2) == 0)) filp->f_mode |= IOCTL_MODE_BIT; if (filp->f_mode & 2) filp->f_mode |= OPEN_WRITE_BIT; diff -u --recursive --new-file v1.1.78/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v1.1.78/linux/drivers/block/ide.c Mon Jan 9 11:24:20 1995 +++ linux/drivers/block/ide.c Tue Jan 10 10:07:20 1995 @@ -82,13 +82,16 @@ * Version 3.4 BETA removed "444" debug message * (sent to Linus) * Version 3.5 correct the bios_cyl field if it's too small - * (linux 1.1.76!) (to help fdisk with brain-dead BIOSs) + * (linux 1.1.76) (to help fdisk with brain-dead BIOSs) * Version 3.6 cosmetic corrections to comments and stuff - * reorganise probing code to make it understandable + * (linux 1.1.77) reorganise probing code to make it understandable * added halfway retry to probing for drive identification * added "hdx=noprobe" command line option * allow setting multmode even when identification fails - * + * Version 3.7 move set_geometry=1 from do_identify() to ide_init() + * increase DRQ_WAIT to eliminate nuisance messages + * wait for DRQ_STAT instead of DATA_READY during probing + * (courtesy of Gary Thomas gary@efland.UU.NET) * To do: * - special 32-bit controller-type detection & support * - figure out why two WD drives on one i/f sometimes don't identify @@ -234,7 +237,7 @@ /* * Timeouts for various operations: */ -#define WAIT_DRQ 3 /* 30msec - spec allows up to 20ms */ +#define WAIT_DRQ 5 /* 50msec - spec allows up to 20ms */ #define WAIT_READY 3 /* 30msec - should be instantaneous */ #define WAIT_PIDENTIFY 100 /* 1sec - should be less than 3ms (?) */ #define WAIT_WORSTCASE 3000 /* 30sec - worst case when spinning up */ @@ -1624,10 +1627,6 @@ #endif /* CONFIG_BLK_DEV_IDECD */ return; } - /* - * for Quantum drives, and also for drives not known to the BIOS: - */ - dev->special.b.set_geometry = 1; /* * Gather up the geometry info. @@ -1738,7 +1737,7 @@ for (timer = jiffies + (timeout / 2); timer > jiffies;) { if ((IN_BYTE(HD_ALTSTATUS,DEV_HWIF) & BUSY_STAT) == 0) { delay_10ms(); /* wait for IRQ & DATA_READY */ - if (OK_STAT(GET_STAT(DEV_HWIF),DATA_READY,BAD_RW_STAT)){ + if (OK_STAT(GET_STAT(DEV_HWIF),DRQ_STAT,BAD_RW_STAT)){ cli(); /* some sys need this */ do_identify(dev); /* drive returned ID */ rc = 0; @@ -1770,7 +1769,7 @@ /* * This routine has the difficult job of finding a drive if it exists, * without getting hung up if it doesn't exist, and without leaving any IRQs - * dangling to haunt us later. The last point actually occured in v2.3, and + * dangling to haunt us later. The last point actually occurred in v2.3, and * is the reason for the slightly complex exit sequence. If a drive is "known" * to exist (from CMOS or kernel parameters), but does not respond right away, * the probe will "hang in there" for the maximum wait time (about 30 seconds). @@ -2041,6 +2040,7 @@ dev->wqueue = NULL; dev->special.all = 0; dev->special.b.recalibrate = 1; + dev->special.b.set_geometry = 1; dev->keep_settings = 0; ide_hd[hwif][drive<name = ide_devname[hwif][drive]; diff -u --recursive --new-file v1.1.78/linux/drivers/block/sbpcd.c linux/drivers/block/sbpcd.c --- v1.1.78/linux/drivers/block/sbpcd.c Mon Jan 9 11:24:20 1995 +++ linux/drivers/block/sbpcd.c Tue Jan 10 10:07:08 1995 @@ -4004,7 +4004,7 @@ static int config_spea(void) { int n_ports=0x10; /* 2:0x00, 8:0x10, 16:0x20, 32:0x30 */ -/* What is n_ports? Number of adresses or base address offset? */ +/* What is n_ports? Number of addresses or base address offset? */ int irq_number=0; /* 2:0x01, 7:0x03, 12:0x05, 15:0x07, OFF:0x00 */ int dma_channel=0; /* 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68, 7:0x78, OFF: 0x00 */ int dack_polarity=0; /* L:0x00, H:0x80 */ diff -u --recursive --new-file v1.1.78/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v1.1.78/linux/drivers/char/Makefile Mon Jan 9 11:24:21 1995 +++ linux/drivers/char/Makefile Tue Jan 10 17:02:17 1995 @@ -95,7 +95,6 @@ dep: $(CPP) -M $(SRCS) > .depend -modules: dummy: # diff -u --recursive --new-file v1.1.78/linux/drivers/char/console.c linux/drivers/char/console.c --- v1.1.78/linux/drivers/char/console.c Mon Jan 9 07:22:01 1995 +++ linux/drivers/char/console.c Wed Jan 11 07:55:50 1995 @@ -293,15 +293,15 @@ #define vcmode (vt_cons[currcons]->vc_mode) #define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct)) -static void * memsetw(void * s, unsigned short c, unsigned int count) +static void memsetw(void * s, unsigned short c, unsigned int count) { -__asm__("cld\n\t" - "rep\n\t" - "stosw" - : /* no output */ - :"a" (c),"D" (s),"c" (count/2) - :"cx","di"); -return s; + unsigned short * addr = (unsigned short *) s; + + count /= 2; + while (count) { + count--; + *(addr++) = c; + } } int vc_cons_allocated(unsigned int i) @@ -681,67 +681,72 @@ pos += video_size_row; scr_end += video_size_row; if (scr_end > video_mem_end) { - __asm__("cld\n\t" - "rep\n\t" - "movsl\n\t" - "movl _video_num_columns,%1\n\t" - "rep\n\t" - "stosw" - : /* no output */ - :"a" (video_erase_char), - "c" ((video_num_lines-1)*video_num_columns>>1), - "D" (video_mem_start), - "S" (origin) - :"cx","di","si"); + unsigned short * d = (unsigned short *) video_mem_start; + unsigned short * s = (unsigned short *) origin; + unsigned int count; + + count = (video_num_lines-1)*video_num_columns; + while (count) { + count--; + *(d++) = *(s++); + } + count = video_num_columns; + while (count) { + count--; + *(d++) = video_erase_char; + } scr_end -= origin-video_mem_start; pos -= origin-video_mem_start; origin = video_mem_start; has_scrolled = 1; } else { - __asm__("cld\n\t" - "rep\n\t" - "stosw" - : /* no output */ - :"a" (video_erase_char), - "c" (video_num_columns), - "D" (scr_end-video_size_row) - :"cx","di"); + unsigned short * d; + unsigned int count; + + d = (unsigned short *) (scr_end - video_size_row); + count = video_num_columns; + while (count) { + count--; + *(d++) = video_erase_char; + } } set_origin(currcons); } else { - __asm__("cld\n\t" - "rep\n\t" - "movsl\n\t" - "movl _video_num_columns,%%ecx\n\t" - "rep\n\t" - "stosw" - : /* no output */ - :"a" (video_erase_char), - "c" ((b-t-1)*video_num_columns>>1), - "D" (origin+video_size_row*t), - "S" (origin+video_size_row*(t+1)) - :"cx","di","si"); + unsigned short * d = (unsigned short *) (origin+video_size_row*t); + unsigned short * s = (unsigned short *) (origin+video_size_row*(t+1)); + unsigned int count = (b-t-1) * video_num_columns; + + while (count) { + count--; + *(d++) = *(s++); + } + count = video_num_columns; + while (count) { + count--; + *(d++) = video_erase_char; + } } } static void scrdown(int currcons, unsigned int t, unsigned int b) { + unsigned short *d, *s; + unsigned int count; + if (b > video_num_lines || t >= b) return; - __asm__("std\n\t" - "rep\n\t" - "movsl\n\t" - "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */ - "movl _video_num_columns,%%ecx\n\t" - "rep\n\t" - "stosw\n\t" - "cld" - : /* no output */ - :"a" (video_erase_char), - "c" ((b-t-1)*video_num_columns>>1), - "D" (origin+video_size_row*b-4), - "S" (origin+video_size_row*(b-1)-4) - :"ax","cx","di","si"); + d = (unsigned short *) origin+video_size_row*b; + s = (unsigned short *) origin+video_size_row*(b-1); + count = (b-t-1)*video_num_columns; + while (count) { + count--; + *(--d) = *(--s); + } + count = video_num_columns; + while (count) { + count--; + *(--d) = video_erase_char; + } has_scrolled = 1; } @@ -796,83 +801,74 @@ static void csi_J(int currcons, int vpar) { unsigned long count; - unsigned long start; + unsigned short * start; switch (vpar) { case 0: /* erase from cursor to end of display */ count = (scr_end-pos)>>1; - start = pos; + start = (unsigned short *) pos; break; case 1: /* erase from start to cursor */ count = ((pos-origin)>>1)+1; - start = origin; + start = (unsigned short *) origin; break; case 2: /* erase whole display */ count = video_num_columns * video_num_lines; - start = origin; + start = (unsigned short *) origin; break; default: return; } - __asm__("cld\n\t" - "rep\n\t" - "stosw\n\t" - : /* no output */ - :"c" (count), - "D" (start),"a" (video_erase_char) - :"cx","di"); + while (count) { + count--; + *(start++) = video_erase_char; + } need_wrap = 0; } static void csi_K(int currcons, int vpar) { - long count; - long start; + unsigned long count; + unsigned short * start; switch (vpar) { case 0: /* erase from cursor to end of line */ count = video_num_columns-x; - start = pos; + start = (unsigned short *) pos; break; case 1: /* erase from start of line to cursor */ - start = pos - (x<<1); + start = (unsigned short *) (pos - (x<<1)); count = x+1; break; case 2: /* erase whole line */ - start = pos - (x<<1); + start = (unsigned short *) (pos - (x<<1)); count = video_num_columns; break; default: return; } - __asm__("cld\n\t" - "rep\n\t" - "stosw\n\t" - : /* no output */ - :"c" (count), - "D" (start),"a" (video_erase_char) - :"cx","di"); + while (count) { + count--; + *(start++) = video_erase_char; + } need_wrap = 0; } static void csi_X(int currcons, int vpar) /* erase the following vpar positions */ { /* not vt100? */ - long count; - long start; + unsigned long count; + unsigned short * start; if (!vpar) vpar++; - start=pos; - count=(vpar > video_num_columns-x) ? (video_num_columns-x) : vpar; + start = (unsigned short *) pos; + count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar; - __asm__("cld\n\t" - "rep\n\t" - "stosw\n\t" - : /* no output */ - :"c" (count), - "D" (start),"a" (video_erase_char) - :"cx","di"); + while (count) { + count--; + *(start++) = video_erase_char; + } need_wrap = 0; } diff -u --recursive --new-file v1.1.78/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v1.1.78/linux/drivers/char/keyboard.c Mon Jan 9 07:22:02 1995 +++ linux/drivers/char/keyboard.c Wed Jan 11 07:55:50 1995 @@ -74,8 +74,11 @@ extern void scrollfront(int); extern int vc_cons_allocated(unsigned int); -#define fake_keyboard_interrupt() \ -__asm__ __volatile__("int $0x21") +#ifdef __i386__ +#define fake_keyboard_interrupt() __asm__ __volatile__("int $0x21") +#else +#define fake_keyboard_interrupt() do ; while (0) +#endif unsigned char kbd_read_mask = 0x01; /* modified by psaux.c */ @@ -611,6 +614,7 @@ static void show_ptregs(void) { +#ifdef __i386__ if (!pt_regs) return; printk("\n"); @@ -625,6 +629,7 @@ printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n", 0xffff & pt_regs->ds,0xffff & pt_regs->es, 0xffff & pt_regs->fs,0xffff & pt_regs->gs); +#endif } static void hold(void) @@ -1176,7 +1181,9 @@ /* nothing */; outb(0xfe,0x64); /* pulse reset low */ } +#ifdef __i386__ __asm__("\tlidt _no_idt"); +#endif } } diff -u --recursive --new-file v1.1.78/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v1.1.78/linux/drivers/char/lp.c Mon Jan 9 11:24:21 1995 +++ linux/drivers/char/lp.c Tue Jan 10 17:02:17 1995 @@ -37,6 +37,9 @@ #ifdef MODULE #include #include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT #endif /* Test if printer is ready (and optionally has no error conditions) */ @@ -48,6 +51,15 @@ (status & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \ (LP_PBUSY|LP_PSELECD|LP_PERRORP) +/* Allow old versions of tunelp to continue to work */ +#define OLD_LPCHAR 0x0001 +#define OLD_LPTIME 0x0002 +#define OLD_LPABORT 0x0004 +#define OLD_LPSETIRQ 0x0005 +#define OLD_LPGETIRQ 0x0006 +#define OLD_LPWAIT 0x0008 +#define OLD_IOCTL_MAX 8 + /* * All my debugging code assumes that you debug with only one printer at * a time. RWWH @@ -320,6 +332,8 @@ if (LP_F(minor) & LP_BUSY) return -EBUSY; + MOD_INC_USE_COUNT; + /* If ABORTOPEN is set and the printer is offline or out of paper, we may still want to open it to perform ioctl()s. Therefore we have commandeered O_NONBLOCK, even though it is being used in @@ -329,34 +343,37 @@ int status = LP_S(minor); if (status & LP_POUTPA) { printk(KERN_INFO "lp%d out of paper\n", minor); + MOD_DEC_USE_COUNT; return -ENOSPC; } else if (!(status & LP_PSELECD)) { printk(KERN_INFO "lp%d off-line\n", minor); + MOD_DEC_USE_COUNT; return -EIO; } else if (!(status & LP_PERRORP)) { printk(KERN_ERR "lp%d printer error\n", minor); + MOD_DEC_USE_COUNT; return -EIO; } } if ((irq = LP_IRQ(minor))) { lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); - if (!lp_table[minor].lp_buffer) + if (!lp_table[minor].lp_buffer) { + MOD_DEC_USE_COUNT; return -ENOMEM; + } ret = request_irq(irq, lp_interrupt, SA_INTERRUPT, "printer"); if (ret) { kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE); lp_table[minor].lp_buffer = NULL; printk("lp%d unable to use interrupt %d, error %d\n", minor, irq, ret); + MOD_DEC_USE_COUNT; return ret; } } LP_F(minor) |= LP_BUSY; -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif return 0; } @@ -372,9 +389,7 @@ } LP_F(minor) &= ~LP_BUSY; -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif } @@ -391,13 +406,19 @@ return -ENODEV; if ((LP_F(minor) & LP_EXIST) == 0) return -ENODEV; + if (cmd <= OLD_IOCTL_MAX) + printk(KERN_NOTICE "lp%d: warning: obsolete ioctl %#x (perhaps you need a new tunelp)\n", + minor, cmd); switch ( cmd ) { + case OLD_LPTIME: case LPTIME: LP_TIME(minor) = arg; break; + case OLD_LPCHAR: case LPCHAR: LP_CHAR(minor) = arg; break; + case OLD_LPABORT: case LPABORT: if (arg) LP_F(minor) |= LP_ABORT; @@ -416,9 +437,11 @@ else LP_F(minor) &= ~LP_CAREFUL; break; + case OLD_LPWAIT: case LPWAIT: LP_WAIT(minor) = arg; break; + case OLD_LPSETIRQ: case LPSETIRQ: { int oldirq; int newirq = arg; @@ -462,11 +485,28 @@ lp_reset(minor); break; } - case LPGETIRQ: + case OLD_LPGETIRQ: retval = LP_IRQ(minor); break; + case LPGETIRQ: + retval = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(int)); + if (retval) + return retval; + memcpy_tofs((int *) arg, &LP_IRQ(minor), sizeof(int)); + break; case LPGETSTATUS: - retval = LP_S(minor); /* in range 0..255 */ + retval = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(int)); + if (retval) + return retval; + else { + int status = LP_S(minor); + memcpy_tofs((int *) arg, &status, sizeof(int)); + } + break; + case LPRESET: + lp_reset(minor); break; default: retval = -EINVAL; diff -u --recursive --new-file v1.1.78/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v1.1.78/linux/drivers/char/mem.c Thu Oct 13 14:07:06 1994 +++ linux/drivers/char/mem.c Wed Jan 11 07:55:50 1995 @@ -87,8 +87,10 @@ { if (vma->vm_offset & ~PAGE_MASK) return -ENXIO; +#ifdef __i386__ if (x86 > 3 && vma->vm_offset >= high_memory) vma->vm_page_prot |= PAGE_PCD; +#endif if (remap_page_range(vma->vm_start, vma->vm_offset, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; vma->vm_inode = inode; diff -u --recursive --new-file v1.1.78/linux/drivers/net/3c501.c linux/drivers/net/3c501.c --- v1.1.78/linux/drivers/net/3c501.c Mon Jan 9 11:24:21 1995 +++ linux/drivers/net/3c501.c Tue Jan 10 10:07:07 1995 @@ -51,7 +51,7 @@ like (eg touching a register at the wrong time). The driver is less efficient than it could be. It switches through - recieve mode even if more transmits are queued. If this worries you buy + receive mode even if more transmits are queued. If this worries you buy a real ethernet card. The combination of slow receive restart and no real multicast @@ -564,7 +564,7 @@ skb->dev = dev; /* - * The read incrememts through the bytes. The interrupt + * The read increments through the bytes. The interrupt * handler will fix the pointer when it returns to * receive mode. */ diff -u --recursive --new-file v1.1.78/linux/drivers/net/atp.c linux/drivers/net/atp.c --- v1.1.78/linux/drivers/net/atp.c Mon Jan 9 11:24:21 1995 +++ linux/drivers/net/atp.c Tue Jan 10 10:07:08 1995 @@ -113,7 +113,7 @@ #ifndef HAVE_PORTRESERVE #define check_region(ioaddr, size) 0 -#define request_region(ioaddr, size,name); do ; while (0) +#define request_region(ioaddr, size,name) do ; while (0) #endif /* use 0 for production, 1 for verification, >2 for debug */ diff -u --recursive --new-file v1.1.78/linux/drivers/net/ni52.c linux/drivers/net/ni52.c --- v1.1.78/linux/drivers/net/ni52.c Mon Jan 9 11:24:22 1995 +++ linux/drivers/net/ni52.c Tue Jan 10 10:07:08 1995 @@ -181,7 +181,7 @@ #ifndef HAVE_PORTRESERVE #define check_region(ioaddr, size) 0 -#define request_region(ioaddr, size,name); do ; while (0) +#define request_region(ioaddr, size,name) do ; while (0) #endif #define NI52_TOTAL_SIZE 16 diff -u --recursive --new-file v1.1.78/linux/drivers/net/ni65.c linux/drivers/net/ni65.c --- v1.1.78/linux/drivers/net/ni65.c Mon Jan 9 11:24:22 1995 +++ linux/drivers/net/ni65.c Tue Jan 10 10:07:09 1995 @@ -54,7 +54,7 @@ #ifndef HAVE_PORTRESERVE #define check_region(ioaddr, size) 0 -#define request_region(ioaddr, size,name); do ; while (0) +#define request_region(ioaddr, size,name) do ; while (0) #endif #ifndef NET_DEBUG diff -u --recursive --new-file v1.1.78/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c --- v1.1.78/linux/drivers/net/sk_g16.c Mon Jan 9 11:24:22 1995 +++ linux/drivers/net/sk_g16.c Tue Jan 10 10:07:09 1995 @@ -329,7 +329,7 @@ #ifndef HAVE_PORTRESERVE #define check_region(ioaddr, size) 0 -#define request_region(ioaddr, size,name); do ; while (0) +#define request_region(ioaddr, size,name) do ; while (0) #endif diff -u --recursive --new-file v1.1.78/linux/drivers/net/slip.c linux/drivers/net/slip.c --- v1.1.78/linux/drivers/net/slip.c Mon Jan 9 07:22:06 1995 +++ linux/drivers/net/slip.c Tue Jan 10 10:07:09 1995 @@ -46,12 +46,6 @@ #define SL_CHECK_TRANSMIT #include -#ifdef SL_COMPRESSED -/* I think following lines must be in the - * 14 Oct 1994 Dmitry Gorodchanin - */ -#define CONFIG_SLIP_COMPRESSED -#endif /* Undef this, if you don't need 6bit encapsulation code in the driver */ #define CONFIG_SLIP_MODE_SLIP6 diff -u --recursive --new-file v1.1.78/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v1.1.78/linux/drivers/scsi/Makefile Mon Jan 9 11:24:22 1995 +++ linux/drivers/scsi/Makefile Tue Jan 10 10:07:08 1995 @@ -2,7 +2,7 @@ # Makefile for kernel/blk_drv/scsi # # Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DONT put your own dependencies here +# removes any old dependencies. DON'T put your own dependencies here # unless its something special (ie not a .c file). # diff -u --recursive --new-file v1.1.78/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v1.1.78/linux/drivers/scsi/sr.c Mon Jan 9 07:22:07 1995 +++ linux/drivers/scsi/sr.c Tue Jan 10 17:02:09 1995 @@ -284,7 +284,7 @@ * * - TOSHIBA: setting density is done here now, mounting PhotoCD's should * work now without running the program "set_density" - * People reported, that it is nessesary to eject and reinsert + * People reported that it is necessary to eject and reinsert * the CD after the set-density call to get this working for * old drives. * And some very new drives don't need this call any more... @@ -302,10 +302,10 @@ int rc; if (!suser()) { - /* I'm not the superuser, so SCSI_IOCTL_SEND_COMMAND is'nt allowed for me. - * That's why mpcd_sector will be initialized with zero, becauce I'm not - * able to get the right value. Nessesary only if access_count is 1, else - * no disk change happend since the last call of this function and we can + /* I'm not the superuser, so SCSI_IOCTL_SEND_COMMAND isn't allowed for me. + * That's why mpcd_sector will be initialized with zero, because I'm not + * able to get the right value. Necessary only if access_count is 1, else + * no disk change happened since the last call of this function and we can * keep the old value. */ if (1 == scsi_CDs[MINOR(inode->i_rdev)].device->access_count) @@ -328,7 +328,7 @@ rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, SCSI_IOCTL_SEND_COMMAND, buf); if (rc != 0) { - printk("sr_photocd: ioctl error: %i\n",rc); + printk("sr_photocd: ioctl error (NEC): 0x%x\n",rc); sector = 0; } else { min = (unsigned long)buf[8+15]/16*10 + (unsigned long)buf[8+15]%16; @@ -361,7 +361,7 @@ rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, SCSI_IOCTL_SEND_COMMAND, buf); if (rc != 0) { - printk("sr_photocd: ioctl error: %i\n",rc); + printk("sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc); } /* ... and then I ask, if there is a multisession-Disk */ @@ -370,8 +370,10 @@ *((unsigned long*)buf+1) = 4; buf[8+0] = 0xc7; buf[8+1] = 3; + rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device, + SCSI_IOCTL_SEND_COMMAND, buf); if (rc != 0) { - printk("sr_photocd: ioctl error: %i\n",rc); + printk("sr_photocd: ioctl error (TOSHIBA #2): 0x%x\n",rc); sector = 0; } else { min = (unsigned long)buf[8+1]/16*10 + (unsigned long)buf[8+1]%16; @@ -574,7 +576,7 @@ #if 1 /* Here we redirect the volume descriptor block of the CD-ROM. - * Nessesary for multisession CD's, until the isofs-rotines + * Necessary for multisession CD's, until the isofs-routines * handle this via the CDROMMULTISESSION_SYS call */ if (block >= 64 && block < 68) { diff -u --recursive --new-file v1.1.78/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c --- v1.1.78/linux/drivers/scsi/sr_ioctl.c Mon Jan 9 07:22:07 1995 +++ linux/drivers/scsi/sr_ioctl.c Tue Jan 10 17:02:09 1995 @@ -421,14 +421,9 @@ } case CDROMMULTISESSION_SYS: /* tell start-of-last-session to kernel */ - { - long *p_lba; - - if(!suser()) return -EACCES; - p_lba =(long*)arg; - *p_lba=scsi_CDs[target].mpcd_sector; - return (0); - } + if(!suser()) return -EACCES; + *((unsigned int *)arg)=scsi_CDs[target].mpcd_sector; + return (0); case BLKRASET: if(!suser()) return -EACCES; diff -u --recursive --new-file v1.1.78/linux/fs/exec.c linux/fs/exec.c --- v1.1.78/linux/fs/exec.c Mon Jan 9 07:22:08 1995 +++ linux/fs/exec.c Wed Jan 11 08:11:02 1995 @@ -535,7 +535,7 @@ flush_thread(); if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || - !permission(bprm->inode,MAY_READ)) + permission(bprm->inode,MAY_READ)) current->dumpable = 0; current->signal = 0; for (i=0 ; i<32 ; i++) { @@ -605,8 +605,9 @@ bprm.e_uid = (i & S_ISUID) ? bprm.inode->i_uid : current->euid; bprm.e_gid = (i & S_ISGID) ? bprm.inode->i_gid : current->egid; } - if (!permission(bprm.inode, MAY_EXEC) || - (!(bprm.inode->i_mode & 0111) && fsuser())) { + if ((retval = permission(bprm.inode, MAY_EXEC)) != 0) + goto exec_error2; + if (!(bprm.inode->i_mode & 0111) && fsuser()) { retval = -EACCES; goto exec_error2; } diff -u --recursive --new-file v1.1.78/linux/fs/ext/namei.c linux/fs/ext/namei.c --- v1.1.78/linux/fs/ext/namei.c Sat Oct 22 16:41:35 1994 +++ linux/fs/ext/namei.c Wed Jan 11 08:11:02 1995 @@ -810,8 +810,7 @@ retval = -EEXIST; if (new_bh) goto end_rename; - retval = -EACCES; - if (!permission(old_inode, MAY_WRITE)) + if ((retval = permission(old_inode, MAY_WRITE)) != 0) goto end_rename; retval = -EINVAL; if (subdir(new_dir, old_inode)) diff -u --recursive --new-file v1.1.78/linux/fs/ext2/acl.c linux/fs/ext2/acl.c --- v1.1.78/linux/fs/ext2/acl.c Mon Aug 15 15:53:47 1994 +++ linux/fs/ext2/acl.c Wed Jan 11 08:11:02 1995 @@ -30,12 +30,12 @@ * Nobody gets write access to an immutable file */ if ((mask & S_IWOTH) && IS_IMMUTABLE(inode)) - return 0; + return -EACCES; /* * Special case, access is always granted for root */ if (fsuser()) - return 1; + return 0; /* * If no ACL, checks using the file mode */ @@ -44,7 +44,7 @@ else if (in_group_p (inode->i_gid)) mode >>= 3; if (((mode & mask & S_IRWXO) == mask)) - return 1; - else return 0; + else + return -EACCES; } diff -u --recursive --new-file v1.1.78/linux/fs/isofs/Makefile linux/fs/isofs/Makefile --- v1.1.78/linux/fs/isofs/Makefile Mon Jan 9 11:24:23 1995 +++ linux/fs/isofs/Makefile Tue Jan 10 17:02:17 1995 @@ -20,6 +20,8 @@ $(LD) -r -o isofs.o $(OBJS) modules: isofs.o + ln -sf ../fs/isofs/isofs.o $(TOPDIR)/modules + dep: $(CPP) -M *.c > .depend diff -u --recursive --new-file v1.1.78/linux/fs/isofs/inode.c linux/fs/isofs/inode.c --- v1.1.78/linux/fs/isofs/inode.c Mon Jan 9 11:24:23 1995 +++ linux/fs/isofs/inode.c Tue Jan 10 17:02:18 1995 @@ -24,6 +24,9 @@ #ifdef MODULE #include #include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT #endif #ifdef LEAK_CHECK @@ -41,9 +44,7 @@ #endif sb->s_dev = 0; unlock_super(sb); -#ifdef MODULE MOD_DEC_USE_COUNT; -#endif return; } @@ -166,8 +167,11 @@ struct iso9660_options opt; + MOD_INC_USE_COUNT; + if (!parse_options((char *) data,&opt)) { s->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } @@ -219,6 +223,7 @@ printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n", dev, iso_blknum); unlock_super(s); + MOD_DEC_USE_COUNT; return NULL; } @@ -256,6 +261,7 @@ printk("Unable to identify CD-ROM format.\n"); s->s_dev = 0; unlock_super(s); + MOD_DEC_USE_COUNT; return NULL; }; @@ -340,19 +346,18 @@ if (!(s->s_mounted)) { s->s_dev=0; printk("get root inode failed\n"); + MOD_DEC_USE_COUNT; return NULL; } if(!check_disk_change(s->s_dev)) { -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif return s; } out: /* Kick out for various error conditions */ brelse(bh); s->s_dev = 0; unlock_super(s); + MOD_DEC_USE_COUNT; return NULL; } @@ -766,12 +771,7 @@ void cleanup_module(void) { - if (MOD_IN_USE) - printk("ne: device busy, remove delayed\n"); - else - { - unregister_filesystem(&iso9660_fs_type); - } + unregister_filesystem(&iso9660_fs_type); } #endif diff -u --recursive --new-file v1.1.78/linux/fs/minix/inode.c linux/fs/minix/inode.c --- v1.1.78/linux/fs/minix/inode.c Mon Jan 9 07:22:08 1995 +++ linux/fs/minix/inode.c Tue Jan 10 17:02:18 1995 @@ -130,12 +130,14 @@ if (32 != sizeof (struct minix_inode)) panic("bad i-node size"); + MOD_INC_USE_COUNT; lock_super(s); set_blocksize(dev, BLOCK_SIZE); if (!(bh = bread(dev,1,BLOCK_SIZE))) { s->s_dev=0; unlock_super(s); printk("MINIX-fs: unable to read superblock\n"); + MOD_DEC_USE_COUNT; return NULL; } ms = (struct minix_super_block *) bh->b_data; @@ -164,6 +166,7 @@ brelse(bh); if (!silent) printk("VFS: Can't find a minix filesystem on dev 0x%04x.\n", dev); + MOD_DEC_USE_COUNT; return NULL; } for (i=0;i < MINIX_I_MAP_SLOTS;i++) @@ -190,6 +193,7 @@ unlock_super(s); brelse(bh); printk("MINIX-fs: bad superblock or unable to read bitmaps\n"); + MOD_DEC_USE_COUNT; return NULL; } set_bit(0,s->u.minix_sb.s_imap[0]->b_data); @@ -203,6 +207,7 @@ s->s_dev = 0; brelse(bh); printk("MINIX-fs: get root inode failed\n"); + MOD_DEC_USE_COUNT; return NULL; } if (!(s->s_flags & MS_RDONLY)) { @@ -216,7 +221,6 @@ else if (s->u.minix_sb.s_mount_state & MINIX_ERROR_FS) printk ("MINIX-fs: mounting file system with errors, " "running fsck is recommended.\n"); - MOD_INC_USE_COUNT; return s; } @@ -538,12 +542,7 @@ void cleanup_module(void) { - if (MOD_IN_USE) - printk("ne: device busy, remove delayed\n"); - else - { - unregister_filesystem(&minix_fs_type); - } + unregister_filesystem(&minix_fs_type); } #endif diff -u --recursive --new-file v1.1.78/linux/fs/msdos/Makefile linux/fs/msdos/Makefile --- v1.1.78/linux/fs/msdos/Makefile Mon Jan 9 11:24:23 1995 +++ linux/fs/msdos/Makefile Tue Jan 10 17:02:18 1995 @@ -20,6 +20,8 @@ $(LD) -r -o msdos.o $(OBJS) modules: msdos.o + ln -sf ../fs/msdos/msdos.o $(TOPDIR)/modules + dep: $(CPP) -M *.c > .depend diff -u --recursive --new-file v1.1.78/linux/fs/msdos/inode.c linux/fs/msdos/inode.c --- v1.1.78/linux/fs/msdos/inode.c Tue Dec 27 08:37:13 1994 +++ linux/fs/msdos/inode.c Tue Jan 10 17:02:18 1995 @@ -19,8 +19,11 @@ #include "msbuffer.h" #ifdef MODULE - #include - #include +#include +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT #endif #include @@ -62,9 +65,7 @@ lock_super(sb); sb->s_dev = 0; unlock_super(sb); - #ifdef MODULE - MOD_DEC_USE_COUNT; - #endif + MOD_DEC_USE_COUNT; return; } @@ -177,6 +178,8 @@ gid_t gid; int umask; int blksize = 512; + + MOD_INC_USE_COUNT; if (hardsect_size[MAJOR(sb->s_dev)] != NULL){ blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]; if (blksize != 512){ @@ -187,6 +190,7 @@ &debug,&fat,&quiet,&blksize) || (blksize != 512 && blksize != 1024)) { sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } cache_init(); @@ -200,6 +204,7 @@ brelse (bh); sb->s_dev = 0; printk("MSDOS bread failed\n"); + MOD_DEC_USE_COUNT; return NULL; } b = (struct msdos_boot_sector *) bh->b_data; @@ -279,6 +284,7 @@ printk("VFS: Can't find a valid MSDOS filesystem on dev 0x%04x.\n", sb->s_dev); sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } sb->s_magic = MSDOS_SUPER_MAGIC; @@ -297,11 +303,9 @@ if (!(sb->s_mounted = iget(sb,MSDOS_ROOT_INO))) { sb->s_dev = 0; printk("get root inode failed\n"); + MOD_DEC_USE_COUNT; return NULL; } - #ifdef MODULE - MOD_INC_USE_COUNT; - #endif return sb; } @@ -514,12 +518,7 @@ void cleanup_module(void) { - if (MOD_IN_USE) - printk("msdos: device busy, remove delayed\n"); - else - { - unregister_filesystem(&msdos_fs_type); - } + unregister_filesystem(&msdos_fs_type); } #endif diff -u --recursive --new-file v1.1.78/linux/fs/namei.c linux/fs/namei.c --- v1.1.78/linux/fs/namei.c Sun Nov 20 21:50:47 1994 +++ linux/fs/namei.c Wed Jan 11 08:11:02 1995 @@ -107,14 +107,14 @@ if (inode->i_op && inode->i_op->permission) return inode->i_op->permission(inode, mask); else if ((mask & S_IWOTH) && IS_IMMUTABLE(inode)) - return 0; /* Nobody gets write access to an immutable file */ + return -EACCES; /* Nobody gets write access to an immutable file */ else if (current->fsuid == inode->i_uid) mode >>= 6; else if (in_group_p(inode->i_gid)) mode >>= 3; if (((mode & mask & 0007) == mask) || fsuser()) - return 1; - return 0; + return 0; + return -EACCES; } /* @@ -182,9 +182,9 @@ iput(dir); return -ENOTDIR; } - if (!perm) { + if (perm != 0) { iput(dir); - return -EACCES; + return perm; } if (!len) { *result = dir; @@ -352,9 +352,9 @@ return -EISDIR; } /* thanks to Paul Pluzhnikov for noticing this was missing.. */ - if (!permission(dir,ACC_MODE(flag))) { + if ((error = permission(dir,ACC_MODE(flag))) != 0) { iput(dir); - return -EACCES; + return error; } *res_inode=dir; return 0; @@ -368,8 +368,8 @@ iput(inode); error = -EEXIST; } - } else if (!permission(dir,MAY_WRITE | MAY_EXEC)) - error = -EACCES; + } else if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) + ; /* error is already set! */ else if (!dir->i_op || !dir->i_op->create) error = -EACCES; else if (IS_RDONLY(dir)) @@ -395,9 +395,9 @@ iput(inode); return -EISDIR; } - if (!permission(inode,ACC_MODE(flag))) { + if ((error = permission(inode,ACC_MODE(flag))) != 0) { iput(inode); - return -EACCES; + return error; } if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { if (IS_NODEV(inode)) { @@ -460,9 +460,9 @@ iput(dir); return -EROFS; } - if (!permission(dir,MAY_WRITE | MAY_EXEC)) { + if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) { iput(dir); - return -EACCES; + return error; } if (!dir->i_op || !dir->i_op->mknod) { iput(dir); @@ -517,9 +517,9 @@ iput(dir); return -EROFS; } - if (!permission(dir,MAY_WRITE | MAY_EXEC)) { + if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) { iput(dir); - return -EACCES; + return error; } if (!dir->i_op || !dir->i_op->mkdir) { iput(dir); @@ -563,9 +563,9 @@ iput(dir); return -EROFS; } - if (!permission(dir,MAY_WRITE | MAY_EXEC)) { + if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) { iput(dir); - return -EACCES; + return error; } /* * A subdirectory cannot be removed from an append-only directory @@ -611,9 +611,9 @@ iput(dir); return -EROFS; } - if (!permission(dir,MAY_WRITE | MAY_EXEC)) { + if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) { iput(dir); - return -EACCES; + return error; } /* * A file cannot be removed from an append-only directory @@ -659,9 +659,9 @@ iput(dir); return -EROFS; } - if (!permission(dir,MAY_WRITE | MAY_EXEC)) { + if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) { iput(dir); - return -EACCES; + return error; } if (!dir->i_op || !dir->i_op->symlink) { iput(dir); @@ -718,10 +718,10 @@ iput(oldinode); return -EXDEV; } - if (!permission(dir,MAY_WRITE | MAY_EXEC)) { + if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) { iput(dir); iput(oldinode); - return -EACCES; + return error; } /* * A link to an append-only or immutable file cannot be created @@ -772,9 +772,9 @@ error = dir_namei(oldname,&old_len,&old_base,NULL,&old_dir); if (error) return error; - if (!permission(old_dir,MAY_WRITE | MAY_EXEC)) { + if ((error = permission(old_dir,MAY_WRITE | MAY_EXEC)) != 0) { iput(old_dir); - return -EACCES; + return error; } if (!old_len || (old_base[0] == '.' && (old_len == 1 || (old_base[1] == '.' && @@ -787,10 +787,10 @@ iput(old_dir); return error; } - if (!permission(new_dir,MAY_WRITE | MAY_EXEC)) { + if ((error = permission(new_dir,MAY_WRITE | MAY_EXEC)) != 0){ iput(old_dir); iput(new_dir); - return -EACCES; + return error; } if (!new_len || (new_base[0] == '.' && (new_len == 1 || (new_base[1] == '.' && diff -u --recursive --new-file v1.1.78/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v1.1.78/linux/fs/nfs/inode.c Mon Jan 9 07:22:08 1995 +++ linux/fs/nfs/inode.c Tue Jan 10 17:02:18 1995 @@ -79,9 +79,11 @@ struct file *filp; dev_t dev = sb->s_dev; + MOD_INC_USE_COUNT; if (!data) { printk("nfs_read_super: missing data argument\n"); sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } fd = data->fd; @@ -92,11 +94,13 @@ if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) { printk("nfs_read_super: invalid file descriptor\n"); sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } if (!S_ISSOCK(filp->f_inode->i_mode)) { printk("nfs_read_super: not a socket\n"); sb->s_dev = 0; + MOD_DEC_USE_COUNT; return NULL; } filp->f_count++; @@ -133,9 +137,9 @@ if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) { sb->s_dev = 0; printk("nfs_read_super: get root inode failed\n"); + MOD_DEC_USE_COUNT; return NULL; } - MOD_INC_USE_COUNT; return sb; } @@ -264,23 +268,12 @@ int init_module(void) { - int i; - register_filesystem(&nfs_fs_type); - return 0; } void cleanup_module(void) { - int i; - - if (MOD_IN_USE) - { - printk("NFS cannot be removed, currently in use\n"); - return; - } - unregister_filesystem(&nfs_fs_type); } diff -u --recursive --new-file v1.1.78/linux/fs/open.c linux/fs/open.c --- v1.1.78/linux/fs/open.c Tue Dec 20 15:09:11 1994 +++ linux/fs/open.c Wed Jan 11 08:11:02 1995 @@ -74,10 +74,14 @@ error = namei(path,&inode); if (error) return error; - if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) { + if (S_ISDIR(inode->i_mode)) { iput(inode); return -EACCES; } + if ((error = permission(inode,MAY_WRITE)) != 0) { + iput(inode); + return error; + } if (IS_RDONLY(inode)) { iput(inode); return -EROFS; @@ -157,9 +161,9 @@ newattrs.ia_ctime = CURRENT_TIME; flags = ATTR_ATIME_SET | ATTR_MTIME_SET; } else { - if (!permission(inode,MAY_WRITE)) { + if ((error = permission(inode,MAY_WRITE)) != 0) { iput(inode); - return -EACCES; + return error; } actime = modtime = newattrs.ia_ctime = CURRENT_TIME; } @@ -190,8 +194,7 @@ current->fsgid = current->gid; res = namei(filename,&inode); if (!res) { - if (!permission(inode, mode)) - res = -EACCES; + res = permission(inode, mode); iput(inode); } current->fsuid = old_fsuid; @@ -211,9 +214,9 @@ iput(inode); return -ENOTDIR; } - if (!permission(inode,MAY_EXEC)) { + if ((error = permission(inode,MAY_EXEC)) != 0) { iput(inode); - return -EACCES; + return error; } iput(current->fs->pwd); current->fs->pwd = inode; @@ -224,6 +227,7 @@ { struct inode * inode; struct file * file; + int error; if (fd >= NR_OPEN || !(file = current->files->fd[fd])) return -EBADF; @@ -231,8 +235,8 @@ return -ENOENT; if (!S_ISDIR(inode->i_mode)) return -ENOTDIR; - if (!permission(inode,MAY_EXEC)) - return -EACCES; + if ((error = permission(inode,MAY_EXEC)) != 0) + return error; iput(current->fs->pwd); current->fs->pwd = inode; inode->i_count++; diff -u --recursive --new-file v1.1.78/linux/fs/proc/array.c linux/fs/proc/array.c --- v1.1.78/linux/fs/proc/array.c Mon Jan 9 11:24:23 1995 +++ linux/fs/proc/array.c Wed Jan 11 08:54:36 1995 @@ -605,6 +605,7 @@ extern int get_irq_list(char *); extern int get_dma_list(char *); extern int get_cpuinfo(char *); +extern int get_pci_list(char*); static int get_root_array(char * page, int type) { @@ -618,6 +619,11 @@ case PROC_MEMINFO: return get_meminfo(page); +#ifdef CONFIG_PCI + case PROC_PCI: + return get_pci_list(page); +#endif + case PROC_CPUINFO: return get_cpuinfo(page); diff -u --recursive --new-file v1.1.78/linux/fs/proc/inode.c linux/fs/proc/inode.c --- v1.1.78/linux/fs/proc/inode.c Mon Jan 9 07:22:08 1995 +++ linux/fs/proc/inode.c Tue Jan 10 17:02:18 1995 @@ -44,6 +44,37 @@ NULL }; + +static int parse_options(char *options,uid_t *uid,gid_t *gid) +{ + char *this_char,*value; + + *uid = current->uid; + *gid = current->gid; + if (!options) return 1; + for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) { + if ((value = strchr(this_char,'=')) != NULL) + *value++ = 0; + if (!strcmp(this_char,"uid")) { + if (!value || !*value) + return 0; + *uid = simple_strtoul(value,&value,0); + if (*value) + return 0; + } + else if (!strcmp(this_char,"gid")) { + if (!value || !*value) + return 0; + *gid = simple_strtoul(value,&value,0); + if (*value) + return 0; + } + else return 0; + } + return 1; +} + + struct super_block *proc_read_super(struct super_block *s,void *data, int silent) { @@ -58,6 +89,7 @@ printk("get root inode failed\n"); return NULL; } + parse_options(data, &s->s_mounted->i_uid, &s->s_mounted->i_gid); return s; } @@ -117,7 +149,7 @@ if (!pid) { switch (ino) { case PROC_KMSG: - inode->i_mode = S_IFREG | S_IRUGO; + inode->i_mode = S_IFREG | S_IRUSR; inode->i_op = &proc_kmsg_inode_operations; break; case PROC_NET: diff -u --recursive --new-file v1.1.78/linux/fs/proc/link.c linux/fs/proc/link.c --- v1.1.78/linux/fs/proc/link.c Thu Oct 20 09:54:33 1994 +++ linux/fs/proc/link.c Wed Jan 11 08:11:02 1995 @@ -103,16 +103,16 @@ unsigned int pid, ino; struct task_struct * p; struct inode * new_inode; - int i; + int i, error; *res_inode = NULL; if (dir) iput(dir); if (!inode) return -ENOENT; - if (!permission(inode, MAY_EXEC)) { + if ((error = permission(inode, MAY_EXEC)) != 0){ iput(inode); - return -EACCES; + return error; } ino = inode->i_ino; pid = ino >> 16; diff -u --recursive --new-file v1.1.78/linux/fs/proc/net.c linux/fs/proc/net.c --- v1.1.78/linux/fs/proc/net.c Mon Jan 9 11:24:23 1995 +++ linux/fs/proc/net.c Wed Jan 11 08:03:11 1995 @@ -42,6 +42,7 @@ /* the get_*_info() functions are in the net code, and are configured in via the standard mechanism... */ extern int unix_get_info(char *, char **, off_t, int); +extern int afinet_get_info(char *, char **, off_t, int); #ifdef CONFIG_INET extern int tcp_get_info(char *, char **, off_t, int); extern int udp_get_info(char *, char **, off_t, int); @@ -144,6 +145,7 @@ { PROC_NET_NR, 2, "nr" }, #endif /* CONFIG_NETROM */ #endif /* CONFIG_AX25 */ + { PROC_NET_SOCKSTAT, 8, "sockstat" }, { 0, 0, NULL } }; @@ -230,6 +232,9 @@ { case PROC_NET_UNIX: length = unix_get_info(page,&start,file->f_pos,thistime); + break; + case PROC_NET_SOCKSTAT: + length = afinet_get_info(page,&start,file->f_pos,thistime); break; #ifdef CONFIG_INET case PROC_NET_ARP: diff -u --recursive --new-file v1.1.78/linux/fs/proc/root.c linux/fs/proc/root.c --- v1.1.78/linux/fs/proc/root.c Mon Dec 12 20:13:07 1994 +++ linux/fs/proc/root.c Wed Jan 11 08:55:07 1995 @@ -59,6 +59,9 @@ { PROC_MEMINFO, 7, "meminfo" }, { PROC_KMSG, 4, "kmsg" }, { PROC_VERSION, 7, "version" }, +#ifdef CONFIG_PCI + { PROC_PCI, 3, "pci" }, +#endif { PROC_CPUINFO, 7, "cpuinfo" }, { PROC_SELF, 4, "self" }, /* will change inode # */ { PROC_NET, 3, "net" }, @@ -74,7 +77,9 @@ { PROC_KSYMS, 5, "ksyms" }, { PROC_DMA, 3, "dma" }, { PROC_IOPORTS, 7, "ioports"}, - { PROC_PROFILE, 7, "profile"}, +#ifdef CONFIG_PROFILE + { PROC_PROFILE, 7, "profile"}, +#endif }; #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0]))) diff -u --recursive --new-file v1.1.78/linux/fs/sysv/Makefile linux/fs/sysv/Makefile --- v1.1.78/linux/fs/sysv/Makefile Mon Jan 9 11:24:23 1995 +++ linux/fs/sysv/Makefile Tue Jan 10 17:02:18 1995 @@ -21,6 +21,8 @@ $(LD) -r -o sysv.o $(OBJS) modules: sysv.o + ln -sf ../fs/sysv/sysv.o $(TOPDIR)/modules + dep: $(CPP) -M *.c > .depend diff -u --recursive --new-file v1.1.78/linux/fs/sysv/inode.c linux/fs/sysv/inode.c --- v1.1.78/linux/fs/sysv/inode.c Mon Jan 9 11:24:23 1995 +++ linux/fs/sysv/inode.c Tue Jan 10 17:18:08 1995 @@ -1000,11 +1000,6 @@ { int i; - if (MOD_IN_USE) { - printk("SysV FS cannot be removed, currently in use\n"); - return; - } - for (i = 0; i < 3; i++) unregister_filesystem(&sysv_fs_type[i]); } diff -u --recursive --new-file v1.1.78/linux/fs/umsdos/Makefile linux/fs/umsdos/Makefile --- v1.1.78/linux/fs/umsdos/Makefile Mon Jan 9 11:24:23 1995 +++ linux/fs/umsdos/Makefile Tue Jan 10 17:02:18 1995 @@ -21,6 +21,7 @@ $(LD) -r -o umsdos.o $(OBJS) modules: umsdos.o + ln -sf ../fs/umsdos/umsdos.o $(TOPDIR)/modules clean: rm -f core *.o *.a *.s diff -u --recursive --new-file v1.1.78/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c --- v1.1.78/linux/fs/umsdos/inode.c Tue Dec 27 08:37:13 1994 +++ linux/fs/umsdos/inode.c Tue Jan 10 17:02:18 1995 @@ -13,13 +13,15 @@ #include #include #include -#include #include #include #ifdef MODULE - #include - #include +#include +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT #endif struct inode *pseudo_root=NULL; /* Useful to simulate the pseudo DOS */ @@ -55,9 +57,7 @@ void UMSDOS_put_super(struct super_block *sb) { msdos_put_super(sb); - #ifdef MODULE - MOD_DEC_USE_COUNT; - #endif + MOD_DEC_USE_COUNT; } @@ -404,7 +404,9 @@ which do not have an EMD file. They behave like normal msdos directory, with all limitation of msdos. */ - struct super_block *sb = msdos_read_super(s,data,silent); + struct super_block *sb; + MOD_INC_USE_COUNT; + sb = msdos_read_super(s,data,silent); printk ("UMSDOS Beta 0.6 (compatibility level %d.%d, fast msdos)\n" ,UMSDOS_VERSION,UMSDOS_RELEASE); if (sb != NULL){ @@ -473,9 +475,8 @@ } iput (pseudo); } - #ifdef MODULE - MOD_INC_USE_COUNT; - #endif + } else { + MOD_DEC_USE_COUNT; } return sb; } @@ -497,12 +498,7 @@ void cleanup_module(void) { - if (MOD_IN_USE) - printk("Umsdos: file system in use, remove delayed\n"); - else - { - unregister_filesystem(&umsdos_fs_type); - } + unregister_filesystem(&umsdos_fs_type); } #endif diff -u --recursive --new-file v1.1.78/linux/fs/xiafs/Makefile linux/fs/xiafs/Makefile --- v1.1.78/linux/fs/xiafs/Makefile Mon Jan 9 11:24:23 1995 +++ linux/fs/xiafs/Makefile Tue Jan 10 17:02:18 1995 @@ -21,6 +21,7 @@ $(LD) -r -o xiafs.o $(OBJS) modules: xiafs.o + ln -sf ../fs/xiafs/xiafs.o $(TOPDIR)/modules dep: $(CPP) -M *.c > .depend diff -u --recursive --new-file v1.1.78/linux/fs/xiafs/inode.c linux/fs/xiafs/inode.c --- v1.1.78/linux/fs/xiafs/inode.c Tue Dec 6 12:39:35 1994 +++ linux/fs/xiafs/inode.c Tue Jan 10 17:02:18 1995 @@ -535,10 +535,6 @@ void cleanup_module(void) { - if (MOD_IN_USE) { - printk("XIA-FS cannot be removed, currently in use\n"); - return; - } unregister_filesystem(&xiafs_fs_type); } diff -u --recursive --new-file v1.1.78/linux/fs/xiafs/namei.c linux/fs/xiafs/namei.c --- v1.1.78/linux/fs/xiafs/namei.c Thu Aug 11 17:11:07 1994 +++ linux/fs/xiafs/namei.c Wed Jan 11 08:11:02 1995 @@ -758,8 +758,7 @@ retval = -EEXIST; if (new_bh) goto end_rename; - retval = -EACCES; - if (!permission(old_inode, MAY_WRITE)) + if ((retval = permission(old_inode, MAY_WRITE)) != 0) goto end_rename; retval = -EINVAL; if (subdir(new_dir, old_inode)) diff -u --recursive --new-file v1.1.78/linux/include/asm-alpha/byteorder.h linux/include/asm-alpha/byteorder.h --- v1.1.78/linux/include/asm-alpha/byteorder.h Mon Jan 9 07:22:09 1995 +++ linux/include/asm-alpha/byteorder.h Tue Jan 10 10:07:07 1995 @@ -20,7 +20,7 @@ * The constant and non-constant versions here are the same. * Maybe I'll come up with an alpha-optimized routine for the * non-constant ones (the constant ones don't need it: gcc - * will optimze it to the correct constant) + * will optimize it to the correct constant) */ extern __inline__ unsigned long int diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/byteorder.h linux/include/asm-sparc/byteorder.h --- v1.1.78/linux/include/asm-sparc/byteorder.h Mon Jan 9 07:22:10 1995 +++ linux/include/asm-sparc/byteorder.h Wed Jan 11 09:00:53 1995 @@ -20,7 +20,7 @@ * The constant and non-constant versions here are the same. * Maybe I'll come up with an alpha-optimized routine for the * non-constant ones (the constant ones don't need it: gcc - * will optimze it to the correct constant) + * will optimize it to the correct constant) */ extern __inline__ unsigned long int diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h --- v1.1.78/linux/include/asm-sparc/page.h Mon Jan 9 07:22:10 1995 +++ linux/include/asm-sparc/page.h Wed Jan 11 09:00:53 1995 @@ -19,7 +19,7 @@ #define PAGE_SHIFT 12 /* This is the virtual page... */ #define PGDIR_SHIFT 18 /* This is the virtual segment */ -#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_SIZE 4096 #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #ifdef __KERNEL__ @@ -65,6 +65,7 @@ * with the following macro */ +#ifndef __ASSEMBLY__ /* for head.S */ extern __inline__ unsigned long get_segmap(unsigned long addr) { register unsigned long entry; @@ -122,6 +123,8 @@ return ctx; } + +#endif /* !(__ASSEMBLY__) */ #endif /* __KERNEL__ */ diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h --- v1.1.78/linux/include/asm-sparc/processor.h Mon Jan 9 11:24:24 1995 +++ linux/include/asm-sparc/processor.h Wed Jan 11 09:00:53 1995 @@ -48,7 +48,7 @@ unsigned long npc; /* next program counter */ /* 8 local registers + 8 in registers * 24 register windows. - * Most sparc's I know of only have 8 windows implemented, + * Most sparcs I know of only have 8 windows implemented, * we determine how many at boot time and store that value * in nwindows. */ @@ -58,8 +58,7 @@ }; #define INIT_TSS { \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, \ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ @@ -84,7 +83,9 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \ - 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + { 0, 0, 0, 0, 0, 0, 0, 0, }, \ + 0, \ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/psr.h linux/include/asm-sparc/psr.h --- v1.1.78/linux/include/asm-sparc/psr.h Mon Jan 2 15:26:45 1995 +++ linux/include/asm-sparc/psr.h Wed Jan 11 09:00:53 1995 @@ -10,6 +10,7 @@ #ifndef __LINUX_SPARC_PSR_H #define __LINUX_SPARC_PSR_H +#define __LINUX_SPARC_V8 /* duh */ #ifdef __LINUX_SPARC_V8 diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/segment.h linux/include/asm-sparc/segment.h --- v1.1.78/linux/include/asm-sparc/segment.h Mon Jan 2 15:26:45 1995 +++ linux/include/asm-sparc/segment.h Wed Jan 11 09:07:01 1995 @@ -8,6 +8,7 @@ #define USER_DS 0x1 #include +#include static inline unsigned char get_user_byte(const char * addr) { diff -u --recursive --new-file v1.1.78/linux/include/asm-sparc/string.h linux/include/asm-sparc/string.h --- v1.1.78/linux/include/asm-sparc/string.h Mon Jan 9 07:22:10 1995 +++ linux/include/asm-sparc/string.h Wed Jan 11 09:00:53 1995 @@ -166,7 +166,7 @@ return retval; } -extern __inline__ char *strchr(const char *src, char c) +extern __inline__ char *strchr(const char *src, int c) { register char temp; register char *trick; @@ -271,7 +271,7 @@ } -extern __inline__ void *memset(void *src, char c, size_t count) +extern __inline__ void *memset(void *src, int c, size_t count) { register void *retval; diff -u --recursive --new-file v1.1.78/linux/include/linux/lp.h linux/include/linux/lp.h --- v1.1.78/linux/include/linux/lp.h Thu Dec 29 20:13:17 1994 +++ linux/include/linux/lp.h Tue Jan 10 10:07:09 1995 @@ -53,20 +53,21 @@ #define LP_INIT_TIME 2 /* IOCTL numbers */ -#define LPCHAR 0x0001 /* corresponds to LP_INIT_CHAR */ -#define LPTIME 0x0002 /* corresponds to LP_INIT_TIME */ -#define LPABORT 0x0004 /* call with TRUE arg to abort on error, +#define LPCHAR 0x0601 /* corresponds to LP_INIT_CHAR */ +#define LPTIME 0x0602 /* corresponds to LP_INIT_TIME */ +#define LPABORT 0x0604 /* call with TRUE arg to abort on error, FALSE to retry. Default is retry. */ -#define LPSETIRQ 0x0005 /* call with new IRQ number, +#define LPSETIRQ 0x0605 /* call with new IRQ number, or 0 for polling (no IRQ) */ -#define LPGETIRQ 0x0006 /* get the current IRQ number */ -#define LPWAIT 0x0008 /* corresponds to LP_INIT_WAIT */ -#define LPCAREFUL 0x0009 /* call with TRUE arg to require out-of-paper, off- +#define LPGETIRQ 0x0606 /* get the current IRQ number */ +#define LPWAIT 0x0608 /* corresponds to LP_INIT_WAIT */ +#define LPCAREFUL 0x0609 /* call with TRUE arg to require out-of-paper, off- line, and error indicators good on all writes, FALSE to ignore them. Default is ignore. */ -#define LPABORTOPEN 0x000a /* call with TRUE arg to abort open() on error, +#define LPABORTOPEN 0x060a /* call with TRUE arg to abort open() on error, FALSE to ignore error. Default is ignore. */ -#define LPGETSTATUS 0x000b /* return LP_S(minor) */ +#define LPGETSTATUS 0x060b /* return LP_S(minor) */ +#define LPRESET 0x060c /* reset printer */ /* timeout for printk'ing a timeout, in jiffies (100ths of a second). This is also used for re-checking error conditions if LP_ABORT is diff -u --recursive --new-file v1.1.78/linux/include/linux/net.h linux/include/linux/net.h --- v1.1.78/linux/include/linux/net.h Mon Jan 9 07:22:10 1995 +++ linux/include/linux/net.h Wed Jan 11 08:03:11 1995 @@ -23,7 +23,7 @@ #include -#define NSOCKETS 128 /* should be dynamic, later... */ +#define NSOCKETS 2000 /* Dynamic, this is MAX LIMIT */ #define NPROTO 16 /* should be enough for now.. */ @@ -80,6 +80,8 @@ struct wait_queue **wait; /* ptr to place to wait on */ struct inode *inode; struct fasync_struct *fasync_list; /* Asynchronous wake up list */ + struct socket *nextsock; /* next on the allocated socks */ + struct socket *prevsock; /* precious on the allocated socks */ }; #define SOCK_INODE(S) ((S)->inode) diff -u --recursive --new-file v1.1.78/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v1.1.78/linux/include/linux/proc_fs.h Mon Jan 9 07:22:11 1995 +++ linux/include/linux/proc_fs.h Wed Jan 11 08:11:02 1995 @@ -15,6 +15,7 @@ PROC_KMSG, PROC_VERSION, PROC_CPUINFO, + PROC_PCI, PROC_SELF, /* will change inode # */ PROC_NET, #ifdef CONFIG_DEBUG_MALLOC @@ -87,6 +88,7 @@ PROC_NET_NR, #endif #endif + PROC_NET_SOCKSTAT, PROC_NET_LAST }; diff -u --recursive --new-file v1.1.78/linux/include/linux/sysv_fs.h linux/include/linux/sysv_fs.h --- v1.1.78/linux/include/linux/sysv_fs.h Sat Nov 5 13:32:13 1994 +++ linux/include/linux/sysv_fs.h Tue Jan 10 17:02:10 1995 @@ -136,7 +136,7 @@ char s_fname[6]; /* file system volume name */ char s_fpack[6]; /* file system pack name */ long s_fill[12]; - long s_state; /* file system state */ + long s_state; /* file system state: 0x7c269d38-s_time means clean */ long s_magic; /* version of file system */ long s_type; /* type of file system: 1 for 512 byte blocks 2 for 1024 byte blocks */ @@ -170,7 +170,7 @@ char s_fname[6]; /* file system volume name */ char s_fpack[6]; /* file system pack name */ long s_fill[14]; - long s_state; /* file system state */ + long s_state; /* file system state: 0xcb096f43 means clean */ long s_magic; /* version of file system */ long s_type; /* type of file system: 1 for 512 byte blocks 2 for 1024 byte blocks */ diff -u --recursive --new-file v1.1.78/linux/include/linux/sysv_fs_sb.h linux/include/linux/sysv_fs_sb.h --- v1.1.78/linux/include/linux/sysv_fs_sb.h Mon Jan 9 07:22:11 1995 +++ linux/include/linux/sysv_fs_sb.h Tue Jan 10 17:02:11 1995 @@ -57,7 +57,7 @@ unsigned long *s_sb_flc_blocks; /* pointer to s_sbd->s_free */ unsigned long *s_sb_total_free_blocks;/* pointer to s_sbd->s_tfree */ unsigned long *s_sb_time; /* pointer to s_sbd->s_time */ - unsigned long *s_sb_state; /* pointer to s_sbd->s_state */ + unsigned long *s_sb_state; /* pointer to s_sbd->s_state, only FSTYPE_SYSV */ /* We keep those superblock entities that don't change here; this saves us an indirection and perhaps a conversion. */ unsigned long s_firstinodezone; /* index of first inode zone */ diff -u --recursive --new-file v1.1.78/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.1.78/linux/kernel/ksyms.c Mon Jan 9 11:24:24 1995 +++ linux/kernel/ksyms.c Tue Jan 10 10:08:21 1995 @@ -188,6 +188,11 @@ X(request_dma), X(free_dma), + /* IO port handling */ + X(check_region), + X(request_region), + X(release_region), + /* process management */ X(wake_up), X(wake_up_interruptible), @@ -246,9 +251,6 @@ X(alloc_skb), X(kfree_skb), X(dev_kfree_skb), - X(snarf_region), - X(request_region), - X(release_region), X(netif_rx), X(dev_rint), X(dev_tint), diff -u --recursive --new-file v1.1.78/linux/net/inet/af_inet.c linux/net/inet/af_inet.c --- v1.1.78/linux/net/inet/af_inet.c Mon Jan 9 11:24:24 1995 +++ linux/net/inet/af_inet.c Wed Jan 11 08:03:11 1995 @@ -154,20 +154,27 @@ struct sock *sk1; struct sock *sk2; int mask; + unsigned long flags; sk->num = num; sk->next = NULL; num = num &(SOCK_ARRAY_SIZE -1); /* We can't have an interrupt re-enter here. */ + save_flags(flags); cli(); + + sk->prot->inuse += 1; + if (sk->prot->highestinuse < sk->prot->inuse) + sk->prot->highestinuse = sk->prot->inuse; + if (sk->prot->sock_array[num] == NULL) { sk->prot->sock_array[num] = sk; - sti(); + restore_flags(flags); return; } - sti(); + restore_flags(flags); for(mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask) { if ((mask & sk->saddr) && @@ -211,6 +218,7 @@ static void remove_sock(struct sock *sk1) { struct sock *sk2; + unsigned long flags; if (!sk1->prot) { @@ -219,12 +227,14 @@ } /* We can't have this changing out from under us. */ + save_flags(flags); cli(); sk2 = sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)]; if (sk2 == sk1) { + sk1->prot->inuse -= 1; sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)] = sk1->next; - sti(); + restore_flags(flags); return; } @@ -235,11 +245,12 @@ if (sk2) { + sk1->prot->inuse -= 1; sk2->next = sk1->next; - sti(); + restore_flags(flags); return; } - sti(); + restore_flags(flags); } /* @@ -1502,6 +1513,12 @@ udp_prot.sock_array[i] = NULL; raw_prot.sock_array[i] = NULL; } + tcp_prot.inuse = 0; + tcp_prot.highestinuse = 0; + udp_prot.inuse = 0; + udp_prot.highestinuse = 0; + raw_prot.inuse = 0; + raw_prot.highestinuse = 0; printk("IP Protocols: "); for(p = inet_protocol_base; p != NULL;) diff -u --recursive --new-file v1.1.78/linux/net/inet/dev.c linux/net/inet/dev.c --- v1.1.78/linux/net/inet/dev.c Mon Jan 9 07:22:12 1995 +++ linux/net/inet/dev.c Tue Jan 10 10:07:07 1995 @@ -281,7 +281,7 @@ return notifier_chain_register(&netdev_chain, nb); } -int unregister_netdevice_notifer(struct notifier_block *nb) +int unregister_netdevice_notifier(struct notifier_block *nb) { return notifier_chain_unregister(&netdev_chain,nb); } @@ -611,7 +611,7 @@ { struct sk_buff *skb; struct packet_type *ptype; - struct packet_type *pt_prev=NULL; + struct packet_type *pt_prev; unsigned short type; /* @@ -684,7 +684,7 @@ * here is minimal but no doubt adds up at the 4,000+ pkts/second * rate we can hit flat out] */ - + pt_prev = NULL; for (ptype = ptype_base; ptype != NULL; ptype = ptype->next) { if ((ptype->type == type || ptype->type == htons(ETH_P_ALL)) && (!ptype->dev || ptype->dev==skb->dev)) diff -u --recursive --new-file v1.1.78/linux/net/inet/ipx.c linux/net/inet/ipx.c --- v1.1.78/linux/net/inet/ipx.c Mon Jan 9 07:22:13 1995 +++ linux/net/inet/ipx.c Tue Jan 10 10:07:20 1995 @@ -32,6 +32,7 @@ * Small correction to promisc mode error fix * Asynchronous I/O support. * Changed to use notifiers and the newer packet_type stuff. + * Assorted major fixes */ #include @@ -432,7 +433,6 @@ } } -/* Called from proc fs */ int ipx_rt_get_info(char *buffer, char **start, off_t offset, int length) { ipx_route *rt; @@ -440,12 +440,13 @@ off_t pos=0; off_t begin=0; - len += sprintf (buffer,"Net Router Flags Dev\n"); + len += sprintf (buffer,"Net Router Flags Dev Frame\n"); for (rt = ipx_router_list; rt != NULL; rt = rt->next) { - len += sprintf (buffer+len,"%08lX %08lX:%02X%02X%02X%02X%02X%02X %02X %s\n", ntohl(rt->net), + len += sprintf (buffer+len,"%08lX %08lX:%02X%02X%02X%02X%02X%02X %02X %s %d\n", ntohl(rt->net), ntohl(rt->router_net), rt->router_node[0], rt->router_node[1], rt->router_node[2], - rt->router_node[3], rt->router_node[4], rt->router_node[5], rt->flags, rt->dev->name); + rt->router_node[3], rt->router_node[4], rt->router_node[5], rt->flags, rt->dev->name, + ntohs(rt->dlink_type)); pos=begin+len; if(pos> 4) & 0x0f]; + *(p++) = ' '; + } + *(p++) = '-'; + *(p++) = ' '; + for (i=0; i < 8 ; i++) *(p++) = ' '<= d[i] && d[i]<'\177' ? d[i] : '.'; + *p = '\000'; + d += i; + printk("%s-%04X: %s\n",str,l*8,b); + } +} + +void dump_addr(char *str,ipx_address *p) { + printk("%s: %08X:%02X%02X%02X%02X%02X%02X:%04X\n", + str,ntohl(p->net),p->node[0],p->node[1],p->node[2], + p->node[3],p->node[4],p->node[5],ntohs(p->sock)); +} + +void dump_hdr(char *str,ipx_packet *p) { + printk("%s: CHKSUM=%04X SIZE=%d (%04X) HOPS=%d (%02X) TYPE=%02X\n", + str,p->ipx_checksum,ntohs(p->ipx_pktsize),ntohs(p->ipx_pktsize), + p->ipx_tctrl,p->ipx_tctrl,p->ipx_type); + dump_addr(" IPX-DST",&p->ipx_dest); + dump_addr(" IPX-SRC",&p->ipx_source); +} + +void dump_pkt(char *str,ipx_packet *p) { + dump_hdr(str,p); + dump_data(str,(unsigned char *)p); +} +#endif + int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) { /* NULL here for pt means the packet was looped back */ @@ -885,6 +930,18 @@ return(0); } + /* + * Ok, before we forward, make sure this is not a local packet on the + * other network + */ + if (rt->router_net == 0) + { + memset(IPXaddr,'\0',6); + memcpy(IPXaddr+(6-rt->dev->addr_len),rt->dev->dev_addr,rt->dev->addr_len); + if (memcmp(IPXaddr,ipx->ipx_dest.node,6) == 0) + goto DELIVER; + } + /* Check for differences in outgoing and incoming packet size */ incoming_size = skb->len - ntohs(ipx->ipx_pktsize); outgoing_size = rt->datalink->header_length + rt->dev->hard_header_len; @@ -900,15 +957,20 @@ return 0; } free_it=1; - skb2->free=1; skb2->len=ntohs(ipx->ipx_pktsize) + outgoing_size; skb2->mem_addr = skb2; - skb2->arp = 1; skb2->sk = NULL; + skb2->free = 1; + skb2->arp = 1; + skb2->len = ntohs(ipx->ipx_pktsize) + outgoing_size; - /* Need to copy with appropriate offsets */ - memcpy((char *)(skb2+1)+outgoing_size, - (char *)(skb+1)+incoming_size, + /* + * NOTE: src arg for memcpy used to be (skb+1)+insize + * however, that doesn't work... (dunno why) + * it should though... + */ + + memcpy((char *)(skb2+1)+outgoing_size,ipx, ntohs(ipx->ipx_pktsize)); } else @@ -931,7 +993,7 @@ return(0); } /************ End of router: Now sanity check stuff for us ***************/ - +DELIVER: /* Ok its for us ! */ if (ln->net == 0L) { /* printk("IPX: Registering local net %lx\n", ipx->ipx_dest.net);*/ @@ -1319,6 +1381,7 @@ /* Called by ddi.c on kernel start up */ static struct packet_type ipx_8023_packet_type = + { 0, /* MUTTER ntohs(ETH_P_8023),*/ 0, /* copy */ diff -u --recursive --new-file v1.1.78/linux/net/inet/packet.c linux/net/inet/packet.c --- v1.1.78/linux/net/inet/packet.c Mon Jan 9 07:22:13 1995 +++ linux/net/inet/packet.c Wed Jan 11 08:03:11 1995 @@ -404,5 +404,6 @@ 128, 0, {NULL,}, - "PACKET" + "PACKET", + 0, 0 }; diff -u --recursive --new-file v1.1.78/linux/net/inet/proc.c linux/net/inet/proc.c --- v1.1.78/linux/net/inet/proc.c Wed Dec 28 09:43:32 1994 +++ linux/net/inet/proc.c Wed Jan 11 08:03:11 1995 @@ -145,6 +145,34 @@ } +/* + * Report socket allocation statistics [mea@utu.fi] + */ +int afinet_get_info(char *buffer, char **start, off_t offset, int length) +{ + /* From net/socket.c */ + extern int socket_get_info(char *, char **, off_t, int); + extern struct proto packet_prot; + + int len = socket_get_info(buffer,start,offset,length); + + len += sprintf(buffer+len,"SOCK_ARRAY_SIZE=%d\n",SOCK_ARRAY_SIZE); + len += sprintf(buffer+len,"TCP: inuse %d highest %d\n", + tcp_prot.inuse, tcp_prot.highestinuse); + len += sprintf(buffer+len,"UDP: inuse %d highest %d\n", + udp_prot.inuse, udp_prot.highestinuse); + len += sprintf(buffer+len,"RAW: inuse %d highest %d\n", + raw_prot.inuse, raw_prot.highestinuse); + len += sprintf(buffer+len,"PAC: inuse %d highest %d\n", + packet_prot.inuse, packet_prot.highestinuse); + *start = buffer + offset; + len -= offset; + if (len > length) + len = length; + return len; +} + + /* * Called from the PROCfs module. This outputs /proc/net/snmp. */ diff -u --recursive --new-file v1.1.78/linux/net/inet/raw.c linux/net/inet/raw.c --- v1.1.78/linux/net/inet/raw.c Mon Dec 12 21:01:10 1994 +++ linux/net/inet/raw.c Wed Jan 11 08:03:11 1995 @@ -314,5 +314,6 @@ 128, 0, {NULL,}, - "RAW" + "RAW", + 0, 0 }; diff -u --recursive --new-file v1.1.78/linux/net/inet/sock.h linux/net/inet/sock.h --- v1.1.78/linux/net/inet/sock.h Mon Jan 9 07:22:13 1995 +++ linux/net/inet/sock.h Wed Jan 11 08:03:11 1995 @@ -91,6 +91,7 @@ unsigned long lingertime; int proc; struct sock *next; + struct sock *prev; /* Doubdly linked chain.. */ struct sock *pair; struct sk_buff * volatile send_head; struct sk_buff * volatile send_tail; @@ -245,6 +246,7 @@ unsigned long retransmits; struct sock * sock_array[SOCK_ARRAY_SIZE]; char name[80]; + int inuse, highestinuse; }; #define TIME_WRITE 1 diff -u --recursive --new-file v1.1.78/linux/net/inet/tcp.c linux/net/inet/tcp.c --- v1.1.78/linux/net/inet/tcp.c Mon Jan 9 11:24:24 1995 +++ linux/net/inet/tcp.c Wed Jan 11 08:03:11 1995 @@ -555,7 +555,7 @@ if (sk->inuse || in_bh) { sk->retransmit_timer.expires = 10; - add_timer(&sk->timer); + add_timer(&sk->retransmit_timer); sti(); return; } @@ -4821,5 +4821,6 @@ 128, 0, {NULL,}, - "TCP" + "TCP", + 0, 0 }; diff -u --recursive --new-file v1.1.78/linux/net/inet/udp.c linux/net/inet/udp.c --- v1.1.78/linux/net/inet/udp.c Mon Jan 9 07:22:13 1995 +++ linux/net/inet/udp.c Wed Jan 11 08:03:11 1995 @@ -599,7 +599,12 @@ if (uh->check && udp_check(uh, len, saddr, daddr)) { - printk("UDP: bad checksum.\n"); + /* wants to know, who sent it, to + go and stomp on the garbage sender... */ + printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n", + ntohl(saddr),ntohs(uh->source), + ntohl(daddr),ntohs(uh->dest), + ulen); udp_statistics.UdpInErrors++; kfree_skb(skb, FREE_WRITE); return(0); @@ -724,6 +729,7 @@ 128, 0, {NULL,}, - "UDP" + "UDP", + 0, 0 }; diff -u --recursive --new-file v1.1.78/linux/net/socket.c linux/net/socket.c --- v1.1.78/linux/net/socket.c Mon Jan 9 07:22:13 1995 +++ linux/net/socket.c Wed Jan 11 08:03:11 1995 @@ -21,7 +21,12 @@ * Alan Cox : Asynchronous I/O support (cribbed from the * tty drivers). * Niibe Yutaka : Asynchronous I/O for writes (4.4BSD style) - * Jeff Uphoff : Made max number of sockets command-line configurable. + * Jeff Uphoff : Made max number of sockets command-line + * configurable. + * Matti Aarnio : Made the number of sockets dynamic, + * to be allocated when needed, and mr. + * Uphoff's max is used as max to be + * allowed to allocate. * * * This program is free software; you can redistribute it and/or @@ -90,9 +95,14 @@ }; /* - * The list of sockets -- allocated in sock_init(). + * The lists of sockets */ -static struct socket *sockets = NULL; + +static struct socket *freesockets = NULL; /* List of free sockets, + pick the first */ +static struct socket *usedsockets = NULL; /* Doubly-linked list of the + active sockets */ + /* * Used to wait for a socket. */ @@ -104,16 +114,23 @@ /* * Maximum number of sockets -- override-able on command-line. */ -static int nsockets = NSOCKETS; - -#define last_socket (sockets + nsockets - 1) +static int maxnsockets = NSOCKETS; +/* + * Number of sockets allocated + */ +static int nsockets = 0; +/* + * Statistics counters of the free/used lists + */ +static int sockets_in_use = 0; +static int sockets_in_free = 0; /* * Overrides default max number of sockets if supplied on command-line. */ void sock_setup(char *str, int *ints) { - nsockets = ints[0] ? ints[1] : NSOCKETS; + maxnsockets = ints[0] ? ints[1] : NSOCKETS; } @@ -214,7 +231,7 @@ return sock; printk("socket.c: uhhuh. stale inode->i_socket pointer\n"); } - for (sock = sockets; sock <= last_socket; ++sock) + for (sock = usedsockets; sock != NULL; sock = sock->nextsock) if (sock->state != SS_FREE && SOCK_INODE(sock) == inode) { printk("socket.c: uhhuh. Found socket despite no inode->i_socket pointer\n"); @@ -247,48 +264,116 @@ static struct socket *sock_alloc(int wait) { struct socket *sock; + int i; while (1) { + if (freesockets == NULL) + { + /* Lets see if we can allocate some more */ + cli(); + /* Alloc them from same memory page, if possible. + Nothing SHOULD prevent us from allocing one at + the time.. */ + for (i = 0; i < 16 && nsockets < maxnsockets; ++i) + { + sock = (struct socket*)kmalloc(sizeof(struct socket),GFP_KERNEL); + if (sock == NULL) break; /* Ah well.. */ + sock->state = SS_FREE; + sock->nextsock = freesockets; + sock->prevsock = NULL; + freesockets = sock; + ++sockets_in_free; + ++nsockets; + } + sti(); +printk("sock_alloc: Alloced some more, now %d sockets\n", nsockets); + } + + cli(); - for (sock = sockets; sock <= last_socket; ++sock) + sock = freesockets; + if (sock != NULL) /* Freelist, we pick + the first -- or only */ { - if (sock->state == SS_FREE) + /* + * Move it to the `usedsockets' linked-list + * at its FRONT (thus ->prevsock = NULL) + */ + freesockets = sock->nextsock; + sock->nextsock = usedsockets; + sock->prevsock = NULL; + /* Is there something in there already ? */ + if (usedsockets != NULL) + /* Yes, attach the `previous' pointer */ + usedsockets->prevsock = sock; + usedsockets = sock; + + --sockets_in_free; + ++sockets_in_use; + sti(); + /* + * Got one.. + */ + sock->state = SS_UNCONNECTED; + sock->flags = 0; + sock->ops = NULL; + sock->data = NULL; + sock->conn = NULL; + sock->iconn = NULL; + sock->fasync_list = NULL; + /* + * This really shouldn't be necessary, but everything + * else depends on inodes, so we grab it. + * Sleeps are also done on the i_wait member of this + * inode. The close system call will iput this inode + * for us. + */ + if (!(SOCK_INODE(sock) = get_empty_inode())) { + printk("NET: sock_alloc: no more inodes\n"); /* - * Got one.. + * Roll-back the linkage */ - sock->state = SS_UNCONNECTED; + cli(); + /* Not the last ? */ + if (sock->nextsock != NULL) + sock->nextsock->prevsock = sock->prevsock; + /* Not the first ? */ + if (sock->prevsock != NULL) + sock->prevsock->nextsock = sock->nextsock; + else + /* It is the first, update the head-handle */ + usedsockets = sock->nextsock; + /* Link it back to the free-list */ + sock->nextsock = freesockets; + sock->prevsock = NULL; /* Not used, but .. */ + freesockets = sock; + ++sockets_in_free; + --sockets_in_use; sti(); - sock->flags = 0; - sock->ops = NULL; - sock->data = NULL; - sock->conn = NULL; - sock->iconn = NULL; - sock->fasync_list = NULL; - /* - * This really shouldn't be necessary, but everything - * else depends on inodes, so we grab it. - * Sleeps are also done on the i_wait member of this - * inode. The close system call will iput this inode - * for us. - */ - if (!(SOCK_INODE(sock) = get_empty_inode())) - { - printk("NET: sock_alloc: no more inodes\n"); - sock->state = SS_FREE; - return(NULL); - } - SOCK_INODE(sock)->i_mode = S_IFSOCK; - SOCK_INODE(sock)->i_uid = current->uid; - SOCK_INODE(sock)->i_gid = current->gid; - SOCK_INODE(sock)->i_socket = sock; - - sock->wait = &SOCK_INODE(sock)->i_wait; - return(sock); + sock->state = SS_FREE; + return(NULL); } + SOCK_INODE(sock)->i_mode = S_IFSOCK; + SOCK_INODE(sock)->i_uid = current->euid; + SOCK_INODE(sock)->i_gid = current->egid; + SOCK_INODE(sock)->i_socket = sock; + + sock->wait = &SOCK_INODE(sock)->i_wait; + + return(sock); } sti(); + + /* + * The rest of these are in fact vestigal from the previous + * version, which didn't have growing list of sockets. + * These may become necessary if there are 2000 (or whatever + * the hard limit is set to) sockets already in system, + * but then the system itself is quite catatonic.. IMO [mea] + */ + /* * If its a 'now or never request' then return. */ @@ -325,6 +410,7 @@ int oldstate; struct inode *inode; struct socket *peersock, *nextsock; + unsigned long flags; if ((oldstate = sock->state) != SS_UNCONNECTED) sock->state = SS_DISCONNECTING; @@ -350,7 +436,28 @@ if (peersock) sock_release_peer(peersock); inode = SOCK_INODE(sock); + /* + * Remove this `sock' from the doubly-linked chain. + */ + save_flags(flags); + cli(); sock->state = SS_FREE; /* this really releases us */ + /* Not the last ? */ + if (sock->nextsock != NULL) + sock->nextsock->prevsock = sock->prevsock; + /* Not the first ? */ + if (sock->prevsock != NULL) + sock->prevsock->nextsock = sock->nextsock; + else + /* It is the first, update the head-handle */ + usedsockets = sock->nextsock; + /* Link it back to the free-list */ + sock->nextsock = freesockets; + sock->prevsock = NULL; /* Not really used, but.. */ + freesockets = sock; + --sockets_in_use; /* Bookkeeping.. */ + ++sockets_in_free; + restore_flags(flags); /* * This will wake anyone waiting for a free socket. @@ -698,8 +805,9 @@ if (!(sock = sock_alloc(1))) { - printk("sock_socket: no more sockets\n"); - return(-EAGAIN); + printk("NET: sock_socket: no more sockets\n"); + return(-ENOSR); /* Was: EAGAIN, but we are out of + system resources! */ } sock->type = type; @@ -871,7 +979,8 @@ if (!(newsock = sock_alloc(0))) { printk("NET: sock_accept: no more sockets\n"); - return(-EAGAIN); + return(-ENOSR); /* Was: EGAIN, but we are out of system + resources! */ } newsock->type = sock->type; newsock->ops = sock->ops; @@ -1406,23 +1515,11 @@ void sock_init(void) { - struct socket *sock; int i; printk("Swansea University Computer Society NET3.019\n"); /* - * The list of sockets. - */ - sockets = (struct socket *)kmalloc(sizeof(struct socket) * nsockets, GFP_KERNEL); - printk("Allocated %d sockets.\n", nsockets); - /* - * Release all sockets. - */ - for (sock = sockets; sock <= last_socket; ++sock) - sock->state = SS_FREE; - - /* * Initialize all address (protocol) families. */ @@ -1447,5 +1544,22 @@ bh_base[NET_BH].routine= net_bh; #endif - +} + +int socket_get_info(char *buffer, char **start, off_t offset, int length) +{ + int len = sprintf(buffer, + "sockets: used %d free %d alloced %d highlimit %d\n", + sockets_in_use, sockets_in_free, + nsockets, maxnsockets); + if (offset >= len) + { + *start = buffer; + return 0; + } + *start = buffer + offset; + len -= offset; + if (len > length) + len = length; + return len; }