diff -u --recursive --new-file v1.1.79/linux/CREDITS linux/CREDITS --- v1.1.79/linux/CREDITS Mon Jan 9 11:24:19 1995 +++ linux/CREDITS Thu Jan 12 13:14:16 1995 @@ -32,6 +32,14 @@ E: balasub@cis.ohio-state.edu D: Wrote SYS V IPC (part of standard kernel since 0.99.10) +N: Dario Ballabio +E: dario@milano.europe.dg.com +D: Author and maintainer of the Ultrastor 14F/34F SCSI driver +D: Author and maintainer of the EATA ISA/EISA SCSI driver +S: Data General Corporation +S: Milano +S: Italy + N: Arindam Banerji E: axb@cse.nd.edu D: Contributed ESDI driver routines needed to port LINUX to the PS/2 MCA. @@ -303,6 +311,16 @@ S: CM2 8HN S: United Kingdom +N: Jochen Hein +E: Hein@Informatik.TU-Clausthal.de +D: National Language Support +D: German Support-Disks for SLS/Slackware called SLT +D: Linux Internationalization Project +D: DOSemu +S: Mohlenweg 19 +S: 34266 Niestetal +S: Germany + N: Michael Hipp E: mhipp@student.uni-tuebingen.de D: drivers for the racal ni5210 & ni6510 ethernet-boards @@ -499,15 +517,10 @@ S: Australia N: John A. Martin -E: jmartin@csc.com E: jam@acm.org E: j.a.martin@ieee.org D: FSSTND contributor D: Credit file compilator -S: Computer Sciences Corporation -S: 1100 West Street -S: Laurel, Maryland 20707-3587 -S: USA N: Kevin E. Martin E: martin@cs.unc.edu @@ -708,6 +721,14 @@ E: csmith@convex.com D: HPFS filesystem S: Richardson, Texas +S: USA + +N: Scott Snyder +E: snyder@fnald0.fnal.gov +D: ATAPI cdrom driver +S: MS 352, Fermilab +S: Post Office Box 500 +S: Batavia, Illinois 60510 S: USA N: Drew Sullivan diff -u --recursive --new-file v1.1.79/linux/Makefile linux/Makefile --- v1.1.79/linux/Makefile Wed Jan 11 21:14:24 1995 +++ linux/Makefile Wed Jan 11 21:11:21 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 79 +SUBLEVEL = 80 ARCH = i386 diff -u --recursive --new-file v1.1.79/linux/arch/alpha/lib/divide.S linux/arch/alpha/lib/divide.S --- v1.1.79/linux/arch/alpha/lib/divide.S Wed Jan 11 21:14:25 1995 +++ linux/arch/alpha/lib/divide.S Wed Jan 11 21:10:52 1995 @@ -45,6 +45,8 @@ * $28 - compare status */ +#define halt .long 0 + /* * Select function type and registers */ @@ -66,17 +68,21 @@ * For 32-bit operations, we need to extend to 64-bit */ #ifdef INTSIZE -#define function func(lu) +#define ufunction func(lu) +#define sfunction func(l) #define LONGIFY(x) zapnot x,15,x +#define SLONGIFY(x) addl x,0,x #else -#define function func(qu) +#define ufunction func(qu) +#define sfunction func(q) #define LONGIFY(x) +#define SLONGIFY(x) #endif .set noat -.globl function -.ent function -function: +.globl ufunction +.ent ufunction +ufunction: subq $30,32,$30 stq $0, 0($30) stq $1, 8($30) @@ -113,4 +119,18 @@ ldq $2, 16($30) addq $30,32,$30 ret $31,($23),1 - .end function + .end ufunction + +/* + * The "signed" version just does a halt if either of the value is + * signed: the kernel shouldn't mess with signed divides anyway (who + * knows what way they'll round..) + */ +.globl sfunction +.ent sfunction +sfunction: + bis $24,$25,$28 + SLONGIFY($28) + bge $28,ufunction + halt + .end sfunction diff -u --recursive --new-file v1.1.79/linux/arch/i386/Makefile linux/arch/i386/Makefile --- v1.1.79/linux/arch/i386/Makefile Mon Jan 9 07:21:55 1995 +++ linux/arch/i386/Makefile Wed Jan 11 21:10:53 1995 @@ -39,8 +39,8 @@ HEAD := arch/i386/kernel/head.o -SUBDIRS := $(SUBDIRS) arch/i386/kernel -ARCHIVES := arch/i386/kernel/kernel.o $(ARCHIVES) +SUBDIRS := $(SUBDIRS) arch/i386/kernel arch/i386/mm +ARCHIVES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(ARCHIVES) ifdef CONFIG_IBCS SUBDIRS := $(SUBDIRS) arch/i386/ibcs diff -u --recursive --new-file v1.1.79/linux/arch/i386/config.in linux/arch/i386/config.in --- v1.1.79/linux/arch/i386/config.in Wed Jan 11 21:14:25 1995 +++ linux/arch/i386/config.in Wed Jan 11 21:17:36 1995 @@ -134,7 +134,7 @@ bool 'DEPCA support' CONFIG_DEPCA n bool 'EtherWorks 3 support' CONFIG_EWRK3 n if [ "$CONFIG_NET_ALPHA" = "y" ]; then -# bool 'Arcnet support' CONFIG_ARCNET n + bool 'Arcnet support' CONFIG_ARCNET n bool 'AT1700 support' CONFIG_AT1700 n # bool 'EtherExpressPro support' CONFIG_EEXPRESS_PRO n bool 'EtherExpress support' CONFIG_EEXPRESS n diff -u --recursive --new-file v1.1.79/linux/arch/i386/kernel/ioport.c linux/arch/i386/kernel/ioport.c --- v1.1.79/linux/arch/i386/kernel/ioport.c Wed Jan 11 21:14:25 1995 +++ linux/arch/i386/kernel/ioport.c Wed Jan 11 21:10:53 1995 @@ -1,5 +1,5 @@ /* - * linux/kernel/ioport.c + * linux/arch/i386/kernel/ioport.c * * This contains the io-permission bitmap code - written by obz, with changes * by Linus. @@ -11,50 +11,8 @@ #include #include -#define IOTABLE_SIZE 32 - -typedef struct resource_entry_t { - u_long from, num; - const char *name; - struct resource_entry_t *next; -} resource_entry_t; - -static resource_entry_t iolist = { 0, 0, "", NULL }; - -static resource_entry_t iotable[IOTABLE_SIZE]; - -#define _IODEBUG - -#ifdef IODEBUG -static char * ios(unsigned long l) -{ - static char str[33] = { '\0' }; - int i; - unsigned long mask; - - for (i = 0, mask = 0x80000000; i < 32; ++i, mask >>= 1) - str[i] = (l & mask) ? '1' : '0'; - return str; -} - -static void dump_io_bitmap(void) -{ - int i, j; - int numl = sizeof(current->tss.io_bitmap) >> 2; - - for (i = j = 0; j < numl; ++i) - { - printk("%4d [%3x]: ", 64*i, 64*i); - printk("%s ", ios(current->tss.io_bitmap[j++])); - if (j < numl) - printk("%s", ios(current->tss.io_bitmap[j++])); - printk("\n"); - } -} -#endif - /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ -asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) +static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) { int mask; unsigned long *bitmap_base = bitmap + (base >> 5); @@ -88,22 +46,6 @@ } /* - * This generates the report for /proc/ioports - */ -int get_ioport_list(char *buf) -{ - resource_entry_t *p; - int len = 0; - - for (p = iolist.next; (p) && (len < 4000); p = p->next) - len += sprintf(buf+len, "%04lx-%04lx : %s\n", - p->from, p->from+p->num-1, p->name); - if (p) - len += sprintf(buf+len, "4K limit reached!\n"); - return len; -} - -/* * this changes the io permissions bitmap in the current task. */ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) @@ -115,9 +57,6 @@ if (!suser()) return -EPERM; -#ifdef IODEBUG - printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off")); -#endif set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on); return 0; } @@ -147,100 +86,4 @@ return -EPERM; *(&eflags) = (eflags & 0xffffcfff) | (level << 12); return 0; -} - -/* - * The workhorse function: find where to put a new entry - */ -static resource_entry_t *find_gap(resource_entry_t *root, - u_long from, u_long num) -{ - unsigned long flags; - resource_entry_t *p; - - if (from > from+num-1) - return NULL; - save_flags(flags); - cli(); - for (p = root; ; p = p->next) { - if ((p != root) && (p->from+p->num-1 >= from)) { - p = NULL; - break; - } - if ((p->next == NULL) || (p->next->from > from+num-1)) - break; - } - restore_flags(flags); - return p; -} - -/* - * Call this from the device driver to register the ioport region. - */ -void request_region(unsigned int from, unsigned int num, const char *name) -{ - resource_entry_t *p; - int i; - - for (i = 0; i < IOTABLE_SIZE; i++) - if (iotable[i].num == 0) - break; - if (i == IOTABLE_SIZE) - printk("warning: ioport table is full\n"); - else { - p = find_gap(&iolist, from, num); - if (p == NULL) - return; - iotable[i].name = name; - iotable[i].from = from; - iotable[i].num = num; - iotable[i].next = p->next; - p->next = &iotable[i]; - return; - } -} - -/* - * 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) -{ - request_region(from,num,"No name given."); -} - -/* - * Call this when the device driver is unloaded - */ -void release_region(unsigned int from, unsigned int num) -{ - resource_entry_t *p, *q; - - for (p = &iolist; ; p = q) { - q = p->next; - if (q == NULL) - break; - if ((q->from == from) && (q->num == num)) { - q->num = 0; - p->next = q->next; - return; - } - } -} - -/* - * Call this to check the ioport region before probing - */ -int check_region(unsigned int from, unsigned int num) -{ - return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0; -} - -/* Called from init/main.c to reserve IO ports. */ -void reserve_setup(char *str, int *ints) -{ - int i; - - for (i = 1; i < ints[0]; i += 2) - request_region(ints[i], ints[i+1], "reserved"); } diff -u --recursive --new-file v1.1.79/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v1.1.79/linux/arch/i386/kernel/process.c Mon Jan 9 07:21:56 1995 +++ linux/arch/i386/kernel/process.c Wed Jan 11 21:10:53 1995 @@ -23,6 +23,27 @@ #include #include +/* + * Tell us the machine setup.. + */ +char hard_math = 0; /* set by boot/head.S */ +char x86 = 0; /* set by boot/head.S to 3 or 4 */ +char x86_model = 0; /* set by boot/head.S */ +char x86_mask = 0; /* set by boot/head.S */ +int x86_capability = 0; /* set by boot/head.S */ +int fdiv_bug = 0; /* set if Pentium(TM) with FP bug */ + +char x86_vendor_id[13] = "Unknown"; + +char ignore_irq13 = 0; /* set if exception 16 works */ +char wp_works_ok = 0; /* set if paging hardware honours WP */ +char hlt_works_ok = 1; /* set if the "hlt" instruction works */ + +/* + * Bus types .. + */ +int EISA_bus = 0; + asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call"); /* diff -u --recursive --new-file v1.1.79/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v1.1.79/linux/arch/i386/kernel/ptrace.c Mon Jan 9 07:21:56 1995 +++ linux/arch/i386/kernel/ptrace.c Wed Jan 11 21:10:53 1995 @@ -87,7 +87,7 @@ unsigned long page; repeat: - page = *PAGE_DIR_OFFSET(vma->vm_task->tss.cr3, addr); + page = *PAGE_DIR_OFFSET(vma->vm_task, addr); if (page & PAGE_PRESENT) { page &= PAGE_MASK; page += PAGE_PTR(addr); @@ -121,7 +121,7 @@ int readonly = 0; repeat: - page = *PAGE_DIR_OFFSET(vma->vm_task->tss.cr3, addr); + page = *PAGE_DIR_OFFSET(vma->vm_task, addr); if (page & PAGE_PRESENT) { page &= PAGE_MASK; page += PAGE_PTR(addr); diff -u --recursive --new-file v1.1.79/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v1.1.79/linux/arch/i386/kernel/traps.c Wed Jan 11 21:14:25 1995 +++ linux/arch/i386/kernel/traps.c Wed Jan 11 21:10:53 1995 @@ -311,6 +311,8 @@ int i; struct desc_struct * p; + if (strncmp((char*)0x0FFFD9, "EISA", 4) == 0) + EISA_bus = 1; set_call_gate(&default_ldt,lcall7); set_trap_gate(0,÷_error); set_trap_gate(1,&debug); diff -u --recursive --new-file v1.1.79/linux/arch/i386/mm/Makefile linux/arch/i386/mm/Makefile --- v1.1.79/linux/arch/i386/mm/Makefile Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/mm/Makefile Wed Jan 11 21:10:53 1995 @@ -0,0 +1,32 @@ +# +# Makefile for the linux i386-specific parts of the memory manager. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +.c.o: + $(CC) $(CFLAGS) -c $< +.s.o: + $(AS) -o $*.o $< +.c.s: + $(CC) $(CFLAGS) -S $< + +OBJS = fault.o + +mm.o: $(OBJS) + $(LD) -r -o mm.o $(OBJS) + +modules: + +dep: + $(CPP) -M *.c > .depend + +# +# include a dependency file if one exists +# +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff -u --recursive --new-file v1.1.79/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v1.1.79/linux/arch/i386/mm/fault.c Thu Jan 1 02:00:00 1970 +++ linux/arch/i386/mm/fault.c Wed Jan 11 21:10:53 1995 @@ -0,0 +1,349 @@ +/* + * linux/arch/i386/mm/fault.c + * + * Copyright (C) 1995 Linus Torvalds + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */ + +extern void scsi_mem_init(unsigned long); +extern void sound_mem_init(void); +extern void die_if_kernel(char *,struct pt_regs *,long); +extern void show_net_buffers(void); + +/* + * Define this if things work differently on a i386 and a i486: + * it will (on a i486) warn about kernel memory accesses that are + * done without a 'verify_area(VERIFY_WRITE,..)' + */ +#undef CONFIG_TEST_VERIFY_AREA + +/* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate + * routines. + */ +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) +{ + struct vm_area_struct * vma; + unsigned long address; + unsigned long page; + + /* get the address */ + __asm__("movl %%cr2,%0":"=r" (address)); + for (vma = current->mm->mmap ; ; vma = vma->vm_next) { + if (!vma) + goto bad_area; + if (vma->vm_end > address) + break; + } + if (vma->vm_start <= address) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) + goto bad_area; + vma->vm_offset -= vma->vm_start - (address & PAGE_MASK); + vma->vm_start = (address & PAGE_MASK); +/* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + if (regs->eflags & VM_MASK) { + unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT; + if (bit < 32) + current->tss.screen_bitmap |= 1 << bit; + } + if (!(vma->vm_page_prot & PAGE_USER)) + goto bad_area; + if (error_code & PAGE_PRESENT) { + if (!(vma->vm_page_prot & (PAGE_RW | PAGE_COW))) + goto bad_area; +#ifdef CONFIG_TEST_VERIFY_AREA + if (regs->cs == KERNEL_CS) + printk("WP fault at %08x\n", regs->eip); +#endif + do_wp_page(vma, address, error_code); + return; + } + do_no_page(vma, address, error_code); + return; + +/* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: + if (error_code & PAGE_USER) { + current->tss.cr2 = address; + current->tss.error_code = error_code; + current->tss.trap_no = 14; + send_sig(SIGSEGV, current, 1); + return; + } +/* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + if (wp_works_ok < 0 && address == TASK_SIZE && (error_code & PAGE_PRESENT)) { + wp_works_ok = 1; + pg0[0] = PAGE_SHARED; + invalidate(); + printk("This processor honours the WP bit even when in supervisor mode. Good.\n"); + return; + } + if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) { + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + pg0[0] = PAGE_SHARED; + } else + printk(KERN_ALERT "Unable to handle kernel paging request"); + printk(" at virtual address %08lx\n",address); + __asm__("movl %%cr3,%0" : "=r" (page)); + printk(KERN_ALERT "current->tss.cr3 = %08lx, %%cr3 = %08lx\n", + current->tss.cr3, page); + page = ((unsigned long *) page)[address >> 22]; + printk(KERN_ALERT "*pde = %08lx\n", page); + if (page & PAGE_PRESENT) { + page &= PAGE_MASK; + address &= 0x003ff000; + page = ((unsigned long *) page)[address >> PAGE_SHIFT]; + printk(KERN_ALERT "*pte = %08lx\n", page); + } + die_if_kernel("Oops", regs, error_code); + do_exit(SIGKILL); +} + +/* + * BAD_PAGE is the page that is used for page faults when linux + * is out-of-memory. Older versions of linux just did a + * do_exit(), but using this instead means there is less risk + * for a process dying in kernel mode, possibly leaving a inode + * unused etc.. + * + * BAD_PAGETABLE is the accompanying page-table: it is initialized + * to point to BAD_PAGE entries. + * + * ZERO_PAGE is a special page that is used for zero-initialized + * data and COW. + */ +unsigned long __bad_pagetable(void) +{ + extern char empty_bad_page_table[PAGE_SIZE]; + + __asm__ __volatile__("cld ; rep ; stosl": + :"a" (BAD_PAGE + PAGE_TABLE), + "D" ((long) empty_bad_page_table), + "c" (PTRS_PER_PAGE) + :"di","cx"); + return (unsigned long) empty_bad_page_table; +} + +unsigned long __bad_page(void) +{ + extern char empty_bad_page[PAGE_SIZE]; + + __asm__ __volatile__("cld ; rep ; stosl": + :"a" (0), + "D" ((long) empty_bad_page), + "c" (PTRS_PER_PAGE) + :"di","cx"); + return (unsigned long) empty_bad_page; +} + +unsigned long __zero_page(void) +{ + extern char empty_zero_page[PAGE_SIZE]; + + __asm__ __volatile__("cld ; rep ; stosl": + :"a" (0), + "D" ((long) empty_zero_page), + "c" (PTRS_PER_PAGE) + :"di","cx"); + return (unsigned long) empty_zero_page; +} + +void show_mem(void) +{ + int i,free = 0,total = 0,reserved = 0; + int shared = 0; + + printk("Mem-info:\n"); + show_free_areas(); + printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + i = high_memory >> PAGE_SHIFT; + while (i-- > 0) { + total++; + if (mem_map[i] & MAP_PAGE_RESERVED) + reserved++; + else if (!mem_map[i]) + free++; + else + shared += mem_map[i]-1; + } + printk("%d pages of RAM\n",total); + printk("%d free pages\n",free); + printk("%d reserved pages\n",reserved); + printk("%d pages shared\n",shared); + show_buffers(); +#ifdef CONFIG_NET + show_net_buffers(); +#endif +} + +extern unsigned long free_area_init(unsigned long, unsigned long); + +/* + * paging_init() sets up the page tables - note that the first 4MB are + * already mapped by head.S. + * + * This routines also unmaps the page at virtual kernel address 0, so + * that we can trap those pesky NULL-reference errors in the kernel. + */ +unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) +{ + unsigned long * pg_dir; + unsigned long * pg_table; + unsigned long tmp; + unsigned long address; + +/* + * Physical page 0 is special; it's not touched by Linux since BIOS + * and SMM (for laptops with [34]86/SL chips) may need it. It is read + * and write protected to detect null pointer references in the + * kernel. + */ +#if 0 + memset((void *) 0, 0, PAGE_SIZE); +#endif + start_mem = PAGE_ALIGN(start_mem); + address = 0; + pg_dir = swapper_pg_dir; + while (address < end_mem) { + tmp = *(pg_dir + 768); /* at virtual addr 0xC0000000 */ + if (!tmp) { + tmp = start_mem | PAGE_TABLE; + *(pg_dir + 768) = tmp; + start_mem += PAGE_SIZE; + } + *pg_dir = tmp; /* also map it in at 0x0000000 for init */ + pg_dir++; + pg_table = (unsigned long *) (tmp & PAGE_MASK); + for (tmp = 0 ; tmp < PTRS_PER_PAGE ; tmp++,pg_table++) { + if (address < end_mem) + *pg_table = address | PAGE_SHARED; + else + *pg_table = 0; + address += PAGE_SIZE; + } + } + invalidate(); + return free_area_init(start_mem, end_mem); +} + +void mem_init(unsigned long start_low_mem, + unsigned long start_mem, unsigned long end_mem) +{ + int codepages = 0; + int reservedpages = 0; + int datapages = 0; + unsigned long tmp; + extern int etext; + + end_mem &= PAGE_MASK; + high_memory = end_mem; + + /* mark usable pages in the mem_map[] */ + start_low_mem = PAGE_ALIGN(start_low_mem); + start_mem = PAGE_ALIGN(start_mem); + + /* + * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000. + * They seem to have done something stupid with the floppy + * controller as well.. + */ + while (start_low_mem < 0x9f000) { + mem_map[MAP_NR(start_low_mem)] = 0; + start_low_mem += PAGE_SIZE; + } + + while (start_mem < high_memory) { + mem_map[MAP_NR(start_mem)] = 0; + start_mem += PAGE_SIZE; + } +#ifdef CONFIG_SCSI + scsi_mem_init(high_memory); +#endif +#ifdef CONFIG_SOUND + sound_mem_init(); +#endif + for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) { + if (mem_map[MAP_NR(tmp)]) { + if (tmp >= 0xA0000 && tmp < 0x100000) + reservedpages++; + else if (tmp < (unsigned long) &etext) + codepages++; + else + datapages++; + continue; + } + mem_map[MAP_NR(tmp)] = 1; + free_page(tmp); + } + tmp = nr_free_pages << PAGE_SHIFT; + printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n", + tmp >> 10, + high_memory >> 10, + codepages << (PAGE_SHIFT-10), + reservedpages << (PAGE_SHIFT-10), + datapages << (PAGE_SHIFT-10)); +/* test if the WP bit is honoured in supervisor mode */ + wp_works_ok = -1; + pg0[0] = PAGE_READONLY; + invalidate(); + __asm__ __volatile__("movb 0,%%al ; movb %%al,0": : :"ax", "memory"); + pg0[0] = 0; + invalidate(); + if (wp_works_ok < 0) + wp_works_ok = 0; +#ifdef CONFIG_TEST_VERIFY_AREA + wp_works_ok = 0; +#endif + return; +} + +void si_meminfo(struct sysinfo *val) +{ + int i; + + i = high_memory >> PAGE_SHIFT; + val->totalram = 0; + val->sharedram = 0; + val->freeram = nr_free_pages << PAGE_SHIFT; + val->bufferram = buffermem; + while (i-- > 0) { + if (mem_map[i] & MAP_PAGE_RESERVED) + continue; + val->totalram++; + if (!mem_map[i]) + continue; + val->sharedram += mem_map[i]-1; + } + val->totalram <<= PAGE_SHIFT; + val->sharedram <<= PAGE_SHIFT; + return; +} diff -u --recursive --new-file v1.1.79/linux/drivers/char/console.c linux/drivers/char/console.c --- v1.1.79/linux/drivers/char/console.c Wed Jan 11 21:14:26 1995 +++ linux/drivers/char/console.c Wed Jan 11 21:10:53 1995 @@ -735,8 +735,8 @@ if (b > video_num_lines || t >= b) return; - d = (unsigned short *) origin+video_size_row*b; - s = (unsigned short *) origin+video_size_row*(b-1); + 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--; diff -u --recursive --new-file v1.1.79/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v1.1.79/linux/drivers/net/Makefile Mon Jan 9 11:24:21 1995 +++ linux/drivers/net/Makefile Wed Jan 11 17:59:29 1995 @@ -171,6 +171,10 @@ NETDRV_OBJS := $(NETDRV_OBJS) 8390.o endif +ifdef CONFIG_ARCNET +NETDRV_OBJS := $(NETDRV_OBJS) arcnet.o +endif + ifdef CONFIG_PI NETDRV_OBJS := $(NETDRV_OBJS) pi2.o CONFIG_PI = CONFIG_PI diff -u --recursive --new-file v1.1.79/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v1.1.79/linux/drivers/net/Space.c Tue Dec 6 13:09:02 1994 +++ linux/drivers/net/Space.c Wed Jan 11 17:57:40 1995 @@ -283,6 +283,14 @@ #define NEXT_DEV (&ppp0_dev) #endif /* PPP */ +#ifdef CONFIG_ARCNET + extern int arcnet_probe(struct device *dev); + static struct device arcnet_dev = { + "arc0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, arcnet_probe, }; +# undef NEXT_DEV +# define NEXT_DEV (&arcnet_dev) +#endif + #ifdef CONFIG_DUMMY extern int dummy_init(struct device *dev); static struct device dummy_dev = { diff -u --recursive --new-file v1.1.79/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c --- v1.1.79/linux/drivers/net/arcnet.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/net/arcnet.c Wed Jan 11 17:47:36 1995 @@ -0,0 +1,1825 @@ +/* + arcnet.c written 1994 by Avery Pennarun, derived from skeleton.c + by Donald Becker. + + Contact Avery at: apenwarr@tourism.807-city.on.ca or + RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9 + + !!! This is a dangerous alpha version !!! + + ********************** + + skeleton.c Written 1993 by Donald Becker. + Copyright 1993 United States Government as represented by the Director, + National Security Agency. This software may only be used and distributed + according to the terms of the GNU Public License as modified by SRC, + incorporated herein by reference. + + The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O + Center of Excellence in Space Data and Information Sciences + Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 + + ********************** + + + TO DO: + + - Polled transmits probably take a lot more CPU time than needed. + Perhaps use the system timer? A better solution would be to + just figure out how to get both xmit and receive IRQ's working + at the same time. No luck yet... + - I'd also like to get ping-pong TX buffers working. + - Test in systems with NON-ARCnet network cards, just to see if + autoprobe kills anything. With any luck, it won't. (It's pretty + strict and careful.) + - cards with shared memory that can be "turned off?" + - examine TRXNET for information about this + */ + +/**************************************************************************/ + +/* define this for "careful" transmitting. Try with and without if you have + * problems. + */ +#define CAREFUL_XMIT + +/* define this for an extra-careful memory detect. This should work all + * the time now, but you never know. + */ +#define STRICT_MEM_DETECT + +/* define this to use the "old-style" limited MTU by default. It basically + * disables packet splitting. ifconfig can still be used to reset the MTU. + * + * leave this disabled if possible, so it will use ethernet defaults, + * which is our goal. + */ +#undef LIMIT_MTU + +/* define this if you have a problem with the card getting "stuck" now and + * then, which can only be fixed by a reboot or resetting the card manually + * via ifconfig up/down. ARCnet will set a timer function which is called + * 8 times every second. + * + * This should no longer be necessary. if you experience "stuck" ARCnet + * drivers, please email apenwarr@tourism.807-city.on.ca or I will remove + * this feature in a future release. + */ +#undef USE_TIMER_HANDLER + +/**************************************************************************/ + +static char *version = + "arcnet.c:v0.32 ALPHA 94/12/26 Avery Pennarun \n"; + +/* Always include 'config.h' first in case the user wants to turn on + or override something. */ +#include + +/* + Sources: + Crynwr arcnet.com/arcether.com packet drivers. + arcnet.c v0.00 dated 1/1/94 and apparently by + Donald Becker - it didn't work :) + skeleton.c v0.05 dated 11/16/93 by Donald Becker + (from Linux Kernel 1.1.45) + ...I sure wish I had the ARCnet data sheets right about now! + RFC's 1201 and 1051 (mostly 1201) - re: ARCnet IP packets + net/inet/eth.c (from kernel 1.1.50) for header-building info... +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "arp.h" + +/* debug levels: + * D_OFF production + * D_NORMAL verification + * D_INIT show init/detect messages + * D_DURING show messages during normal use (ie interrupts) + * D_TX show tx packets + * D_RX show tx+rx packets + */ +#define D_OFF 0 +#define D_NORMAL 1 +#define D_INIT 2 +#define D_EXTRA 3 +#define D_DURING 4 +#define D_TX 5 +#define D_RX 6 + +#ifndef NET_DEBUG +#define NET_DEBUG D_INIT +#endif +static unsigned int net_debug = NET_DEBUG; + +#ifndef HAVE_AUTOIRQ +/* From auto_irq.c, in ioport.h for later versions. */ +extern void autoirq_setup(int waittime); +extern int autoirq_report(int waittime); +/* The map from IRQ number (as passed to the interrupt handler) to + 'struct device'. */ +extern struct device *irq2dev_map[16]; +#endif + +#ifndef HAVE_PORTRESERVE +#define check_region(ioaddr, size) 0 +#define snarf_region(ioaddr, size); do ; while (0) +#endif + +/* macro to simplify debug checking */ +#define BUGLVL(x) if (net_debug>=x) + +/* The number of low I/O ports used by the ethercard. */ +#define ETHERCARD_TOTAL_SIZE 16 + + +/* Handy defines for ARCnet specific stuff */ + /* COM 9026 (?) --> ARCnet register addresses */ +#define INTMASK (ioaddr+0) /* writable */ +#define STATUS (ioaddr+0) /* readable */ +#define COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ +#define RESET (ioaddr+8) /* software reset writable */ + + /* time needed for various things (in clock ticks, 1/100 sec) */ +#define RESETtime 40 /* reset */ +#define XMITtime 10 /* send */ +#define ACKtime 10 /* acknowledge */ + + /* these are the max/min lengths of packet data. (including + * ClientData header) + * note: packet sizes 250, 251, 252 are impossible (God knows why) + * so exception packets become necessary. + * + * These numbers are compared with the length of the full packet, + * including ClientData header. + */ +#define MTU (253+EXTRA_CLIENTDATA) /* normal packet max size */ +#define MinTU (257+EXTRA_CLIENTDATA) /* extended packet min size */ +#define XMTU (508+EXTRA_CLIENTDATA) /* extended packet max size */ + + /* status/interrupt mask bit fields */ +#define TXFREEflag 0x001 /* transmitter available */ +#define TXACKflag 0x002 /* transmitted msg. ackd */ +#define RECONflag 0x004 /* system reconfigured */ +#define TESTflag 0x008 /* test flag */ +#define RESETflag 0x010 /* power-on-reset */ +#define RES1flag 0x020 /* unused */ +#define RES2flag 0x040 /* unused */ +#define NORXflag 0x080 /* receiver inhibited */ + + /* in the command register, the following bits have these meanings: + * 0-2 command + * 3-4 page number (for enable rcv/xmt command) + * 7 receive broadcasts + */ +#define NOTXcmd 0x001 /* disable transmitter */ +#define NORXcmd 0x002 /* disable receiver */ +#define TXcmd 0x003 /* enable transmitter */ +#define RXcmd 0x004 /* enable receiver */ +#define CONFIGcmd 0x005 /* define configuration */ +#define CFLAGScmd 0x006 /* clear flags */ +#define TESTcmd 0x007 /* load test flags */ + + /* flags for "clear flags" command */ +#define RESETclear 0x008 /* power-on-reset */ +#define CONFIGclear 0x010 /* system reconfigured */ + + /* flags for "load test flags" command */ +#define TESTload 0x008 /* test flag (diagnostic) */ + + /* byte deposited into first address of buffers on reset */ +#define TESTvalue 0321 /* that's octal for 0xD1 :) */ + + /* for "enable receiver" command */ +#define RXbcasts 0x080 /* receive broadcasts */ + + /* flags for "define configuration" command */ +#define NORMALconf 0x000 /* 1-249 byte packets */ +#define EXTconf 0x008 /* 250-504 byte packets */ + + /* buffers (4 total) used for receive and xmit. + */ +#define EnableReceiver() outb(RXcmd|(recbuf<<3)|RXbcasts,COMMAND) +#define TXbuf 2 + + /* Protocol ID's */ +#define ARC_P_IP 212 /* 0xD4 */ +#define ARC_P_ARP 213 /* 0xD5 */ +#define ARC_P_RARP 214 /* 0xD6 */ + + /* Length of time between "stuck" checks */ +#define TIMERval (HZ/8) /* about 1/8 second */ + + /* these structures define the format of an arcnet packet. */ +#define NORMAL 0 +#define EXTENDED 1 +#define EXCEPTION 2 + + /* the header required by the card itself */ +struct HardHeader +{ + u_char source, /* source ARCnet - filled in automagically */ + destination, /* destination ARCnet - 0 for broadcast */ + offset1, /* offset of ClientData (256-byte packets) */ + offset2; /* offset of ClientData (512-byte packets) */ +}; + + /* a complete ARCnet packet */ +union ArcPacket +{ + struct HardHeader hardheader; /* the hardware header */ + u_char raw[512]; /* raw packet info, incl ClientData */ +}; + + /* the "client data" header - RFC-1201 information + * notice that this screws up if it's not an even number of bytes + * + */ +struct ClientData +{ + /* data that's NOT part of real packet */ + u_char daddr; /* Destination address - stored here, + * but WE MUST GET RID OF IT BEFORE SENDING A + * PACKET!! + */ + u_char stupid; /* filler to make struct an even # of bytes */ + + /* data that IS part of real packet */ + u_char protocol_id, /* ARC_P_IP, ARC_P_ARP, or ARC_P_RARP */ + split_flag; /* for use with split packets */ + u_short sequence; /* sequence number (?) */ +}; +#define EXTRA_CLIENTDATA (sizeof(struct ClientData)-4) + + +/* "Incoming" is information needed for each address that could be sending + * to us. Mostly for partially-received split packets. + */ +struct Incoming +{ + struct sk_buff *skb; /* packet data buffer */ + unsigned char lastpacket, /* number of last packet (from 1) */ + numpackets; /* number of packets in split */ + u_short sequence; /* sequence number of assembly */ +}; + + +/* Information that needs to be kept for each board. */ +struct arcnet_local { + struct enet_statistics stats; + u_char arcnum; /* arcnet number - our 8-bit address */ + u_short sequence; /* sequence number (incs with each packet) */ + u_char recbuf; /* receive buffer # (0 or 1) */ + int intx; /* in TX routine? */ + struct timer_list timer; /* the timer interrupt struct */ + struct Incoming incoming[256]; /* one from each address */ +}; + + +/* Index to functions, as function prototypes. */ + +extern int arcnet_probe(struct device *dev); +static int arcnet_memprobe(struct device *dev,u_char *addr); +static int arcnet_ioprobe(struct device *dev, short ioaddr); + +static int arcnet_open(struct device *dev); +static int arcnet_close(struct device *dev); + +static int arcnet_send_packet(struct sk_buff *skb, struct device *dev); +static void careful_xmit_wait(struct device *dev); +static int arcnet_tx(struct device *dev,struct ClientData *hdr,short length, + char *data); + +static void arcnet_interrupt(int reg_ptr); +static void arcnet_inthandler(struct device *dev); +static void arcnet_rx(struct device *dev,int recbuf); + + +static void arcnet_timer(unsigned long arg); + +static struct enet_statistics *arcnet_get_stats(struct device *dev); +static void set_multicast_list(struct device *dev, int num_addrs, void *addrs); + + /* annoying functions for header/arp/etc building */ +int arc_header(unsigned char *buff,struct device *dev,unsigned short type, + void *daddr,void *saddr,unsigned len,struct sk_buff *skb); +int arc_rebuild_header(void *eth,struct device *dev,unsigned long raddr, + struct sk_buff *skb); +unsigned short arc_type_trans(struct sk_buff *skb,struct device *dev); + + +#define tx_done(dev) 1 +#define JIFFER(time) for (delayval=jiffies+(time); delayval>=jiffies;); +static int arcnet_reset(struct device *dev); + + +/* Check for a network adaptor of this type, and return '0' if one exists. + * If dev->base_addr == 0, probe all likely locations. + * If dev->base_addr == 1, always return failure. + * If dev->base_addr == 2, allocate space for the device and return success + * (detachable devices only). + */ +int +arcnet_probe(struct device *dev) +{ + /* I refuse to probe anything less than 0x200, because anyone using + * an address like that should probably be shot. + */ + int *port, ports[] = {/* first the suggested values! */ + 0x300,0x2E0,0x2F0,0x2D0, + /* ...now everything else possible. */ + 0x200,0x210,0x220,0x230,0x240,0x250,0x260,0x270, + 0x280,0x290,0x2a0,0x2b0,0x2c0, + 0x310,0x320,0x330,0x340,0x350,0x360,0x370, + 0x380,0x390,0x3a0,0x3b0,0x3c0,0x3d0,0x3e0,0x3f0, + /* a null ends the list */ + 0}; + /* I'm not going to probe under 0xA0000 either, for similar reasons. + */ + unsigned long *addr, addrs[] = {0xD0000,0xE0000,0xA0000,0xB0000, + 0xC0000,0xF0000, + /* from */ + 0xE1000, + 0xDD000,0xDC000, + 0xD9000,0xD8000,0xD5000,0xD4000,0xD1000, + 0xCD000,0xCC000, + 0xC9000,0xC8000,0xC5000,0xC4000, + /* terminator */ + 0}; + int base_addr=dev->base_addr, status=0,delayval; + struct arcnet_local *lp; + + if (net_debug) printk(version); + + BUGLVL(D_INIT) + printk("arcnet: given: base %Xh, IRQ %Xh, shmem %lXh\n", + dev->base_addr,dev->irq,dev->mem_start); + + if (base_addr > 0x1ff) /* Check a single specified location. */ + status=arcnet_ioprobe(dev, base_addr); + else if (base_addr > 0) /* Don't probe at all. */ + return ENXIO; + else for (port = &ports[0]; *port; port++) + { + int ioaddr = *port; + if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE)) + { + BUGLVL(D_INIT) + printk("arcnet: Skipping %Xh because of check_region...\n", + ioaddr); + continue; + } + + status=arcnet_ioprobe(dev, ioaddr); + if (!status) break; + } + + if (status) return status; + + /* ioprobe turned out okay. Now give it a couple seconds to finish + * initializing... + */ + BUGLVL(D_INIT) + printk("arcnet: ioprobe okay! Waiting for reset...\n"); + JIFFER(100); + + /* okay, now we have to find the shared memory area. */ + BUGLVL(D_INIT) + printk("arcnet: starting memory probe, given %lXh\n", + dev->mem_start); + if (dev->mem_start) /* value given - probe just that one */ + { + status=arcnet_memprobe(dev,(u_char *)dev->mem_start); + if (status) return status; + } + else /* no value given - probe everything */ + { + for (addr = &addrs[0]; *addr; addr++) { + status=arcnet_memprobe(dev,(u_char *)(*addr)); + if (!status) break; + } + + if (status) return status; + } + + /* now reserve the irq... */ + { int irqval = request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet"); + if (irqval) { + printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, + dev->irq, irqval); + return EAGAIN; + } + } + + /* Grab the region so we can find another board if autoIRQ fails. */ + snarf_region(dev->base_addr, ETHERCARD_TOTAL_SIZE); + + printk("%s: ARCnet card found at %03Xh, IRQ %d, ShMem at %lXh.\n", dev->name, + dev->base_addr, dev->irq, dev->mem_start); + + /* Initialize the device structure. */ + dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); + memset(dev->priv, 0, sizeof(struct arcnet_local)); + lp=(struct arcnet_local *)(dev->priv); + + dev->open = arcnet_open; + dev->stop = arcnet_close; + dev->hard_start_xmit = arcnet_send_packet; + dev->get_stats = arcnet_get_stats; +#ifdef HAVE_MULTICAST + dev->set_multicast_list = &set_multicast_list; +#endif + + /* Fill in the fields of the device structure with ethernet-generic values. */ + ether_setup(dev); + + /* And now fill particular ones with arcnet values :) */ + + dev->type=ARPHRD_ARCNET; + dev->hard_header_len=sizeof(struct ClientData); + BUGLVL(D_EXTRA) + printk("arcnet: ClientData header size is %d.\narcnet: HardHeader size is %d.\n", + sizeof(struct ClientData),sizeof(struct HardHeader)); +#if LIMIT_MTU /* the old way - normally, now use ethernet default */ + dev->mtu=512-sizeof(struct HardHeader)+EXTRA_CLIENTDATA; +#endif + /* since we strip EXTRA_CLIENTDATA bytes off before sending, + * we let Linux add that many bytes to the packet data... + */ + dev->addr_len=1; + dev->broadcast[0]=0x00; + + BUGLVL(D_INIT) printk("arcnet: arcnet_probe: resetting card.\n"); + arcnet_reset(dev); + JIFFER(50); + BUGLVL(D_NORMAL) + printk("arcnet: We appear to be station %d (%02Xh)\n", + lp->arcnum,lp->arcnum); + if (lp->arcnum==0) + printk("arcnet: WARNING! Station address 0 is reserved for broadcasts!\n"); + if (lp->arcnum==255) + printk("arcnet: WARNING! Station address 255 may confuse DOS networking programs!\n"); + dev->dev_addr[0]=lp->arcnum; + lp->sequence=1; + lp->recbuf=0; + + dev->hard_header = arc_header; +/* dev->add_arp = arc_add_arp; AVE unavailable in 1.1.51?! */ + dev->rebuild_header = arc_rebuild_header; + dev->type_trans = arc_type_trans; + + return 0; +} + +int arcnet_ioprobe(struct device *dev, short ioaddr) +{ + int delayval,airq; + + BUGLVL(D_INIT) + printk("arcnet: probing address %Xh\n",ioaddr); + + BUGLVL(D_INIT) + printk("arcnet: status1=%Xh\n",inb(STATUS)); + + + /* very simple - all we have to do is reset the card, and if there's + * no irq, it's not an ARCnet. We can also kill two birds with + * one stone because we detect the IRQ at the same time :) + */ + + /* reset the card by reading the reset port */ + inb(RESET); + JIFFER(RESETtime); + + /* if status port is FF, there's certainly no arcnet... give up. */ + if (inb(STATUS)==0xFF) + { + BUGLVL(D_INIT) + printk("arcnet: probe failed. Status port empty.\n"); + return ENODEV; + } + + /* we'll try to be reasonably sure it's an arcnet by making sure + * the value of the COMMAND port changes automatically once in a + * while. I have no idea what those values ARE, but at least + * they work. + */ + { + int initval,curval; + + curval=initval=inb(COMMAND); + delayval=jiffies+5; + while (delayval>=jiffies && curval==initval) + curval=inb(COMMAND); + + if (curval==initval) + { + printk("arcnet: probe failed. never-changing command port (%02Xh).\n", + initval); + return ENODEV; + } + } + + BUGLVL(D_INIT) + printk("arcnet: status2=%Xh\n",inb(STATUS)); + + /* now we turn the reset bit off so we can IRQ next reset... */ + outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND); + JIFFER(ACKtime); + if (inb(STATUS) & RESETflag) /* reset flag STILL on */ + { + BUGLVL(D_INIT) + printk("arcnet: probe failed. eternal reset flag1...(status=%Xh)\n", + inb(STATUS)); + return ENODEV; + } + + /* set up automatic IRQ detection */ + autoirq_setup(0); + + /* enable reset IRQ's (shouldn't be necessary, but hey) */ + outb(RESETflag,INTMASK); + + /* now reset it again to generate an IRQ */ + inb(RESET); + JIFFER(RESETtime); + + BUGLVL(D_INIT) + printk("arcnet: status3=%Xh\n",inb(STATUS)); + + /* enable reset IRQ's again */ + outb(RESETflag,INTMASK); + + /* and turn the reset flag back off */ + outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND); + JIFFER(ACKtime); + + BUGLVL(D_INIT) + printk("arcnet: status4=%Xh\n",inb(STATUS)); + + /* now reset it again to generate an IRQ */ + inb(RESET); + JIFFER(RESETtime); + + BUGLVL(D_INIT) + printk("arcnet: status5=%Xh\n",inb(STATUS)); + + airq = autoirq_report(0); + if (net_debug>=D_INIT && airq) + printk("arcnet: autoirq is %d\n", airq); + + /* if there was no autoirq AND the user hasn't set any defaults, + * give up. + */ + if (!airq && !(dev->base_addr && dev->irq)) + { + BUGLVL(D_INIT) + printk("arcnet: probe failed. no autoirq...\n"); + return ENODEV; + } + + /* otherwise we probably have a card. Let's make sure. */ + + if (inb(STATUS) & RESETflag) /* reset flag on */ + { + /* now we turn the reset bit off */ + outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND); + JIFFER(ACKtime); + } + + if (inb(STATUS) & RESETflag) /* reset flag STILL on */ + { + BUGLVL(D_INIT) + printk("arcnet: probe failed. eternal reset flag...(status=%Xh)\n", + inb(STATUS)); + return ENODEV; + } + + /* okay, we've got a real, live ARCnet on our hands. */ + if (!dev->base_addr) dev->base_addr=ioaddr; + + if (dev->irq < 2) /* "Auto-IRQ" */ + { + /* we already did the autoirq above, so store the values */ + dev->irq=airq; + } + else if (dev->irq == 2) + { + if (net_debug) + printk("arcnet: IRQ2 == IRQ9, don't worry.\n"); + dev->irq = 9; + } + + BUGLVL(D_INIT) + printk("arcnet: irq and base address seem okay. (%Xh, IRQ %d)\n", + dev->base_addr,dev->irq); + return 0; +} + +/* A memory probe that is called after the card is reset. + * It checks for the official TESTvalue in byte 0 and makes sure the buffer + * has certain characteristics of an ARCnet... + */ +int arcnet_memprobe(struct device *dev,u_char *addr) +{ + BUGLVL(D_INIT) + printk("arcnet: probing memory at %lXh\n",(u_long)addr); + + dev->mem_start=0; + +#ifdef STRICT_MEM_DETECT /* probably better. */ + /* ARCnet memory byte 0 is TESTvalue */ + if (addr[0]!=TESTvalue) + { + BUGLVL(D_INIT) + printk("arcnet: probe failed. addr=%lXh, addr[0]=%Xh (not %Xh)\n", + (unsigned long)addr,addr[0],TESTvalue); + return ENODEV; + } + + /* now verify the shared memory writability */ + addr[0]=0x42; + if (addr[0]!=0x42) + { + BUGLVL(D_INIT) + printk("arcnet: probe failed. addr=%lXh, addr[0]=%Xh (not 42h)\n", + (unsigned long)addr,addr[0]); + return ENODEV; + } +#else + if (addr[0]!=TESTvalue) + { + BUGLVL(D_INIT) + printk("arcnet: probe failed. addr=%lXh, addr[0]=%Xh (not %Xh)\n", + (unsigned long)addr,addr[0],TESTvalue); + return ENODEV; + } +#endif + + /* got it! fill in dev */ + dev->mem_start=(unsigned long)addr; + dev->mem_end=dev->mem_start+512*4-1; + dev->rmem_start=dev->mem_start+512*0; + dev->rmem_end=dev->mem_start+512*2-1; + + return 0; +} + + +/* Open/initialize the board. This is called (in the current kernel) + sometime after booting when the 'ifconfig' program is run. + + This routine should set everything up anew at each open, even + registers that "should" only need to be set once at boot, so that + there is non-reboot way to recover if something goes wrong. + */ +static int +arcnet_open(struct device *dev) +{ + struct arcnet_local *lp = (struct arcnet_local *)dev->priv; +/* int ioaddr = dev->base_addr;*/ + + if (net_debug) printk(version); + +#if 0 /* Yup, they're hardwired in arcnets */ + /* This is used if the interrupt line can turned off (shared). + See 3c503.c for an example of selecting the IRQ at config-time. */ + if (request_irq(dev->irq, &arcnet_interrupt, 0, "arcnet")) { + return -EAGAIN; + } +#endif + + irq2dev_map[dev->irq] = dev; + + /* Reset the hardware here. */ + BUGLVL(D_EXTRA) printk("arcnet: arcnet_open: resetting card.\n"); + if (arcnet_reset(dev)) return -ENODEV; + +/* chipset_init(dev, 1);*/ +/* outb(0x00, ioaddr);*/ + +/* lp->open_time = jiffies;*/ + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* grab a timer handler to recover from any missed IRQ's */ + init_timer(&lp->timer); + lp->timer.expires = TIMERval; /* length of time */ + lp->timer.data = (unsigned long)dev; /* pointer to "dev" structure */ + lp->timer.function = &arcnet_timer; /* timer handler */ +#ifdef USE_TIMER_HANDLER + add_timer(&lp->timer); +#endif + + return 0; +} + + +/* The inverse routine to arcnet_open(). */ +static int +arcnet_close(struct device *dev) +{ + struct arcnet_local *lp = (struct arcnet_local *)dev->priv; + int ioaddr = dev->base_addr, delayval; + +/* lp->open_time = 0;*/ + + dev->tbusy = 1; + dev->start = 0; + + /* release the timer */ + del_timer(&lp->timer); + + /* Flush the Tx and disable Rx here. */ + /* resetting the card should do the job. */ + /*inb(RESET);*/ + + outb(0,INTMASK); /* no IRQ's */ + outb(NOTXcmd,COMMAND); /* disable transmit */ + JIFFER(ACKtime); + outb(NORXcmd,COMMAND); /* disable receive */ + +#if 0 /* we better not do this - hard wired IRQ's */ + /* If not IRQ jumpered, free up the line. */ + outw(0x00, ioaddr+0); /* Release the physical interrupt line. */ + free_irq(dev->irq); + irq2dev_map[dev->irq] = 0; +#endif + + /* Update the statistics here. */ + + return 0; +} + + +static int +arcnet_send_packet(struct sk_buff *skb, struct device *dev) +{ + struct arcnet_local *lp = (struct arcnet_local *)dev->priv; + int ioaddr=dev->base_addr,stat=0; +/* short daddr;*/ + + lp->intx++; + + BUGLVL(D_DURING) + printk("arcnet: transmit requested (status=%Xh, inTX=%d)\n", + inb(STATUS),lp->intx); + + if (dev->tbusy) + { + /* If we get here, some higher level has decided we are broken. + There should really be a "kick me" function call instead. */ + int tickssofar = jiffies - dev->trans_start; + int recbuf=lp->recbuf; + int status=inb(STATUS); + + if (tickssofar < 5) return 1; + + BUGLVL(D_INIT) + printk("arcnet: transmit timed out (status=%Xh, inTX=%d, tickssofar=%d)\n", + status,lp->intx,tickssofar); + + /* Try to restart the adaptor. */ + /*arcnet_reset(dev);*/ + + if (status&NORXflag) EnableReceiver(); + if (!(status&TXFREEflag)) outb(NOTXcmd,COMMAND); + dev->tbusy=0; + mark_bh(NET_BH); + dev->trans_start = jiffies; + lp->intx--; + return 1; + } + + /* If some higher layer thinks we've missed a tx-done interrupt + we are passed NULL. Caution: dev_tint() handles the cli()/sti() + itself. */ + if (skb == NULL) { + BUGLVL(D_INIT) + printk("arcnet: tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)\n", + inb(STATUS),lp->intx,jiffies-dev->trans_start); + dev_tint(dev); + lp->intx--; + return 0; + } + + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (set_bit(0, (void*)&dev->tbusy) != 0) + { + printk("arcnet: Transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n", + inb(STATUS),lp->intx,jiffies-dev->trans_start); + stat=-EBUSY; + } + else { + short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + struct ClientData *hdr=(struct ClientData*)skb->data; + + if (length<=XMTU) /* fits in one packet? */ + { + BUGLVL(D_TX) printk("arcnet: not splitting %d-byte packet. (split_flag=%d)\n", + length,hdr->split_flag); + BUGLVL(D_INIT) if (hdr->split_flag) + printk("arcnet: short packet has split_flag set?! (split_flag=%d)\n", + hdr->split_flag); + stat=arcnet_tx(dev,hdr, + length-sizeof(struct ClientData), + ((char *)skb->data)+sizeof(struct ClientData)); + } + else /* too big for one - split it */ + { + u_char *data=(u_char *)skb->data + + sizeof(struct ClientData); + int dataleft=length-sizeof(struct ClientData), + maxsegsize=XMTU-sizeof(struct ClientData), + numsegs=(dataleft+maxsegsize-1)/maxsegsize, + seglen,segnum=0; + + BUGLVL(D_TX) printk("arcnet: packet (%d bytes) split into %d fragments:\n", + length,numsegs); + + while (!stat && dataleft) + { + if (!segnum) /* first packet */ + hdr->split_flag=((numsegs-2)<<1)+1; + else + hdr->split_flag=segnum<<1; + + seglen=maxsegsize; + if (seglen>dataleft) seglen=dataleft; + + BUGLVL(D_TX) printk("arcnet: packet #%d (%d bytes) of %d (%d total), splitflag=%d\n", + segnum+1,seglen,numsegs,length,hdr->split_flag); + + stat=arcnet_tx(dev,hdr,seglen,data); + + dataleft-=seglen; + data+=seglen; + segnum++; + +#if 0 /* sequence # should not update here... I think! */ + /* sequence number goes up on each packet */ + hdr->sequence++; + lp->sequence++; +#endif + } + } + + /* I don't know if this should be in or out of these braces, + * but freeing it too often seems worse than too little. + * (maybe?) (v0.30) + */ + if (!stat) dev_kfree_skb(skb, FREE_WRITE); + + /* we're done now */ + if (stat!=-EBUSY) + { + dev->tbusy=0; + mark_bh(NET_BH); /* Inform upper layers. */ + /* this should be on an IRQ, but can't + * because ARCnets (at least mine) are stupid. + */ + } + } + + lp->intx--; + + if (!stat) lp->stats.tx_packets++; + return stat; +} + +#ifdef CAREFUL_XMIT +static void careful_xmit_wait(struct device *dev) +{ + int ioaddr=dev->base_addr; + struct arcnet_local *lp = (struct arcnet_local *)dev->priv; + + /* wait patiently for tx to become available again */ + while ( !(inb(STATUS)&TXFREEflag) ) + { + if (jiffies-dev->trans_start > 20 || !dev->tbusy) + { + BUGLVL(D_INIT) + printk("arcnet: CAREFUL_XMIT timeout. (busy=%d, status=%Xh)\n", + dev->tbusy,inb(STATUS)); + lp->stats.tx_errors++; + + outb(NOTXcmd,COMMAND); + return; + } + } + BUGLVL(D_TX) printk("arcnet: transmit completed successfully. (status=%Xh)\n", + inb(STATUS)); +} +#endif + +static int +arcnet_tx(struct device *dev,struct ClientData *hdr,short length, + char *data) +{ + int ioaddr = dev->base_addr; +#if 0 + struct arcnet_local *lp = (struct arcnet_local *)dev->priv; +#endif + struct ClientData *arcsoft; + union ArcPacket *arcpacket = + (union ArcPacket *)(dev->mem_start+512*TXbuf); + u_char pkttype; + int offset; + short daddr; + + length+=sizeof(struct ClientData); + + BUGLVL(D_TX) + printk("arcnet: arcnet_tx: hdr:%ph, length:%d, data:%ph\n", + hdr,length,data); + +#if 0 + /* make sure transmitter is available before sending */ + if (! (inb(STATUS) & TXFREEflag)) + { + BUGLVL(D_TX) + printk("arcnet: transmitter in use! (status=%Xh)\n", + inb(STATUS)); + return -EBUSY; + } +#endif + /* Gruesome hack because tx+rx irq's don't work at + * the same time (or so it seems to me) + * + * Our transmits just won't be interrupt driven, I guess. (ugh) + */ +#ifdef CAREFUL_XMIT + careful_xmit_wait(dev); +#endif + + /* clean out the page to make debugging make more sense :) */ + BUGLVL(D_DURING) + memset((void *)dev->mem_start+TXbuf*512,0x42,512); + + daddr=arcpacket->hardheader.destination=hdr->daddr; + + /* load packet into shared memory */ + if (length<=MTU) /* Normal (256-byte) Packet */ + { + pkttype=NORMAL; + + arcpacket->hardheader.offset1=offset=256-length + + EXTRA_CLIENTDATA; + arcsoft=(struct ClientData *) + (&arcpacket->raw[offset-EXTRA_CLIENTDATA]); + } + else if (length>=MinTU) /* Extended (512-byte) Packet */ + { + pkttype=EXTENDED; + + arcpacket->hardheader.offset1=0; + arcpacket->hardheader.offset2=offset=512-length + + EXTRA_CLIENTDATA; + arcsoft=(struct ClientData *) + (&arcpacket->raw[offset-EXTRA_CLIENTDATA]); + } + else /* Exception Packet */ + { + pkttype=EXCEPTION; + + arcpacket->hardheader.offset1=0; + arcpacket->hardheader.offset2=offset=512-length-4 + + EXTRA_CLIENTDATA; + arcsoft=(struct ClientData *) + (&arcpacket->raw[offset+4-EXTRA_CLIENTDATA]); + + /* exception-specific stuff - these four bytes + * make the packet long enough to fit in a 512-byte + * frame. + */ + arcpacket->raw[offset+0]=arcsoft->protocol_id; + arcpacket->raw[offset+1]=0xFF; /* FF flag */ + arcpacket->raw[offset+2]=0xFF; /* FF padding */ + arcpacket->raw[offset+3]=0xFF; /* FF padding */ + } + + + /* copy the packet into ARCnet shmem + * - the first bytes of ClientData header are skipped + */ + memcpy((u_char*)arcsoft+EXTRA_CLIENTDATA, + (u_char*)hdr+EXTRA_CLIENTDATA, + sizeof(struct ClientData)-EXTRA_CLIENTDATA); + memcpy((u_char*)arcsoft+sizeof(struct ClientData), + data, + length-sizeof(struct ClientData)); + + BUGLVL(D_DURING) printk("arcnet: transmitting packet to station %02Xh (%d bytes, type=%d)\n", + daddr,length,pkttype); + + BUGLVL(D_TX) + { + int countx,county; + + printk("arcnet: packet dump [tx] follows:"); + + for (county=0; county<16+(pkttype!=NORMAL)*16; county++) + { + printk("\n[%04X] ",county*16); + for (countx=0; countx<16; countx++) + printk("%02X ", + arcpacket->raw[county*16+countx]); + } + + printk("\n"); + } + + + /* start sending */ + outb(TXcmd|(TXbuf<<3),COMMAND); + + dev->trans_start = jiffies; + + BUGLVL(D_TX) printk("arcnet: transmit started successfully. (status=%Xh)\n", + inb(STATUS)); +#ifdef CAREFUL_XMIT + #if 0 + careful_xmit_wait(dev); + + /* if we're not broadcasting, make sure the xmit was ack'd. + * if it wasn't, there is probably no card with that + * address... or else it missed our tx somehow. + */ + if (daddr && !(inb(STATUS)&TXACKflag)) + { + BUGLVL(D_INIT) + printk("arcnet: transmit not acknowledged. (status=%Xh, daddr=%02Xh)\n", + inb(STATUS),daddr); + lp->stats.tx_errors++; + return -ENONET; /* "machine is not on the network" */ + } + #endif +#endif + + return 0; +} + + +/* The typical workload of the driver: + Handle the network interface interrupts. */ +static void +arcnet_interrupt(int reg_ptr) +{ + int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); + struct device *dev = (struct device *)(irq2dev_map[irq]); + + if (dev == NULL) { + if (net_debug >= D_DURING) + printk("arcnet: irq %d for unknown device.\n", irq); + return; + } + + arcnet_inthandler(dev); +} + +static void +arcnet_inthandler(struct device *dev) +{ + struct arcnet_local *lp; + int ioaddr, status, boguscount = 20; + + dev->interrupt = 1; + + ioaddr = dev->base_addr; + lp = (struct arcnet_local *)dev->priv; + + BUGLVL(D_DURING) + printk("arcnet: in net_interrupt (status=%Xh)\n",inb(STATUS)); + + do + { + status = inb(STATUS); + + if (!dev->start) + { + BUGLVL(D_EXTRA) + printk("arcnet: ARCnet not yet initialized. irq ignored. (status=%Xh)\n", + inb(STATUS)); + break; + } + + /* RESET flag was enabled - card is resetting and if RX + * is disabled, it's NOT because we just got a packet. + */ + if (status & RESETflag) + { + BUGLVL(D_INIT) + printk("arcnet: reset irq (status=%Xh)\n", + status); + break; + } + +#if 1 /* yes, it's silly to disable this part but it makes good testing */ + /* RX is inhibited - we must have received something. */ + if (status & NORXflag) + { + int recbuf=lp->recbuf=!lp->recbuf; + + BUGLVL(D_DURING) + printk("arcnet: receive irq (status=%Xh)\n", + status); + + /* enable receive of our next packet */ + EnableReceiver(); + + /* Got a packet. */ + arcnet_rx(dev,!recbuf); + } +#endif + +#if 0 /* this doesn't actually work, and will now zonk everything. leave + * disabled until I fix it. + */ + /* it can only be a xmit-done irq if we're xmitting :) */ + else if (dev->tbusy && status&TXFREEflag) + { + BUGLVL(D_DURING) + printk("arcnet: transmit IRQ?!? (status=%Xh)\n", + status); + + /*lp->stats.tx_packets++;*/ + dev->tbusy = 0; + mark_bh(NET_BH); /* Inform upper layers. */ + + break; + } + else + break; +#endif + +#if 0 + break; /* delete me */ +#endif + } while (--boguscount); + + BUGLVL(D_DURING) + printk("arcnet: net_interrupt complete (status=%Xh)\n", + inb(STATUS)); + + dev->interrupt=0; + return; +} + +/* A packet has arrived; grab it from the buffers and possibly unsplit it. + */ +static void +arcnet_rx(struct device *dev,int recbuf) +{ + struct arcnet_local *lp = (struct arcnet_local *)dev->priv; + int ioaddr = dev->base_addr; +/* int status = inb(STATUS);*/ + + struct sk_buff *skb; + + union ArcPacket *arcpacket= + (union ArcPacket *)(dev->mem_start+recbuf*512); + struct ClientData *soft,*arcsoft; + short length,offset; + u_char pkttype,daddr,saddr; + + daddr=arcpacket->hardheader.destination; + saddr=arcpacket->hardheader.source; + + /* if source is 0, it's not a "used" packet! */ + if (saddr==0) + { + /*BUGLVL(D_DURING)*/ + printk("arcnet: discarding old packet. (status=%Xh)\n", + inb(STATUS)); + lp->stats.rx_errors++; + return; + } + arcpacket->hardheader.source=0; + + if (arcpacket->hardheader.offset1) /* Normal Packet */ + { + offset=arcpacket->hardheader.offset1; + arcsoft=(struct ClientData *) + (&arcpacket->raw[offset-EXTRA_CLIENTDATA]); + length=256-offset+EXTRA_CLIENTDATA; + pkttype=NORMAL; + } + else /* ExtendedPacket or ExceptionPacket */ + { + offset=arcpacket->hardheader.offset2; + arcsoft=(struct ClientData *) + (&arcpacket->raw[offset-EXTRA_CLIENTDATA]); + + if (arcsoft->split_flag!=0xFF) /* Extended Packet */ + { + length=512-offset+EXTRA_CLIENTDATA; + pkttype=EXTENDED; + } + else /* Exception Packet */ + { + /* skip over 4-byte junkola */ + arcsoft=(struct ClientData *) + ((u_char *)arcsoft + 4); + length=512-offset+EXTRA_CLIENTDATA-4; + pkttype=EXCEPTION; + } + } + + if (!arcsoft->split_flag) /* not split */ + { + struct Incoming *in=&lp->incoming[saddr]; + + BUGLVL(D_RX) printk("arcnet: incoming is not split (splitflag=%d)\n", + arcsoft->split_flag); + + if (in->skb) /* already assembling one! */ + { + BUGLVL(D_INIT) printk("arcnet: aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", + in->sequence,arcsoft->split_flag, + arcsoft->sequence); + kfree_skb(in->skb,FREE_WRITE); + in->skb=NULL; + } + + in->sequence=arcsoft->sequence; + + skb = alloc_skb(length, GFP_ATOMIC); + if (skb == NULL) { + printk("%s: Memory squeeze, dropping packet.\n", + dev->name); + lp->stats.rx_dropped++; + return; + } + soft=(struct ClientData *)skb->data; + + skb->len = length; + skb->dev = dev; + + memcpy((u_char *)soft+EXTRA_CLIENTDATA, + (u_char *)arcsoft+EXTRA_CLIENTDATA, + length-EXTRA_CLIENTDATA); + soft->daddr=daddr; + + BUGLVL(D_DURING) + printk("arcnet: received packet from %02Xh to %02Xh (%d bytes, type=%d)\n", + saddr,daddr,length,pkttype); + BUGLVL(D_RX) + { + int countx,county; + + printk("arcnet: packet dump [rx-unsplit] follows:"); + + for (county=0; county<16+(pkttype!=NORMAL)*16; county++) + { + printk("\n[%04X] ",county*16); + for (countx=0; countx<16; countx++) + printk("%02X ", + arcpacket->raw[county*16+countx]); + } + + printk("\n"); + } + + /* ARP packets have problems when sent from DOS. + * source address is always 0! So we take the hardware + * source addr (which is impossible to fumble) and insert + * it ourselves. + */ + if (soft->protocol_id == ARC_P_ARP) + { + struct arphdr *arp=(struct arphdr *) + ((char *)soft+sizeof(struct ClientData)); + + /* make sure addresses are the right length */ + if (arp->ar_hln==1 && arp->ar_pln==4) + { + char *cptr=(char *)(arp)+sizeof(struct arphdr); + + if (!*cptr) /* is saddr = 00? */ + { + BUGLVL(D_DURING) + printk("arcnet: ARP source address was 00h, set to %02Xh.\n", + saddr); + *cptr=saddr; + } + else BUGLVL(D_DURING) + { + printk("arcnet: ARP source address (%Xh) is fine.\n", + *cptr); + } + } + else + { + printk("arcnet: funny-shaped ARP packet. (%Xh, %Xh)\n", + arp->ar_hln,arp->ar_pln); + } + } + + netif_rx(skb); + lp->stats.rx_packets++; + } + else /* split packet */ + { + /* NOTE: MSDOS ARP packet correction should only need to + * apply to unsplit packets, since ARP packets are so short. + * + * My interpretation of the RFC1201 (ARCnet) document is that + * if a packet is received out of order, the entire assembly + * process should be aborted. + * + * The RFC also mentions "it is possible for successfully + * received packets to be retransmitted." I'm hoping this + * means only the most recent one, which is the only one + * currently allowed. + * + * We allow multiple assembly processes, one for each + * ARCnet card possible on the network. Seems rather like + * a waste of memory. Necessary? + */ + + struct Incoming *in=&lp->incoming[saddr]; + + BUGLVL(D_RX) printk("arcnet: packet is split (splitflag=%d, seq=%d)\n", + arcsoft->split_flag,in->sequence); + + if (in->skb && in->sequence!=arcsoft->sequence) + { + BUGLVL(D_INIT) printk("arcnet: wrong seq number, aborting assembly (expected=%d, seq=%d, splitflag=%d)\n", + in->sequence,arcsoft->sequence, + arcsoft->split_flag); + kfree_skb(in->skb,FREE_WRITE); + in->skb=NULL; + in->lastpacket=in->numpackets=0; + return; + } + + if (arcsoft->split_flag & 1) /* first packet in split */ + { + BUGLVL(D_RX) printk("arcnet: brand new splitpacket (splitflag=%d)\n", + arcsoft->split_flag); + if (in->skb) /* already assembling one! */ + { + BUGLVL(D_INIT) printk("arcnet: aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n", + in->sequence,arcsoft->split_flag, + arcsoft->sequence); + kfree_skb(in->skb,FREE_WRITE); + } + + in->sequence=arcsoft->sequence; + in->numpackets=((unsigned)arcsoft->split_flag>>1)+2; + in->lastpacket=1; + + if (in->numpackets>16) + { + printk("arcnet: incoming packet more than 16 segments; dropping. (splitflag=%d)\n", + arcsoft->split_flag); + lp->stats.rx_dropped++; + return; + } + + in->skb=skb=alloc_skb(508*in->numpackets + + sizeof(struct ClientData), + GFP_ATOMIC); + if (skb == NULL) { + printk("%s: (split) memory squeeze, dropping packet.\n", + dev->name); + lp->stats.rx_dropped++; + return; + } + + /* I don't know what this is for, but it DOES avoid + * warnings... + */ + skb->free=1; + + if (skb==NULL) + { + printk("%s: Memory squeeze, dropping packet.\n", + dev->name); + lp->stats.rx_dropped++; + return; + } + soft=(struct ClientData *)skb->data; + + skb->len=sizeof(struct ClientData); + skb->dev=dev; + + memcpy((u_char *)soft+EXTRA_CLIENTDATA, + (u_char *)arcsoft+EXTRA_CLIENTDATA, + sizeof(struct ClientData)-EXTRA_CLIENTDATA); + soft->split_flag=0; /* final packet won't be split */ + } + else /* not first packet */ + { + int packetnum=((unsigned)arcsoft->split_flag>>1) + 1; + + /* if we're not assembling, there's no point + * trying to continue. + */ + if (!in->skb) + { + BUGLVL(D_INIT) printk("arcnet: can't continue split without starting first! (splitflag=%d, seq=%d)\n", + arcsoft->split_flag,arcsoft->sequence); + return; + } + + in->lastpacket++; + if (packetnum!=in->lastpacket) /* not the right flag! */ + { + /* harmless duplicate? ignore. */ + if (packetnum==in->lastpacket-1) + { + BUGLVL(D_INIT) printk("arcnet: duplicate splitpacket ignored! (splitflag=%d)\n", + arcsoft->split_flag); + return; + } + + /* "bad" duplicate, kill reassembly */ + BUGLVL(D_INIT) printk("arcnet: out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", + in->sequence,arcsoft->split_flag, + arcsoft->sequence); + kfree_skb(in->skb,FREE_WRITE); + in->skb=NULL; + in->lastpacket=in->numpackets=0; + return; + } + + soft=(struct ClientData *)in->skb->data; + } + + skb=in->skb; + + memcpy(skb->data+skb->len, + (u_char *)arcsoft+sizeof(struct ClientData), + length-sizeof(struct ClientData)); + + skb->len+=length-sizeof(struct ClientData); + + soft->daddr=daddr; + + BUGLVL(D_DURING) + printk("arcnet: received packet from %02Xh to %02Xh (%d bytes, type=%d)\n", + saddr,daddr,length,pkttype); + BUGLVL(D_RX) + { + int countx,county; + + printk("arcnet: packet dump [rx-split] follows:"); + + for (county=0; county<16+(pkttype!=NORMAL)*16; county++) + { + printk("\n[%04X] ",county*16); + for (countx=0; countx<16; countx++) + printk("%02X ", + arcpacket->raw[county*16+countx]); + } + + printk("\n"); + } + + /* are we done? */ + if (in->lastpacket == in->numpackets) + { + if (!skb || !in->skb) + printk("arcnet: ?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n", + skb,in->skb); + in->skb=NULL; + in->lastpacket=in->numpackets=0; + netif_rx(skb); + lp->stats.rx_packets++; + } + } + + /* If any worth-while packets have been received, dev_rint() + has done a mark_bh(NET_BH) for us and will work on them + when we get to the bottom-half routine. */ + /* arcnet: pardon? */ +} + + + +/* this function is called every once in a while to make sure the ARCnet + * isn't stuck. + * + * If we miss a receive IRQ, the receiver (and IRQ) is permanently disabled + * and we might never receive a packet again! This will check if this + * is the case, and if so, re-enable the receiver. + */ +static void +arcnet_timer(unsigned long arg) +{ + struct device *dev=(struct device *)arg; + struct arcnet_local *lp = (struct arcnet_local *)dev->priv; + short ioaddr=dev->base_addr; + int status=inb(STATUS); + + /* if we didn't interrupt the IRQ handler, and RX's are still + * disabled, and we're not resetting the card... then we're stuck! + */ + if (!dev->interrupt && dev->start + && status&NORXflag && !status&RESETflag) + { + BUGLVL(D_INIT) + printk("arcnet: timer: ARCnet was stuck! (status=%Xh)\n", + status); + + arcnet_inthandler(dev); + } + + /* requeue ourselves */ + init_timer(&lp->timer); + lp->timer.expires=TIMERval; + add_timer(&lp->timer); +} + + +/* Get the current statistics. This may be called with the card open or + closed. */ +static struct enet_statistics * +arcnet_get_stats(struct device *dev) +{ + struct arcnet_local *lp = (struct arcnet_local *)dev->priv; +/* short ioaddr = dev->base_addr;*/ + + return &lp->stats; +} + +/* Set or clear the multicast filter for this adaptor. + num_addrs == -1 Promiscuous mode, receive all packets + num_addrs == 0 Normal mode, clear multicast list + num_addrs > 0 Multicast mode, receive normal and MC packets, and do + best-effort filtering. + */ +static void +set_multicast_list(struct device *dev, int num_addrs, void *addrs) +{ +#if 0 /* no promiscuous mode at all */ + struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); + + short ioaddr = dev->base_addr; + if (num_addrs) { + outw(69, ioaddr); /* Enable promiscuous mode */ + } else + outw(99, ioaddr); /* Disable promiscuous mode, use normal mode */ +#endif +} + +int arcnet_reset(struct device *dev) +{ + struct arcnet_local *lp=(struct arcnet_local *)dev->priv; + short ioaddr=dev->base_addr; + int delayval,recbuf=lp->recbuf; + + outb(0,INTMASK); /* no IRQ's, please! */ + + BUGLVL(D_INIT) + printk("arcnet: Resetting %s (status=%Xh)\n", + dev->name,inb(STATUS)); + + inb(RESET); /* Reset by reading this port */ + JIFFER(RESETtime); + + outb(CFLAGScmd|RESETclear|CONFIGclear,COMMAND); /* clear flags & end reset */ + + /* after a reset, the first byte of shared mem is TESTvalue and the + * second byte is our 8-bit ARCnet address + */ + { + u_char *cardmem = (u_char *) dev->mem_start; + if (cardmem[0] != TESTvalue) + { + BUGLVL(D_INIT) + printk("arcnet: reset failed: TESTvalue not present.\n"); + return 1; + } + lp->arcnum=cardmem[1]; /* save address for later use */ + } + + /* clear out status variables */ + recbuf=lp->recbuf=0; + dev->tbusy=0; + + /* enable IRQ's on completed receive + * I messed around for a long time, but I couldn't get tx and rx + * irq's to work together. It looks like one or the other but not + * both... . The Crynwr driver uses only rx, and so do I now. + */ + outb(NORXflag,INTMASK); + + /* enable extended (512-byte) packets */ + outb(CONFIGcmd|EXTconf,COMMAND); + JIFFER(ACKtime); + + /* clean out all the memory to make debugging make more sense :) */ + BUGLVL(D_DURING) + memset((void *)dev->mem_start,0x42,2048); + + /* and enable receive of our first packet to the first buffer */ + EnableReceiver(); + + /* done! return success. */ + return 0; +} + + +/* + * Create the ARCnet ClientData header for an arbitrary protocol layer + * + * saddr=NULL means use device source address (always will anyway) + * daddr=NULL means leave destination address (eg unresolved arp) + */ +int arc_header(unsigned char *buff,struct device *dev,unsigned short type, + void *daddr,void *saddr,unsigned len,struct sk_buff *skb) +{ + struct ClientData *head = (struct ClientData *)buff; + struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); + + /* set the protocol ID according to RFC-1201 */ + switch(type) + { + case ETH_P_IP: + head->protocol_id=ARC_P_IP; + break; + case ETH_P_ARP: + head->protocol_id=ARC_P_ARP; + break; + case ETH_P_RARP: + head->protocol_id=ARC_P_RARP; + break; + default: + printk("arcnet: I don't understand protocol %d (%Xh)\n", + type,type); + return 0; + } + +#if 0 + /* + * Set the source hardware address. + * AVE: we can't do this, so we don't. Code below is directly + * stolen from eth.c driver and won't work. + */ + if(saddr) + memcpy(eth->h_source,saddr,dev->addr_len); + else + memcpy(eth->h_source,dev->dev_addr,dev->addr_len); +#endif + +#if 0 + /* + * Anyway, the loopback-device should never use this function... + * + * And the chances of it using the ARCnet version of it are so + * tiny that I don't think we have to worry :) + */ + if (dev->flags & IFF_LOOPBACK) + { + memset(eth->h_dest, 0, dev->addr_len); + return(dev->hard_header_len); + } +#endif + + head->split_flag=0; /* split packets are done elsewhere */ + head->sequence=(lp->sequence++); + + /* supposedly if daddr is NULL, we should ignore it... */ + if(daddr) + { + head->daddr=((u_char*)daddr)[0]; + return dev->hard_header_len; + } + else + head->daddr=0; /* better fill one in anyway */ + + return -dev->hard_header_len; +} + + +/* + * Rebuild the ARCnet ClientData header. This is called after an ARP + * (or in future other address resolution) has completed on this + * sk_buff. We now let ARP fill in the other fields. + */ +int arc_rebuild_header(void *buff,struct device *dev,unsigned long dst, + struct sk_buff *skb) +{ + struct ClientData *head = (struct ClientData *)buff; + + /* + * Only ARP/IP is currently supported + */ + + if(head->protocol_id != ARC_P_IP) + { + printk("arcnet: I don't understand resolve type %d (%Xh) addresses!\n", + head->protocol_id,head->protocol_id); + head->daddr=0; + /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/ + return 0; + } + + /* + * Try and get ARP to resolve the header. + */ +#ifdef CONFIG_INET + return arp_find(&(head->daddr), dst, dev, dev->pa_addr, skb)? 1 : 0; +#else + return 0; +#endif +} + +/* + * Determine the packet's protocol ID. + * + * With ARCnet we have to convert everything to Ethernet-style stuff. + */ +unsigned short arc_type_trans(struct sk_buff *skb,struct device *dev) +{ + struct ClientData *head = (struct ClientData *) skb->data; + /*unsigned char *rawp;*/ + + if (head->daddr==0) + skb->pkt_type=PACKET_BROADCAST; + +#if 0 /* code for ethernet with multicast */ + if(*eth->h_dest&1) + { + if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) + skb->pkt_type=PACKET_BROADCAST; + else + skb->pkt_type=PACKET_MULTICAST; + } +#endif + + if(dev->flags&IFF_PROMISC) + { + /* if we're not sending to ourselves :) */ + if (head->daddr != dev->dev_addr[0]) + skb->pkt_type=PACKET_OTHERHOST; + } + + /* now return the protocol number */ + switch (head->protocol_id) + { + case ARC_P_IP: return htons(ETH_P_IP); /* what the heck is + an htons, anyway? */ + case ARC_P_ARP: return htons(ETH_P_ARP); + case ARC_P_RARP: return htons(ETH_P_RARP); + case 0xFA: /* IPX */ + case 0xDD: /* Appletalk */ + default: + BUGLVL(D_DURING) + printk("arcnet: received packet of unknown protocol id %d (%Xh)\n", + head->protocol_id,head->protocol_id); + return 0; + } + +#if 0 /* more ethernet-specific junk */ + if (ntohs(eth->h_proto) >= 1536) + return eth->h_proto; + + rawp = (unsigned char *)(eth + 1); + + if (*(unsigned short *)rawp == 0xFFFF) + return htons(ETH_P_802_3); + if (*(unsigned short *)rawp == 0xAAAA) + return htons(ETH_P_SNAP); + + return htons(ETH_P_802_2); +#endif + + return htons(ETH_P_IP); +} + + + +/* + * Local variables: + * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c" + * version-control: t + * kept-new-versions: 5 + * tab-width: 4 + * End: + */ + diff -u --recursive --new-file v1.1.79/linux/fs/msdos/inode.c linux/fs/msdos/inode.c --- v1.1.79/linux/fs/msdos/inode.c Wed Jan 11 21:14:28 1995 +++ linux/fs/msdos/inode.c Wed Jan 11 21:10:53 1995 @@ -46,9 +46,8 @@ clear_inode(inode); if (depend) { if (MSDOS_I(depend)->i_old != inode) { - printk("Invalid link (0x%X): expected 0x%X, got 0x%X\n", - (int) depend,(int) inode,(int) MSDOS_I(depend)-> - i_old); + printk("Invalid link (0x%p): expected 0x%p, got 0x%p\n", + depend, inode, MSDOS_I(depend)->i_old); fs_panic(sb,"..."); return; } diff -u --recursive --new-file v1.1.79/linux/fs/proc/array.c linux/fs/proc/array.c --- v1.1.79/linux/fs/proc/array.c Wed Jan 11 21:14:28 1995 +++ linux/fs/proc/array.c Wed Jan 11 21:10:53 1995 @@ -15,7 +15,7 @@ * * * Danny ter Haar : Some minor additions for cpuinfo - * + * * * Alessandro Rubini : profile extension. * @@ -332,7 +332,7 @@ if (!p || !*p || ptr >= TASK_SIZE) return 0; - page = *PAGE_DIR_OFFSET((*p)->tss.cr3,ptr); + page = *PAGE_DIR_OFFSET(*p,ptr); if (!(page & PAGE_PRESENT)) return 0; page &= PAGE_MASK; @@ -513,7 +513,7 @@ return 0; tpag = (*p)->mm->end_code / PAGE_SIZE; if ((*p)->state != TASK_ZOMBIE) { - pagedir = (unsigned long *) (*p)->tss.cr3; + pagedir = PAGE_DIR_OFFSET(*p, 0); for (i = 0; i < 0x300; ++i) { if ((ptbl = pagedir[i]) == 0) { tpag -= PTRS_PER_PAGE; diff -u --recursive --new-file v1.1.79/linux/fs/proc/mem.c linux/fs/proc/mem.c --- v1.1.79/linux/fs/proc/mem.c Sun Nov 27 20:19:53 1994 +++ linux/fs/proc/mem.c Wed Jan 11 21:10:53 1995 @@ -24,7 +24,8 @@ static int mem_read(struct inode * inode, struct file * file,char * buf, int count) { - unsigned long addr, pid, cr3; + struct task_struct * tsk; + unsigned long addr, pid; char *tmp; unsigned long pte, page; int i; @@ -33,20 +34,20 @@ return -EINVAL; pid = inode->i_ino; pid >>= 16; - cr3 = 0; + tsk = NULL; for (i = 1 ; i < NR_TASKS ; i++) if (task[i] && task[i]->pid == pid) { - cr3 = task[i]->tss.cr3; + tsk = task[i]; break; } - if (!cr3) + if (!tsk) return -EACCES; addr = file->f_pos; tmp = buf; while (count > 0) { if (current->signal & ~current->blocked) break; - pte = *PAGE_DIR_OFFSET(cr3,addr); + pte = *PAGE_DIR_OFFSET(tsk,addr); if (!(pte & PAGE_PRESENT)) break; pte &= PAGE_MASK; @@ -72,7 +73,8 @@ static int mem_write(struct inode * inode, struct file * file,char * buf, int count) { - unsigned long addr, pid, cr3; + struct task_struct * tsk; + unsigned long addr, pid; char *tmp; unsigned long pte, page; int i; @@ -82,19 +84,19 @@ addr = file->f_pos; pid = inode->i_ino; pid >>= 16; - cr3 = 0; + tsk = NULL; for (i = 1 ; i < NR_TASKS ; i++) if (task[i] && task[i]->pid == pid) { - cr3 = task[i]->tss.cr3; + tsk = task[i]; break; } - if (!cr3) + if (!tsk) return -EACCES; tmp = buf; while (count > 0) { if (current->signal & ~current->blocked) break; - pte = *PAGE_DIR_OFFSET(cr3,addr); + pte = *PAGE_DIR_OFFSET(tsk,addr); if (!(pte & PAGE_PRESENT)) break; pte &= PAGE_MASK; @@ -144,21 +146,22 @@ mem_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma) { - unsigned long *src_table, *dest_table, stmp, dtmp, cr3; + struct task_struct *tsk; + unsigned long *src_table, *dest_table, stmp, dtmp; struct vm_area_struct *src_vma = 0; int i; /* Get the source's task information */ - cr3 = 0; + tsk = NULL; for (i = 1 ; i < NR_TASKS ; i++) if (task[i] && task[i]->pid == (inode->i_ino >> 16)) { - cr3 = task[i]->tss.cr3; + tsk = task[i]; src_vma = task[i]->mm->mmap; break; } - if (!cr3) + if (!tsk) return -EACCES; /* Ensure that we have a valid source area. (Has to be mmap'ed and @@ -173,7 +176,7 @@ if (!src_vma || (src_vma->vm_flags & VM_SHM)) return -EINVAL; - src_table = PAGE_DIR_OFFSET(cr3, stmp); + src_table = PAGE_DIR_OFFSET(tsk, stmp); if (!*src_table) return -EINVAL; src_table = (unsigned long *)((*src_table & PAGE_MASK) + PAGE_PTR(stmp)); @@ -197,10 +200,10 @@ while (src_vma && stmp > src_vma->vm_end) src_vma = src_vma->vm_next; - src_table = PAGE_DIR_OFFSET(cr3, stmp); + src_table = PAGE_DIR_OFFSET(tsk, stmp); src_table = (unsigned long *)((*src_table & PAGE_MASK) + PAGE_PTR(stmp)); - dest_table = PAGE_DIR_OFFSET(current->tss.cr3, dtmp); + dest_table = PAGE_DIR_OFFSET(current, dtmp); if (!*dest_table) { *dest_table = get_free_page(GFP_KERNEL); diff -u --recursive --new-file v1.1.79/linux/fs/proc/net.c linux/fs/proc/net.c --- v1.1.79/linux/fs/proc/net.c Wed Jan 11 21:14:28 1995 +++ linux/fs/proc/net.c Wed Jan 11 21:10:53 1995 @@ -42,7 +42,6 @@ /* 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); @@ -52,6 +51,7 @@ extern int dev_get_info(char *, char **, off_t, int); extern int rt_get_info(char *, char **, off_t, int); extern int snmp_get_info(char *, char **, off_t, int); +extern int afinet_get_info(char *, char **, off_t, int); extern int ip_acct_procinfo(char *, char **, off_t, int); extern int ip_fw_blk_procinfo(char *, char **, off_t, int); extern int ip_fw_fwd_procinfo(char *, char **, off_t, int); @@ -118,6 +118,7 @@ { PROC_NET_TCP, 3, "tcp" }, { PROC_NET_UDP, 3, "udp" }, { PROC_NET_SNMP, 4, "snmp" }, + { PROC_NET_SOCKSTAT, 8, "sockstat" }, #ifdef CONFIG_INET_RARP { PROC_NET_RARP, 4, "rarp"}, #endif @@ -145,7 +146,6 @@ { PROC_NET_NR, 2, "nr" }, #endif /* CONFIG_NETROM */ #endif /* CONFIG_AX25 */ - { PROC_NET_SOCKSTAT, 8, "sockstat" }, { 0, 0, NULL } }; @@ -233,10 +233,10 @@ case PROC_NET_UNIX: length = unix_get_info(page,&start,file->f_pos,thistime); break; +#ifdef CONFIG_INET case PROC_NET_SOCKSTAT: length = afinet_get_info(page,&start,file->f_pos,thistime); break; -#ifdef CONFIG_INET case PROC_NET_ARP: length = arp_get_info(page,&start,file->f_pos,thistime); break; diff -u --recursive --new-file v1.1.79/linux/include/asm-alpha/dma.h linux/include/asm-alpha/dma.h --- v1.1.79/linux/include/asm-alpha/dma.h Sun Jan 1 19:49:18 1995 +++ linux/include/asm-alpha/dma.h Wed Jan 11 21:10:53 1995 @@ -73,6 +73,9 @@ #define MAX_DMA_CHANNELS 8 +/* The maximum address that we can perform a DMA transfer to on this platform */ +#define MAX_DMA_ADDRESS 0x1000000 + /* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ #define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ diff -u --recursive --new-file v1.1.79/linux/include/asm-alpha/page.h linux/include/asm-alpha/page.h --- v1.1.79/linux/include/asm-alpha/page.h Sun Nov 27 20:19:54 1994 +++ linux/include/asm-alpha/page.h Wed Jan 11 21:10:53 1995 @@ -36,14 +36,32 @@ /* 64-bit machines, beware! SRB. */ #define SIZEOF_PTR_LOG2 4 - /* to find an entry in a page-table-directory */ -#define PAGE_DIR_OFFSET(base,address) ((unsigned long*)((base)+\ - ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)*2&PTR_MASK&~PAGE_MASK))) - /* to find an entry in a page-table */ +/* to find an entry in a page-table-directory */ +/* + * XXXXX This isn't right: we shouldn't use the ptbr, but the L2 pointer. + * This is just for getting it through the compiler right now + */ +#define PAGE_DIR_OFFSET(tsk,address) \ +((unsigned long *) ((tsk)->tss.ptbr + ((((unsigned long)(address)) >> 21) & PTR_MASK & ~PAGE_MASK))) + +/* to find an entry in a page-table */ #define PAGE_PTR(address) \ ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) - /* the no. of pointers that fit on a page */ + +/* the no. of pointers that fit on a page */ #define PTRS_PER_PAGE (PAGE_SIZE/sizeof(void*)) + +/* to set the page-dir */ +/* + * XXXXX This isn't right: we shouldn't use the ptbr, but the L2 pointer. + * This is just for getting it through the compiler right now + */ +#define SET_PAGE_DIR(tsk,pgdir) \ +do { \ + (tsk)->tss.ptbr = (unsigned long) (pgdir); \ + if ((tsk) == current) \ + invalidate(); \ +} while (0) #endif /* __KERNEL__ */ diff -u --recursive --new-file v1.1.79/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h --- v1.1.79/linux/include/asm-alpha/processor.h Mon Jan 9 11:24:23 1995 +++ linux/include/asm-alpha/processor.h Wed Jan 11 21:10:53 1995 @@ -18,8 +18,13 @@ /* * Bus types */ -extern int EISA_bus; +#define EISA_bus 1 #define MCA_bus 0 + +/* + * The alpha has no problems with write protection + */ +#define wp_works_ok 1 struct thread_struct { unsigned long ksp; diff -u --recursive --new-file v1.1.79/linux/include/asm-i386/page.h linux/include/asm-i386/page.h --- v1.1.79/linux/include/asm-i386/page.h Sun Nov 27 20:19:54 1994 +++ linux/include/asm-i386/page.h Wed Jan 11 21:10:53 1995 @@ -27,14 +27,24 @@ /* 64-bit machines, beware! SRB. */ #define SIZEOF_PTR_LOG2 2 - /* to find an entry in a page-table-directory */ -#define PAGE_DIR_OFFSET(base,address) ((unsigned long*)((base)+\ - ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)*2&PTR_MASK&~PAGE_MASK))) - /* to find an entry in a page-table */ +/* to find an entry in a page-table-directory */ +#define PAGE_DIR_OFFSET(tsk,address) \ +((((unsigned long)(address)) >> 22) + (unsigned long *) (tsk)->tss.cr3) + +/* to find an entry in a page-table */ #define PAGE_PTR(address) \ - ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) - /* the no. of pointers that fit on a page */ +((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) + +/* the no. of pointers that fit on a page */ #define PTRS_PER_PAGE (PAGE_SIZE/sizeof(void*)) + +/* to set the page-dir */ +#define SET_PAGE_DIR(tsk,pgdir) \ +do { \ + (tsk)->tss.cr3 = (unsigned long) (pgdir); \ + if ((tsk) == current) \ + __asm__ __volatile__("movl %0,%%cr3": :"a" ((tsk)->tss.cr3)); \ +} while (0) #endif /* __KERNEL__ */ diff -u --recursive --new-file v1.1.79/linux/include/asm-sparc/vac-ops.h linux/include/asm-sparc/vac-ops.h --- v1.1.79/linux/include/asm-sparc/vac-ops.h Mon Jan 2 15:26:45 1995 +++ linux/include/asm-sparc/vac-ops.h Thu Jan 12 08:14:50 1995 @@ -8,12 +8,10 @@ success, 1 on failure. */ -extern __inline__ int enable_vac() +extern __inline__ int enable_vac(void) { - int success; + int success=0; - &success; - __asm__ __volatile__("lduba [%1] 2, %0\n\t" "or %0, 0x10, %0\n\t" "stba %0, [%1] 2\n\t" @@ -28,9 +26,9 @@ success, 1 on failure. */ -extern __inline__ int disable_vac() +extern __inline__ int disable_vac(void) { - int success; + int success=0; __asm__ __volatile__("lduba [%1] 0x2, %0\n\t" "xor %0, 0x10, %0\n\t" diff -u --recursive --new-file v1.1.79/linux/include/linux/mm.h linux/include/linux/mm.h --- v1.1.79/linux/include/linux/mm.h Thu Dec 29 19:58:42 1994 +++ linux/include/linux/mm.h Thu Jan 12 13:14:16 1995 @@ -87,7 +87,7 @@ unsigned long (*wppage)(struct vm_area_struct * area, unsigned long address, unsigned long page); void (*swapout)(struct vm_area_struct *, unsigned long, unsigned long *); - unsigned long (*swapin)(struct vm_area_struct *, unsigned long); + unsigned long (*swapin)(struct vm_area_struct *, unsigned long, unsigned long); }; extern unsigned long __bad_page(void); @@ -282,11 +282,7 @@ #ifdef SWAP_CACHE_INFO swap_cache_find_total++; #endif - __asm__ __volatile__("xchgl %0,%1" - :"=m" (swap_cache[addr >> PAGE_SHIFT]), - "=r" (entry) - :"0" (swap_cache[addr >> PAGE_SHIFT]), - "1" (0)); + entry = (unsigned long) xchg_ptr(swap_cache + (addr >> PAGE_SHIFT), NULL); #ifdef SWAP_CACHE_INFO if (entry) swap_cache_find_success++; @@ -301,11 +297,7 @@ #ifdef SWAP_CACHE_INFO swap_cache_del_total++; #endif - __asm__ __volatile__("xchgl %0,%1" - :"=m" (swap_cache[addr >> PAGE_SHIFT]), - "=r" (entry) - :"0" (swap_cache[addr >> PAGE_SHIFT]), - "1" (0)); + entry = (unsigned long) xchg_ptr(swap_cache + (addr >> PAGE_SHIFT), NULL); if (entry) { #ifdef SWAP_CACHE_INFO swap_cache_del_success++; diff -u --recursive --new-file v1.1.79/linux/include/linux/net.h linux/include/linux/net.h --- v1.1.79/linux/include/linux/net.h Wed Jan 11 21:14:29 1995 +++ linux/include/linux/net.h Thu Jan 12 11:38:28 1995 @@ -24,6 +24,7 @@ #define NSOCKETS 2000 /* Dynamic, this is MAX LIMIT */ +#define NSOCKETS_UNIX 128 /* unix domain static limit */ #define NPROTO 16 /* should be enough for now.. */ diff -u --recursive --new-file v1.1.79/linux/include/linux/shm.h linux/include/linux/shm.h --- v1.1.79/linux/include/linux/shm.h Sat Nov 5 14:50:03 1994 +++ linux/include/linux/shm.h Thu Jan 12 13:14:16 1995 @@ -50,7 +50,6 @@ bits 14..8 (SHM_ID) the id of the shared memory segment bits 29..15 (SHM_IDX) the index of the page within the shared memory segment (actually only bits 24..15 get used since SHMMAX is so low) - bit 31 (SHM_READ_ONLY) flag whether the page belongs to a read-only attach */ #define SHM_ID_SHIFT 8 @@ -63,9 +62,7 @@ #define _SHM_IDX_BITS 15 #define SHM_IDX_MASK ((1<<_SHM_IDX_BITS)-1) -#define SHM_READ_ONLY (1<<31) - -/* We must have SHM_ID_SHIFT + _SHM_ID_BITS + _SHM_IDX_BITS + 1 <= 32 +/* We must have SHM_ID_SHIFT + _SHM_ID_BITS + _SHM_IDX_BITS <= 32 and SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS). */ #define SHMMAX 0x3fa000 /* max shared seg size (bytes) */ diff -u --recursive --new-file v1.1.79/linux/init/main.c linux/init/main.c --- v1.1.79/linux/init/main.c Mon Jan 9 07:22:11 1995 +++ linux/init/main.c Wed Jan 11 21:10:53 1995 @@ -437,8 +437,6 @@ } low_memory_start = PAGE_ALIGN(low_memory_start); memory_start = paging_init(memory_start,memory_end); - if (strncmp((char*)0x0FFFD9, "EISA", 4) == 0) - EISA_bus = 1; trap_init(); init_IRQ(); sched_init(); diff -u --recursive --new-file v1.1.79/linux/ipc/shm.c linux/ipc/shm.c --- v1.1.79/linux/ipc/shm.c Wed Nov 30 21:47:40 1994 +++ linux/ipc/shm.c Thu Jan 12 13:14:16 1995 @@ -22,7 +22,7 @@ static void killseg (int id); static void shm_open (struct vm_area_struct *shmd); static void shm_close (struct vm_area_struct *shmd); -static unsigned long shm_swap_in (struct vm_area_struct *, unsigned long); +static unsigned long shm_swap_in (struct vm_area_struct *, unsigned long, unsigned long); static int shm_tot = 0; /* total number of shared memory pages */ static int shm_rss = 0; /* number of shared memory pages that are in memory */ @@ -378,12 +378,11 @@ { unsigned long *page_table; unsigned long tmp, shm_sgn; - unsigned long page_dir = shmd->vm_task->tss.cr3; /* check that the range is unmapped */ if (!remap) for (tmp = shmd->vm_start; tmp < shmd->vm_end; tmp += PAGE_SIZE) { - page_table = PAGE_DIR_OFFSET(page_dir,tmp); + page_table = PAGE_DIR_OFFSET(shmd->vm_task,tmp); if (*page_table & PAGE_PRESENT) { page_table = (ulong *) (PAGE_MASK & *page_table); page_table += ((tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1)); @@ -403,7 +402,7 @@ /* check that the range has page_tables */ for (tmp = shmd->vm_start; tmp < shmd->vm_end; tmp += PAGE_SIZE) { - page_table = PAGE_DIR_OFFSET(page_dir,tmp); + page_table = PAGE_DIR_OFFSET(shmd->vm_task,tmp); if (*page_table & PAGE_PRESENT) { page_table = (ulong *) (PAGE_MASK & *page_table); page_table += ((tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1)); @@ -429,7 +428,7 @@ shm_sgn = shmd->vm_pte + ((shmd->vm_offset >> PAGE_SHIFT) << SHM_IDX_SHIFT); for (tmp = shmd->vm_start; tmp < shmd->vm_end; tmp += PAGE_SIZE, shm_sgn += (1 << SHM_IDX_SHIFT)) { - page_table = PAGE_DIR_OFFSET(page_dir,tmp); + page_table = PAGE_DIR_OFFSET(shmd->vm_task,tmp); page_table = (ulong *) (PAGE_MASK & *page_table); page_table += (tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1); *page_table = shm_sgn; @@ -496,8 +495,7 @@ return -EIDRM; } - shmd->vm_pte = (SHM_SWP_TYPE << 1) | (id << SHM_ID_SHIFT) | - (shmflg & SHM_RDONLY ? SHM_READ_ONLY : 0); + shmd->vm_pte = (SHM_SWP_TYPE << 1) | (id << SHM_ID_SHIFT); shmd->vm_start = addr; shmd->vm_end = addr + shp->shm_npages * PAGE_SIZE; shmd->vm_task = current; @@ -604,30 +602,40 @@ /* * page not present ... go through shm_pages */ -static unsigned long shm_swap_in(struct vm_area_struct * vma, unsigned long code) +static unsigned long shm_swap_in(struct vm_area_struct * shmd, unsigned long offset, unsigned long code) { unsigned long page; struct shmid_ds *shp; unsigned int id, idx; id = (code >> SHM_ID_SHIFT) & SHM_ID_MASK; + if (id != ((shmd->vm_pte >> SHM_ID_SHIFT) & SHM_ID_MASK)) { + printk ("shm_swap_in: code id = %d and shmd id = %ld differ\n", + id, (shmd->vm_pte >> SHM_ID_SHIFT) & SHM_ID_MASK); + return BAD_PAGE | PAGE_SHARED; + } if (id > max_shmid) { - printk ("shm_no_page: id=%d too big. proc mem corrupted\n", id); + printk ("shm_swap_in: id=%d too big. proc mem corrupted\n", id); return BAD_PAGE | PAGE_SHARED; } shp = shm_segs[id]; if (shp == IPC_UNUSED || shp == IPC_NOID) { - printk ("shm_no_page: id=%d invalid. Race.\n", id); + printk ("shm_swap_in: id=%d invalid. Race.\n", id); return BAD_PAGE | PAGE_SHARED; } idx = (code >> SHM_IDX_SHIFT) & SHM_IDX_MASK; + if (idx != (offset >> PAGE_SHIFT)) { + printk ("shm_swap_in: code idx = %u and shmd idx = %lu differ\n", + idx, offset >> PAGE_SHIFT); + return BAD_PAGE | PAGE_SHARED; + } if (idx >= shp->shm_npages) { - printk ("shm_no_page : too large page index. id=%d\n", id); + printk ("shm_swap_in : too large page index. id=%d\n", id); return BAD_PAGE | PAGE_SHARED; } if (!(shp->shm_pages[idx] & PAGE_PRESENT)) { - if(!(page = get_free_page(GFP_KERNEL))) { + if (!(page = get_free_page(GFP_KERNEL))) { oom(current); return BAD_PAGE | PAGE_SHARED; } @@ -652,8 +660,7 @@ done: current->mm->min_flt++; page = shp->shm_pages[idx]; - if (code & SHM_READ_ONLY) /* write-protect */ - page &= ~PAGE_RW; + page &= ~(PAGE_RW & ~shmd->vm_page_prot); /* write-protect */ mem_map[MAP_NR(page)]++; return page; } @@ -716,7 +723,7 @@ tmp = shmd->vm_start + (idx << PAGE_SHIFT) - shmd->vm_offset; if (!(tmp >= shmd->vm_start && tmp < shmd->vm_end)) continue; - pte = PAGE_DIR_OFFSET(shmd->vm_task->tss.cr3,tmp); + pte = PAGE_DIR_OFFSET(shmd->vm_task,tmp); if (!(*pte & PAGE_PRESENT)) { printk("shm_swap: bad pgtbl! id=%ld start=%lx idx=%ld\n", id, shmd->vm_start, idx); @@ -732,8 +739,7 @@ *pte &= ~PAGE_ACCESSED; continue; } - tmp = shmd->vm_pte | idx << SHM_IDX_SHIFT; - *pte = tmp; + *pte = shmd->vm_pte | idx << SHM_IDX_SHIFT; mem_map[MAP_NR(page)]--; shmd->vm_task->mm->rss--; invalid++; diff -u --recursive --new-file v1.1.79/linux/kernel/Makefile linux/kernel/Makefile --- v1.1.79/linux/kernel/Makefile Mon Jan 9 07:22:11 1995 +++ linux/kernel/Makefile Wed Jan 11 21:10:53 1995 @@ -17,7 +17,8 @@ $(CC) $(CFLAGS) -c $< OBJS = sched.o dma.o fork.o exec_domain.o panic.o printk.o vsprintf.o sys.o \ - module.o ksyms.o exit.o signal.o itimer.o info.o time.o softirq.o + module.o ksyms.o exit.o signal.o itimer.o info.o time.o softirq.o \ + resource.o all: kernel.o diff -u --recursive --new-file v1.1.79/linux/kernel/fork.c linux/kernel/fork.c --- v1.1.79/linux/kernel/fork.c Mon Jan 9 07:22:11 1995 +++ linux/kernel/fork.c Thu Jan 12 08:53:01 1995 @@ -169,13 +169,18 @@ { int nr; struct task_struct *p; + unsigned long new_stack; unsigned long clone_flags = COPYVM | SIGCHLD; if(!(p = (struct task_struct*)__get_free_page(GFP_KERNEL))) goto bad_fork; + new_stack = get_free_page(GFP_KERNEL); + if (!new_stack) + goto bad_fork_free; nr = find_empty_process(); if (nr < 0) goto bad_fork_free; + *p = *current; if (p->exec_domain && p->exec_domain->use_count) @@ -184,7 +189,8 @@ (*p->binfmt->use_count)++; p->did_exec = 0; - p->kernel_stack_page = 0; + p->kernel_stack_page = new_stack; + *(unsigned long *) p->kernel_stack_page = STACK_MAGIC; p->state = TASK_UNINTERRUPTIBLE; p->flags &= ~(PF_PTRACED|PF_TRACESYS); p->pid = last_pid; @@ -201,11 +207,6 @@ p->start_time = jiffies; task[nr] = p; - /* build new kernel stack */ - if (!(p->kernel_stack_page = get_free_page(GFP_KERNEL))) - goto bad_fork_cleanup; - *(unsigned long *)p->kernel_stack_page = STACK_MAGIC; - /* copy all the process information */ clone_flags = copy_thread(nr, COPYVM | SIGCHLD, p, ®s); if (copy_mm(clone_flags, p)) @@ -222,8 +223,8 @@ bad_fork_cleanup: task[nr] = NULL; REMOVE_LINKS(p); - free_page(p->kernel_stack_page); bad_fork_free: + free_page(new_stack); free_page((long) p); bad_fork: return -EAGAIN; diff -u --recursive --new-file v1.1.79/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.1.79/linux/kernel/ksyms.c Wed Jan 11 21:14:29 1995 +++ linux/kernel/ksyms.c Thu Jan 12 13:14:16 1995 @@ -69,8 +69,14 @@ X(rename_module_symbol), /* system info variables */ + /* These check that they aren't defines (0/1) */ +#ifndef EISA_bus X(EISA_bus), -#ifdef __i386__ +#endif +#ifndef MCA_bus + X(MCA_bus), +#endif +#ifndef wp_works_ok X(wp_works_ok), #endif @@ -282,11 +288,13 @@ X(__down), #if defined(CONFIG_MSDOS_FS) && !defined(CONFIG_UMSDOS_FS) /* support for umsdos fs */ + X(msdos_bmap), X(msdos_create), X(msdos_file_read), X(msdos_file_write), X(msdos_lookup), X(msdos_mkdir), + X(msdos_mmap), X(msdos_put_inode), X(msdos_put_super), X(msdos_read_inode), diff -u --recursive --new-file v1.1.79/linux/kernel/resource.c linux/kernel/resource.c --- v1.1.79/linux/kernel/resource.c Thu Jan 1 02:00:00 1970 +++ linux/kernel/resource.c Wed Jan 11 21:23:14 1995 @@ -0,0 +1,138 @@ +/* + * linux/kernel/resource.c + * + * Copyright (C) 1995 Linus Torvalds + * David Hinds + * + * Kernel io-region resource management + */ + +#include +#include +#include +#include +#include + +#define IOTABLE_SIZE 32 + +typedef struct resource_entry_t { + u_long from, num; + const char *name; + struct resource_entry_t *next; +} resource_entry_t; + +static resource_entry_t iolist = { 0, 0, "", NULL }; + +static resource_entry_t iotable[IOTABLE_SIZE]; + +/* + * This generates the report for /proc/ioports + */ +int get_ioport_list(char *buf) +{ + resource_entry_t *p; + int len = 0; + + for (p = iolist.next; (p) && (len < 4000); p = p->next) + len += sprintf(buf+len, "%04lx-%04lx : %s\n", + p->from, p->from+p->num-1, p->name); + if (p) + len += sprintf(buf+len, "4K limit reached!\n"); + return len; +} + +/* + * The workhorse function: find where to put a new entry + */ +static resource_entry_t *find_gap(resource_entry_t *root, + u_long from, u_long num) +{ + unsigned long flags; + resource_entry_t *p; + + if (from > from+num-1) + return NULL; + save_flags(flags); + cli(); + for (p = root; ; p = p->next) { + if ((p != root) && (p->from+p->num-1 >= from)) { + p = NULL; + break; + } + if ((p->next == NULL) || (p->next->from > from+num-1)) + break; + } + restore_flags(flags); + return p; +} + +/* + * Call this from the device driver to register the ioport region. + */ +void request_region(unsigned int from, unsigned int num, const char *name) +{ + resource_entry_t *p; + int i; + + for (i = 0; i < IOTABLE_SIZE; i++) + if (iotable[i].num == 0) + break; + if (i == IOTABLE_SIZE) + printk("warning: ioport table is full\n"); + else { + p = find_gap(&iolist, from, num); + if (p == NULL) + return; + iotable[i].name = name; + iotable[i].from = from; + iotable[i].num = num; + iotable[i].next = p->next; + p->next = &iotable[i]; + return; + } +} + +/* + * 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) +{ + request_region(from,num,"No name given."); +} + +/* + * Call this when the device driver is unloaded + */ +void release_region(unsigned int from, unsigned int num) +{ + resource_entry_t *p, *q; + + for (p = &iolist; ; p = q) { + q = p->next; + if (q == NULL) + break; + if ((q->from == from) && (q->num == num)) { + q->num = 0; + p->next = q->next; + return; + } + } +} + +/* + * Call this to check the ioport region before probing + */ +int check_region(unsigned int from, unsigned int num) +{ + return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0; +} + +/* Called from init/main.c to reserve IO ports. */ +void reserve_setup(char *str, int *ints) +{ + int i; + + for (i = 1; i < ints[0]; i += 2) + request_region(ints[i], ints[i+1], "reserved"); +} diff -u --recursive --new-file v1.1.79/linux/kernel/sched.c linux/kernel/sched.c --- v1.1.79/linux/kernel/sched.c Mon Jan 9 07:22:12 1995 +++ linux/kernel/sched.c Wed Jan 11 21:10:54 1995 @@ -65,27 +65,6 @@ int need_resched = 0; unsigned long event = 0; -/* - * Tell us the machine setup.. - */ -char hard_math = 0; /* set by boot/head.S */ -char x86 = 0; /* set by boot/head.S to 3 or 4 */ -char x86_model = 0; /* set by boot/head.S */ -char x86_mask = 0; /* set by boot/head.S */ -int x86_capability = 0; /* set by boot/head.S */ -int fdiv_bug = 0; /* set if Pentium(TM) with FP bug */ - -char x86_vendor_id[13] = "Unknown"; - -char ignore_irq13 = 0; /* set if exception 16 works */ -char wp_works_ok = 0; /* set if paging hardware honours WP */ -char hlt_works_ok = 1; /* set if the "hlt" instruction works */ - -/* - * Bus types .. - */ -int EISA_bus = 0; - extern int _setitimer(int, struct itimerval *, struct itimerval *); unsigned long * prof_buffer = NULL; unsigned long prof_len = 0; @@ -494,7 +473,7 @@ time_status = TIME_OK; break; } - if (xtime.tv_sec > last_rtc_update + 660) + if (time_status != TIME_BAD && xtime.tv_sec > last_rtc_update + 660) if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else diff -u --recursive --new-file v1.1.79/linux/lib/string.c linux/lib/string.c --- v1.1.79/linux/lib/string.c Mon Jan 9 07:22:12 1995 +++ linux/lib/string.c Wed Jan 11 21:10:54 1995 @@ -201,7 +201,7 @@ /* * find the first occurrence of byte 'c', or 1 past the area if none */ -extern inline void * memscan(void * addr, unsigned char c, size_t size) +void * memscan(void * addr, unsigned char c, size_t size) { unsigned char * p = (unsigned char *) addr; diff -u --recursive --new-file v1.1.79/linux/mm/filemap.c linux/mm/filemap.c --- v1.1.79/linux/mm/filemap.c Tue Dec 6 11:38:44 1994 +++ linux/mm/filemap.c Wed Jan 11 21:10:54 1995 @@ -90,7 +90,7 @@ unsigned long poff, pcnt, pc; size = size >> PAGE_SHIFT; - dir = PAGE_DIR_OFFSET(current->tss.cr3,start); + dir = PAGE_DIR_OFFSET(current,start); poff = (start >> PAGE_SHIFT) & (PTRS_PER_PAGE-1); start -= vma->vm_start; if ((pcnt = PTRS_PER_PAGE - poff) > size) diff -u --recursive --new-file v1.1.79/linux/mm/memory.c linux/mm/memory.c --- v1.1.79/linux/mm/memory.c Mon Jan 9 07:22:12 1995 +++ linux/mm/memory.c Thu Jan 12 13:14:16 1995 @@ -47,22 +47,8 @@ #include #include -/* - * Define this if things work differently on a i386 and a i486: - * it will (on a i486) warn about kernel memory accesses that are - * done without a 'verify_area(VERIFY_WRITE,..)' - */ -#undef CONFIG_TEST_VERIFY_AREA - unsigned long high_memory = 0; -extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */ - -extern void scsi_mem_init(unsigned long); -extern void sound_mem_init(void); -extern void die_if_kernel(char *,struct pt_regs *,long); -extern void show_net_buffers(void); - /* * The free_area_list arrays point to the queue heads of the free areas * of different sizes @@ -130,20 +116,18 @@ void clear_page_tables(struct task_struct * tsk) { int i; - unsigned long pg_dir; unsigned long * page_dir; if (!tsk) return; if (tsk == task[0]) panic("task[0] (swapper) doesn't support exec()\n"); - pg_dir = tsk->tss.cr3; - page_dir = (unsigned long *) pg_dir; + page_dir = PAGE_DIR_OFFSET(tsk, 0); if (!page_dir || page_dir == swapper_pg_dir) { printk("Trying to clear kernel page-directory: not good\n"); return; } - if (mem_map[MAP_NR(pg_dir)] > 1) { + if (mem_map[MAP_NR((unsigned long) page_dir)] > 1) { unsigned long * new_pg; if (!(new_pg = (unsigned long*) get_free_page(GFP_KERNEL))) { @@ -152,8 +136,8 @@ } for (i = 768 ; i < 1024 ; i++) new_pg[i] = page_dir[i]; - free_page(pg_dir); - tsk->tss.cr3 = (unsigned long) new_pg; + free_page((unsigned long) page_dir); + SET_PAGE_DIR(tsk, new_pg); return; } for (i = 0 ; i < 768 ; i++,page_dir++) @@ -168,7 +152,6 @@ void free_page_tables(struct task_struct * tsk) { int i; - unsigned long pg_dir; unsigned long * page_dir; if (!tsk) @@ -177,22 +160,19 @@ printk("task[0] (swapper) killed: unable to recover\n"); panic("Trying to free up swapper memory space"); } - pg_dir = tsk->tss.cr3; - if (!pg_dir || pg_dir == (unsigned long) swapper_pg_dir) { + page_dir = PAGE_DIR_OFFSET(tsk, 0); + if (!page_dir || page_dir == swapper_pg_dir) { printk("Trying to free kernel page-directory: not good\n"); return; } - tsk->tss.cr3 = (unsigned long) swapper_pg_dir; - if (tsk == current) - __asm__ __volatile__("movl %0,%%cr3": :"a" (tsk->tss.cr3)); - if (mem_map[MAP_NR(pg_dir)] > 1) { - free_page(pg_dir); + SET_PAGE_DIR(tsk, swapper_pg_dir); + if (mem_map[MAP_NR((unsigned long) page_dir)] > 1) { + free_page((unsigned long) page_dir); return; } - page_dir = (unsigned long *) pg_dir; - for (i = 0 ; i < PTRS_PER_PAGE ; i++,page_dir++) - free_one_table(page_dir); - free_page(pg_dir); + for (i = 0 ; i < PTRS_PER_PAGE ; i++) + free_one_table(page_dir + i); + free_page((unsigned long) page_dir); invalidate(); } @@ -206,9 +186,9 @@ { unsigned long pg_dir; - pg_dir = current->tss.cr3; + pg_dir = (unsigned long) PAGE_DIR_OFFSET(current, 0); mem_map[MAP_NR(pg_dir)]++; - tsk->tss.cr3 = pg_dir; + SET_PAGE_DIR(tsk, pg_dir); return 0; } @@ -220,15 +200,14 @@ int copy_page_tables(struct task_struct * tsk) { int i; - unsigned long old_pg_dir, *old_page_dir; - unsigned long new_pg_dir, *new_page_dir; + unsigned long *old_page_dir; + unsigned long *new_page_dir; - if (!(new_pg_dir = get_free_page(GFP_KERNEL))) + new_page_dir = (unsigned long *) get_free_page(GFP_KERNEL); + if (!new_page_dir) return -ENOMEM; - old_pg_dir = current->tss.cr3; - tsk->tss.cr3 = new_pg_dir; - old_page_dir = (unsigned long *) old_pg_dir; - new_page_dir = (unsigned long *) new_pg_dir; + old_page_dir = PAGE_DIR_OFFSET(current, 0); + SET_PAGE_DIR(tsk, new_page_dir); for (i = 0 ; i < PTRS_PER_PAGE ; i++,old_page_dir++,new_page_dir++) { int j; unsigned long old_pg_table, *old_page_table; @@ -295,7 +274,7 @@ return -EINVAL; } size = (size + ~PAGE_MASK) >> PAGE_SHIFT; - dir = PAGE_DIR_OFFSET(current->tss.cr3,from); + dir = PAGE_DIR_OFFSET(current,from); poff = (from >> PAGE_SHIFT) & (PTRS_PER_PAGE-1); if ((pcnt = PTRS_PER_PAGE - poff) > size) pcnt = size; @@ -353,7 +332,7 @@ printk("zeromap_page_range: from = %08lx\n",from); return -EINVAL; } - dir = PAGE_DIR_OFFSET(current->tss.cr3,from); + dir = PAGE_DIR_OFFSET(current,from); size = (size + ~PAGE_MASK) >> PAGE_SHIFT; poff = (from >> PAGE_SHIFT) & (PTRS_PER_PAGE-1); if ((pcnt = PTRS_PER_PAGE - poff) > size) @@ -415,7 +394,7 @@ printk("remap_page_range: from = %08lx, to=%08lx\n",from,to); return -EINVAL; } - dir = PAGE_DIR_OFFSET(current->tss.cr3,from); + dir = PAGE_DIR_OFFSET(current,from); size = (size + ~PAGE_MASK) >> PAGE_SHIFT; poff = (from >> PAGE_SHIFT) & (PTRS_PER_PAGE-1); if ((pcnt = PTRS_PER_PAGE - poff) > size) @@ -493,7 +472,7 @@ printk("put_page: trying to put page %08lx at %08lx\n",page,address); return 0; } - page_table = PAGE_DIR_OFFSET(tsk->tss.cr3,address); + page_table = PAGE_DIR_OFFSET(tsk,address); if ((*page_table) & PAGE_PRESENT) page_table = (unsigned long *) (PAGE_MASK & *page_table); else { @@ -527,7 +506,7 @@ printk("put_dirty_page: trying to put page %08lx at %08lx\n",page,address); if (mem_map[MAP_NR(page)] != 1) printk("mem_map disagrees with %08lx at %08lx\n",page,address); - page_table = PAGE_DIR_OFFSET(tsk->tss.cr3,address); + page_table = PAGE_DIR_OFFSET(tsk,address); if (PAGE_PRESENT & *page_table) page_table = (unsigned long *) (PAGE_MASK & *page_table); else { @@ -567,7 +546,7 @@ unsigned long new_page; new_page = __get_free_page(GFP_KERNEL); - pde = PAGE_DIR_OFFSET(vma->vm_task->tss.cr3,address); + pde = PAGE_DIR_OFFSET(vma->vm_task,address); pte = *pde; if (!(pte & PAGE_PRESENT)) goto end_wp_page; @@ -720,8 +699,8 @@ unsigned long from_page; unsigned long to_page; - from_page = (unsigned long)PAGE_DIR_OFFSET(from_area->vm_task->tss.cr3,from_address); - to_page = (unsigned long)PAGE_DIR_OFFSET(to_area->vm_task->tss.cr3,to_address); + from_page = (unsigned long)PAGE_DIR_OFFSET(from_area->vm_task,from_address); + to_page = (unsigned long)PAGE_DIR_OFFSET(to_area->vm_task,to_address); /* is there a page-directory at from? */ from = *(unsigned long *) from_page; if (!(from & PAGE_PRESENT)) @@ -854,7 +833,7 @@ unsigned long page; unsigned long *p; - p = PAGE_DIR_OFFSET(tsk->tss.cr3,address); + p = PAGE_DIR_OFFSET(tsk,address); if (PAGE_PRESENT & *p) return *p; if (*p) { @@ -862,7 +841,7 @@ *p = 0; } page = get_free_page(GFP_KERNEL); - p = PAGE_DIR_OFFSET(tsk->tss.cr3,address); + p = PAGE_DIR_OFFSET(tsk,address); if (PAGE_PRESENT & *p) { free_page(page); return *p; @@ -886,7 +865,7 @@ unsigned long page; if (vma->vm_ops && vma->vm_ops->swapin) - page = vma->vm_ops->swapin(vma, entry); + page = vma->vm_ops->swapin(vma, address - vma->vm_start + vma->vm_offset, entry); else page = swap_in(entry); if (*pge != entry) { @@ -963,320 +942,4 @@ return; free_page(page); oom(current); -} - -/* - * This routine handles page faults. It determines the address, - * and the problem, and then passes it off to one of the appropriate - * routines. - */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) -{ - struct vm_area_struct * vma; - unsigned long address; - unsigned long page; - - /* get the address */ - __asm__("movl %%cr2,%0":"=r" (address)); - for (vma = current->mm->mmap ; ; vma = vma->vm_next) { - if (!vma) - goto bad_area; - if (vma->vm_end > address) - break; - } - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) - goto bad_area; - vma->vm_offset -= vma->vm_start - (address & PAGE_MASK); - vma->vm_start = (address & PAGE_MASK); -/* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ -good_area: - if (regs->eflags & VM_MASK) { - unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT; - if (bit < 32) - current->tss.screen_bitmap |= 1 << bit; - } - if (!(vma->vm_page_prot & PAGE_USER)) - goto bad_area; - if (error_code & PAGE_PRESENT) { - if (!(vma->vm_page_prot & (PAGE_RW | PAGE_COW))) - goto bad_area; -#ifdef CONFIG_TEST_VERIFY_AREA - if (regs->cs == KERNEL_CS) - printk("WP fault at %08x\n", regs->eip); -#endif - do_wp_page(vma, address, error_code); - return; - } - do_no_page(vma, address, error_code); - return; - -/* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ -bad_area: - if (error_code & PAGE_USER) { - current->tss.cr2 = address; - current->tss.error_code = error_code; - current->tss.trap_no = 14; - send_sig(SIGSEGV, current, 1); - return; - } -/* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ - if (wp_works_ok < 0 && address == TASK_SIZE && (error_code & PAGE_PRESENT)) { - wp_works_ok = 1; - pg0[0] = PAGE_SHARED; - invalidate(); - printk("This processor honours the WP bit even when in supervisor mode. Good.\n"); - return; - } - if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) { - printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); - pg0[0] = PAGE_SHARED; - } else - printk(KERN_ALERT "Unable to handle kernel paging request"); - printk(" at virtual address %08lx\n",address); - __asm__("movl %%cr3,%0" : "=r" (page)); - printk(KERN_ALERT "current->tss.cr3 = %08lx, %%cr3 = %08lx\n", - current->tss.cr3, page); - page = ((unsigned long *) page)[address >> 22]; - printk(KERN_ALERT "*pde = %08lx\n", page); - if (page & PAGE_PRESENT) { - page &= PAGE_MASK; - address &= 0x003ff000; - page = ((unsigned long *) page)[address >> PAGE_SHIFT]; - printk(KERN_ALERT "*pte = %08lx\n", page); - } - die_if_kernel("Oops", regs, error_code); - do_exit(SIGKILL); -} - -/* - * BAD_PAGE is the page that is used for page faults when linux - * is out-of-memory. Older versions of linux just did a - * do_exit(), but using this instead means there is less risk - * for a process dying in kernel mode, possibly leaving a inode - * unused etc.. - * - * BAD_PAGETABLE is the accompanying page-table: it is initialized - * to point to BAD_PAGE entries. - * - * ZERO_PAGE is a special page that is used for zero-initialized - * data and COW. - */ -unsigned long __bad_pagetable(void) -{ - extern char empty_bad_page_table[PAGE_SIZE]; - - __asm__ __volatile__("cld ; rep ; stosl": - :"a" (BAD_PAGE + PAGE_TABLE), - "D" ((long) empty_bad_page_table), - "c" (PTRS_PER_PAGE) - :"di","cx"); - return (unsigned long) empty_bad_page_table; -} - -unsigned long __bad_page(void) -{ - extern char empty_bad_page[PAGE_SIZE]; - - __asm__ __volatile__("cld ; rep ; stosl": - :"a" (0), - "D" ((long) empty_bad_page), - "c" (PTRS_PER_PAGE) - :"di","cx"); - return (unsigned long) empty_bad_page; -} - -unsigned long __zero_page(void) -{ - extern char empty_zero_page[PAGE_SIZE]; - - __asm__ __volatile__("cld ; rep ; stosl": - :"a" (0), - "D" ((long) empty_zero_page), - "c" (PTRS_PER_PAGE) - :"di","cx"); - return (unsigned long) empty_zero_page; -} - -void show_mem(void) -{ - int i,free = 0,total = 0,reserved = 0; - int shared = 0; - - printk("Mem-info:\n"); - show_free_areas(); - printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - i = high_memory >> PAGE_SHIFT; - while (i-- > 0) { - total++; - if (mem_map[i] & MAP_PAGE_RESERVED) - reserved++; - else if (!mem_map[i]) - free++; - else - shared += mem_map[i]-1; - } - printk("%d pages of RAM\n",total); - printk("%d free pages\n",free); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); - show_buffers(); -#ifdef CONFIG_NET - show_net_buffers(); -#endif -} - -extern unsigned long free_area_init(unsigned long, unsigned long); - -/* - * paging_init() sets up the page tables - note that the first 4MB are - * already mapped by head.S. - * - * This routines also unmaps the page at virtual kernel address 0, so - * that we can trap those pesky NULL-reference errors in the kernel. - */ -unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) -{ - unsigned long * pg_dir; - unsigned long * pg_table; - unsigned long tmp; - unsigned long address; - -/* - * Physical page 0 is special; it's not touched by Linux since BIOS - * and SMM (for laptops with [34]86/SL chips) may need it. It is read - * and write protected to detect null pointer references in the - * kernel. - */ -#if 0 - memset((void *) 0, 0, PAGE_SIZE); -#endif - start_mem = PAGE_ALIGN(start_mem); - address = 0; - pg_dir = swapper_pg_dir; - while (address < end_mem) { - tmp = *(pg_dir + 768); /* at virtual addr 0xC0000000 */ - if (!tmp) { - tmp = start_mem | PAGE_TABLE; - *(pg_dir + 768) = tmp; - start_mem += PAGE_SIZE; - } - *pg_dir = tmp; /* also map it in at 0x0000000 for init */ - pg_dir++; - pg_table = (unsigned long *) (tmp & PAGE_MASK); - for (tmp = 0 ; tmp < PTRS_PER_PAGE ; tmp++,pg_table++) { - if (address < end_mem) - *pg_table = address | PAGE_SHARED; - else - *pg_table = 0; - address += PAGE_SIZE; - } - } - invalidate(); - return free_area_init(start_mem, end_mem); -} - -void mem_init(unsigned long start_low_mem, - unsigned long start_mem, unsigned long end_mem) -{ - int codepages = 0; - int reservedpages = 0; - int datapages = 0; - unsigned long tmp; - extern int etext; - - end_mem &= PAGE_MASK; - high_memory = end_mem; - - /* mark usable pages in the mem_map[] */ - start_low_mem = PAGE_ALIGN(start_low_mem); - start_mem = PAGE_ALIGN(start_mem); - - /* - * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000. - * They seem to have done something stupid with the floppy - * controller as well.. - */ - while (start_low_mem < 0x9f000) { - mem_map[MAP_NR(start_low_mem)] = 0; - start_low_mem += PAGE_SIZE; - } - - while (start_mem < high_memory) { - mem_map[MAP_NR(start_mem)] = 0; - start_mem += PAGE_SIZE; - } -#ifdef CONFIG_SCSI - scsi_mem_init(high_memory); -#endif -#ifdef CONFIG_SOUND - sound_mem_init(); -#endif - for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) { - if (mem_map[MAP_NR(tmp)]) { - if (tmp >= 0xA0000 && tmp < 0x100000) - reservedpages++; - else if (tmp < (unsigned long) &etext) - codepages++; - else - datapages++; - continue; - } - mem_map[MAP_NR(tmp)] = 1; - free_page(tmp); - } - tmp = nr_free_pages << PAGE_SHIFT; - printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n", - tmp >> 10, - high_memory >> 10, - codepages << (PAGE_SHIFT-10), - reservedpages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10)); -/* test if the WP bit is honoured in supervisor mode */ - wp_works_ok = -1; - pg0[0] = PAGE_READONLY; - invalidate(); - __asm__ __volatile__("movb 0,%%al ; movb %%al,0": : :"ax", "memory"); - pg0[0] = 0; - invalidate(); - if (wp_works_ok < 0) - wp_works_ok = 0; -#ifdef CONFIG_TEST_VERIFY_AREA - wp_works_ok = 0; -#endif - return; -} - -void si_meminfo(struct sysinfo *val) -{ - int i; - - i = high_memory >> PAGE_SHIFT; - val->totalram = 0; - val->sharedram = 0; - val->freeram = nr_free_pages << PAGE_SHIFT; - val->bufferram = buffermem; - while (i-- > 0) { - if (mem_map[i] & MAP_PAGE_RESERVED) - continue; - val->totalram++; - if (!mem_map[i]) - continue; - val->sharedram += mem_map[i]-1; - } - val->totalram <<= PAGE_SHIFT; - val->sharedram <<= PAGE_SHIFT; - return; } diff -u --recursive --new-file v1.1.79/linux/mm/mprotect.c linux/mm/mprotect.c --- v1.1.79/linux/mm/mprotect.c Fri Nov 18 15:17:48 1994 +++ linux/mm/mprotect.c Wed Jan 11 21:10:54 1995 @@ -24,7 +24,7 @@ unsigned long page, offset; int nr; - dir = PAGE_DIR_OFFSET(current->tss.cr3, start); + dir = PAGE_DIR_OFFSET(current, start); offset = (start >> PAGE_SHIFT) & (PTRS_PER_PAGE-1); nr = (end - start) >> PAGE_SHIFT; while (nr > 0) { diff -u --recursive --new-file v1.1.79/linux/mm/swap.c linux/mm/swap.c --- v1.1.79/linux/mm/swap.c Mon Jan 9 07:22:12 1995 +++ linux/mm/swap.c Wed Jan 11 21:10:54 1995 @@ -77,14 +77,8 @@ #ifdef SWAP_CACHE_INFO swap_cache_add_total++; #endif - if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { - __asm__ __volatile__ ( - "xchgl %0,%1\n" - : "=m" (swap_cache[addr >> PAGE_SHIFT]), - "=r" (entry) - : "0" (swap_cache[addr >> PAGE_SHIFT]), - "1" (entry) - ); + if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { + entry = (unsigned long) xchg_ptr(swap_cache + (addr >> PAGE_SHIFT), (void *) entry); if (entry) { printk("swap_cache: replacing non-NULL entry\n"); } @@ -398,7 +392,7 @@ if (address < vma->vm_start) address = vma->vm_start; - pgdir = (address >> PGDIR_SHIFT) + (unsigned long *) p->tss.cr3; + pgdir = PAGE_DIR_OFFSET(p, address); offset = address & ~PGDIR_MASK; address &= PGDIR_MASK; for ( ; address < TASK_SIZE ; @@ -754,7 +748,7 @@ if (!p) continue; for (pgt = 0 ; pgt < PTRS_PER_PAGE ; pgt++) { - ppage = pgt + ((unsigned long *) p->tss.cr3); + ppage = pgt + PAGE_DIR_OFFSET(p, 0); page = *ppage; if (!page) continue; diff -u --recursive --new-file v1.1.79/linux/mm/vmalloc.c linux/mm/vmalloc.c --- v1.1.79/linux/mm/vmalloc.c Mon Jan 9 07:22:12 1995 +++ linux/mm/vmalloc.c Wed Jan 11 21:10:54 1995 @@ -39,7 +39,7 @@ p = &init_task; do { - ((unsigned long *) p->tss.cr3)[dindex] = value; + PAGE_DIR_OFFSET(p,0)[dindex] = value; p = p->next_task; } while (p != &init_task); } diff -u --recursive --new-file v1.1.79/linux/net/inet/arp.c linux/net/inet/arp.c --- v1.1.79/linux/net/inet/arp.c Mon Jan 9 07:22:12 1995 +++ linux/net/inet/arp.c Wed Jan 11 17:57:40 1995 @@ -580,7 +580,9 @@ break; #endif case ARPHRD_ETHER: +#ifdef CONFIG_ARCNET case ARPHRD_ARCNET: +#endif if(arp->ar_pro != htons(ETH_P_IP)) { kfree_skb(skb, FREE_READ); @@ -1054,10 +1056,12 @@ htype = ARPHRD_ETHER; hlen = ETH_ALEN; break; +#ifdef CONFIG_ARCNET case ARPHRD_ARCNET: htype = ARPHRD_ARCNET; hlen = 1; /* length of arcnet addresses */ break; +#endif #ifdef CONFIG_AX25 case ARPHRD_AX25: htype = ARPHRD_AX25; diff -u --recursive --new-file v1.1.79/linux/net/inet/sock.h linux/net/inet/sock.h --- v1.1.79/linux/net/inet/sock.h Wed Jan 11 21:14:29 1995 +++ linux/net/inet/sock.h Wed Jan 11 17:50:56 1995 @@ -91,7 +91,7 @@ unsigned long lingertime; int proc; struct sock *next; - struct sock *prev; /* Doubdly linked chain.. */ + struct sock *prev; /* Doubly linked chain.. */ struct sock *pair; struct sk_buff * volatile send_head; struct sk_buff * volatile send_tail; diff -u --recursive --new-file v1.1.79/linux/net/socket.c linux/net/socket.c --- v1.1.79/linux/net/socket.c Wed Jan 11 21:14:30 1995 +++ linux/net/socket.c Wed Jan 11 17:50:56 1995 @@ -287,7 +287,6 @@ ++nsockets; } sti(); -printk("sock_alloc: Alloced some more, now %d sockets\n", nsockets); } @@ -367,7 +366,7 @@ sti(); /* - * The rest of these are in fact vestigal from the previous + * The rest of these are in fact vestigial 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, @@ -979,7 +978,7 @@ if (!(newsock = sock_alloc(0))) { printk("NET: sock_accept: no more sockets\n"); - return(-ENOSR); /* Was: EGAIN, but we are out of system + return(-ENOSR); /* Was: EAGAIN, but we are out of system resources! */ } newsock->type = sock->type; diff -u --recursive --new-file v1.1.79/linux/net/unix/sock.c linux/net/unix/sock.c --- v1.1.79/linux/net/unix/sock.c Mon Jan 9 07:22:13 1995 +++ linux/net/unix/sock.c Thu Jan 12 11:37:34 1995 @@ -55,7 +55,7 @@ * space that need not be wasted. */ -struct unix_proto_data unix_datas[NSOCKETS]; +struct unix_proto_data unix_datas[NSOCKETS_UNIX]; static int unix_proto_create(struct socket *sock, int protocol); static int unix_proto_dup(struct socket *newsock, struct socket *oldsock); diff -u --recursive --new-file v1.1.79/linux/net/unix/unix.h linux/net/unix/unix.h --- v1.1.79/linux/net/unix/unix.h Wed Aug 10 19:26:51 1994 +++ linux/net/unix/unix.h Thu Jan 12 11:39:39 1995 @@ -43,10 +43,10 @@ int lock_flag; }; -extern struct unix_proto_data unix_datas[NSOCKETS]; +extern struct unix_proto_data unix_datas[NSOCKETS_UNIX]; -#define last_unix_data (unix_datas + NSOCKETS - 1) +#define last_unix_data (unix_datas + NSOCKETS_UNIX - 1) #define UN_DATA(SOCK) ((struct unix_proto_data *)(SOCK)->data)