diff -u --recursive --new-file v1.1.87/linux/CREDITS linux/CREDITS --- v1.1.87/linux/CREDITS Mon Jan 30 08:53:05 1995 +++ linux/CREDITS Tue Jan 31 09:39:02 1995 @@ -329,7 +329,7 @@ D: German Support-Disks for SLS/Slackware called SLT D: Linux Internationalization Project D: DOSemu -S: Mohlenweg 19 +S: Muehlenweg 19 S: 34266 Niestetal S: Germany diff -u --recursive --new-file v1.1.87/linux/Makefile linux/Makefile --- v1.1.87/linux/Makefile Mon Jan 30 08:53:05 1995 +++ linux/Makefile Tue Jan 31 17:32:12 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 87 +SUBLEVEL = 88 ARCH = i386 diff -u --recursive --new-file v1.1.87/linux/README.modules linux/README.modules --- v1.1.87/linux/README.modules Thu Jan 26 07:49:02 1995 +++ linux/README.modules Tue Jan 31 09:39:02 1995 @@ -18,7 +18,7 @@ make zImage or make zlilo In "make config", you select what you want to include in the kernel. -You will generally select the miminal set that is needed to boot: +You will generally select the minimal set that is needed to boot: The filesystem of your root partition A scsi driver, but see below for a list of SCSI modules! diff -u --recursive --new-file v1.1.87/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v1.1.87/linux/arch/alpha/kernel/entry.S Sun Jan 22 21:39:37 1995 +++ linux/arch/alpha/kernel/entry.S Tue Jan 31 09:30:47 1995 @@ -68,11 +68,33 @@ .ent entInt entInt: SAVE_ALL +/* start atomic operation with respect to software interrupts */ + lda $0,intr_count + ldq $1,0($0) + addq $1,1,$1 + stq $1,0($0) +/* set up the arguments to the C interrupt handler */ bis $30,$30,$19 lda $27,do_entInt jsr $26,($27),do_entInt +/* ok, check if we need to do software interrupts */ +1: lda $0,intr_count + ldq $1,0($0) + subq $1,1,$1 + bne $1,2f /* interrupt within interrupt: return now */ + lda $2,bh_active + ldq $3,0($2) + lda $2,bh_mask + ldq $2,0($2) + and $2,$3,$2 + bne $2,3f +2: stq $1,0($0) RESTORE_ALL rti +.align 5 +3: lda $27,do_bottom_half + jsr $26,($27),do_bottom_half + br $31,1b .end entInt .align 5 diff -u --recursive --new-file v1.1.87/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c --- v1.1.87/linux/arch/alpha/mm/fault.c Thu Jan 26 07:49:02 1995 +++ linux/arch/alpha/mm/fault.c Tue Jan 31 09:30:47 1995 @@ -18,6 +18,7 @@ #include #include +#include extern void die_if_kernel(char *,struct pt_regs *,long); diff -u --recursive --new-file v1.1.87/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v1.1.87/linux/arch/alpha/mm/init.c Mon Jan 30 08:53:06 1995 +++ linux/arch/alpha/mm/init.c Tue Jan 31 09:30:47 1995 @@ -18,6 +18,7 @@ #include #include +#include #include extern void scsi_mem_init(unsigned long); @@ -38,10 +39,10 @@ * ZERO_PAGE is a special page that is used for zero-initialized * data and COW. */ -pte_t * __bad_pagetable(void) +pmd_t * __bad_pagetable(void) { memset((void *) EMPTY_PGT, 0, PAGE_SIZE); - return (pte_t *) EMPTY_PGT; + return (pmd_t *) EMPTY_PGT; } pte_t __bad_page(void) @@ -151,7 +152,7 @@ start_mem = PAGE_ALIGN(start_mem); /* - * Mark the pages used by the kernel as reserved,, + * Mark the pages used by the kernel as reserved.. */ tmp = KERNEL_START; while (tmp < start_mem) { diff -u --recursive --new-file v1.1.87/linux/arch/i386/boot/compressed/Makefile linux/arch/i386/boot/compressed/Makefile --- v1.1.87/linux/arch/i386/boot/compressed/Makefile Mon Jan 30 08:53:06 1995 +++ linux/arch/i386/boot/compressed/Makefile Tue Jan 31 08:58:00 1995 @@ -34,7 +34,7 @@ xtract: xtract.c $(HOSTCC) $(CFLAGS) -o xtract xtract.c -piggyback: xtract.c +piggyback: piggyback.c $(HOSTCC) $(CFLAGS) -o piggyback piggyback.c clean: diff -u --recursive --new-file v1.1.87/linux/arch/i386/config.in linux/arch/i386/config.in --- v1.1.87/linux/arch/i386/config.in Mon Jan 30 08:53:06 1995 +++ linux/arch/i386/config.in Tue Jan 31 14:36:23 1995 @@ -149,6 +149,7 @@ bool 'EtherExpress support' CONFIG_EEXPRESS n bool 'NI5210 support' CONFIG_NI52 n bool 'NI6510 support' CONFIG_NI65 n + bool 'WaveLAN support' CONFIG_WAVELAN n fi bool 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS n bool 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN n diff -u --recursive --new-file v1.1.87/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v1.1.87/linux/arch/i386/kernel/process.c Sun Jan 22 23:03:57 1995 +++ linux/arch/i386/kernel/process.c Mon Jan 30 13:08:04 1995 @@ -21,7 +21,9 @@ #include #include +#include #include +#include asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call"); @@ -45,6 +47,41 @@ if (hlt_works_ok && !need_resched) __asm__("hlt"); schedule(); + } +} + +/* + * This routine reboots the machine by asking the keyboard + * controller to pulse the reset-line low. We try that for a while, + * and if it doesn't work, we do some other stupid things. + */ +static long no_idt[2] = {0, 0}; + +static inline void kb_wait(void) +{ + int i; + + for (i=0; i<0x10000; i++) + if ((inb_p(0x64) & 0x02) == 0) + break; +} + +void hard_reset_now(void) +{ + int i, j; + + sti(); +/* rebooting needs to touch the page at absolute addr 0 */ + pg0[0] = 7; + *((unsigned short *)0x472) = 0x1234; + for (;;) { + for (i=0; i<100; i++) { + kb_wait(); + for(j = 0; j < 100000 ; j++) + /* nothing */; + outb(0xfe,0x64); /* pulse reset low */ + } + __asm__ __volatile__("\tlidt %0": "=m" (no_idt)); } } diff -u --recursive --new-file v1.1.87/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c --- v1.1.87/linux/arch/i386/kernel/ptrace.c Sun Jan 22 23:03:57 1995 +++ linux/arch/i386/kernel/ptrace.c Mon Jan 30 13:08:04 1995 @@ -9,10 +9,11 @@ #include #include #include +#include #include +#include #include -#include /* * does not yet catch signals sent when the child dies. diff -u --recursive --new-file v1.1.87/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c --- v1.1.87/linux/arch/i386/kernel/vm86.c Thu Jan 26 07:49:03 1995 +++ linux/arch/i386/kernel/vm86.c Mon Jan 30 13:08:04 1995 @@ -12,6 +12,7 @@ #include #include +#include #include /* diff -u --recursive --new-file v1.1.87/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v1.1.87/linux/arch/i386/mm/fault.c Sun Jan 22 23:03:57 1995 +++ linux/arch/i386/mm/fault.c Mon Jan 30 13:08:04 1995 @@ -18,6 +18,7 @@ #include #include +#include extern void die_if_kernel(char *,struct pt_regs *,long); diff -u --recursive --new-file v1.1.87/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v1.1.87/linux/arch/i386/mm/init.c Thu Jan 26 07:49:03 1995 +++ linux/arch/i386/mm/init.c Tue Jan 31 09:39:01 1995 @@ -18,6 +18,7 @@ #include #include +#include extern void scsi_mem_init(unsigned long); extern void sound_mem_init(void); @@ -137,7 +138,7 @@ } pg_table = (pte_t *) pgd_page(pg_dir[768]); - /* also map it tempoarily at 0x0000000 for init */ + /* also map it temporarily at 0x0000000 for init */ pgd_set(pg_dir+768, pg_table); pgd_set(pg_dir, pg_table); pg_dir++; diff -u --recursive --new-file v1.1.87/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S --- v1.1.87/linux/arch/mips/kernel/head.S Mon Jan 30 06:41:55 1995 +++ linux/arch/mips/kernel/head.S Tue Jan 31 09:39:02 1995 @@ -436,7 +436,7 @@ .data /* - * Inital mapping tables for supported Mips boards. + * Initial mapping tables for supported Mips boards. * First item is always the number of wired TLB entries, * following by EntryHi/EntryLo pairs and page mask. * Since everything must be quad-aligned (8) we insert diff -u --recursive --new-file v1.1.87/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v1.1.87/linux/arch/mips/kernel/irq.c Mon Jan 30 06:41:55 1995 +++ linux/arch/mips/kernel/irq.c Tue Jan 31 09:39:02 1995 @@ -16,8 +16,8 @@ */ /* - * The Deskstation Tyne is almost completly like an IBM compatible PC with - * another type of microprocessor. Therefore this code is almost completly + * The Deskstation Tyne is almost completely like an IBM compatible PC with + * another type of microprocessor. Therefore this code is almost completely * the same. More work needs to be done to support Acer PICA and other * machines. */ diff -u --recursive --new-file v1.1.87/linux/arch/sparc/kernel/ioport.c linux/arch/sparc/kernel/ioport.c --- v1.1.87/linux/arch/sparc/kernel/ioport.c Thu Jan 26 07:49:03 1995 +++ linux/arch/sparc/kernel/ioport.c Tue Jan 31 09:39:01 1995 @@ -1,6 +1,6 @@ /* ioport.c: I/O access on the Sparc. Work in progress.. Most of the things * in this file are for the sole purpose of getting the kernel - * throught the compiler. :-) + * through the compiler. :-) * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ diff -u --recursive --new-file v1.1.87/linux/arch/sparc/kernel/probe.c linux/arch/sparc/kernel/probe.c --- v1.1.87/linux/arch/sparc/kernel/probe.c Thu Jan 26 07:49:03 1995 +++ linux/arch/sparc/kernel/probe.c Tue Jan 31 09:39:01 1995 @@ -236,7 +236,7 @@ void probe_clock(int fchild) { - /* TODO :> I just can't stomache it right now... */ + /* TODO :> I just can't stomach it right now... */ return; } diff -u --recursive --new-file v1.1.87/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v1.1.87/linux/arch/sparc/mm/init.c Thu Jan 26 07:49:03 1995 +++ linux/arch/sparc/mm/init.c Tue Jan 31 09:39:01 1995 @@ -95,7 +95,7 @@ * unmaps the bootup page table (as we're now in KSEG, so we don't need it). * * The bootup sequence put the virtual page table into high memory: that - * means that we cah change the L1 page table by just using VL1p below. + * means that we can change the L1 page table by just using VL1p below. */ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) diff -u --recursive --new-file v1.1.87/linux/drivers/block/README.aztcd linux/drivers/block/README.aztcd --- v1.1.87/linux/drivers/block/README.aztcd Sun Jan 22 23:03:57 1995 +++ linux/drivers/block/README.aztcd Tue Jan 31 09:39:01 1995 @@ -22,7 +22,7 @@ 7. OTHER DRIVES 8. IF YOU DON'T SUCCEED ... DEBUGGING 9. TECHNICAL HISTORY OF THE DRIVER - 10. ACKNOWLEDGEMENTS + 10. ACKNOWLEDGMENTS 11. PROGRAMMING ADD ONS: CDPLAY.C APPENDIX: Source code of cdplay.c ---------------------------------------------------------------------------- @@ -51,7 +51,7 @@ in /usr/include/linux and the source code 'aztcd.c', which normally resides in /usr/src/linux/drivers/block. It uses /dev/aztcd0, which must be a valid block device with major number 29 and reside in directory /dev. To mount a CD-ROM, -your kernel needs to have the ISO9660-filesysytem support included. +your kernel needs to have the ISO9660-filesystem support included. 3. CONFIGURING YOUR KERNEL @@ -86,7 +86,7 @@ If your kernel is not yet configured for the AZTECH driver and the ISO9660- filesystem, you have to recompile your kernel: -- Edit aztcd.h to set the I/O-adress to your I/O-Base adress (AZT_BASE_ADDR), +- Edit aztcd.h to set the I/O-address to your I/O-Base address (AZT_BASE_ADDR), the driver does not use interrupts or DMA, so if you are using an AZTECH CD268, an ORCHID CD-3110 or ORCHID/WEARNES CDD110 that's the only item you have to set up. @@ -172,7 +172,7 @@ the same as AZTECH CDA268-01A, especially they seem to use the same command codes. So it was quite simple to make the AZTECH driver work with these drives. -Unfortuntately I do not have any of these drives available, so I couldn't test +Unfortunately I do not have any of these drives available, so I couldn't test it myself. But I've got reports, that it works with ORCHID CDS3110 and Game- Wave32 sound cards and also with WEARNES CDD110 in some different combinations. In some installations, it seems necessary to initialize the drive with the DOS @@ -195,7 +195,7 @@ DMA: not used Base Address: something like 300, 320 ... You can check this, when you start the DOS driver, which came with your - drive. By appropiately configuring the drive and the DOS driver you can + drive. By appropriately configuring the drive and the DOS driver you can check, whether your drive does operate in this mode correctly under DOS. If it does not operate under DOS, it won't under Linux. Make sure the Base Address is configured correctly in aztcd.h, also make @@ -297,7 +297,7 @@ The AZTECH-Driver is a rework of the Mitsumi-Driver. Four major items had to be reworked: -a) The Mitsumi drive does issue complete status informations acknowleding +a) The Mitsumi drive does issue complete status information acknowledging each command, the Aztech drive does only signal that the command was processed. So whenever the complete status information is needed, an extra ACMD_GET_STATUS command is issued. The handshake procedure for the drive @@ -326,7 +326,7 @@ uses a different command than for cooked mode, which I only have implemen- ted in the ioctl-section but not in the section which is used by the ISO9660- -The driver was developped on an AST PC with Intel 486/DX2, 8MB RAM, 340MB IDE +The driver was developed on an AST PC with Intel 486/DX2, 8MB RAM, 340MB IDE hard disk and on an AST PC with Intel Pentium 60MHz, 16MB RAM, 520MB IDE running Linux kernel version 1.0.9 from the LST 1.8 Distribution. The kernel was compiled with gcc.2.5.8. My CD-ROM drive is an Aztech CDA268-01A. My @@ -341,7 +341,7 @@ Mitsumi driver, where I did not completely understand their code. -10. ACKNOWLEDGEMENTS +10. ACKNOWLEDGMENTS Without the help of P.Bush, Aztech, who delivered technical information about the Aztech Drive and without the help of E.Moenkeberg, GWDG, who did a great job in analyzing the command structure of various CD-ROM drives, this @@ -360,7 +360,7 @@ and suggested a lot of patches for them. Joseph Piskor and Peter Nugent were the first users with the ORCHID CD3110 -and also were very patient with the problems, which occured. +and also were very patient with the problems which occurred. Anybody, who is interested in these items should have a look at 'ftp.gwdg.de', directory 'pub/linux/cdrom' and at 'ftp.cdrom.com', directory 'pub/cdrom'. @@ -415,7 +415,7 @@ Copyright 1994, 1995 Werner Zimmermann (zimmerma@rz.fht-esslingen.de) -This programm originally was written to test the audio functions of the +This program originally was written to test the audio functions of the AZTECH.CDROM-driver, but it should work with every CD-ROM drive. Before using it, you should set a symlink from /dev/cdrom to your real CDROM device. @@ -592,7 +592,7 @@ } break; case 'a': cmd=CDROMPLAYMSF; - printf("Adress (min:sec:frame) "); + printf("Address (min:sec:frame) "); scanf("%d:%d:%d",&arg1,&arg2,&arg3); msf.cdmsf_min0 =arg1; msf.cdmsf_sec0 =arg2; @@ -603,12 +603,12 @@ msf.cdmsf_sec1=00; msf.cdmsf_frame1=00; if (ioctl(handle,cmd,&msf)) - { printf("Drive error or invalid adress\n"); + { printf("Drive error or invalid address\n"); } break; #ifdef AZT_PRIVATE_IOCTLS /*not supported by every CDROM driver*/ case 'd': cmd=CDROMREADMODE1; - printf("Adress (min:sec:frame) "); + printf("Address (min:sec:frame) "); scanf("%d:%d:%d",&arg1,&arg2,&arg3); azt.msf.cdmsf_min0 =arg1; azt.msf.cdmsf_sec0 =arg2; @@ -616,7 +616,7 @@ if (azt.msf.cdmsf_sec0 > 59) azt.msf.cdmsf_sec0 =59; if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74; if (ioctl(handle,cmd,&azt.msf)) - { printf("Drive error, invalid adress or unsupported command\n"); + { printf("Drive error, invalid address or unsupported command\n"); } k=0; getchar(); @@ -641,7 +641,7 @@ } break; case 'w': cmd=CDROMREADMODE2; - printf("Adress (min:sec:frame) "); + printf("Address (min:sec:frame) "); scanf("%d:%d:%d",&arg1,&arg2,&arg3); azt.msf.cdmsf_min0 =arg1; azt.msf.cdmsf_sec0 =arg2; @@ -649,7 +649,7 @@ if (azt.msf.cdmsf_sec0 > 59) azt.msf.cdmsf_sec0 =59; if (azt.msf.cdmsf_frame0> 74) azt.msf.cdmsf_frame0=74; if (ioctl(handle,cmd,&azt)) - { printf("Drive error, invalid adress or unsupported command\n"); + { printf("Drive error, invalid address or unsupported command\n"); } k=0; for (i=0;i<146;i++) diff -u --recursive --new-file v1.1.87/linux/drivers/block/README.ide linux/drivers/block/README.ide --- v1.1.87/linux/drivers/block/README.ide Mon Jan 30 06:41:56 1995 +++ linux/drivers/block/README.ide Tue Jan 31 09:39:01 1995 @@ -98,11 +98,11 @@ Some Terminology ---------------- -IDE = Integrated Drive Electonics, meaning that each drive has a built-in +IDE = Integrated Drive Electronics, meaning that each drive has a built-in controller, which is why an "IDE interface card" is not a "controller card". IDE drives are designed to attach almost directly to the ISA bus of an AT-style -computer. The typcial IDE interface card merely provides I/O port address +computer. The typical IDE interface card merely provides I/O port address decoding and tri-state buffers, although several newer localbus cards go much beyond the basics. When purchasing a localbus IDE interface, avoid cards with an onboard BIOS and those which require special drivers. Instead, look for a @@ -119,7 +119,7 @@ ATAPI = ATA Packet Interface, a new protocol for controlling the drives, similar to SCSI protocols, created at the same time as the ATA2 standard. ATAPI is currently used for controlling CDROM and TAPE devices, and will -likely also soon be used for Floppy drives, removeable R/W cartridges, +likely also soon be used for Floppy drives, removable R/W cartridges, and for high capacity hard disk drives. How To Use *Big* ATA/IDE drives with Linux diff -u --recursive --new-file v1.1.87/linux/drivers/block/aztcd.c linux/drivers/block/aztcd.c --- v1.1.87/linux/drivers/block/aztcd.c Thu Jan 26 07:49:04 1995 +++ linux/drivers/block/aztcd.c Tue Jan 31 09:39:01 1995 @@ -32,7 +32,7 @@ frame can be read in sequence, this is also the reason for 3. getting 'timeout in state 4' messages, but nevertheless it works - W.Zimmermann, Okt. 31, 1994 + W.Zimmermann, Oct. 31, 1994 V0.1 Version is ALPHA, problems #2 and #3 resolved. W.Zimmermann, Nov. 3, 1994 V0.2 Modification to some comments, debugging aids for partial test @@ -67,24 +67,24 @@ W.Zimmermann, Nov. 18, 1994 V0.42 Included getAztStatus command in GetQChannelInfo() to allow reading Q-channel info on audio disks, if drive is stopped, - and some other bug fixes in the audio stuff, suggestet by + and some other bug fixes in the audio stuff, suggested by Robby Schirmer. Added more ioctls (reading data in mode 1 and mode 2). Completely removed the old azt_poll() routine. Detection of ORCHID CDS-3110 in aztcd_init implemented. Additional debugging aids (see the readme file). - W.Zimmermann, Dez. 9, 1994 - V0.50 Autodetection of drives inplemented. - W.Zimmermann, Dez. 12, 1994 + W.Zimmermann, Dec. 9, 1994 + V0.50 Autodetection of drives implemented. + W.Zimmermann, Dec. 12, 1994 V0.52 Prepared for including in the standard kernel, renamed most variables to contain 'azt', included autoconf.h - W.Zimmermann, Dez. 16, 1994 + W.Zimmermann, Dec. 16, 1994 V0.6 Version for being included in the standard Linux kernel. Renamed source and header file to aztcd.c and aztcd.h - W.Zimmermann, Dez. 24, 1994 + W.Zimmermann, Dec. 24, 1994 V0.7 Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl, - which causes kernel crashs, when playing audio, changed + which causes kernel crashes when playing audio, changed include-files (config.h instead of autoconf.h, removed delay.h) W.Zimmermann, Jan. 8, 1995 @@ -209,7 +209,7 @@ /* Macros for the drive hardware interface handshake, these macros use busy waiting */ -/* Wait for OP_OK = drive answers with AFL_OP_OK after recieving a command*/ +/* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/ # define OP_OK op_ok() void op_ok(void) { aztTimeOutCount=0; @@ -222,7 +222,7 @@ } while (aztIndatum!=AFL_OP_OK); } -/* Wait for PA_OK = drive answers with AFL_PA_OK after recieving parameters*/ +/* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/ # define PA_OK pa_ok() void pa_ok(void) { aztTimeOutCount=0; @@ -377,7 +377,7 @@ } -/* used in azt_poll to poll the status, expects another programm to issue a +/* used in azt_poll to poll the status, expects another program to issue a * ACMD_GET_STATUS directly before */ static int aztStatus(void) @@ -637,7 +637,7 @@ */ break; case CDROMEJECT: - /* all drives can atleast stop! */ + /* all drives can at least stop! */ if (aztAudioStatus == CDROM_AUDIO_PLAY) { if (aztSendCmd(ACMD_STOP)) return -1; STEN_LOW_WAIT; @@ -1439,7 +1439,7 @@ } /* - * Read the table of contents (TOC) and TOC header if neccessary + * Read the table of contents (TOC) and TOC header if necessary */ static int aztUpdateToc() { diff -u --recursive --new-file v1.1.87/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v1.1.87/linux/drivers/block/floppy.c Mon Jan 30 08:53:06 1995 +++ linux/drivers/block/floppy.c Tue Jan 31 09:30:47 1995 @@ -121,6 +121,7 @@ #include #include #include +#include /* CMOS defines */ #include #include @@ -2851,11 +2852,6 @@ return 0; #undef IOCTL_ALLOWED } - -#define CMOS_READ(addr) ({ \ -outb_p(addr,0x70); \ -inb_p(0x71); \ -}) static void set_base_type(int drive,int code) { diff -u --recursive --new-file v1.1.87/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v1.1.87/linux/drivers/block/hd.c Mon Jan 16 14:18:16 1995 +++ linux/drivers/block/hd.c Tue Jan 31 09:30:47 1995 @@ -34,6 +34,7 @@ #include #include #include +#include /* CMOS defines */ #define REALLY_SLOW_IO #include @@ -46,12 +47,6 @@ #define HD_IRQ 14 static int revalidate_hddisk(int, int); - -static inline unsigned char CMOS_READ(unsigned char addr) -{ - outb_p(addr,0x70); - return inb_p(0x71); -} #define HD_DELAY 0 diff -u --recursive --new-file v1.1.87/linux/drivers/char/ChangeLog linux/drivers/char/ChangeLog --- v1.1.87/linux/drivers/char/ChangeLog Mon Jan 9 07:22:01 1995 +++ linux/drivers/char/ChangeLog Tue Jan 31 09:39:02 1995 @@ -1,3 +1,31 @@ +Thu Jan 26 09:02:49 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (rs_init, set_serial_info, get_serial_info, rs_close): + Support close_wait and close_wait2 in the serial driver. + This is helpful for slow devices (like serial plotters) so + that their outputs don't get flushed upon device close. + This has to be configurable because normally we don't want + ports to be hung up for long periods of time during a + close when they are not connected to a device, or the + device is powered off. + + The default is to wait 30 seconds after shutting down the + receiver (to prevent echo wars). This is done by setting + close_wait=ASYNC_CLOSE_WAIT_NONE, close_wait2 = 3000. If + XON/XOFF handshaking is used, then the 30 second timeout + should happen before the receiver is shutdown; this is + done by reversing the values of close_wait and + close_wait2. In the case of a very slow device, the + timeouts for close_wait or close_wait2 should be lengthed. + If either value is set to 0, the kernel will wait forever + for all of the data to be transmitted. + +Thu Jan 17 01:17:20 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (startup, change_speed, rs_init): Add support to detect + the StarTech 16650 chip. Treat it as a 16450 for now, + because of its FIFO bugs. + Thu Jan 5 21:21:57 1995 * serial.c: (receive_char): Added counter to prevent infinite loop diff -u --recursive --new-file v1.1.87/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v1.1.87/linux/drivers/char/keyboard.c Mon Jan 16 14:18:18 1995 +++ linux/drivers/char/keyboard.c Mon Jan 30 13:08:04 1995 @@ -1158,34 +1158,6 @@ sti(); } -long no_idt[2] = {0, 0}; - -/* - * This routine reboots the machine by asking the keyboard - * controller to pulse the reset-line low. We try that for a while, - * and if it doesn't work, we do some other stupid things. - */ -#ifdef __i386__ -void hard_reset_now(void) -{ - int i, j; - - sti(); -/* rebooting needs to touch the page at absolute addr 0 */ - pg0[0] = 7; - *((unsigned short *)0x472) = 0x1234; - for (;;) { - for (i=0; i<100; i++) { - kb_wait(); - for(j = 0; j < 100000 ; j++) - /* nothing */; - outb(0xfe,0x64); /* pulse reset low */ - } - __asm__("\tlidt _no_idt"); - } -} -#endif - unsigned long kbd_init(unsigned long kmem_start) { int i; diff -u --recursive --new-file v1.1.87/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v1.1.87/linux/drivers/char/serial.c Thu Jan 26 07:49:05 1995 +++ linux/drivers/char/serial.c Tue Jan 31 09:39:02 1995 @@ -877,7 +877,15 @@ * Clear the FIFO buffers and disable them * (they will be reenabled in change_speed()) */ - if (info->type == PORT_16550A) { + if (info->type == PORT_16650) { + serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); +#if 0 + info->xmit_fifo_size = 32; +#else + info->xmit_fifo_size = 1; +#endif + } else if (info->type == PORT_16550A) { serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)); info->xmit_fifo_size = 16; @@ -1148,6 +1156,18 @@ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; else fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; + } else if (info->type == PORT_16650) { + /* + * On the 16650, we disable the FIFOs altogether + * because of a design bug in how the implement + * things. We could support it by completely changing + * how we handle the interrupt driver, but not today.... + * + * N.B. Because there's no way to set a FIFO trigger + * at 1 char, we'd probably disable at speed below + * 2400 baud anyway... + */ + fcr = 0; } else fcr = 0; @@ -1404,6 +1424,8 @@ tmp.flags = info->flags; tmp.baud_base = info->baud_base; tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.closing_wait2 = info->closing_wait2; tmp.custom_divisor = info->custom_divisor; tmp.hub6 = info->hub6; memcpy_tofs(retinfo,&tmp,sizeof(*retinfo)); @@ -1471,6 +1493,8 @@ info->custom_divisor = new_serial.custom_divisor; info->type = new_serial.type; info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + info->closing_wait2 = new_serial.closing_wait2; release_region(info->port,8); if (change_port || change_irq) { @@ -1871,6 +1895,8 @@ info->normal_termios = *tty->termios; if (info->flags & ASYNC_CALLOUT_ACTIVE) info->callout_termios = *tty->termios; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + wait_until_sent(tty, info->closing_wait); /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the @@ -1881,7 +1907,7 @@ info->read_status_mask &= ~UART_LSR_DR; if (info->flags & ASYNC_INITIALIZED) { serial_out(info, UART_IER, info->IER); - wait_until_sent(tty, 3000); /* 30 seconds timeout */ + wait_until_sent(tty, info->closing_wait2); /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -2329,6 +2355,10 @@ if (info->flags & ASYNC_AUTO_IRQ) info->irq = do_auto_irq(info); + scratch2 = serial_in(info, UART_LCR); + serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB); + serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */ + serial_outp(info, UART_LCR, scratch2); serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); scratch = serial_in(info, UART_IIR) >> 6; info->xmit_fifo_size = 1; @@ -2343,8 +2373,15 @@ info->type = PORT_16550; break; case 3: - info->type = PORT_16550A; - info->xmit_fifo_size = 16; + serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB); + if (serial_in(info, UART_EFR) == 0) { + info->type = PORT_16650; + info->xmit_fifo_size = 32; + } else { + info->type = PORT_16550A; + info->xmit_fifo_size = 16; + } + serial_outp(info, UART_LCR, scratch2); break; } if (info->type == PORT_16450) { @@ -2457,6 +2494,8 @@ info->type = PORT_UNKNOWN; info->custom_divisor = 0; info->close_delay = 50; + info->closing_wait = ASYNC_CLOSING_WAIT_NONE; + info->closing_wait2 = 3000; info->x_char = 0; info->event = 0; info->count = 0; @@ -2491,6 +2530,9 @@ break; case PORT_16550A: printk(" is a 16550A\n"); + break; + case PORT_16650: + printk(" is a 16650\n"); break; default: printk("\n"); diff -u --recursive --new-file v1.1.87/linux/drivers/net/3c501.c linux/drivers/net/3c501.c --- v1.1.87/linux/drivers/net/3c501.c Thu Jan 26 07:49:05 1995 +++ linux/drivers/net/3c501.c Tue Jan 31 14:33:21 1995 @@ -677,12 +677,15 @@ void cleanup_module(void) { - if (MOD_IN_USE) - printk("3c501: device busy, remove delayed\n"); - else - { - unregister_netdev(&dev_3c501); - } + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + unregister_netdev(&dev_3c501); + + /* Free up the private structure, or leak memory :-) */ + kfree(dev_3c501.priv); + dev_3c501.priv = NULL; /* gets re-allocated by el1_probe1 */ + + /* If we don't do this, we can't re-insmod it later. */ + release_region(dev_3c501.base_addr, EL1_IO_EXTENT); } #endif /* MODULE */ diff -u --recursive --new-file v1.1.87/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v1.1.87/linux/drivers/net/Makefile Mon Jan 30 06:41:56 1995 +++ linux/drivers/net/Makefile Tue Jan 31 14:36:24 1995 @@ -164,6 +164,12 @@ MODULES := $(MODULES) eexpress.o endif +ifdef CONFIG_WAVELAN +NETDRV_OBJS := $(NETDRV_OBJS) wavelan.o +else +MODULES := $(MODULES) wavelan.o +endif + ifdef CONFIG_ZNET NETDRV_OBJS := $(NETDRV_OBJS) znet.o endif diff -u --recursive --new-file v1.1.87/linux/drivers/net/README.wavelan linux/drivers/net/README.wavelan --- v1.1.87/linux/drivers/net/README.wavelan Thu Jan 1 02:00:00 1970 +++ linux/drivers/net/README.wavelan Tue Jan 31 14:36:24 1995 @@ -0,0 +1,49 @@ +#if defined(CONFIG_WAVELAN) + +Tue Jan 31 10:42:35 EST 1995 + +0. This document refers to Version 5 of the Linux WaveLAN device driver software. + It has been tested successfully under the 1.1.87 release of the Linux + kernel. It is `beta-test' software, so caveat emptor. Please report bugs + to me so that I can fix them quickly. + +1. At present the driver only autoprobes for a WaveLAN card at I/O address 0x390. + The version of the card that I use (NCR) supports four I/O addresses (selectable + via a pair of DIP switches). If you want the driver to autoprobe a different + subset of the four valid addresses then you will need to edit + .../drivers/net/wavelan.c (near line 714) and change the initialisation of the + `iobase[]' array. Normally, I use a LILO configuration file directive to + obviate the need for autoprobing entirely, a course of action I heartily + recommend. + +2. By default, the driver uses the Network ID (NWID) stored in the card's Parameter + Storage Area (PSA). However, the PSA NWID can be overridden by a value passed + explicitly as the third numeric argument to LILO's "ether=" directive, either + at the LILO prompt at boot time or within LILO's configuration file. + For example, the following line from such a LILO configuration file would + auto-configure the IRQ value, set the I/O base to 0x390 and set the NWID to + 0x4321, all on a WaveLAN card labelled "eth0": + + .. + append ="ether=0,0x390,0x4321,eth0" + .. + +3. The files that comprise this software must be incorporated into the Linux + kernel source tree (usually rooted at /usr/src/linux). Following that a + "make clean; make config; make dep; make zImage" should produce a Linux + kernel incorporating the WaveLAN driver, ready for installation. + The files: + drivers/net/wavelan.[ch] + drivers/net/i82586.h + are unique to this package and simply may be moved into place. The + others are modified versions of pre-existing files and must + be incorporated more carefully. However, the regions of modified code + within these files are small and are bracketted by the preprocessor + symbol CONFIG_WAVELAN, so incorporation should be straightforward. + +4. If you encounter any problems send me some email. + +Good luck, +Bruce Janson (bruce@cs.usyd.edu.au) + +#endif /* defined(CONFIG_WAVELAN) */ diff -u --recursive --new-file v1.1.87/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v1.1.87/linux/drivers/net/Space.c Mon Jan 30 06:41:56 1995 +++ linux/drivers/net/Space.c Tue Jan 31 14:36:24 1995 @@ -51,6 +51,9 @@ extern int ewrk3_probe(struct device *); extern int de4x5_probe(struct device *); extern int el1_probe(struct device *); +#if defined(CONFIG_WAVELAN) +extern int wavelan_probe(struct device *); +#endif /* defined(CONFIG_WAVELAN) */ extern int el16_probe(struct device *); extern int elplus_probe(struct device *); extern int ac3200_probe(struct device *); @@ -121,6 +124,9 @@ #ifdef CONFIG_EL1 /* 3c501 */ && el1_probe(dev) #endif +#if defined(CONFIG_WAVELAN) /* WaveLAN */ + && wavelan_probe(dev) +#endif /* defined(CONFIG_WAVELAN) */ #ifdef CONFIG_EL16 /* 3c507 */ && el16_probe(dev) #endif diff -u --recursive --new-file v1.1.87/linux/drivers/net/de4x5.h linux/drivers/net/de4x5.h --- v1.1.87/linux/drivers/net/de4x5.h Mon Jan 30 06:41:56 1995 +++ linux/drivers/net/de4x5.h Tue Jan 31 09:39:01 1995 @@ -78,7 +78,7 @@ ** EISA Configuration Register 2 bit definitions */ #define ER2_BRS 0xc0 /* Boot ROM Size */ -#define ER2_BRA 0x3c /* Boot ROM Adress <16:13> */ +#define ER2_BRA 0x3c /* Boot ROM Address <16:13> */ /* ** EISA Configuration Register 3 bit definitions @@ -247,7 +247,7 @@ #define OMR_BP 0x00010000 /* Back Pressure */ #define OMR_TR 0x0000c000 /* Threshold Control Bits */ #define OMR_ST 0x00002000 /* Start/Stop Transmission Command */ -#define OMR_FC 0x00001000 /* Force Collisio Mode */ +#define OMR_FC 0x00001000 /* Force Collision Mode */ #define OMR_OM 0x00000c00 /* Operating Mode */ #define OMR_FD 0x00000200 /* Full Duplex Mode */ #define OMR_FKD 0x00000100 /* Flaky Oscillator Disable */ @@ -343,7 +343,7 @@ /* ** DC21040 SIA Transmit and Receive Register (DE4X5_STRR) */ -#define STRR_SPP 0x00004000 /* Set Polarit Plus */ +#define STRR_SPP 0x00004000 /* Set Polarity Plus */ #define STRR_APE 0x00002000 /* Auto Polarity Enable */ #define STRR_LTE 0x00001000 /* Link Test Enable */ #define STRR_SQE 0x00000800 /* Signal Quality Enable */ diff -u --recursive --new-file v1.1.87/linux/drivers/net/i82586.h linux/drivers/net/i82586.h --- v1.1.87/linux/drivers/net/i82586.h Thu Jan 1 02:00:00 1970 +++ linux/drivers/net/i82586.h Tue Jan 31 14:36:24 1995 @@ -0,0 +1,410 @@ +#if defined(CONFIG_WAVELAN) +/* + * Intel 82586 IEEE 802.3 Ethernet LAN Coprocessor. + * + * See: + * Intel Microcommunications 1991 + * p1-1 to p1-37 + * Intel order No. 231658 + * ISBN 1-55512-119-5 + * + * Unfortunately, the above chapter mentions neither + * the System Configuration Pointer (SCP) nor the + * Intermediate System Configuration Pointer (ISCP), + * so we probably need to look elsewhere for the + * whole story -- some recommend the "Intel LAN + * Components manual" but I have neither a copy + * nor a full reference. But "elsewhere" may be + * in the same publication... + * The description of a later device, the + * "82596CA High-Performance 32-Bit Local Area Network + * Coprocessor", (ibid. p1-38 to p1-109) does mention + * the SCP and ISCP and also has an i82586 compatibility + * mode. Even more useful is "AP-235 An 82586 Data Link + * Driver" (ibid. p1-337 to p1-417). + */ + +#define I82586_MEMZ (64 * 1024) + +#define I82586_SCP_ADDR (I82586_MEMZ - sizeof(scp_t)) + +#define ADDR_LEN 6 +#define I82586NULL 0xFFFF + +#define toff(t,p,f) (unsigned short)((void *)(&((t *)((void *)0 + (p)))->f) - (void *)0) + +/* + * System Configuration Pointer (SCP). + */ +typedef struct scp_t scp_t; +struct scp_t +{ + unsigned short scp_sysbus; /* 82586 bus width: */ +#define SCP_SY_16BBUS (0x0 << 0) /* 16 bits */ +#define SCP_SY_8BBUS (0x1 << 0) /* 8 bits. */ + unsigned short scp_junk[2]; /* Unused */ + unsigned short scp_iscpl; /* lower 16 bits of ISCP_ADDR */ + unsigned short scp_iscph; /* upper 16 bits of ISCP_ADDR */ +}; + +/* + * Intermediate System Configuration Pointer (ISCP). + */ +typedef struct iscp_t iscp_t; +struct iscp_t +{ + unsigned short iscp_busy; /* set by CPU before first CA, */ + /* cleared by 82586 after read. */ + unsigned short iscp_offset; /* offset of SCB */ + unsigned short iscp_basel; /* base of SCB */ + unsigned short iscp_baseh; /* " */ +}; + +/* + * System Control Block (SCB). + * The 82586 writes its status to scb_status and then + * raises an interrupt to alert the CPU. + * The CPU writes a command to scb_command and + * then issues a Channel Attention (CA) to alert the 82586. + */ +typedef struct scb_t scb_t; +struct scb_t +{ + unsigned short scb_status; /* Status of 82586 */ +#define SCB_ST_INT (0xF << 12) /* Some of: */ +#define SCB_ST_CX (0x1 << 15) /* Cmd completed */ +#define SCB_ST_FR (0x1 << 14) /* Frame received */ +#define SCB_ST_CNA (0x1 << 13) /* Cmd unit not active */ +#define SCB_ST_RNR (0x1 << 12) /* Rcv unit not ready */ +#define SCB_ST_JUNK0 (0x1 << 11) /* 0 */ +#define SCB_ST_CUS (0x7 << 8) /* Cmd unit status */ +#define SCB_ST_CUS_IDLE (0 << 8) /* Idle */ +#define SCB_ST_CUS_SUSP (1 << 8) /* Suspended */ +#define SCB_ST_CUS_ACTV (2 << 8) /* Active */ +#define SCB_ST_JUNK1 (0x1 << 7) /* 0 */ +#define SCB_ST_RUS (0x7 << 4) /* Rcv unit status */ +#define SCB_ST_RUS_IDLE (0 << 4) /* Idle */ +#define SCB_ST_RUS_SUSP (1 << 4) /* Suspended */ +#define SCB_ST_RUS_NRES (2 << 4) /* No resources */ +#define SCB_ST_RUS_RDY (4 << 4) /* Ready */ + unsigned short scb_command; /* Next command */ +#define SCB_CMD_ACK_CX (0x1 << 15) /* Ack cmd completion */ +#define SCB_CMD_ACK_FR (0x1 << 14) /* Ack frame received */ +#define SCB_CMD_ACK_CNA (0x1 << 13) /* Ack CU not active */ +#define SCB_CMD_ACK_RNR (0x1 << 12) /* Ack RU not ready */ +#define SCB_CMD_JUNKX (0x1 << 11) /* Unused */ +#define SCB_CMD_CUC (0x7 << 8) /* Command Unit command */ +#define SCB_CMD_CUC_NOP (0 << 8) /* Nop */ +#define SCB_CMD_CUC_GO (1 << 8) /* Start cbl_offset */ +#define SCB_CMD_CUC_RES (2 << 8) /* Resume execution */ +#define SCB_CMD_CUC_SUS (3 << 8) /* Suspend " */ +#define SCB_CMD_CUC_ABT (4 << 8) /* Abort " */ +#define SCB_CMD_RESET (0x1 << 7) /* Reset chip (hardware) */ +#define SCB_CMD_RUC (0x7 << 4) /* Receive Unit command */ +#define SCB_CMD_RUC_NOP (0 << 4) /* Nop */ +#define SCB_CMD_RUC_GO (1 << 4) /* Start rfa_offset */ +#define SCB_CMD_RUC_RES (2 << 4) /* Resume reception */ +#define SCB_CMD_RUC_SUS (3 << 4) /* Suspend " */ +#define SCB_CMD_RUC_ABT (4 << 4) /* Abort " */ + unsigned short scb_cbl_offset; /* Offset of first command unit */ + /* Action Command */ + unsigned short scb_rfa_offset; /* Offset of first Receive */ + /* Frame Descriptor in the */ + /* Receive Frame Area */ + unsigned short scb_crcerrs; /* Properly aligned frames */ + /* received with a CRC error */ + unsigned short scb_alnerrs; /* Misaligned frames received */ + /* with a CRC error */ + unsigned short scb_rscerrs; /* Frames lost due to no space */ + unsigned short scb_ovrnerrs; /* Frames lost due to slow bus */ +}; + +#define scboff(p,f) toff(scb_t, p, f) + +/* + * The eight Action Commands. + */ +typedef enum acmd_e acmd_e; +enum acmd_e +{ + acmd_nop = 0, /* Do nothing */ + acmd_ia_setup = 1, /* Load an (ethernet) address into the */ + /* 82586 */ + acmd_configure = 2, /* Update the 82586 operating parameters */ + acmd_mc_setup = 3, /* Load a list of (ethernet) multicast */ + /* addresses into the 82586 */ + acmd_transmit = 4, /* Transmit a frame */ + acmd_tdr = 5, /* Perform a Time Domain Reflectometer */ + /* test on the serial link */ + acmd_dump = 6, /* Copy 82586 registers to memory */ + acmd_diagnose = 7, /* Run an internal self test */ +}; + +/* + * Generic Action Command header. + */ +typedef struct ach_t ach_t; +struct ach_t +{ + unsigned short ac_status; /* Command status: */ +#define AC_SFLD_C (0x1 << 15) /* Command completed */ +#define AC_SFLD_B (0x1 << 14) /* Busy executing */ +#define AC_SFLD_OK (0x1 << 13) /* Completed error free */ +#define AC_SFLD_A (0x1 << 12) /* Command aborted */ +#define AC_SFLD_FAIL (0x1 << 11) /* Selftest failed */ +#define AC_SFLD_S10 (0x1 << 10) /* No carrier sense */ + /* during transmission */ +#define AC_SFLD_S9 (0x1 << 9) /* Tx unsuccessful: */ + /* (stopped) lost CTS */ +#define AC_SFLD_S8 (0x1 << 8) /* Tx unsuccessful: */ + /* (stopped) slow DMA */ +#define AC_SFLD_S7 (0x1 << 7) /* Tx deferred: */ + /* other link traffic */ +#define AC_SFLD_S6 (0x1 << 6) /* Heart Beat: collision */ + /* detect after last tx */ +#define AC_SFLD_S5 (0x1 << 5) /* Tx stopped: */ + /* excessive collisions */ +#define AC_SFLD_MAXCOL (0xF << 0) /* Collision count */ + unsigned short ac_command; /* Command specifier: */ +#define AC_CFLD_EL (0x1 << 15) /* End of command list */ +#define AC_CFLD_S (0x1 << 14) /* Suspend on completion */ +#define AC_CFLD_I (0x1 << 13) /* Interrupt on completion */ +#define AC_CFLD_CMD (0x7 << 0) /* acmd_e */ + unsigned short ac_link; /* Next Action Command */ +}; + +#define acoff(p,f) toff(ach_t, p, f) + +/* + * The Nop Action Command. + */ +typedef struct ac_nop_t ac_nop_t; +struct ac_nop_t +{ + ach_t nop_h; +}; + +/* + * The IA-Setup Action Command. + */ +typedef struct ac_ias_t ac_ias_t; +struct ac_ias_t +{ + ach_t ias_h; + unsigned char ias_addr[ADDR_LEN]; /* The (ethernet) address */ +}; + +/* + * The Configure Action Command. + */ +typedef struct ac_cfg_t ac_cfg_t; +struct ac_cfg_t +{ + ach_t cfg_h; + unsigned char cfg_byte_cnt; /* Size foll data: 4-12 */ +#define AC_CFG_BYTE_CNT(v) (((v) & 0xF) << 0) + unsigned char cfg_fifolim; /* FIFO threshold */ +#define AC_CFG_FIFOLIM(v) (((v) & 0xF) << 0) + unsigned char cfg_byte8; +#define AC_CFG_SAV_BF(v) (((v) & 0x1) << 7) /* Save rxd bad frames */ +#define AC_CFG_SRDY(v) (((v) & 0x1) << 6) /* SRDY/ARDY pin means */ + /* external sync. */ + unsigned char cfg_byte9; +#define AC_CFG_ELPBCK(v) (((v) & 0x1) << 7) /* External loopback */ +#define AC_CFG_ILPBCK(v) (((v) & 0x1) << 6) /* Internal loopback */ +#define AC_CFG_PRELEN(v) (((v) & 0x3) << 4) /* Preamble length */ +#define AC_CFG_PLEN_2 0 /* 2 bytes */ +#define AC_CFG_PLEN_4 1 /* 4 bytes */ +#define AC_CFG_PLEN_8 2 /* 8 bytes */ +#define AC_CFG_PLEN_16 3 /* 16 bytes */ +#define AC_CFG_ALOC(v) (((v) & 0x1) << 3) /* Addr/len data is */ + /* explicit in buffers */ +#define AC_CFG_ADDRLEN(v) (((v) & 0x7) << 0) /* Bytes per address */ + unsigned char cfg_byte10; +#define AC_CFG_BOFMET(v) (((v) & 0x1) << 7) /* Use alternate expo. */ + /* backoff method */ +#define AC_CFG_ACR(v) (((v) & 0x7) << 4) /* Accelerated cont. res. */ +#define AC_CFG_LINPRIO(v) (((v) & 0x7) << 0) /* Linear priority */ + unsigned char cfg_ifs; /* Interframe spacing */ + unsigned char cfg_slotl; /* Slot time (low byte) */ + unsigned char cfg_byte13; +#define AC_CFG_RETRYNUM(v) (((v) & 0xF) << 4) /* Max. collision retry */ +#define AC_CFG_SLTTMHI(v) (((v) & 0x7) << 0) /* Slot time (high bits) */ + unsigned char cfg_byte14; +#define AC_CFG_FLGPAD(v) (((v) & 0x1) << 7) /* Pad with HDLC flags */ +#define AC_CFG_BTSTF(v) (((v) & 0x1) << 6) /* Do HDLC bitstuffing */ +#define AC_CFG_CRC16(v) (((v) & 0x1) << 5) /* 16 bit CCITT CRC */ +#define AC_CFG_NCRC(v) (((v) & 0x1) << 4) /* Insert no CRC */ +#define AC_CFG_TNCRS(v) (((v) & 0x1) << 3) /* Tx even if no carrier */ +#define AC_CFG_MANCH(v) (((v) & 0x1) << 2) /* Manchester coding */ +#define AC_CFG_BCDIS(v) (((v) & 0x1) << 1) /* Disable broadcast */ +#define AC_CFG_PRM(v) (((v) & 0x1) << 0) /* Promiscuous mode */ + unsigned char cfg_byte15; +#define AC_CFG_ICDS(v) (((v) & 0x1) << 7) /* Internal collision */ + /* detect source */ +#define AC_CFG_CDTF(v) (((v) & 0x7) << 4) /* Collision detect */ + /* filter in bit times */ +#define AC_CFG_ICSS(v) (((v) & 0x1) << 3) /* Internal carrier */ + /* sense source */ +#define AC_CFG_CSTF(v) (((v) & 0x7) << 0) /* Carrier sense */ + /* filter in bit times */ + unsigned short cfg_min_frm_len; +#define AC_CFG_MNFRM(v) (((v) & 0xFF) << 0) /* Min. bytes/frame (<= 255) */ +}; + +/* + * The MC-Setup Action Command. + */ +typedef struct ac_mcs_t ac_mcs_t; +struct ac_mcs_t +{ + ach_t mcs_h; + unsigned short mcs_cnt; /* No. of bytes of MC addresses */ + unsigned short mcs_data[3]; /* The first MC address .. */ +}; + +/* + * The Transmit Action Command. + */ +typedef struct ac_tx_t ac_tx_t; +struct ac_tx_t +{ + ach_t tx_h; + unsigned short tx_tbd_offset; /* Address of list of buffers. */ +#if 0 +Linux packets are passed down with the destination MAC address +and length/type field already prepended to the data, +so we do not need to insert it. Consistent with this +we must also set the AC_CFG_ALOC(..) flag during the +ac_cfg_t action command. + unsigned char tx_addr[ADDR_LEN]; /* The frame dest. address */ + unsigned short tx_length; /* The frame length */ +#endif /* 0 */ +}; + +/* + * The Time Domain Reflectometer Action Command. + */ +typedef struct ac_tdr_t ac_tdr_t; +struct ac_tdr_t +{ + ach_t tdr_h; + unsigned short tdr_result; /* Result. */ +#define AC_TDR_LNK_OK (0x1 << 15) /* No link problem */ +#define AC_TDR_XCVR_PRB (0x1 << 14) /* Txcvr cable problem */ +#define AC_TDR_ET_OPN (0x1 << 13) /* Open on the link */ +#define AC_TDR_ET_SRT (0x1 << 12) /* Short on the link */ +#define AC_TDR_TIME (0x7FF << 0) /* Distance to problem */ + /* site in transmit */ + /* clock cycles */ +}; + +/* + * The Dump Action Command. + */ +typedef struct ac_dmp_t ac_dmp_t; +struct ac_dmp_t +{ + ach_t dmp_h; + unsigned short dmp_offset; /* Result. */ +}; + +/* + * Size of the result of the dump command. + */ +#define DUMPBYTES 170 + +/* + * The Diagnose Action Command. + */ +typedef struct ac_dgn_t ac_dgn_t; +struct ac_dgn_t +{ + ach_t dgn_h; +}; + +/* + * Transmit Buffer Descriptor (TBD). + */ +typedef struct tbd_t tbd_t; +struct tbd_t +{ + unsigned short tbd_status; /* Written by the CPU */ +#define TBD_STATUS_EOF (0x1 << 15) /* This TBD is the */ + /* last for this frame */ +#define TBD_STATUS_ACNT (0x3FFF << 0) /* Actual count of data */ + /* bytes in this buffer */ + unsigned short tbd_next_bd_offset; /* Next in list */ + unsigned short tbd_bufl; /* Buffer address (low) */ + unsigned short tbd_bufh; /* " " (high) */ +}; + +/* + * Receive Buffer Descriptor (RBD). + */ +typedef struct rbd_t rbd_t; +struct rbd_t +{ + unsigned short rbd_status; /* Written by the 82586 */ +#define RBD_STATUS_EOF (0x1 << 15) /* This RBD is the */ + /* last for this frame */ +#define RBD_STATUS_F (0x1 << 14) /* ACNT field is valid */ +#define RBD_STATUS_ACNT (0x3FFF << 0) /* Actual no. of data */ + /* bytes in this buffer */ + unsigned short rbd_next_rbd_offset; /* Next rbd in list */ + unsigned short rbd_bufl; /* Data pointer (low) */ + unsigned short rbd_bufh; /* " " (high) */ + unsigned short rbd_el_size; /* EL+Data buf. size */ +#define RBD_EL (0x1 << 15) /* This BD is the */ + /* last in the list */ +#define RBD_SIZE (0x3FFF << 0) /* No. of bytes the */ + /* buffer can hold */ +}; + +#define rbdoff(p,f) toff(rbd_t, p, f) + +/* + * Frame Descriptor (FD). + */ +typedef struct fd_t fd_t; +struct fd_t +{ + unsigned short fd_status; /* Written by the 82586 */ +#define FD_STATUS_C (0x1 << 15) /* Completed storing frame */ +#define FD_STATUS_B (0x1 << 14) /* FD was consumed by RU */ +#define FD_STATUS_OK (0x1 << 13) /* Frame rxd successfully */ +#define FD_STATUS_S11 (0x1 << 11) /* CRC error */ +#define FD_STATUS_S10 (0x1 << 10) /* Alignment error */ +#define FD_STATUS_S9 (0x1 << 9) /* Ran out of resources */ +#define FD_STATUS_S8 (0x1 << 8) /* Rx DMA overrun */ +#define FD_STATUS_S7 (0x1 << 7) /* Frame too short */ +#define FD_STATUS_S6 (0x1 << 6) /* No EOF flag */ + unsigned short fd_command; /* Command */ +#define FD_COMMAND_EL (0x1 << 15) /* Last FD in list */ +#define FD_COMMAND_S (0x1 << 14) /* Suspend RU after rx */ + unsigned short fd_link_offset; /* Next FD */ + unsigned short fd_rbd_offset; /* First RBD (data) */ + /* Prepared by CPU, */ + /* updated by 82586 */ +#if 0 +I think the rest is unused since we +have set AC_CFG_ALOC(..). However, just +in case, we leave the space. +#endif /* 0 */ + unsigned char fd_dest[ADDR_LEN]; /* Destination address */ + /* Written by 82586 */ + unsigned char fd_src[ADDR_LEN]; /* Source address */ + /* Written by 82586 */ + unsigned short fd_length; /* Frame length or type */ + /* Written by 82586 */ +}; + +#define fdoff(p,f) toff(fd_t, p, f) + +/* + * This software may only be used and distributed + * according to the terms of the GNU Public License. + * + * For more details, see wavelan.c. + */ +#endif /* defined(CONFIG_WAVELAN) */ diff -u --recursive --new-file v1.1.87/linux/drivers/net/ppp.c linux/drivers/net/ppp.c --- v1.1.87/linux/drivers/net/ppp.c Mon Jan 30 06:41:57 1995 +++ linux/drivers/net/ppp.c Tue Jan 31 09:39:02 1995 @@ -374,7 +374,7 @@ /* RFC 1331, section 7.2 says the minimum value is 1500 bytes */ if (mru < PPP_MRU) - mru = new_mru = PPP_MRU; + mru = PPP_MRU; mtu = (mtu * 2) + 20; mru = (mru * 2) + 20; @@ -1409,8 +1409,8 @@ case PPPIOCSMRU: error = verify_area (VERIFY_READ, (void *) l, sizeof (temp_i)); if (error == 0) { - PRINTKN (3,(KERN_INFO "ppp_ioctl: set mru to %x\n", temp_i)); temp_i = (int) get_fs_long (l); + PRINTKN (3,(KERN_INFO "ppp_ioctl: set mru to %d\n", temp_i)); if (ppp->mru != temp_i) ppp_changedmtu (ppp, ppp->dev->mtu, temp_i); } diff -u --recursive --new-file v1.1.87/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c --- v1.1.87/linux/drivers/net/wavelan.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/net/wavelan.c Tue Jan 31 14:36:24 1995 @@ -0,0 +1,2338 @@ +/* + * AT&T GIS (nee NCR) WaveLAN card: + * An Ethernet-like radio transceiver + * controlled by an Intel 82586 coprocessor. + */ + +#include + +#if defined(CONFIG_WAVELAN) +#if defined(MODULE) +#include +#include +#endif /* defined(MODULE) */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define STRUCT_CHECK 1 +#include "i82586.h" +#include "wavelan.h" + +#ifndef WAVELAN_DEBUG +#define WAVELAN_DEBUG 0 +#endif /* WAVELAN_DEBUG */ + +#define nels(a) (sizeof(a) / sizeof(a[0])) + +#define WATCHDOG_JIFFIES 512 /* TODO: express in HZ. */ + +typedef struct device device; +typedef struct enet_statistics en_stats; +typedef struct net_local net_local; +typedef struct timer_list timer_list; + +struct net_local +{ + en_stats stats; + unsigned int tx_n_in_use; + unsigned char nwid[2]; + unsigned short hacr; + unsigned short rx_head; + unsigned short rx_last; + unsigned short tx_first_free; + unsigned short tx_first_in_use; + unsigned int nresets; + unsigned int correct_nwid; + unsigned int wrong_nwid; + unsigned int promiscuous; + timer_list watchdog; + device *dev; + net_local *prev; + net_local *next; +}; + +extern int wavelan_probe(device *); /* See Space.c */ + +static char *version = "wavelan.c:v5 31/1/95\n"; + +/* + * Entry point forward declarations. + */ +static int wavelan_probe1(device *, unsigned short); +static int wavelan_open(device *); +static int wavelan_send_packet(struct sk_buff *, device *); +static void wavelan_interrupt(int, struct pt_regs *); +static int wavelan_close(device *); +static en_stats *wavelan_get_stats(device *); +static void wavelan_set_multicast_list(device *, int, void *); + +/* + * Other forward declarations. + */ +static void wavelan_cu_show_one(device *, net_local *, int, unsigned short); +static void wavelan_cu_start(device *); +static void wavelan_ru_start(device *); +static void wavelan_watchdog(unsigned long); +#if 0 +static void wavelan_psa_show(psa_t *); +static void wavelan_mmc_show(unsigned short); +#endif /* 0 */ +static void wavelan_scb_show(unsigned short); +static void wavelan_ru_show(device *); +static void wavelan_cu_show(device *); +static void wavelan_dev_show(device *); +static void wavelan_local_show(device *); + +static unsigned int wavelan_debug = WAVELAN_DEBUG; +static net_local *first_wavelan = (net_local *)0; + +static +void +busy_loop(int i) +{ + while (i-- > 0) + ; +} + +static +unsigned long +wavelan_splhi(void) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + return flags; +} + +static +void +wavelan_splx(unsigned long flags) +{ + restore_flags(flags); +} + +static +unsigned short +hasr_read(unsigned short ioaddr) +{ + return inw(HASR(ioaddr)); +} + +static +void +hacr_write(unsigned short ioaddr, int hacr) +{ + outw(hacr, HACR(ioaddr)); +} + +static +void +hacr_write_slow(unsigned short ioaddr, int hacr) +{ + hacr_write(ioaddr, hacr); + /* delay might only be needed sometimes */ + busy_loop(1000); +} + +/* + * Set the channel attention bit. + */ +static +void +set_chan_attn(unsigned short ioaddr, unsigned short current_hacr) +{ + hacr_write(ioaddr, current_hacr | HACR_CA); +} + +/* + * Reset, and then set host adaptor into default mode. + */ +static +void +wavelan_reset(unsigned short ioaddr) +{ + hacr_write_slow(ioaddr, HACR_RESET); + hacr_write(ioaddr, HACR_DEFAULT); +} + +static +void +wavelan_16_off(unsigned short ioaddr, unsigned short hacr) +{ + hacr &= ~HACR_16BITS; + + hacr_write(ioaddr, hacr); +} + +static +void +wavelan_16_on(unsigned short ioaddr, unsigned short hacr) +{ + hacr |= HACR_16BITS; + + hacr_write(ioaddr, hacr); +} + +static +void +wavelan_ints_off(device *dev) +{ + unsigned short ioaddr; + net_local *lp; + unsigned long x; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + x = wavelan_splhi(); + + lp->hacr &= ~HACR_INTRON; + hacr_write(ioaddr, lp->hacr); + + wavelan_splx(x); +} + +static +void +wavelan_ints_on(device *dev) +{ + unsigned short ioaddr; + net_local *lp; + unsigned long x; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + x = wavelan_splhi(); + + lp->hacr |= HACR_INTRON; + hacr_write(ioaddr, lp->hacr); + + wavelan_splx(x); +} + +/* + * Read bytes from the PSA. + */ +static +void +psa_read(unsigned short ioaddr, unsigned short hacr, int o, unsigned char *b, int n) +{ + wavelan_16_off(ioaddr, hacr); + + while (n-- > 0) + { + outw(o, PIOR2(ioaddr)); + o++; + *b++ = inb(PIOP2(ioaddr)); + } + + wavelan_16_on(ioaddr, hacr); +} + +/* + * Read bytes from the on-board RAM. + */ +static +void +obram_read(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) +{ + n = (n + 1) / (sizeof(unsigned short) / sizeof(unsigned char)); + + outw(o, PIOR1(ioaddr)); + + insw(PIOP1(ioaddr), (unsigned short *)b, n); +} + +/* + * Write bytes to the on-board RAM. + */ +static +void +obram_write(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) +{ + n = (n + 1) / (sizeof(unsigned short) / sizeof(unsigned char)); + + outw(o, PIOR1(ioaddr)); + + outsw(PIOP1(ioaddr), (unsigned short *)b, n); +} + +/* + * Read bytes from the MMC. + */ +static +void +mmc_read(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) +{ + while (n-- > 0) + { + while (inw(HASR(ioaddr)) & HASR_MMC_BUSY) + ; + + outw(o << 1, MMCR(ioaddr)); + o++; + + while (inw(HASR(ioaddr)) & HASR_MMC_BUSY) + ; + + *b++ = (unsigned char)(inw(MMCR(ioaddr)) >> 8); + } +} + +/* + * Write bytes to the MMC. + */ +static +void +mmc_write(unsigned short ioaddr, unsigned short o, unsigned char *b, int n) +{ + while (n-- > 0) + { + while (inw(HASR(ioaddr)) & HASR_MMC_BUSY) + ; + + outw((unsigned short)(((unsigned short)*b << 8) | (o << 1) | 1), MMCR(ioaddr)); + b++; + o++; + } +} + +/* + * Map values from the irq parameter register to irq numbers. + */ +static +int +wavelan_map_irq(unsigned short ioaddr, unsigned char irqval) +{ + int irq; + static int irqvals[] = + { + 0, 0, 0, 0x01, + 0x02, 0x04, 0, 0x08, + 0, 0, 0x10, 0x20, + 0x40, 0, 0, 0x80, + }; + + for (irq = 0; irq < nels(irqvals); irq++) + { + if (irqvals[irq] == (int)irqval) + return irq; + } + + return -1; +} + +/* + * Initialize the Modem Management Controller. + */ +static +void +wavelan_mmc_init(device *dev, psa_t *psa) +{ + unsigned short ioaddr; + net_local *lp; + mmw_t m; + int configured; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + memset(&m, 0x00, sizeof(m)); + + /* + * configured = psa->psa_conf_status & 1; + * + * For now we use the persistent PSA + * information as little as possible, thereby + * allowing us to return to the same known state + * during a hardware reset. + */ + configured = 0; + + /* + * Set default modem control parameters. + * See NCR document 407-0024326 Rev. A. + */ + m.mmw_jabber_enable = 0x01; + m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN; + m.mmw_ifs = 0x20; + m.mmw_mod_delay = 0x04; + m.mmw_jam_time = 0x38; + + m.mmw_encr_enable = 0; + m.mmw_des_io_invert = 0; + m.mmw_freeze = 0; + m.mmw_decay_prm = 0; + m.mmw_decay_updat_prm = 0; + + if (configured) + { + /* + * Use configuration defaults from parameter storage area. + */ + if (psa->psa_undefined & 1) + m.mmw_loopt_sel = 0x00; + else + m.mmw_loopt_sel = MMW_LOOPT_SEL_UNDEFINED; + + m.mmw_thr_pre_set = psa->psa_thr_pre_set & 0x3F; + m.mmw_quality_thr = psa->psa_quality_thr & 0x0F; + } + else + { + if (lp->promiscuous) + m.mmw_loopt_sel = MMW_LOOPT_SEL_UNDEFINED; + else + m.mmw_loopt_sel = 0x00; + + /* + * 0x04 for AT, + * 0x01 for MCA. + */ + if (psa->psa_comp_number & 1) + m.mmw_thr_pre_set = 0x01; + else + m.mmw_thr_pre_set = 0x04; + + m.mmw_quality_thr = 0x03; + } + + m.mmw_netw_id_l = lp->nwid[1]; + m.mmw_netw_id_h = lp->nwid[0]; + + mmc_write(ioaddr, 0, (unsigned char *)&m, sizeof(m)); +} + +static +void +wavelan_ack(device *dev) +{ + unsigned short ioaddr; + net_local *lp; + unsigned short scb_cs; + int i; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs)); + scb_cs &= SCB_ST_INT; + + if (scb_cs == 0) + return; + + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); + + set_chan_attn(ioaddr, lp->hacr); + + for (i = 1000000; i > 0; i--) + { + obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); + if (scb_cs == 0) + break; + } + + if (i <= 0) + printk("%s: wavelan_ack(): board not accepting command.\n", dev->name); +} + +/* + * Set channel attention bit and busy wait until command has + * completed, then acknowledge the command completion. + */ +static +int +wavelan_synchronous_cmd(device *dev, char *str) +{ + unsigned short ioaddr; + net_local *lp; + unsigned short scb_cmd; + ach_t cb; + int i; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO; + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cmd, sizeof(scb_cmd)); + + set_chan_attn(ioaddr, lp->hacr); + + for (i = 64000; i > 0; i--) + { + obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); + if (cb.ac_status & AC_SFLD_C) + break; + } + + if (i <= 0 || !(cb.ac_status & AC_SFLD_OK)) + { + printk("%s: %s failed; status = 0x%x\n", dev->name, str, cb.ac_status); + wavelan_scb_show(ioaddr); + return -1; + } + + wavelan_ack(dev); + + return 0; +} + +static +int +wavelan_hardware_reset(device *dev) +{ + unsigned short ioaddr; + psa_t psa; + net_local *lp; + scp_t scp; + iscp_t iscp; + scb_t scb; + ach_t cb; + int i; + ac_cfg_t cfg; + ac_ias_t ias; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + lp->nresets++; + + wavelan_reset(ioaddr); + lp->hacr = HACR_DEFAULT; + + /* + * Clear the onboard RAM. + */ + { + unsigned char zeroes[512]; + + memset(&zeroes[0], 0x00, sizeof(zeroes)); + + for (i = 0; i < I82586_MEMZ; i += sizeof(zeroes)) + obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes)); + } + + psa_read(ioaddr, lp->hacr, 0, (unsigned char *)&psa, sizeof(psa)); + + wavelan_mmc_init(dev, &psa); + + /* + * Construct the command unit structures: + * scp, iscp, scb, cb. + */ + memset(&scp, 0x00, sizeof(scp)); + scp.scp_sysbus = SCP_SY_16BBUS; + scp.scp_iscpl = OFFSET_ISCP; + obram_write(ioaddr, OFFSET_SCP, (unsigned char *)&scp, sizeof(scp)); + + memset(&iscp, 0x00, sizeof(iscp)); + iscp.iscp_busy = 1; + iscp.iscp_offset = OFFSET_SCB; + obram_write(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp)); + + memset(&scb, 0x00, sizeof(scb)); + scb.scb_command = SCB_CMD_RESET; + scb.scb_cbl_offset = OFFSET_CU; + scb.scb_rfa_offset = OFFSET_RU; + obram_write(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); + + set_chan_attn(ioaddr, lp->hacr); + + for (i = 1000000; i > 0; i--) + { + obram_read(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp)); + + if (iscp.iscp_busy == (unsigned short)0) + break; + } + + if (i <= 0) + printk("%s: wavelan_hardware_reset(): iscp_busy timeout.\n", dev->name); + + for (i = 15000; i > 0; i--) + { + obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); + + if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA)) + break; + } + + if (i <= 0) + printk("%s: wavelan_hardware_reset(): status: expected 0x%02x, got 0x%02x.\n", dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status); + + wavelan_ack(dev); + + memset(&cb, 0x00, sizeof(cb)); + cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose); + cb.ac_link = OFFSET_CU; + obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); + + if (wavelan_synchronous_cmd(dev, "diag()") == -1) + return -1; + + obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb)); + if (cb.ac_status & AC_SFLD_FAIL) + { + printk("%s: wavelan_hardware_reset(): i82586 Self Test failed.\n", dev->name); + return -1; + } + + memset(&cfg, 0x00, sizeof(cfg)); + +#if 0 + /* + * The default board configuration. + */ + cfg.fifolim_bytecnt = 0x080c; + cfg.addrlen_mode = 0x2600; + cfg.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */ + cfg.slot_time = 0xf00c; /* slottime=12 */ + cfg.hardware = 0x0008; /* tx even w/o CD */ + cfg.min_frame_len = 0x0040; +#endif /* 0 */ + + /* + * For Linux we invert AC_CFG_ALOC(..) so as to conform + * to the way that net packets reach us from above. + * (See also ac_tx_t.) + */ + cfg.cfg_byte_cnt = AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t)); + cfg.cfg_fifolim = AC_CFG_FIFOLIM(8); + cfg.cfg_byte8 = AC_CFG_SAV_BF(0) | + AC_CFG_SRDY(0); + cfg.cfg_byte9 = AC_CFG_ELPBCK(0) | + AC_CFG_ILPBCK(0) | + AC_CFG_PRELEN(AC_CFG_PLEN_2) | + AC_CFG_ALOC(1) | + AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE); + cfg.cfg_byte10 = AC_CFG_BOFMET(0) | + AC_CFG_ACR(0) | + AC_CFG_LINPRIO(0); + cfg.cfg_ifs = 32; + cfg.cfg_slotl = 0; + cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) | + AC_CFG_SLTTMHI(2); + cfg.cfg_byte14 = AC_CFG_FLGPAD(0) | + AC_CFG_BTSTF(0) | + AC_CFG_CRC16(0) | + AC_CFG_NCRC(0) | + AC_CFG_TNCRS(1) | + AC_CFG_MANCH(0) | + AC_CFG_BCDIS(0) | + AC_CFG_PRM(lp->promiscuous); + cfg.cfg_byte15 = AC_CFG_ICDS(0) | + AC_CFG_CDTF(0) | + AC_CFG_ICSS(0) | + AC_CFG_CSTF(0); +/* + cfg.cfg_min_frm_len = AC_CFG_MNFRM(64); +*/ + cfg.cfg_min_frm_len = AC_CFG_MNFRM(8); + + cfg.cfg_h.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_configure); + cfg.cfg_h.ac_link = OFFSET_CU; + obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cfg, sizeof(cfg)); + + if (wavelan_synchronous_cmd(dev, "reset()-configure") == -1) + return -1; + + memset(&ias, 0x00, sizeof(ias)); + ias.ias_h.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_ia_setup); + ias.ias_h.ac_link = OFFSET_CU; + memcpy(&ias.ias_addr[0], (unsigned char *)&dev->dev_addr[0], sizeof(ias.ias_addr)); + obram_write(ioaddr, OFFSET_CU, (unsigned char *)&ias, sizeof(ias)); + + if (wavelan_synchronous_cmd(dev, "reset()-address") == -1) + return -1; + + wavelan_ints_on(dev); + + if (wavelan_debug > 4) + { + wavelan_scb_show(ioaddr); + printk("%s: Initialized WaveLAN.\n", dev->name); + } + + wavelan_ru_start(dev); + wavelan_cu_start(dev); + + return 0; +} + +#if STRUCT_CHECK == 1 + +static +char * +wavelan_struct_check(void) +{ +#define SC(t,s,n) if (sizeof(t) != s) return n + SC(psa_t, PSA_SIZE, "psa_t"); + SC(mmw_t, MMW_SIZE, "mmw_t"); + SC(mmr_t, MMR_SIZE, "mmr_t"); + SC(ha_t, HA_SIZE, "ha_t"); +#undef SC + + return (char *)0; +} + +#endif /* STRUCT_CHECK == 1 */ + +/* + * Check for a network adaptor of this type. + * Return '0' iff one exists. + * (There seem to be different interpretations of + * the initial value of dev->base_addr. + * We follow the example in drivers/net/ne.c.) + */ +int +wavelan_probe(device *dev) +{ + int i; + short base_addr; + static unsigned short iobase[] = + { +#if 0 + Leave out 0x3C0 for now -- seems to clash + with some video controllers. + Leave out the others too -- we will always + use 0x390 and leave 0x300 for the Ethernet device. + 0x300, 0x390, 0x3E0, 0x3C0, +#endif /* 0 */ + 0x390, + }; + +#if STRUCT_CHECK == 1 + if (wavelan_struct_check() != (char *)0) + { + printk("%s: structure/compiler botch: \"%s\"\n", dev->name, wavelan_struct_check()); + return ENODEV; + } +#endif /* STRUCT_CHECK == 1 */ + + base_addr = dev->base_addr; + + if (base_addr < 0) + /* + * Don't probe at all. + */ + return ENXIO; + + if (base_addr > 0x100) + /* + * Check a single specified location. + */ + return wavelan_probe1(dev, base_addr); + + for (i = 0; i < nels(iobase); i++) + { + if (check_region(iobase[i], sizeof(ha_t))) + continue; + + if (wavelan_probe1(dev, iobase[i]) == 0) + return 0; + } + + return ENODEV; +} + +static +int +wavelan_probe1(device *dev, unsigned short ioaddr) +{ + psa_t psa; + int irq; + int i; + net_local *lp; + + wavelan_reset(ioaddr); + + psa_read(ioaddr, HACR_DEFAULT, 0, (unsigned char *)&psa, sizeof(psa)); + + /* + * Check the first three octets of the MAC address + * for the manufacturer's code. + */ + if + ( + psa.psa_univ_mac_addr[0] != SA_ADDR0 + || + psa.psa_univ_mac_addr[1] != SA_ADDR1 + || + psa.psa_univ_mac_addr[2] != SA_ADDR2 + ) + return ENODEV; + + printk("%s: WaveLAN at %#x,", dev->name, ioaddr); + + if ((irq = wavelan_map_irq(ioaddr, psa.psa_int_req_no)) == -1) + { + printk(" could not wavelan_map_irq(0x%x, %d).\n", ioaddr, psa.psa_int_req_no); + return EAGAIN; + } + + dev->irq = irq; + + request_region(ioaddr, sizeof(ha_t), "wavelan"); + dev->base_addr = ioaddr; + + /* + * Apparently the third numeric argument to LILO's + * `ether=' control line arrives here as `dev->mem_start'. + * If it is non-zero we use it instead of the PSA NWID. + */ + if (dev->mem_start != 0) + { + psa.psa_nwid[0] = (dev->mem_start >> 8) & 0xFF; + psa.psa_nwid[1] = (dev->mem_start >> 0) & 0xFF; + } + + dev->mem_start = 0x0000; + dev->mem_end = 0x0000; + dev->if_port = 0; + + memcpy(&dev->dev_addr[0], &psa.psa_univ_mac_addr[0], WAVELAN_ADDR_SIZE); + + for (i = 0; i < WAVELAN_ADDR_SIZE; i++) + printk("%s%02x", (i == 0) ? " " : ":", dev->dev_addr[i]); + + printk(", IRQ %d", dev->irq); + printk(", nwid 0x%02x%02x", psa.psa_nwid[0], psa.psa_nwid[1]); + + printk(", PC"); + switch (psa.psa_comp_number) + { + case PSA_COMP_PC_AT_915: + case PSA_COMP_PC_AT_2400: + printk("-AT"); + break; + + case PSA_COMP_PC_MC_915: + case PSA_COMP_PC_MC_2400: + printk("-MC"); + break; + + case PSA_COMP_PCMCIA_915: + printk("MCIA"); + break; + + default: + printk("???"); + break; + } + + printk(", "); + switch (psa.psa_subband) + { + case PSA_SUBBAND_915: + printk("915"); + break; + + case PSA_SUBBAND_2425: + printk("2425"); + break; + + case PSA_SUBBAND_2460: + printk("2460"); + break; + + case PSA_SUBBAND_2484: + printk("2484"); + break; + + case PSA_SUBBAND_2430_5: + printk("2430.5"); + break; + + default: + printk("???"); + break; + } + printk(" MHz"); + + printk("\n"); + + if (wavelan_debug) + printk(version); + + dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL); + memset(dev->priv, 0x00, sizeof(net_local)); + lp = (net_local *)dev->priv; + + if (first_wavelan == (net_local *)0) + { + first_wavelan = lp; + lp->prev = lp; + lp->next = lp; + } + else + { + lp->prev = first_wavelan->prev; + lp->next = first_wavelan; + first_wavelan->prev->next = lp; + first_wavelan->prev = lp; + } + lp->dev = dev; + + lp->hacr = HACR_DEFAULT; + + lp->nwid[0] = psa.psa_nwid[0]; + lp->nwid[1] = psa.psa_nwid[1]; + + lp->watchdog.function = wavelan_watchdog; + lp->watchdog.data = (unsigned long)dev; + + dev->open = wavelan_open; + dev->stop = wavelan_close; + dev->hard_start_xmit = wavelan_send_packet; + dev->get_stats = wavelan_get_stats; + dev->set_multicast_list = &wavelan_set_multicast_list; + + /* + * Fill in the fields of the device structure + * with ethernet-generic values. + */ + ether_setup(dev); + + dev->mtu = WAVELAN_MTU; + + return 0; +} + +/* + * Construct the fd and rbd structures. + * Start the receive unit. + */ +static +void +wavelan_ru_start(device *dev) +{ + unsigned short ioaddr; + net_local *lp; + unsigned short scb_cs; + fd_t fd; + rbd_t rbd; + unsigned short rx; + unsigned short rx_next; + int i; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs)); + if ((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY) + return; + + lp->rx_head = OFFSET_RU; + + for (i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next) + { + rx_next = (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ; + + fd.fd_status = 0; + fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0; + fd.fd_link_offset = rx_next; + fd.fd_rbd_offset = rx + sizeof(fd); + obram_write(ioaddr, rx, (unsigned char *)&fd, sizeof(fd)); + + rbd.rbd_status = 0; + rbd.rbd_next_rbd_offset = I82586NULL; + rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd); + rbd.rbd_bufh = 0; + rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ); + obram_write(ioaddr, rx + sizeof(fd), (unsigned char *)&rbd, sizeof(rbd)); + + lp->rx_last = rx; + } + + obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset), (unsigned char *)&lp->rx_head, sizeof(lp->rx_head)); + + scb_cs = SCB_CMD_RUC_GO; + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); + + set_chan_attn(ioaddr, lp->hacr); + + for (i = 1000000; i > 0; i--) + { + obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); + if (scb_cs == 0) + break; + } + + if (i <= 0) + printk("%s: wavelan_ru_start(): board not accepting command.\n", dev->name); +} + +/* + * Initialise the transmit blocks. + * Start the command unit executing the NOP + * self-loop of the first transmit block. + */ +static +void +wavelan_cu_start(device *dev) +{ + unsigned short ioaddr; + net_local *lp; + int i; + unsigned short txblock; + unsigned short first_nop; + unsigned short scb_cs; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + lp->tx_first_free = OFFSET_CU; + lp->tx_first_in_use = I82586NULL; + + for + ( + i = 0, txblock = OFFSET_CU; + i < NTXBLOCKS; + i++, txblock += TXBLOCKZ + ) + { + ac_tx_t tx; + ac_nop_t nop; + tbd_t tbd; + unsigned short tx_addr; + unsigned short nop_addr; + unsigned short tbd_addr; + unsigned short buf_addr; + + tx_addr = txblock; + nop_addr = tx_addr + sizeof(tx); + tbd_addr = nop_addr + sizeof(nop); + buf_addr = tbd_addr + sizeof(tbd); + + tx.tx_h.ac_status = 0; + tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I; + tx.tx_h.ac_link = nop_addr; + tx.tx_tbd_offset = tbd_addr; + obram_write(ioaddr, tx_addr, (unsigned char *)&tx, sizeof(tx)); + + nop.nop_h.ac_status = 0; + nop.nop_h.ac_command = acmd_nop; + nop.nop_h.ac_link = nop_addr; + obram_write(ioaddr, nop_addr, (unsigned char *)&nop, sizeof(nop)); + + tbd.tbd_status = TBD_STATUS_EOF; + tbd.tbd_next_bd_offset = I82586NULL; + tbd.tbd_bufl = buf_addr; + tbd.tbd_bufh = 0; + obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd)); + } + + first_nop = OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t); + obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset), (unsigned char *)&first_nop, sizeof(first_nop)); + + scb_cs = SCB_CMD_CUC_GO; + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); + + set_chan_attn(ioaddr, lp->hacr); + + for (i = 1000000; i > 0; i--) + { + obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs)); + if (scb_cs == 0) + break; + } + + if (i <= 0) + printk("%s: wavelan_cu_start(): board not accepting command.\n", dev->name); + + lp->tx_n_in_use = 0; + dev->tbusy = 0; +} + +static +int +wavelan_open(device *dev) +{ + unsigned short ioaddr; + net_local *lp; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + if (dev->irq == 0) + return -ENXIO; + + if + ( + irq2dev_map[dev->irq] != (device *)0 + /* This is always true, but avoid the false IRQ. */ + || + (irq2dev_map[dev->irq] = dev) == (device *)0 + || + request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN") != 0 + ) + { + irq2dev_map[dev->irq] = (device *)0; + return -EAGAIN; + } + + if (wavelan_hardware_reset(dev) == -1) + { + free_irq(dev->irq); + irq2dev_map[dev->irq] = (device *)0; + return -EAGAIN; + } + + dev->interrupt = 0; + dev->start = 1; + +#if defined(MODULE) + MOD_INC_USE_COUNT; +#endif /* defined(MODULE) */ + + return 0; +} + +static +void +hardware_send_packet(device *dev, void *buf, short length) +{ + unsigned short ioaddr; + net_local *lp; + unsigned short txblock; + unsigned short txpred; + unsigned short tx_addr; + unsigned short nop_addr; + unsigned short tbd_addr; + unsigned short buf_addr; + ac_tx_t tx; + ac_nop_t nop; + tbd_t tbd; + unsigned long x; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + x = wavelan_splhi(); + + txblock = lp->tx_first_free; + txpred = txblock - TXBLOCKZ; + if (txpred < OFFSET_CU) + txpred += NTXBLOCKS * TXBLOCKZ; + lp->tx_first_free += TXBLOCKZ; + if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) + lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ; + +/* +if (lp->tx_n_in_use > 0) + printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); +*/ + + lp->tx_n_in_use++; + + tx_addr = txblock; + nop_addr = tx_addr + sizeof(tx); + tbd_addr = nop_addr + sizeof(nop); + buf_addr = tbd_addr + sizeof(tbd); + + /* + * Transmit command. + */ + tx.tx_h.ac_status = 0; + obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), (unsigned char *)&tx.tx_h.ac_status, sizeof(tx.tx_h.ac_status)); + + /* + * NOP command. + */ + nop.nop_h.ac_status = 0; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), (unsigned char *)&nop.nop_h.ac_status, sizeof(nop.nop_h.ac_status)); + nop.nop_h.ac_link = nop_addr; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), (unsigned char *)&nop.nop_h.ac_link, sizeof(nop.nop_h.ac_link)); + + /* + * Transmit buffer descriptor. + */ + tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & length); + tbd.tbd_next_bd_offset = I82586NULL; + tbd.tbd_bufl = buf_addr; + tbd.tbd_bufh = 0; + obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd)); + + /* + * Data. + */ + obram_write(ioaddr, buf_addr, buf, length); + + /* + * Overwrite the predecessor NOP link + * so that it points to this txblock. + */ + nop_addr = txpred + sizeof(tx); + nop.nop_h.ac_status = 0; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), (unsigned char *)&nop.nop_h.ac_status, sizeof(nop.nop_h.ac_status)); + nop.nop_h.ac_link = txblock; + obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), (unsigned char *)&nop.nop_h.ac_link, sizeof(nop.nop_h.ac_link)); + + if (lp->tx_first_in_use == I82586NULL) + lp->tx_first_in_use = txblock; + + if (lp->tx_n_in_use < NTXBLOCKS - 1) + dev->tbusy = 0; + + dev->trans_start = jiffies; + + if (lp->watchdog.next == (timer_list *)0) + wavelan_watchdog((unsigned long)dev); + + wavelan_splx(x); + + if (wavelan_debug > 4) + { + unsigned char *a; + + a = (unsigned char *)buf; + + printk + ( + "%s: tx: dest %02x:%02x:%02x:%02x:%02x:%02x, length %d, tbd.tbd_bufl 0x%x.\n", + dev->name, + a[0], a[1], a[2], a[3], a[4], a[5], + length, + buf_addr + ); + } +} + +static +int +wavelan_send_packet(struct sk_buff *skb, device *dev) +{ + unsigned short ioaddr; + + ioaddr = dev->base_addr; + + if (dev->tbusy) + { + /* + * If we get here, some higher level + * has decided we are broken. + */ + int tickssofar; + + tickssofar = jiffies - dev->trans_start; + + /* + * But for the moment, we will rely on wavelan_watchdog() + * instead as it allows finer control over exactly when we + * make the determination of failure. + * + if (tickssofar < 5) + */ + return 1; + + wavelan_scb_show(ioaddr); + wavelan_ru_show(dev); + wavelan_cu_show(dev); + wavelan_dev_show(dev); + wavelan_local_show(dev); + + printk("%s: transmit timed out -- resetting board.\n", dev->name); + + (void)wavelan_hardware_reset(dev); + } + + /* + * 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 == (struct sk_buff *)0) + { + dev_tint(dev); + return 0; + } + + /* + * Block a timer-based transmit from overlapping. + */ + if (set_bit(0, (void *)&dev->tbusy) == 0) + { + short length; + unsigned char *buf; + + length = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; + buf = skb->data; + + hardware_send_packet(dev, buf, length); + } + else + printk("%s: Transmitter access conflict.\n", dev->name); + + dev_kfree_skb(skb, FREE_WRITE); + + return 0; +} + +#if 0 +static +int +addrcmp(unsigned char *a0, unsigned char *a1) +{ + int i; + + for (i = 0; i < WAVELAN_ADDR_SIZE; i++) + { + if (a0[i] != a1[i]) + return a0[i] - a1[i]; + } + + return 0; +} +#endif /* 0 */ + +/* + * Transfer as many packets as we can + * from the device RAM. + * Called by the interrupt handler. + */ +static +void +wavelan_receive(device *dev) +{ + unsigned short ioaddr; + net_local *lp; + int nreaped; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + nreaped = 0; + + for (;;) + { + fd_t fd; + rbd_t rbd; + ushort pkt_len; + int sksize; + struct sk_buff *skb; + + obram_read(ioaddr, lp->rx_head, (unsigned char *)&fd, sizeof(fd)); + + if ((fd.fd_status & FD_STATUS_C) != FD_STATUS_C) + break; + + nreaped++; + + if + ( + (fd.fd_status & (FD_STATUS_B | FD_STATUS_OK)) + != + (FD_STATUS_B | FD_STATUS_OK) + ) + { + /* + * Not sure about this one -- it does not seem + * to be an error so we will keep quiet about it. + if ((fd.fd_status & FD_STATUS_B) != FD_STATUS_B) + printk("%s: frame not consumed by RU.\n", dev->name); + */ + + if ((fd.fd_status & FD_STATUS_OK) != FD_STATUS_OK) + printk("%s: frame not received successfully.\n", dev->name); + } + + if ((fd.fd_status & (FD_STATUS_S6 | FD_STATUS_S7 | FD_STATUS_S8 | FD_STATUS_S9 | FD_STATUS_S10 | FD_STATUS_S11)) != 0) + { + lp->stats.rx_errors++; + + if ((fd.fd_status & FD_STATUS_S6) != 0) + printk("%s: no EOF flag.\n", dev->name); + + if ((fd.fd_status & FD_STATUS_S7) != 0) + { + lp->stats.rx_length_errors++; + printk("%s: frame too short.\n", dev->name); + } + + if ((fd.fd_status & FD_STATUS_S8) != 0) + { + lp->stats.rx_over_errors++; + printk("%s: rx DMA overrun.\n", dev->name); + } + + if ((fd.fd_status & FD_STATUS_S9) != 0) + { + lp->stats.rx_fifo_errors++; + printk("%s: ran out of resources.\n", dev->name); + } + + if ((fd.fd_status & FD_STATUS_S10) != 0) + { + lp->stats.rx_frame_errors++; + printk("%s: alignment error.\n", dev->name); + } + + if ((fd.fd_status & FD_STATUS_S11) != 0) + { + lp->stats.rx_crc_errors++; + printk("%s: CRC error.\n", dev->name); + } + } + + if (fd.fd_rbd_offset == I82586NULL) + printk("%s: frame has no data.\n", dev->name); + else + { + obram_read(ioaddr, fd.fd_rbd_offset, (unsigned char *)&rbd, sizeof(rbd)); + + if ((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF) + printk("%s: missing EOF flag.\n", dev->name); + + if ((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F) + printk("%s: missing F flag.\n", dev->name); + + pkt_len = rbd.rbd_status & RBD_STATUS_ACNT; + +#if 0 + { + unsigned char addr[WAVELAN_ADDR_SIZE]; + int i; + static unsigned char toweraddr[WAVELAN_ADDR_SIZE] = + { + 0x08, 0x00, 0x0e, 0x20, 0x3e, 0xd3, + }; + + obram_read(ioaddr, rbd.rbd_bufl + sizeof(addr), &addr[0], sizeof(addr)); + if + ( + /* + addrcmp(&addr[0], &dev->dev_addr[0]) != 0 + && + */ + addrcmp(&addr[0], toweraddr) != 0 + ) + { + printk("%s: foreign MAC source addr=", dev->name); + for (i = 0; i < WAVELAN_ADDR_SIZE; i++) + printk("%s%02x", (i == 0) ? "" : ":", addr[i]); + printk("\n"); + } + } +#endif /* 0 */ + + if (wavelan_debug > 0) + { + unsigned char addr[WAVELAN_ADDR_SIZE]; + unsigned short ltype; + int i; + +#if 0 + printk("%s: fd_dest=", dev->name); + for (i = 0; i < WAVELAN_ADDR_SIZE; i++) + printk("%s%02x", (i == 0) ? "" : ":", fd.fd_dest[i]); + printk("\n"); + + printk("%s: fd_src=", dev->name); + for (i = 0; i < WAVELAN_ADDR_SIZE; i++) + printk("%s%02x", (i == 0) ? "" : ":", fd.fd_src[i]); + printk("\n"); + printk("%s: fd_length=%d\n", dev->name, fd.fd_length); +#endif /* 0 */ + + obram_read(ioaddr, rbd.rbd_bufl, &addr[0], sizeof(addr)); + printk("%s: dest=", dev->name); + for (i = 0; i < WAVELAN_ADDR_SIZE; i++) + printk("%s%02x", (i == 0) ? "" : ":", addr[i]); + printk("\n"); + + obram_read(ioaddr, rbd.rbd_bufl + sizeof(addr), &addr[0], sizeof(addr)); + printk("%s: src=", dev->name); + for (i = 0; i < WAVELAN_ADDR_SIZE; i++) + printk("%s%02x", (i == 0) ? "" : ":", addr[i]); + printk("\n"); + + obram_read(ioaddr, rbd.rbd_bufl + sizeof(addr) * 2, (unsigned char *)<ype, sizeof(ltype)); + printk("%s: ntohs(length/type)=0x%04x\n", dev->name, ntohs(ltype)); + } + + sksize = pkt_len; + + if ((skb = alloc_skb(sksize, GFP_ATOMIC)) == (struct sk_buff *)0) + { + printk("%s: could not alloc_skb(%d, GFP_ATOMIC).\n", dev->name, sksize); + lp->stats.rx_dropped++; + } + else + { + skb->len = pkt_len; + skb->dev = dev; + + obram_read(ioaddr, rbd.rbd_bufl, skb->data, pkt_len); + + if (wavelan_debug > 5) + { + int i; + int maxi; + + printk("%s: pkt_len=%d, data=\"", dev->name, pkt_len); + + if ((maxi = pkt_len) > 16) + maxi = 16; + + for (i = 0; i < maxi; i++) + { + unsigned char c; + + c = skb->data[i]; + if (c >= ' ' && c <= '~') + printk(" %c", skb->data[i]); + else + printk("%02x", skb->data[i]); + } + + if (maxi < pkt_len) + printk(".."); + + printk("\"\n\n"); + } + + netif_rx(skb); + + lp->stats.rx_packets++; + } + } + + fd.fd_status = 0; + obram_write(ioaddr, fdoff(lp->rx_head, fd_status), (unsigned char *)&fd.fd_status, sizeof(fd.fd_status)); + + fd.fd_command = FD_COMMAND_EL; + obram_write(ioaddr, fdoff(lp->rx_head, fd_command), (unsigned char *)&fd.fd_command, sizeof(fd.fd_command)); + + fd.fd_command = 0; + obram_write(ioaddr, fdoff(lp->rx_last, fd_command), (unsigned char *)&fd.fd_command, sizeof(fd.fd_command)); + + lp->rx_last = lp->rx_head; + lp->rx_head = fd.fd_link_offset; + } + +/* + if (nreaped > 1) + printk("r%d", nreaped); +*/ +} + +/* + * Command completion interrupt. + * Reclaim as many freed tx buffers as we can. + */ +static +int +wavelan_complete(device *dev, unsigned short ioaddr, net_local *lp) +{ + int nreaped; + + nreaped = 0; + + for (;;) + { + unsigned short tx_status; + + if (lp->tx_first_in_use == I82586NULL) + break; + + obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status)); + + if ((tx_status & AC_SFLD_C) == 0) + break; + + nreaped++; + + --lp->tx_n_in_use; + +/* +if (lp->tx_n_in_use > 0) + printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); +*/ + + if (lp->tx_n_in_use <= 0) + lp->tx_first_in_use = I82586NULL; + else + { + lp->tx_first_in_use += TXBLOCKZ; + if (lp->tx_first_in_use >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) + lp->tx_first_in_use -= NTXBLOCKS * TXBLOCKZ; + } + + if (tx_status & AC_SFLD_OK) + { + int ncollisions; + + lp->stats.tx_packets++; + ncollisions = tx_status & AC_SFLD_MAXCOL; + lp->stats.collisions += ncollisions; + /* + if (ncollisions > 0) + printk("%s: tx completed after %d collisions.\n", dev->name, ncollisions); + */ + } + else + { + lp->stats.tx_errors++; + if (tx_status & AC_SFLD_S10) + { + lp->stats.tx_carrier_errors++; + if (wavelan_debug > 0) + printk("%s: tx error: no CS.\n", dev->name); + } + if (tx_status & AC_SFLD_S9) + { + lp->stats.tx_carrier_errors++; + printk("%s: tx error: lost CTS.\n", dev->name); + } + if (tx_status & AC_SFLD_S8) + { + lp->stats.tx_fifo_errors++; + printk("%s: tx error: slow DMA.\n", dev->name); + } + if (tx_status & AC_SFLD_S6) + { + lp->stats.tx_heartbeat_errors++; + if (wavelan_debug > 0) + printk("%s: tx error: heart beat.\n", dev->name); + } + if (tx_status & AC_SFLD_S5) + { + lp->stats.tx_aborted_errors++; + if (wavelan_debug > 0) + printk("%s: tx error: too many collisions.\n", dev->name); + } + } + + if (wavelan_debug > 5) + printk("%s: tx completed, tx_status 0x%04x.\n", dev->name, tx_status); + } + +/* + if (nreaped > 1) + printk("c%d", nreaped); +*/ + + /* + * Inform upper layers. + */ + if (lp->tx_n_in_use < NTXBLOCKS - 1) + { + dev->tbusy = 0; + mark_bh(NET_BH); + } + + return nreaped; +} + +static +void +wavelan_watchdog(unsigned long a) +{ + device *dev; + net_local *lp; + unsigned short ioaddr; + unsigned long x; + unsigned int nreaped; + + x = wavelan_splhi(); + + dev = (device *)a; + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + if (lp->tx_n_in_use <= 0) + { + wavelan_splx(x); + return; + } + + lp->watchdog.expires = WATCHDOG_JIFFIES; + add_timer(&lp->watchdog); + + if (jiffies - dev->trans_start < WATCHDOG_JIFFIES) + { + wavelan_splx(x); + return; + } + + nreaped = wavelan_complete(dev, ioaddr, lp); + + printk("%s: warning: wavelan_watchdog(): %d reaped, %d remain.\n", dev->name, nreaped, lp->tx_n_in_use); + /* + wavelan_scb_show(ioaddr); + wavelan_ru_show(dev); + wavelan_cu_show(dev); + wavelan_dev_show(dev); + wavelan_local_show(dev); + */ + + wavelan_splx(x); +} + +static +void +wavelan_interrupt(int irq, struct pt_regs *regs) +{ + device *dev; + unsigned short ioaddr; + net_local *lp; + unsigned short hasr; + unsigned short status; + unsigned short ack_cmd; + + if ((dev = (device *)(irq2dev_map[irq])) == (device *)0) + { + printk("wavelan_interrupt(): irq %d for unknown device.\n", irq); + return; + } + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + dev->interrupt = 1; + + if ((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR) + { + unsigned char dce_status; + + /* + * Interrupt from the modem management controller. + * This will clear it -- ignored for now. + */ + mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status)); + if (wavelan_debug > 4) + printk("%s: warning: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", dev->name, dce_status); + } + + if ((hasr & HASR_82586_INTR) == 0) + { + dev->interrupt = 0; + if (wavelan_debug > 4) + printk("%s: warning: wavelan_interrupt() but (hasr & HASR_82586_INTR) == 0.\n", dev->name); + return; + } + + obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&status, sizeof(status)); + + /* + * Acknowledge the interrupt(s). + */ + ack_cmd = status & SCB_ST_INT; + + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&ack_cmd, sizeof(ack_cmd)); + + set_chan_attn(ioaddr, lp->hacr); + + if (wavelan_debug > 4) + printk("%s: interrupt, status 0x%04x.\n", dev->name, status); + + if ((status & SCB_ST_CX) == SCB_ST_CX) + { + /* + * Command completed. + */ + if (wavelan_debug > 5) + printk("%s: command completed.\n", dev->name); + (void)wavelan_complete(dev, ioaddr, lp); + } + + if ((status & SCB_ST_FR) == SCB_ST_FR) + { + /* + * Frame received. + */ + if (wavelan_debug > 5) + printk("%s: received packet.\n", dev->name); + wavelan_receive(dev); + } + + if + ( + (status & SCB_ST_CNA) == SCB_ST_CNA + || + (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && dev->start) + ) + { + printk("%s: warning: CU inactive -- restarting.\n", dev->name); + + (void)wavelan_hardware_reset(dev); + } + + if + ( + (status & SCB_ST_RNR) == SCB_ST_RNR + || + (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && dev->start) + ) + { + printk("%s: warning: RU not ready -- restarting.\n", dev->name); + + (void)wavelan_hardware_reset(dev); + } + + dev->interrupt = 0; +} + +static +int +wavelan_close(device *dev) +{ + unsigned short ioaddr; + net_local *lp; + unsigned short scb_cmd; + + ioaddr = dev->base_addr; + lp = (net_local *)dev->priv; + + dev->tbusy = 1; + dev->start = 0; + + /* + * Flush the Tx and disable Rx. + */ + scb_cmd = (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & SCB_CMD_RUC_SUS); + obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cmd, sizeof(scb_cmd)); + set_chan_attn(ioaddr, lp->hacr); + + wavelan_ints_off(dev); + + free_irq(dev->irq); + irq2dev_map[dev->irq] = (device *)0; + + /* + * Release the ioport-region. + */ + release_region(ioaddr, sizeof(ha_t)); + +#if defined(MODULE) + MOD_DEC_USE_COUNT; +#endif /* defined(MODULE) */ + + return 0; +} + +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ +static +en_stats * +wavelan_get_stats(device *dev) +{ + net_local *lp; + + lp = (net_local *)dev->priv; + + return &lp->stats; +} + +static +void +wavelan_set_multicast_list(device *dev, int num_addrs, void *addrs) +{ + net_local *lp; + + lp = (net_local *)dev->priv; + + switch (num_addrs) + { + case -1: + /* + * Promiscuous mode: receive all packets. + */ + lp->promiscuous = 1; + (void)wavelan_hardware_reset(dev); + break; + + case 0: + /* + * Normal mode: disable promiscuous mode, + * clear multicast list. + */ + lp->promiscuous = 0; + (void)wavelan_hardware_reset(dev); + break; + + default: + /* + * Multicast mode: receive normal and + * multicast packets and do best-effort filtering. + */ + break; + } +} + +/* + * Extra WaveLAN-specific device data. + * "cat /proc/net/wavelan" -- see fs/proc/net.c. + */ +static +int +sprintf_stats(char *buffer, device *dev) +{ + net_local *lp; + unsigned char v; + mmr_t m; + + lp = (net_local *)dev->priv; + + if (lp == (net_local *)0) + return sprintf(buffer, "%6s: No statistics available.\n", dev->name); + + v = (unsigned char)1; + mmc_write(dev->base_addr, mmwoff(0, mmw_freeze), &v, sizeof(v)); + + mmc_read(dev->base_addr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, sizeof(m.mmr_dce_status)); + mmc_read(dev->base_addr, mmroff(0, mmr_correct_nwid_h), &m.mmr_correct_nwid_h, sizeof(m.mmr_correct_nwid_h)); + mmc_read(dev->base_addr, mmroff(0, mmr_correct_nwid_l), &m.mmr_correct_nwid_l, sizeof(m.mmr_correct_nwid_l)); + mmc_read(dev->base_addr, mmroff(0, mmr_wrong_nwid_h), &m.mmr_wrong_nwid_h, sizeof(m.mmr_wrong_nwid_h)); + mmc_read(dev->base_addr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, sizeof(m.mmr_wrong_nwid_l)); + mmc_read(dev->base_addr, mmroff(0, mmr_signal_lvl), &m.mmr_signal_lvl, sizeof(m.mmr_signal_lvl)); + mmc_read(dev->base_addr, mmroff(0, mmr_silence_lvl), &m.mmr_silence_lvl, sizeof(m.mmr_silence_lvl)); + mmc_read(dev->base_addr, mmroff(0, mmr_sgnl_qual), &m.mmr_sgnl_qual, sizeof(m.mmr_sgnl_qual)); + + v = (unsigned char)0; + mmc_write(dev->base_addr, mmwoff(0, mmw_freeze), &v, sizeof(v)); + + lp->correct_nwid += (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l; + lp->wrong_nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; + + return sprintf + ( + buffer, + "%6s: %02x %08x %08x %02x %02x %02x %02x %u\n", + dev->name, + m.mmr_dce_status, + lp->correct_nwid, + lp->wrong_nwid, + m.mmr_signal_lvl, + m.mmr_silence_lvl, + m.mmr_sgnl_qual, + lp->tx_n_in_use, + lp->nresets + ); +} + +int +wavelan_get_info(char *buffer, char **start, off_t offset, int length) +{ + int len; + off_t begin; + off_t pos; + int size; + unsigned long x; + + len = 0; + begin = 0; + pos = 0; + + size = sprintf(buffer, "%s", "Iface | dce +nwid -nwid lvl slnc qual ntxq nrst\n"); + + pos += size; + len += size; + + x = wavelan_splhi(); + + if (first_wavelan != (net_local *)0) + { + net_local *lp; + + lp = first_wavelan; + do + { + size = sprintf_stats(buffer + len, lp->dev); + + len += size; + pos = begin + len; + + if (pos < offset) + { + len = 0; + begin = pos; + } + + if (pos > offset + length) + break; + } + while ((lp = lp->next) != first_wavelan); + } + + wavelan_splx(x); + + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ + + return len; +} + +#if defined(MODULE) +char kernel_version[] = UTS_RELEASE; +static struct device dev_wavelan = +{ + " " /* "wavelan" */, + 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, wavelan_probe +}; + +int +init_module(void) +{ + if (register_netdev(&dev_wavelan) != 0) + return -EIO; + return 0; +} + +void +cleanup_module(void) +{ + if (MOD_IN_USE) + printk("wavelan: device busy, remove delayed\n"); + else + { + unregister_netdev(&dev_wavelan); + kfree_s(dev_wavelan.priv, sizeof(struct net_local)); + dev_wavelan.priv = NULL; + } +} +#endif /* defined(MODULE) */ + +static +void +wavelan_cu_show_one(device *dev, net_local *lp, int i, unsigned short p) +{ + unsigned short ioaddr; + ac_tx_t actx; + + ioaddr = dev->base_addr; + + printk("%d: 0x%x:", i, p); + + obram_read(ioaddr, p, (unsigned char *)&actx, sizeof(actx)); + printk(" status=0x%x,", actx.tx_h.ac_status); + printk(" command=0x%x,", actx.tx_h.ac_command); + +/* + { + tbd_t tbd; + + obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd)); + printk(" tbd_status=0x%x,", tbd.tbd_status); + } +*/ + + printk("|"); +} + +#if 0 +static +void +wavelan_psa_show(psa_t *p) +{ + printk("psa:"); + + printk("psa_io_base_addr_1: 0x%02x,", p->psa_io_base_addr_1); + printk("psa_io_base_addr_2: 0x%02x,", p->psa_io_base_addr_2); + printk("psa_io_base_addr_3: 0x%02x,", p->psa_io_base_addr_3); + printk("psa_io_base_addr_4: 0x%02x,", p->psa_io_base_addr_4); + printk("psa_rem_boot_addr_1: 0x%02x,", p->psa_rem_boot_addr_1); + printk("psa_rem_boot_addr_2: 0x%02x,", p->psa_rem_boot_addr_2); + printk("psa_rem_boot_addr_3: 0x%02x,", p->psa_rem_boot_addr_3); + printk("psa_holi_params: 0x%02x,", p->psa_holi_params); + printk("psa_int_req_no: %d,", p->psa_int_req_no); + printk + ( + "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x,", + p->psa_univ_mac_addr[0], + p->psa_univ_mac_addr[1], + p->psa_univ_mac_addr[2], + p->psa_univ_mac_addr[3], + p->psa_univ_mac_addr[4], + p->psa_univ_mac_addr[5] + ); + printk + ( + "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x,", + p->psa_local_mac_addr[0], + p->psa_local_mac_addr[1], + p->psa_local_mac_addr[2], + p->psa_local_mac_addr[3], + p->psa_local_mac_addr[4], + p->psa_local_mac_addr[5] + ); + printk("psa_univ_local_sel: %d,", p->psa_univ_local_sel); + printk("psa_comp_number: %d,", p->psa_comp_number); + printk("psa_thr_pre_set: 0x%02x,", p->psa_thr_pre_set); + printk("psa_feature_select/decay_prm: 0x%02x,", p->psa_feature_select); + printk("psa_subband/decay_update_prm: %d,", p->psa_subband); + printk("psa_quality_thr: 0x%02x,", p->psa_quality_thr); + printk("psa_mod_delay: 0x%02x,", p->psa_mod_delay); + printk("psa_nwid: 0x%02x%02x,", p->psa_nwid[0], p->psa_nwid[1]); + printk("psa_undefined: %d,", p->psa_undefined); + printk("psa_encryption_select: %d,", p->psa_encryption_select); + printk + ( + "psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x,", + p->psa_encryption_key[0], + p->psa_encryption_key[1], + p->psa_encryption_key[2], + p->psa_encryption_key[3], + p->psa_encryption_key[4], + p->psa_encryption_key[5], + p->psa_encryption_key[6], + p->psa_encryption_key[7] + ); + printk("psa_databus_width: %d,", p->psa_databus_width); + printk("psa_call_code/auto_squelch: 0x%02x,", p->psa_call_code); + printk("psa_no_of_retries: %d,", p->psa_no_of_retries); + printk("psa_acr: %d,", p->psa_acr); + printk("psa_dump_count: %d,", p->psa_dump_count); + printk("psa_nwid_prefix: 0x%02x,", p->psa_nwid_prefix); + printk("psa_conf_status: %d,", p->psa_conf_status); + printk("psa_crc: 0x%02x%02x,", p->psa_crc[0], p->psa_crc[1]); + printk("psa_crc_status: 0x%02x,", p->psa_crc_status); + + printk("\n"); +} + +static +void +wavelan_mmc_show(unsigned short ioaddr) +{ + mmr_t m; + + mmc_read(ioaddr, 0, (unsigned char *)&m, sizeof(m)); + + printk("mmr:"); + printk(" des_status: 0x%x", m.mmr_des_status); + printk(" des_avail: 0x%x", m.mmr_des_avail); + printk(" des_io_invert: 0x%x", m.mmr_des_io_invert); + printk + ( + " dce_status: 0x%x[%s%s%s%s]", + m.mmr_dce_status & 0x0F, + (m.mmr_dce_status & MMR_DCE_STATUS_ENERG_DET) ? "energy detected," : "", + (m.mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ? "loop test indicated," : "", + (m.mmr_dce_status & MMR_DCE_STATUS_XMTITR_IND) ? "transmitter on," : "", + (m.mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ? "jabber timer expired," : "" + ); + printk(" correct_nwid: %d", m.mmr_correct_nwid_h << 8 | m.mmr_correct_nwid_l); + printk(" wrong_nwid: %d", (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l); + printk(" thr_pre_set: 0x%x", m.mmr_thr_pre_set); + printk(" signal_lvl: %d", m.mmr_signal_lvl); + printk(" silence_lvl: %d", m.mmr_silence_lvl); + printk(" sgnl_qual: 0x%x", m.mmr_sgnl_qual); + printk(" netw_id_l: %x", m.mmr_netw_id_l); + + printk("\n"); +} +#endif /* 0 */ + +static +void +wavelan_scb_show(unsigned short ioaddr) +{ + scb_t scb; + + obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb)); + + printk("scb:"); + + printk(" status:"); + printk + ( + " stat 0x%x[%s%s%s%s]", + (scb.scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA | SCB_ST_RNR)) >> 12, + (scb.scb_status & SCB_ST_CX) ? "cmd completion interrupt," : "", + (scb.scb_status & SCB_ST_FR) ? "frame received," : "", + (scb.scb_status & SCB_ST_CNA) ? "cmd unit not active," : "", + (scb.scb_status & SCB_ST_RNR) ? "rcv unit not ready," : "" + ); + printk + ( + " cus 0x%x[%s%s%s]", + (scb.scb_status & SCB_ST_CUS) >> 8, + ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_IDLE) ? "idle" : "", + ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_SUSP) ? "suspended" : "", + ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_ACTV) ? "active" : "" + ); + printk + ( + " rus 0x%x[%s%s%s%s]", + (scb.scb_status & SCB_ST_RUS) >> 4, + ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_IDLE) ? "idle" : "", + ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_SUSP) ? "suspended" : "", + ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_NRES) ? "no resources" : "", + ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_RDY) ? "ready" : "" + ); + + printk(" command:"); + printk + ( + " ack 0x%x[%s%s%s%s]", + (scb.scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR | SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12, + (scb.scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "", + (scb.scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "", + (scb.scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "", + (scb.scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : "" + ); + printk + ( + " cuc 0x%x[%s%s%s%s%s]", + (scb.scb_command & SCB_CMD_CUC) >> 8, + ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_NOP) ? "nop" : "", + ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_GO) ? "start cbl_offset" : "", + ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_RES) ? "resume execution" : "", + ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_SUS) ? "suspend execution" : "", + ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_ABT) ? "abort execution" : "" + ); + printk + ( + " ruc 0x%x[%s%s%s%s%s]", + (scb.scb_command & SCB_CMD_RUC) >> 4, + ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_NOP) ? "nop" : "", + ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_GO) ? "start rfa_offset" : "", + ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_RES) ? "resume reception" : "", + ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_SUS) ? "suspend reception" : "", + ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_ABT) ? "abort reception" : "" + ); + + printk(" cbl_offset 0x%x", scb.scb_cbl_offset); + printk(" rfa_offset 0x%x", scb.scb_rfa_offset); + + printk(" crcerrs %d", scb.scb_crcerrs); + printk(" alnerrs %d", scb.scb_alnerrs); + printk(" rscerrs %d", scb.scb_rscerrs); + printk(" ovrnerrs %d", scb.scb_ovrnerrs); + + printk("\n"); +} + +static +void +wavelan_ru_show(device *dev) +{ + net_local *lp; + + lp = (net_local *)dev->priv; + + printk("ru:"); + /* + * Not implemented yet... + */ + printk("\n"); +} + +static +void +wavelan_cu_show(device *dev) +{ + net_local *lp; + unsigned int i; + unsigned short p; + + lp = (net_local *)dev->priv; + + printk("cu:"); + printk("\n"); + + for (i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++) + { + wavelan_cu_show_one(dev, lp, i, p); + + p += TXBLOCKZ; + if (p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) + p -= NTXBLOCKS * TXBLOCKZ; + } +} + +static +void +wavelan_dev_show(device *dev) +{ + printk("dev:"); + printk(" start=%d,", dev->start); + printk(" tbusy=%d,", dev->tbusy); + printk(" interrupt=%d,", dev->interrupt); + printk(" trans_start=%ld,", dev->trans_start); + printk(" flags=0x%x,", dev->flags); + printk("\n"); +} + +static +void +wavelan_local_show(device *dev) +{ + net_local *lp; + + lp = (net_local *)dev->priv; + + printk("local:"); + printk(" tx_n_in_use=%d,", lp->tx_n_in_use); + printk(" hacr=0x%x,", lp->hacr); + printk(" rx_head=0x%x,", lp->rx_head); + printk(" rx_last=0x%x,", lp->rx_last); + printk(" tx_first_free=0x%x,", lp->tx_first_free); + printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use); + printk("\n"); +} + +/* + * This software may only be used and distributed + * according to the terms of the GNU Public License. + * + * This software was developed as a component of the + * Linux operating system. + * It is based on other device drivers and information + * either written or supplied by: + * Ajay Bakre (bakre@paul.rutgers.edu), + * Donald Becker (becker@cesdis.gsfc.nasa.gov), + * Loeke Brederveld (Loeke.Brederveld@Utrecht.NCR.com), + * Anders Klemets (klemets@it.kth.se), + * Vladimir V. Kolpakov (w@stier.koenig.ru), + * Marc Meertens (Marc.Meertens@Utrecht.NCR.com), + * Pauline Middelink (middelin@polyware.iaf.nl), + * Robert Morris (rtm@das.harvard.edu), + * Girish Welling (welling@paul.rutgers.edu), + * + * Thanks go also to: + * James Ashton (jaa101@syseng.anu.edu.au), + * Alan Cox (iialan@iiit.swan.ac.uk), + * Allan Creighton (allanc@cs.usyd.edu.au), + * Matthew Geier (matthew@cs.usyd.edu.au), + * Remo di Giovanni (remo@cs.usyd.edu.au), + * Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM), + * Tim Nicholson (tim@cs.usyd.edu.au), + * Jeff Noxon (jeff@oylpatch.sccsi.com), + * Ian Parkin (ian@cs.usyd.edu.au), + * John Rosenberg (johnr@cs.usyd.edu.au), + * George Rossi (george@phm.gov.au), + * Arthur Scott (arthur@cs.usyd.edu.au), + * Peter Storey, + * for their assistance and advice. + * + * Please send bug reports, updates, comments to: + * + * Bruce Janson Email: bruce@cs.usyd.edu.au + * Basser Department of Computer Science Phone: +61-2-351-3423 + * University of Sydney, N.S.W., 2006, AUSTRALIA Fax: +61-2-351-3838 + */ +#endif /* defined(CONFIG_WAVELAN) */ diff -u --recursive --new-file v1.1.87/linux/drivers/net/wavelan.h linux/drivers/net/wavelan.h --- v1.1.87/linux/drivers/net/wavelan.h Thu Jan 1 02:00:00 1970 +++ linux/drivers/net/wavelan.h Tue Jan 31 14:36:24 1995 @@ -0,0 +1,254 @@ +#if defined(CONFIG_WAVELAN) +#define WAVELAN_ADDR_SIZE 6 /* Size of a MAC address */ +#define SA_ADDR0 0x08 /* First octet of WaveLAN MAC addresses */ +#define SA_ADDR1 0x00 /* Second octet of WaveLAN MAC addresses */ +#define SA_ADDR2 0x0E /* Third octet of WaveLAN MAC addresses */ +#define WAVELAN_MTU 1500 /* Maximum size of WaveLAN packet */ + +/* + * Parameter Storage Area (PSA). + */ +typedef struct psa_t psa_t; +struct psa_t +{ + unsigned char psa_io_base_addr_1; /* Base address 1 ??? */ + unsigned char psa_io_base_addr_2; /* Base address 2 */ + unsigned char psa_io_base_addr_3; /* Base address 3 */ + unsigned char psa_io_base_addr_4; /* Base address 4 */ + unsigned char psa_rem_boot_addr_1; /* Remote Boot Address 1 */ + unsigned char psa_rem_boot_addr_2; /* Remote Boot Address 2 */ + unsigned char psa_rem_boot_addr_3; /* Remote Boot Address 3 */ + unsigned char psa_holi_params; /* HOst Lan Interface (HOLI) Parameters */ + unsigned char psa_int_req_no; /* Interrupt Request Line */ + unsigned char psa_unused0[7]; /* unused */ + unsigned char psa_univ_mac_addr[WAVELAN_ADDR_SIZE]; /* Universal (factory) MAC Address */ + unsigned char psa_local_mac_addr[WAVELAN_ADDR_SIZE]; /* Local MAC Address */ + unsigned char psa_univ_local_sel; /* Universal Local Selection */ +#define PSA_UNIVERSAL 0 /* Universal (factory) */ +#define PSA_LOCAL 1 /* Local */ + unsigned char psa_comp_number; /* Compatability Number: */ +#define PSA_COMP_PC_AT_915 0 /* PC-AT 915 MHz */ +#define PSA_COMP_PC_MC_915 1 /* PC-MC 915 MHz */ +#define PSA_COMP_PC_AT_2400 2 /* PC-AT 2.4 GHz */ +#define PSA_COMP_PC_MC_2400 3 /* PC-MC 2.4 GHz */ +#define PSA_COMP_PCMCIA_915 4 /* PCMCIA 915 MHz */ + unsigned char psa_thr_pre_set; /* Modem Threshold Preset */ + unsigned char psa_feature_select; /* ??? */ +#if 0 + + unsigned char psa_decay_prm; /* Modem Decay */ +#endif /* 0 */ + unsigned char psa_subband; /* Subband */ +#define PSA_SUBBAND_915 0 /* 915 MHz */ +#define PSA_SUBBAND_2425 1 /* 2425 MHz */ +#define PSA_SUBBAND_2460 2 /* 2460 MHz */ +#define PSA_SUBBAND_2484 3 /* 2484 MHz */ +#define PSA_SUBBAND_2430_5 4 /* 2430.5 MHz */ +#if 0 + + unsigned char psa_decay_updat_prm; /* Modem Decay Update ??? */ +#endif /* 0 */ + unsigned char psa_quality_thr; /* Modem Quality Threshold */ + unsigned char psa_mod_delay; /* Modem Delay ??? */ + unsigned char psa_nwid[2]; /* Network ID */ + unsigned char psa_undefined; /* undefined */ + unsigned char psa_encryption_select; /* Encryption On Off */ + unsigned char psa_encryption_key[8]; /* Encryption Key */ + unsigned char psa_databus_width; /* 8/16 bit bus width */ + unsigned char psa_call_code; /* ??? */ +#if 0 + + unsigned char psa_auto_squelch; /* Automatic Squelch level On off ??? */ +#endif /* 0 */ + unsigned char psa_no_of_retries; /* LAN Cont. No of retries */ + unsigned char psa_acr; /* LAN Cont. ACR */ + unsigned char psa_dump_count; /* number of Dump Commands in TFB */ + unsigned char psa_unused1[4]; /* unused */ + unsigned char psa_nwid_prefix; /* ??? */ + unsigned char psa_unused2[3]; /* unused */ + unsigned char psa_conf_status; /* Card Configuration Status */ + unsigned char psa_crc[2]; /* CRC over PSA */ + unsigned char psa_crc_status; /* CRC Valid Flag */ +}; +#if STRUCT_CHECK == 1 +#define PSA_SIZE 64 +#endif /* STRUCT_CHECK == 1 */ + +/* + * Modem Management Controller (MMC) write structure. + */ +typedef struct mmw_t mmw_t; +struct mmw_t +{ + unsigned char mmw_encr_key[8]; /* encryption key */ + unsigned char mmw_encr_enable; /* enable/disable encryption */ + unsigned char mmw_unused0[1]; /* unused */ + unsigned char mmw_des_io_invert; /* ??? */ + unsigned char mmw_unused1[5]; /* unused */ + unsigned char mmw_loopt_sel; /* looptest selection */ +#define MMW_LOOPT_SEL_UNDEFINED 0x40 /* undefined */ +#define MMW_LOOPT_SEL_INT 0x20 /* activate Attention Request */ +#define MMW_LOOPT_SEL_LS 0x10 /* looptest without collision avoidance */ +#define MMW_LOOPT_SEL_LT3A 0x08 /* looptest 3a */ +#define MMW_LOOPT_SEL_LT3B 0x04 /* looptest 3b */ +#define MMW_LOOPT_SEL_LT3C 0x02 /* looptest 3c */ +#define MMW_LOOPT_SEL_LT3D 0x01 /* looptest 3d */ + unsigned char mmw_jabber_enable; /* jabber timer enable */ + unsigned char mmw_freeze; /* freeze / unfreeeze signal level */ + unsigned char mmw_anten_sel; /* antenna selection */ +#define MMW_ANTEN_SEL_SEL 0x01 /* direct antenna selection */ +#define MMW_ANTEN_SEL_ALG_EN 0x02 /* antenna selection algorithm enable */ + unsigned char mmw_ifs; /* inter frame spacing */ + unsigned char mmw_mod_delay; /* modem delay */ + unsigned char mmw_jam_time; /* jamming time */ + unsigned char mmw_unused2[1]; /* unused */ + unsigned char mmw_thr_pre_set; /* level threshold preset */ + unsigned char mmw_decay_prm; /* decay parameters */ + unsigned char mmw_decay_updat_prm; /* decay update parameterz */ + unsigned char mmw_quality_thr; /* quality (z-quotient) threshold */ + unsigned char mmw_netw_id_l; /* NWID low order byte */ + unsigned char mmw_netw_id_h; /* NWID high order byte */ +}; +#if STRUCT_CHECK == 1 +#define MMW_SIZE 30 +#endif /* STRUCT_CHECK == 1 */ + +#define mmwoff(p,f) (unsigned short)((void *)(&((mmw_t *)((void *)0 + (p)))->f) - (void *)0) + +/* + * Modem Management Controller (MMC) read structure. + */ +typedef struct mmr_t mmr_t; +struct mmr_t +{ + unsigned char mmr_unused0[8]; /* unused */ + unsigned char mmr_des_status; /* encryption status */ + unsigned char mmr_des_avail; /* encryption available (0x55 read) */ + unsigned char mmr_des_io_invert; /* des I/O invert register */ + unsigned char mmr_unused1[5]; /* unused */ + unsigned char mmr_dce_status; /* DCE status */ +#define MMR_DCE_STATUS_ENERG_DET 0x01 /* energy detected */ +#define MMR_DCE_STATUS_LOOPT_IND 0x02 /* loop test indicated */ +#define MMR_DCE_STATUS_XMTITR_IND 0x04 /* transmitter on */ +#define MMR_DCE_STATUS_JBR_EXPIRED 0x08 /* jabber timer expired */ + unsigned char mmr_unused2[3]; /* unused */ + unsigned char mmr_correct_nwid_l; /* no. of correct NWID's rxd (low) */ + unsigned char mmr_correct_nwid_h; /* no. of correct NWID's rxd (high) */ + unsigned char mmr_wrong_nwid_l; /* count of wrong NWID's received (low) */ + unsigned char mmr_wrong_nwid_h; /* count of wrong NWID's received (high) */ + unsigned char mmr_thr_pre_set; /* level threshold preset */ + unsigned char mmr_signal_lvl; /* signal level */ + unsigned char mmr_silence_lvl; /* silence level */ + unsigned char mmr_sgnl_qual; /* signal quality */ +#define MMR_SGNL_QUAL_0 0x01 /* signal quality 0 */ +#define MMR_SGNL_QUAL_1 0x02 /* signal quality 1 */ +#define MMR_SGNL_QUAL_2 0x04 /* signal quality 2 */ +#define MMR_SGNL_QUAL_3 0x08 /* signal quality 3 */ +#define MMR_SGNL_QUAL_S_A 0x80 /* currently selected antenna */ + unsigned char mmr_netw_id_l; /* NWID low order byte ??? */ + unsigned char mmr_unused3[1]; /* unused */ +}; +#if STRUCT_CHECK == 1 +#define MMR_SIZE 30 +#endif /* STRUCT_CHECK == 1 */ + +#define MMR_LEVEL_MASK 0x3F + +#define mmroff(p,f) (unsigned short)((void *)(&((mmr_t *)((void *)0 + (p)))->f) - (void *)0) + +/* + * Host Adaptor structure. + * (base is board port address). + */ +typedef union hacs_u hacs_u; +union hacs_u +{ + unsigned short hu_command; /* Command register */ +#define HACR_RESET 0x0001 /* Reset board */ +#define HACR_CA 0x0002 /* Set Channel Attention for 82586 */ +#define HACR_16BITS 0x0004 /* 16 bits operation (0 => 8bits) */ +#define HACR_OUT0 0x0008 /* General purpose output pin 0 */ + /* not used - must be 1 */ +#define HACR_OUT1 0x0010 /* General purpose output pin 1 */ + /* not used - must be 1 */ +#define HACR_82586_INT_ENABLE 0x0020 /* Enable 82586 interrupts */ +#define HACR_MMC_INT_ENABLE 0x0040 /* Enable MMC interrupts */ +#define HACR_INTR_CLR_ENABLE 0x0080 /* Enable interrupt status read/clear */ + unsigned short hu_status; /* Status Register */ +#define HASR_82586_INTR 0x0001 /* Interrupt request from 82586 */ +#define HASR_MMC_INTR 0x0002 /* Interrupt request from MMC */ +#define HASR_MMC_BUSY 0x0004 /* MMC busy indication */ +#define HASR_PSA_BUSY 0x0008 /* LAN parameter storage area busy */ +}; + +typedef struct ha_t ha_t; +struct ha_t +{ + hacs_u ha_cs; /* Command and status registers */ +#define ha_command ha_cs.hu_command +#define ha_status ha_cs.hu_status + unsigned short ha_mmcr; /* Modem Management Ctrl Register */ + unsigned short ha_pior0; /* Program I/O Address Register Port 0 */ + unsigned short ha_piop0; /* Program I/O Port 0 */ + unsigned short ha_pior1; /* Program I/O Address Register Port 1 */ + unsigned short ha_piop1; /* Program I/O Port 1 */ + unsigned short ha_pior2; /* Program I/O Address Register Port 2 */ + unsigned short ha_piop2; /* Program I/O Port 2 */ +}; +#if STRUCT_CHECK == 1 +#define HA_SIZE 16 +#endif /* STRUCT_CHECK == 1 */ + +#define hoff(p,f) (unsigned short)((void *)(&((ha_t *)((void *)0 + (p)))->f) - (void *)0) +#define HACR(p) hoff(p, ha_command) +#define HASR(p) hoff(p, ha_status) +#define MMCR(p) hoff(p, ha_mmcr) +#define PIOR0(p) hoff(p, ha_pior0) +#define PIOP0(p) hoff(p, ha_piop0) +#define PIOR1(p) hoff(p, ha_pior1) +#define PIOP1(p) hoff(p, ha_piop1) +#define PIOR2(p) hoff(p, ha_pior2) +#define PIOP2(p) hoff(p, ha_piop2) + +/* + * Program I/O Mode Register values. + */ +#define STATIC_PIO 0 /* Mode 1: static mode */ + /* RAM access ??? */ +#define AUTOINCR_PIO 1 /* Mode 2: auto increment mode */ + /* RAM access ??? */ +#define AUTODECR_PIO 2 /* Mode 3: auto decrement mode */ + /* RAM access ??? */ +#define PARAM_ACCESS_PIO 3 /* Mode 4: LAN parameter access mode */ + /* Parameter access. */ +#define PIO_MASK 3 /* register mask */ +#define PIOM(cmd,piono) ((u_short)cmd << 10 << (piono * 2)) + +#define HACR_DEFAULT (HACR_OUT0 | HACR_OUT1 | HACR_16BITS | PIOM(STATIC_PIO, 0) | PIOM(AUTOINCR_PIO, 1) | PIOM(PARAM_ACCESS_PIO, 2)) +#define HACR_INTRON (HACR_82586_INT_ENABLE | HACR_MMC_INT_ENABLE | HACR_INTR_CLR_ENABLE) + +#define MAXDATAZ (WAVELAN_ADDR_SIZE + WAVELAN_ADDR_SIZE + 2 + WAVELAN_MTU) + +/* + * Onboard 64k RAM layout. + * (Offsets from 0x0000.) + */ +#define OFFSET_RU 0x0000 +#define OFFSET_CU 0x8000 +#define OFFSET_SCB (OFFSET_ISCP - sizeof(scb_t)) +#define OFFSET_ISCP (OFFSET_SCP - sizeof(iscp_t)) +#define OFFSET_SCP I82586_SCP_ADDR + +#define RXBLOCKZ (sizeof(fd_t) + sizeof(rbd_t) + MAXDATAZ) +#define TXBLOCKZ (sizeof(ac_tx_t) + sizeof(ac_nop_t) + sizeof(tbd_t) + MAXDATAZ) + +#define NRXBLOCKS ((OFFSET_CU - OFFSET_RU) / RXBLOCKZ) +#define NTXBLOCKS ((OFFSET_SCB - OFFSET_CU) / TXBLOCKZ) + +/* + * This software may only be used and distributed + * according to the terms of the GNU Public License. + * + * For more details, see wavelan.c. + */ +#endif /* defined(CONFIG_WAVELAN) */ diff -u --recursive --new-file v1.1.87/linux/drivers/scsi/ChangeLog linux/drivers/scsi/ChangeLog --- v1.1.87/linux/drivers/scsi/ChangeLog Sun Jan 22 21:39:40 1995 +++ linux/drivers/scsi/ChangeLog Tue Jan 31 09:39:01 1995 @@ -74,7 +74,7 @@ scsi_init_malloc to get some memory we know will be safe). * scsi.c: Change dma freelist to be a set of pages. This allows - us to dynamicly adjust the size of the list by adding more pages + us to dynamically adjust the size of the list by adding more pages to the pagelist. Fix scsi_malloc and scsi_free accordingly. * scsi_module.c: Fix include. diff -u --recursive --new-file v1.1.87/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.1.87/linux/drivers/scsi/scsi.c Mon Jan 30 06:41:57 1995 +++ linux/drivers/scsi/scsi.c Tue Jan 31 09:36:21 1995 @@ -578,14 +578,6 @@ } /* for lun ends */ shpnt->host_queue = NULL; /* No longer needed here */ - printk("scsi : detected "); - for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) - if(sdtpnt->dev_noticed && sdtpnt->name) - printk("%d SCSI %s%s ", sdtpnt->dev_noticed, sdtpnt->name, - (sdtpnt->dev_noticed != 1) ? "s" : ""); - - printk("total.\n"); - /* Last device block does not exist. Free memory. */ scsi_init_free((char *) SDpnt, sizeof(Scsi_Device)); @@ -1955,6 +1947,11 @@ if(scsi_loadable_module_flag) { retval = (unsigned long) kmalloc(size, priority); } else { + /* + * Keep all memory aligned on 16-byte boundaries. Some host adaptors + * (e.g. BusLogic BT-445S) require DMA buffers to be aligned that way. + */ + size = (size + 15) & ~15; retval = scsi_init_memory_start; scsi_init_memory_start += size; } @@ -1968,6 +1965,7 @@ if((unsigned long) ptr > scsi_init_memory_start) { kfree(ptr); } else { + size = (size + 15) & ~15; /* Use the same alignment as scsi_init_malloc(). */ if(((unsigned long) ptr) + size == scsi_init_memory_start) scsi_init_memory_start = (unsigned long) ptr; } @@ -1993,7 +1991,8 @@ /* Init a few things so we can "malloc" memory. */ scsi_loadable_module_flag = 0; - scsi_init_memory_start = memory_start; + /* Align everything on 16-byte boundaries. */ + scsi_init_memory_start = (memory_start + 15) & ~ 15; timer_table[SCSI_TIMER].fn = scsi_main_timeout; timer_table[SCSI_TIMER].expires = 0; @@ -2006,6 +2005,13 @@ for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) scan_scsis(shpnt); /* scan for scsi devices */ + printk("scsi : detected "); + for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) + if (sdtpnt->dev_noticed && sdtpnt->name) + printk("%d SCSI %s%s ", sdtpnt->dev_noticed, sdtpnt->name, + (sdtpnt->dev_noticed != 1) ? "s" : ""); + printk("total.\n"); + for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)(); @@ -2068,7 +2074,6 @@ dma_sectors = (dma_sectors + 15) & 0xfff0; dma_free_sectors = dma_sectors; /* This must be a multiple of 16 */ - scsi_init_memory_start = (scsi_init_memory_start + 3) & 0xfffffffc; dma_malloc_freelist = (unsigned char *) scsi_init_malloc(dma_sectors >> 3, GFP_ATOMIC); memset(dma_malloc_freelist, 0, dma_sectors >> 3); @@ -2077,9 +2082,6 @@ scsi_init_malloc(dma_sectors >> 1, GFP_ATOMIC); memset(dma_malloc_pages, 0, dma_sectors >> 1); - /* Some host adapters require buffers to be word aligned */ - if(scsi_init_memory_start & 1) scsi_init_memory_start++; - for(i=0; i< dma_sectors >> 3; i++) dma_malloc_pages[i] = (unsigned char *) scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA); diff -u --recursive --new-file v1.1.87/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v1.1.87/linux/drivers/scsi/sd.c Thu Jan 26 07:49:06 1995 +++ linux/drivers/scsi/sd.c Tue Jan 31 09:39:01 1995 @@ -87,7 +87,7 @@ return -ENXIO; /* No such device */ /* - * See if we are requesting a non-existant partition. + * See if we are requesting a non-existent partition. */ if(sd_sizes[MINOR(inode->i_rdev)] == 0) return -ENXIO; diff -u --recursive --new-file v1.1.87/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v1.1.87/linux/drivers/scsi/sr.c Mon Jan 30 08:53:06 1995 +++ linux/drivers/scsi/sr.c Tue Jan 31 09:39:01 1995 @@ -349,7 +349,7 @@ min = (unsigned long) rec[15]/16*10 + (unsigned long) rec[15]%16; sec = (unsigned long) rec[16]/16*10 + (unsigned long) rec[16]%16; frame = (unsigned long) rec[17]/16*10 + (unsigned long) rec[17]%16; - /* if rec[14] is'nt 0xb0, the drive does not support multisession CD's, use zero */ + /* if rec[14] isn't 0xb0, the drive does not support multisession CD's, use zero */ sector = (0xb0 == rec[14]) ? min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame : 0; #ifdef DEBUG printk("NEC: (%2x) %2li:%02li:%02li = %li\n",buf[8+14],min,sec,frame,sector); @@ -377,7 +377,7 @@ if (rc != 0) { printk("sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc); sector = 0; - break; /* if the first ioctl fails, we don't call the secound one */ + break; /* if the first ioctl fails, we don't call the second one */ } is_xa = (rec[0] == 0x20); #ifdef DEBUG @@ -411,7 +411,7 @@ printk("sr_photocd: get_density: 0x%x\n",rec[4]); #endif - /* ...and only if nessesary a set_density */ + /* ...and only if necessary a set_density */ if ((rec[4] != 0x81 && is_xa) || (rec[4] != 0 && !is_xa)) { #ifdef DEBUG printk("sr_photocd: doing set_density\n"); diff -u --recursive --new-file v1.1.87/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v1.1.87/linux/fs/binfmt_elf.c Mon Jan 30 06:41:57 1995 +++ linux/fs/binfmt_elf.c Mon Jan 30 13:08:04 1995 @@ -33,6 +33,7 @@ #include #include +#include #include diff -u --recursive --new-file v1.1.87/linux/fs/exec.c linux/fs/exec.c --- v1.1.87/linux/fs/exec.c Mon Jan 30 06:41:57 1995 +++ linux/fs/exec.c Mon Jan 30 13:08:04 1995 @@ -42,6 +42,7 @@ #include #include +#include #include diff -u --recursive --new-file v1.1.87/linux/fs/msdos/msbuffer.h linux/fs/msdos/msbuffer.h --- v1.1.87/linux/fs/msdos/msbuffer.h Mon Jan 30 06:41:57 1995 +++ linux/fs/msdos/msbuffer.h Tue Jan 31 09:36:21 1995 @@ -15,7 +15,7 @@ /* These macros exist to avoid modifying all the code */ /* They should be removed one day I guess */ -/* The versionning mecanism of the modules system define those macros */ +/* The versioning mechanism of the modules system define those macros */ /* This remove some warnings */ #ifdef brelse #undef brelse diff -u --recursive --new-file v1.1.87/linux/fs/proc/array.c linux/fs/proc/array.c --- v1.1.87/linux/fs/proc/array.c Thu Jan 26 07:49:08 1995 +++ linux/fs/proc/array.c Mon Jan 30 13:08:04 1995 @@ -44,6 +44,7 @@ #include #include +#include #include #define LOAD_INT(x) ((x) >> FSHIFT) diff -u --recursive --new-file v1.1.87/linux/fs/proc/mem.c linux/fs/proc/mem.c --- v1.1.87/linux/fs/proc/mem.c Sun Jan 22 23:03:59 1995 +++ linux/fs/proc/mem.c Mon Jan 30 13:08:04 1995 @@ -13,6 +13,7 @@ #include #include #include +#include /* * mem_write isn't really a good idea right now. It needs diff -u --recursive --new-file v1.1.87/linux/fs/proc/net.c linux/fs/proc/net.c --- v1.1.87/linux/fs/proc/net.c Mon Jan 30 06:41:58 1995 +++ linux/fs/proc/net.c Tue Jan 31 14:36:24 1995 @@ -55,6 +55,9 @@ 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); +#if defined(CONFIG_WAVELAN) +extern int wavelan_get_info(char *, char **, off_t, int); +#endif /* defined(CONFIG_WAVELAN) */ 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); @@ -145,6 +148,9 @@ #ifdef CONFIG_IP_ACCT { PROC_NET_IPACCT, 7, "ip_acct"}, #endif +#if defined(CONFIG_WAVELAN) + { PROC_NET_WAVELAN, 7, "wavelan" }, +#endif /* defined(CONFIG_WAVELAN) */ #endif /* CONFIG_INET */ #ifdef CONFIG_IPX { PROC_NET_IPX_ROUTE, 9, "ipx_route" }, @@ -305,6 +311,11 @@ length = rarp_get_info(page,&start,file->f_pos,thistime); break; #endif /* CONFIG_INET_RARP */ +#if defined(CONFIG_WAVELAN) + case PROC_NET_WAVELAN: + length = wavelan_get_info(page, &start, file->f_pos, thistime); + break; +#endif /* defined(CONFIG_WAVELAN) */ #endif /* CONFIG_INET */ #ifdef CONFIG_IPX case PROC_NET_IPX_INTERFACE: diff -u --recursive --new-file v1.1.87/linux/fs/umsdos/README linux/fs/umsdos/README --- v1.1.87/linux/fs/umsdos/README Wed Aug 10 19:26:28 1994 +++ linux/fs/umsdos/README Tue Jan 31 09:39:02 1995 @@ -16,7 +16,7 @@ There is plenty of documentation on it in the source. A formated document made from those comments is available from -sunsite.unc.edu:/pub/Linux/ALPHA/umsdos +sunsite.unc.edu:/pub/Linux/system/Filesystems/umsdos. Mostly... @@ -53,9 +53,9 @@ $5 per directory. Add any applicable taxes. \end joke_section -A utility umssync creates those and maintain them. It is available -from the same directory above (sunsite) in the file umsdos_progs-0.3.tar.gz. -A compiled version is available in umsdos-0.3a.bin.tar.gz. +A utility umssync creates those. The kernel maintain them. It is available +from the same directory above (sunsite) in the file umsdos_progs-0.7.tar.gz. +A compiled version is available in umsdos_progs-0.7.bin.tar.gz. So in our example, after mounting mnt, we do @@ -79,6 +79,18 @@ Umsdos won't notice new files, but will signal removed file (it won't crash). Using umssync in /etc/rc will make sure the DOS directory is in sync with the --linux-.---. + +It is a good idea to put the following command in your RC file just +after the "mount -a": + + mount -a + /sbin/umssync -i+ -c+ -r99 /umsdos_mount_point + + (You put one for each umsdos mount point in the fstab) + +This will insure nice operation. A umsdos.fsck is in the making, +so you will be allowed to managed umsdos partition in the same way +other filesystem are, using the generic fsck front end. Hope this helps! diff -u --recursive --new-file v1.1.87/linux/fs/umsdos/ioctl.c linux/fs/umsdos/ioctl.c --- v1.1.87/linux/fs/umsdos/ioctl.c Mon Jan 30 06:41:58 1995 +++ linux/fs/umsdos/ioctl.c Tue Jan 31 09:36:21 1995 @@ -167,7 +167,7 @@ }else if (cmd == UMSDOS_RENAME_DOS){ /* #Specification: ioctl / UMSDOS_RENAME_DOS A file or directory is rename in a DOS directory - (not moved accross directory). The source name + (not moved across directory). The source name is in the dos_dirent.name field and the destination is in umsdos_dirent.name field. diff -u --recursive --new-file v1.1.87/linux/include/asm-alpha/page.h linux/include/asm-alpha/page.h --- v1.1.87/linux/include/asm-alpha/page.h Mon Jan 30 08:53:06 1995 +++ linux/include/asm-alpha/page.h Tue Jan 31 09:30:47 1995 @@ -1,43 +1,14 @@ #ifndef _ALPHA_PAGE_H #define _ALPHA_PAGE_H -#define CONFIG_STRICT_MM_TYPECHECKS - -#define invalidate_all() \ -__asm__ __volatile__( \ - "lda $16,-2($31)\n\t" \ - ".long 51" \ - : : :"$1", "$16", "$17", "$22","$23","$24","$25") - -#define invalidate() \ -__asm__ __volatile__( \ - "lda $16,-1($31)\n\t" \ - ".long 51" \ - : : :"$1", "$16", "$17", "$22","$23","$24","$25") - /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 13 -#define PMD_SHIFT 23 -#define PGDIR_SHIFT 33 - #define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) - #define PAGE_MASK (~(PAGE_SIZE-1)) -#define PMD_MASK (~(PMD_SIZE-1)) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) #ifdef __KERNEL__ -#define PAGE_OFFSET 0xFFFFFC0000000000 -#define MAP_NR(addr) ((((unsigned long) (addr)) - PAGE_OFFSET) >> PAGE_SHIFT) -#define MAP_PAGE_RESERVED (1<<31) - -typedef unsigned int mem_map_t; - -#define VMALLOC_START 0xFFFFFE0000000000 -#define VMALLOC_VMADDR(x) ((unsigned long)(x)) +#define CONFIG_STRICT_MM_TYPECHECKS #ifdef CONFIG_STRICT_MM_TYPECHECKS /* @@ -77,253 +48,26 @@ #endif -/* - * OSF/1 PAL-code-imposed page table bits - */ -#define _PAGE_VALID 0x0001 -#define _PAGE_FOR 0x0002 /* used for page protection (fault on read) */ -#define _PAGE_FOW 0x0004 /* used for page protection (fault on write) */ -#define _PAGE_FOE 0x0008 /* used for page protection (fault on exec) */ -#define _PAGE_ASM 0x0010 -#define _PAGE_KRE 0x0100 /* xxx - see below on the "accessed" bit */ -#define _PAGE_URE 0x0200 /* xxx */ -#define _PAGE_KWE 0x1000 /* used to do the dirty bit in software */ -#define _PAGE_UWE 0x2000 /* used to do the dirty bit in software */ - -/* .. and these are ours ... */ -#define _PAGE_COW 0x10000 -#define _PAGE_DIRTY 0x20000 -#define _PAGE_ACCESSED 0x40000 - -/* - * NOTE! The "accessed" bit isn't necessarily exact: it can be kept exactly - * by software (use the KRE/URE/KWE/UWE bits appropritely), but I'll fake it. - * Under Linux/AXP, the "accessed" bit just means "read", and I'll just use - * the KRE/URE bits to watch for it. That way we don't need to overload the - * KWE/UWE bits with both handling dirty and accessed. - * - * Note that the kernel uses the accessed bit just to check whether to page - * out a page or not, so it doesn't have to be exact anyway. - */ - -#define __DIRTY_BITS (_PAGE_DIRTY | _PAGE_KWE | _PAGE_UWE) -#define __ACCESS_BITS (_PAGE_ACCESSED | _PAGE_KRE | _PAGE_URE) - -#define _PFN_MASK 0xFFFFFFFF00000000 - -#define _PAGE_TABLE (_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS) -#define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS) - -/* - * All the normal masks have the "page accessed" bits on, as any time they are used, - * the page is accessed. They are cleared only by the page-out routines - */ -#define PAGE_NONE __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE) -#define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS) -#define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_COW) -#define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) -#define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE) - -#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x)) - -#define __P000 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE) -#define __P001 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOW | _PAGE_FOE) -#define __P010 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR | _PAGE_FOE) -#define __P011 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOE) -#define __P100 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR | _PAGE_FOW) -#define __P101 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOW) -#define __P110 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR) -#define __P111 _PAGE_NORMAL(_PAGE_COW) - -#define __S000 _PAGE_NORMAL(_PAGE_FOR | _PAGE_FOW | _PAGE_FOE) -#define __S001 _PAGE_NORMAL(_PAGE_FOW | _PAGE_FOE) -#define __S010 _PAGE_NORMAL(_PAGE_FOR | _PAGE_FOE) -#define __S011 _PAGE_NORMAL(_PAGE_FOE) -#define __S100 _PAGE_NORMAL(_PAGE_FOR | _PAGE_FOW) -#define __S101 _PAGE_NORMAL(_PAGE_FOW) -#define __S110 _PAGE_NORMAL(_PAGE_FOR) -#define __S111 _PAGE_NORMAL(0) - -/* - * BAD_PAGETABLE is used when we need a bogus page-table, while - * BAD_PAGE is used for a bogus page. - * - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -extern pte_t __bad_page(void); -extern pmd_t * __bad_pagetable(void); - -extern unsigned long __zero_page(void); - -#define BAD_PAGETABLE __bad_pagetable() -#define BAD_PAGE __bad_page() -#define ZERO_PAGE __zero_page() +#define invalidate_all() \ +__asm__ __volatile__( \ + "lda $16,-2($31)\n\t" \ + ".long 51" \ + : : :"$1", "$16", "$17", "$22","$23","$24","$25") -/* number of bits that fit into a memory pointer */ -#define BITS_PER_PTR (8*sizeof(unsigned long)) +#define invalidate() \ +__asm__ __volatile__( \ + "lda $16,-1($31)\n\t" \ + ".long 51" \ + : : :"$1", "$16", "$17", "$22","$23","$24","$25") /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) -/* to align the pointer to a pointer address */ -#define PTR_MASK (~(sizeof(void*)-1)) - -/* sizeof(void*)==1<>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) - -/* This one will go away */ -#define PTRS_PER_PAGE 1024 - -#define PTRS_PER_PTE 1024 -#define PTRS_PER_PMD 1024 -#define PTRS_PER_PGD 1024 +#define PAGE_OFFSET 0xFFFFFC0000000000 +#define MAP_NR(addr) ((((unsigned long) (addr)) - PAGE_OFFSET) >> PAGE_SHIFT) +#define MAP_PAGE_RESERVED (1<<31) -extern unsigned long high_memory; - -/* - * Conversion functions: convert a page and protection to a page entry, - * and a page entry and page directory to the page they refer to. - */ -extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot) -{ pte_t pte; pte_val(pte) = ((page-PAGE_OFFSET) << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; } - -extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } - -extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) -{ pmd_val(*pmdp) = _PAGE_TABLE | ((((unsigned long) ptep) - PAGE_OFFSET) << (32-PAGE_SHIFT)); } - -extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp) -{ pgd_val(*pgdp) = _PAGE_TABLE | ((((unsigned long) pmdp) - PAGE_OFFSET) << (32-PAGE_SHIFT)); } - -extern inline unsigned long pte_page(pte_t pte) -{ return PAGE_OFFSET + ((pte_val(pte) & _PFN_MASK) >> (32-PAGE_SHIFT)); } - -extern inline pte_t * pmd_page(pmd_t pmd) -{ return (pte_t *) (PAGE_OFFSET + ((pmd_val(pmd) & _PFN_MASK) >> (32-PAGE_SHIFT))); } - -extern inline pmd_t * pgd_page(pgd_t pgd) -{ return (pmd_t *) (PAGE_OFFSET + ((pgd_val(pgd) & _PFN_MASK) >> (32-PAGE_SHIFT))); } - -extern inline int pte_none(pte_t pte) { return !pte_val(pte); } -extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; } -extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } - -extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); } -extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~_PFN_MASK) != _PAGE_TABLE || (unsigned long) pmd_page(pmd) > high_memory; } -extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_VALID; } -extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = 0; } - -extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); } -extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~_PFN_MASK) != _PAGE_TABLE || (unsigned long) pgd_page(pgd) > high_memory; } -extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_VALID; } -extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; } - -/* - * The following only work if pte_present() is true. - * Undefined behaviour if not.. - */ -extern inline int pte_read(pte_t pte) { return !(pte_val(pte) & _PAGE_FOR); } -extern inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_FOW); } -extern inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_FOE); } -extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } -extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; } - -extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOW; return pte; } -extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOR; return pte; } -extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOE; return pte; } -extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(__DIRTY_BITS); return pte; } -extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~(__ACCESS_BITS); return pte; } -extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; } -extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= _PAGE_FOW; return pte; } -extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) &= _PAGE_FOR; return pte; } -extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) &= _PAGE_FOE; return pte; } -extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= __DIRTY_BITS; return pte; } -extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= __ACCESS_BITS; return pte; } -extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; } - -/* to set the page-dir */ -extern inline void SET_PAGE_DIR(struct task_struct * tsk, pgd_t * pgdir) -{ - tsk->tss.ptbr = ((unsigned long) pgdir - PAGE_OFFSET) >> PAGE_SHIFT; - if (tsk == current) - invalidate(); -} - -/* to find an entry in a page-table-directory */ -extern inline pgd_t * PAGE_DIR_OFFSET(struct task_struct * tsk, unsigned long address) -{ - return (pgd_t *) ((tsk->tss.ptbr << PAGE_SHIFT) + PAGE_OFFSET) + - ((address >> 33) & (PTRS_PER_PGD - 1)); -} - -/* to find an entry in the second-level page-table-directory */ -extern inline pmd_t * PAGE_MIDDLE_OFFSET(pgd_t * dir, unsigned long address) -{ - return pgd_page(*dir) + ((address >> 23) & (PTRS_PER_PMD - 1)); -} - -/* to find an entry in the third-level page-table-directory */ -extern inline pte_t * PAGE_ENTRY_OFFSET(pmd_t * dir, unsigned long address) -{ - return pmd_page(*dir) + ((address >> 13) & (PTRS_PER_PTE - 1)); -} - -extern inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address) -{ - unsigned long page; - - address = (address >> 13) & (PTRS_PER_PTE - 1); - if (pmd_none(*pmd)) { - pte_t *page = (pte_t *) get_free_page(GFP_KERNEL); - if (pmd_none(*pmd)) { - if (page) { - pmd_set(pmd, page); - return page + address; - } - pmd_set(pmd, BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long) page); - } - if (pmd_bad(*pmd)) { - printk("pte_alloc: bad pmd\n"); - pmd_set(pmd, BAD_PAGETABLE); - return NULL; - } - return pmd_page(*pmd) + address; -} - -extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address) -{ - unsigned long page; - - address = (address >> 23) & (PTRS_PER_PMD - 1); - if (pgd_none(*pgd)) { - pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL); - if (pgd_none(*pgd)) { - if (page) { - pgd_set(pgd, page); - return page + address; - } - pgd_set(pgd, BAD_PAGETABLE); - return NULL; - } - free_page((unsigned long) page); - } - if (pgd_bad(*pgd)) { - printk("pmd_alloc: bad pgd\n"); - pgd_set(pgd, BAD_PAGETABLE); - return NULL; - } - return pgd_page(*pgd) + address; -} +typedef unsigned int mem_map_t; #endif /* __KERNEL__ */ diff -u --recursive --new-file v1.1.87/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h --- v1.1.87/linux/include/asm-alpha/pgtable.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-alpha/pgtable.h Tue Jan 31 09:30:47 1995 @@ -0,0 +1,349 @@ +#ifndef _ALPHA_PGTABLE_H +#define _ALPHA_PGTABLE_H + +/* + * This file contains the functions and defines necessary to modify and use + * the alpha page table tree. + * + * This hopefully works with any standard alpha page-size, as defined + * in (currently 8192). + */ + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3)) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT (PAGE_SHIFT + 2*(PAGE_SHIFT-3)) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * entries per page directory level: the alpha is three-level, with + * all levels having a one-page page table. + */ +#define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) +#define PTRS_PER_PMD (1UL << (PAGE_SHIFT-3)) +#define PTRS_PER_PGD (1UL << (PAGE_SHIFT-3)) + +/* the no. of pointers that fit on a page: this will go away */ +#define PTRS_PER_PAGE (1UL << (PAGE_SHIFT-3)) + +#define VMALLOC_START 0xFFFFFE0000000000 +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) + +/* + * OSF/1 PAL-code-imposed page table bits + */ +#define _PAGE_VALID 0x0001 +#define _PAGE_FOR 0x0002 /* used for page protection (fault on read) */ +#define _PAGE_FOW 0x0004 /* used for page protection (fault on write) */ +#define _PAGE_FOE 0x0008 /* used for page protection (fault on exec) */ +#define _PAGE_ASM 0x0010 +#define _PAGE_KRE 0x0100 /* xxx - see below on the "accessed" bit */ +#define _PAGE_URE 0x0200 /* xxx */ +#define _PAGE_KWE 0x1000 /* used to do the dirty bit in software */ +#define _PAGE_UWE 0x2000 /* used to do the dirty bit in software */ + +/* .. and these are ours ... */ +#define _PAGE_COW 0x10000 +#define _PAGE_DIRTY 0x20000 +#define _PAGE_ACCESSED 0x40000 + +/* + * NOTE! The "accessed" bit isn't necessarily exact: it can be kept exactly + * by software (use the KRE/URE/KWE/UWE bits appropritely), but I'll fake it. + * Under Linux/AXP, the "accessed" bit just means "read", and I'll just use + * the KRE/URE bits to watch for it. That way we don't need to overload the + * KWE/UWE bits with both handling dirty and accessed. + * + * Note that the kernel uses the accessed bit just to check whether to page + * out a page or not, so it doesn't have to be exact anyway. + */ + +#define __DIRTY_BITS (_PAGE_DIRTY | _PAGE_KWE | _PAGE_UWE) +#define __ACCESS_BITS (_PAGE_ACCESSED | _PAGE_KRE | _PAGE_URE) + +#define _PFN_MASK 0xFFFFFFFF00000000 + +#define _PAGE_TABLE (_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS) +#define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS) + +/* + * All the normal masks have the "page accessed" bits on, as any time they are used, + * the page is accessed. They are cleared only by the page-out routines + */ +#define PAGE_NONE __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE) +#define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS) +#define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_COW) +#define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) +#define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE) + +#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x)) + +#define __P000 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE) +#define __P001 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOW | _PAGE_FOE) +#define __P010 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR | _PAGE_FOE) +#define __P011 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOE) +#define __P100 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR | _PAGE_FOW) +#define __P101 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOW) +#define __P110 _PAGE_NORMAL(_PAGE_COW | _PAGE_FOR) +#define __P111 _PAGE_NORMAL(_PAGE_COW) + +#define __S000 _PAGE_NORMAL(_PAGE_FOR | _PAGE_FOW | _PAGE_FOE) +#define __S001 _PAGE_NORMAL(_PAGE_FOW | _PAGE_FOE) +#define __S010 _PAGE_NORMAL(_PAGE_FOR | _PAGE_FOE) +#define __S011 _PAGE_NORMAL(_PAGE_FOE) +#define __S100 _PAGE_NORMAL(_PAGE_FOR | _PAGE_FOW) +#define __S101 _PAGE_NORMAL(_PAGE_FOW) +#define __S110 _PAGE_NORMAL(_PAGE_FOR) +#define __S111 _PAGE_NORMAL(0) + +/* + * BAD_PAGETABLE is used when we need a bogus page-table, while + * BAD_PAGE is used for a bogus page. + * + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern pte_t __bad_page(void); +extern pmd_t * __bad_pagetable(void); + +extern unsigned long __zero_page(void); + +#define BAD_PAGETABLE __bad_pagetable() +#define BAD_PAGE __bad_page() +#define ZERO_PAGE __zero_page() + +/* number of bits that fit into a memory pointer */ +#define BITS_PER_PTR (8*sizeof(unsigned long)) + +/* to align the pointer to a pointer address */ +#define PTR_MASK (~(sizeof(void*)-1)) + +/* sizeof(void*)==1<>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) + +extern unsigned long high_memory; + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot) +{ pte_t pte; pte_val(pte) = ((page-PAGE_OFFSET) << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; } + +extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } + +extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep) +{ pmd_val(*pmdp) = _PAGE_TABLE | ((((unsigned long) ptep) - PAGE_OFFSET) << (32-PAGE_SHIFT)); } + +extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp) +{ pgd_val(*pgdp) = _PAGE_TABLE | ((((unsigned long) pmdp) - PAGE_OFFSET) << (32-PAGE_SHIFT)); } + +extern inline unsigned long pte_page(pte_t pte) +{ return PAGE_OFFSET + ((pte_val(pte) & _PFN_MASK) >> (32-PAGE_SHIFT)); } + +extern inline unsigned long pmd_page(pmd_t pmd) +{ return PAGE_OFFSET + ((pmd_val(pmd) & _PFN_MASK) >> (32-PAGE_SHIFT)); } + +extern inline unsigned long pgd_page(pgd_t pgd) +{ return PAGE_OFFSET + ((pgd_val(pgd) & _PFN_MASK) >> (32-PAGE_SHIFT)); } + +extern inline int pte_none(pte_t pte) { return !pte_val(pte); } +extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; } +extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } + +extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); } +extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~_PFN_MASK) != _PAGE_TABLE || pmd_page(pmd) > high_memory; } +extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_VALID; } +extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = 0; } + +extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); } +extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~_PFN_MASK) != _PAGE_TABLE || pgd_page(pgd) > high_memory; } +extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_VALID; } +extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; } + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +extern inline int pte_read(pte_t pte) { return !(pte_val(pte) & _PAGE_FOR); } +extern inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_FOW); } +extern inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_FOE); } +extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } +extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } +extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; } + +extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOW; return pte; } +extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOR; return pte; } +extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) |= _PAGE_FOE; return pte; } +extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~(__DIRTY_BITS); return pte; } +extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~(__ACCESS_BITS); return pte; } +extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; } +extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= _PAGE_FOW; return pte; } +extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) &= _PAGE_FOR; return pte; } +extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) &= _PAGE_FOE; return pte; } +extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= __DIRTY_BITS; return pte; } +extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= __ACCESS_BITS; return pte; } +extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; } + +/* to set the page-dir */ +extern inline void SET_PAGE_DIR(struct task_struct * tsk, pgd_t * pgdir) +{ + tsk->tss.ptbr = ((unsigned long) pgdir - PAGE_OFFSET) >> PAGE_SHIFT; + if (tsk == current) + invalidate(); +} + +#define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address)) + +/* to find an entry in a page-table-directory */ +extern inline pgd_t * pgd_offset(struct task_struct * tsk, unsigned long address) +{ + return (pgd_t *) ((tsk->tss.ptbr << PAGE_SHIFT) + PAGE_OFFSET) + + ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)); +} + +/* Find an entry in the second-level page table.. */ +extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) +{ + return (pmd_t *) pgd_page(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PMD - 1)); +} + +/* Find an entry in the third-level page table.. */ +extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address) +{ + return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); +} + +/* + * Allocate and free page tables. The xxx_kernel() versions are + * used to allocate a kernel page table - this turns on ASN bits + * if any, and marks the page tables reserved. + */ +extern inline void pte_free_kernel(pte_t * pte) +{ + mem_map[MAP_NR(pte)] = 1; + free_page((unsigned long) pte); +} + +extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + if (pmd_none(*pmd)) { + pte_t *page = (pte_t *) get_free_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (page) { + pmd_set(pmd, page); + mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED; + return page + address; + } + pmd_set(pmd, (pte_t *) BAD_PAGETABLE); + return NULL; + } + free_page((unsigned long) page); + } + if (pmd_bad(*pmd)) { + printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + pmd_set(pmd, (pte_t *) BAD_PAGETABLE); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + address; +} + +extern inline void pmd_free_kernel(pmd_t * pmd) +{ + mem_map[MAP_NR(pmd)] = 1; + free_page((unsigned long) pmd); +} + +extern inline pmd_t * pmd_alloc_kernel(pgd_t *pgd, unsigned long address) +{ + address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); + if (pgd_none(*pgd)) { + pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL); + if (pgd_none(*pgd)) { + if (page) { + pgd_set(pgd, page); + mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED; + return page + address; + } + pgd_set(pgd, BAD_PAGETABLE); + return NULL; + } + free_page((unsigned long) page); + } + if (pgd_bad(*pgd)) { + printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); + pgd_set(pgd, BAD_PAGETABLE); + return NULL; + } + return (pmd_t *) pgd_page(*pgd) + address; +} + +extern inline void pte_free(pte_t * pte) +{ + free_page((unsigned long) pte); +} + +extern inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + if (pmd_none(*pmd)) { + pte_t *page = (pte_t *) get_free_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (page) { + pmd_set(pmd, page); + return page + address; + } + pmd_set(pmd, (pte_t *) BAD_PAGETABLE); + return NULL; + } + free_page((unsigned long) page); + } + if (pmd_bad(*pmd)) { + printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + pmd_set(pmd, (pte_t *) BAD_PAGETABLE); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + address; +} + +extern inline void pmd_free(pmd_t * pmd) +{ + free_page((unsigned long) pmd); +} + +extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address) +{ + address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1); + if (pgd_none(*pgd)) { + pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL); + if (pgd_none(*pgd)) { + if (page) { + pgd_set(pgd, page); + return page + address; + } + pgd_set(pgd, BAD_PAGETABLE); + return NULL; + } + free_page((unsigned long) page); + } + if (pgd_bad(*pgd)) { + printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); + pgd_set(pgd, BAD_PAGETABLE); + return NULL; + } + return (pmd_t *) pgd_page(*pgd) + address; +} + +extern pgd_t swapper_pg_dir[1024]; + +#endif /* _ALPHA_PGTABLE_H */ diff -u --recursive --new-file v1.1.87/linux/include/asm-i386/page.h linux/include/asm-i386/page.h --- v1.1.87/linux/include/asm-i386/page.h Thu Jan 26 07:49:15 1995 +++ linux/include/asm-i386/page.h Mon Jan 30 13:08:04 1995 @@ -1,49 +1,31 @@ #ifndef _I386_PAGE_H #define _I386_PAGE_H -#define CONFIG_STRICT_MM_TYPECHECKS - -#define invalidate() \ -__asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax") - /* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 12 -#define PGDIR_SHIFT 22 -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) #ifdef __KERNEL__ -#define PAGE_OFFSET 0 -#define MAP_NR(addr) ((addr) >> PAGE_SHIFT) -#define MAP_PAGE_RESERVED (1<<15) - -typedef unsigned short mem_map_t; - -/* Just any arbitrary offset to the start of the vmalloc VM area: the - * current 8MB value just means that there will be a 8MB "hole" after the - * physical memory until the kernel virtual memory starts. That means that - * any out-of-bounds memory accesses will hopefully be caught. - * The vmalloc() routines leaves a hole of 4kB between each vmalloced - * area for the same reason. ;) - */ -#define VMALLOC_OFFSET (8*1024*1024) -#define VMALLOC_START ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) -#define VMALLOC_VMADDR(x) (TASK_SIZE + (unsigned long)(x)) +#define CONFIG_STRICT_MM_TYPECHECKS #ifdef CONFIG_STRICT_MM_TYPECHECKS /* * These are used to make use of C type-checking.. */ typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long pmd; } pmd_t; typedef struct { unsigned long pgd; } pgd_t; typedef struct { unsigned long pgprot; } pgprot_t; #define pte_val(x) ((x).pte) +#define pmd_val(x) ((x).pmd) #define pgd_val(x) ((x).pgd) #define pgprot_val(x) ((x).pgprot) #define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } ) @@ -52,171 +34,34 @@ * .. while these make it easier on the compiler */ typedef unsigned long pte_t; +typedef unsigned long pmd_t; typedef unsigned long pgd_t; typedef unsigned long pgprot_t; #define pte_val(x) (x) +#define pmd_val(x) (x) #define pgd_val(x) (x) #define pgprot_val(x) (x) #define __pte(x) (x) +#define __pmd(x) (x) #define __pgd(x) (x) #define __pgprot(x) (x) #endif -#define _PAGE_PRESENT 0x001 -#define _PAGE_RW 0x002 -#define _PAGE_USER 0x004 -#define _PAGE_ACCESSED 0x020 -#define _PAGE_DIRTY 0x040 -#define _PAGE_COW 0x200 /* implemented in software (one of the AVL bits) */ - -#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) - -#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) -#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) - -/* - * The i386 can't do page protection for execute, and considers that the same are read. - * Also, write permissions imply read permissions. This is the closest we can get.. - */ -#define __P000 PAGE_NONE -#define __P001 PAGE_READONLY -#define __P010 PAGE_COPY -#define __P011 PAGE_COPY -#define __P100 PAGE_READONLY -#define __P101 PAGE_READONLY -#define __P110 PAGE_COPY -#define __P111 PAGE_COPY - -#define __S000 PAGE_NONE -#define __S001 PAGE_READONLY -#define __S010 PAGE_SHARED -#define __S011 PAGE_SHARED -#define __S100 PAGE_READONLY -#define __S101 PAGE_READONLY -#define __S110 PAGE_SHARED -#define __S111 PAGE_SHARED - -/* - * 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 - -/* page table for 0-4MB for everybody */ -extern unsigned long pg0[1024]; - -/* - * BAD_PAGETABLE is used when we need a bogus page-table, while - * BAD_PAGE is used for a bogus page. - * - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -extern pte_t __bad_page(void); -extern pte_t * __bad_pagetable(void); - -extern unsigned long __zero_page(void); - -#define BAD_PAGETABLE __bad_pagetable() -#define BAD_PAGE __bad_page() -#define ZERO_PAGE __zero_page() - -/* number of bits that fit into a memory pointer */ -#define BITS_PER_PTR (8*sizeof(unsigned long)) - -/* to mask away the intra-page address bits */ -#define PAGE_MASK (~(PAGE_SIZE-1)) - -/* to mask away the intra-page address bits */ -#define PGDIR_MASK (~(PGDIR_SIZE-1)) +#define invalidate() \ +__asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax") /* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) - -/* to align the pointer to a pointer address */ -#define PTR_MASK (~(sizeof(void*)-1)) +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) -/* sizeof(void*)==1<> 22) + (pgd_t *) (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 */ -#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) - -extern unsigned long high_memory; - -extern inline int pte_none(pte_t pte) { return !pte_val(pte); } -extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } -extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } - -extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); } -extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; } -extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_PRESENT; } -extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; } +/* This handles the memory map.. */ +#define PAGE_OFFSET 0 +#define MAP_NR(addr) (((unsigned long)(addr)) >> PAGE_SHIFT) +#define MAP_PAGE_RESERVED (1<<15) -/* - * The following only work if pte_present() is true. - * Undefined behaviour if not.. - */ -extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } -extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } -extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } -extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } -extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; } - -extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; } -extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } -extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } -extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } -extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } -extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; } -extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; } -extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } -extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } -extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } -extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } -extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; } - -/* - * Conversion functions: convert a page and protection to a page entry, - * and a page entry and page directory to the page they refer to. - */ -extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot) -{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; } - -extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } - -extern inline unsigned long pte_page(pte_t pte) { return pte_val(pte) & PAGE_MASK; } -extern inline unsigned long pgd_page(pgd_t pgd) { return pgd_val(pgd) & PAGE_MASK; } - -extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep) -{ pgd_val(*pgdp) = _PAGE_TABLE | (unsigned long) ptep; } +typedef unsigned short mem_map_t; #endif /* __KERNEL__ */ diff -u --recursive --new-file v1.1.87/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h --- v1.1.87/linux/include/asm-i386/pgtable.h Thu Jan 1 02:00:00 1970 +++ linux/include/asm-i386/pgtable.h Tue Jan 31 09:30:48 1995 @@ -0,0 +1,305 @@ +#ifndef _I386_PGTABLE_H +#define _I386_PGTABLE_H + +/* + * The Linux memory management assumes a three-level page table setup. On + * the i386, we use that, but "fold" the mid level into the top-level page + * table, so that we physically have the same two-level page table as the + * i386 mmu expects. + * + * This file contains the functions and defines necessary to modify and use + * the i386 page table tree. + */ + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define PMD_SHIFT 22 +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT 22 +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * entries per page directory level: the i386 is two-level, so + * we don't really have any PMD directory physically. + */ +#define PTRS_PER_PTE 1024 +#define PTRS_PER_PMD 1 +#define PTRS_PER_PGD 1024 + +/* the no. of pointers that fit on a page: this will go away */ +#define PTRS_PER_PAGE (PAGE_SIZE/sizeof(void*)) + +/* Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ +#define VMALLOC_OFFSET (8*1024*1024) +#define VMALLOC_START ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) +#define VMALLOC_VMADDR(x) (TASK_SIZE + (unsigned long)(x)) + +#define _PAGE_PRESENT 0x001 +#define _PAGE_RW 0x002 +#define _PAGE_USER 0x004 +#define _PAGE_ACCESSED 0x020 +#define _PAGE_DIRTY 0x040 +#define _PAGE_COW 0x200 /* implemented in software (one of the AVL bits) */ + +#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) + +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_COW) +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) + +/* + * The i386 can't do page protection for execute, and considers that the same are read. + * Also, write permissions imply read permissions. This is the closest we can get.. + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY +#define __P101 PAGE_READONLY +#define __P110 PAGE_COPY +#define __P111 PAGE_COPY + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY +#define __S101 PAGE_READONLY +#define __S110 PAGE_SHARED +#define __S111 PAGE_SHARED + +/* + * 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 + +/* page table for 0-4MB for everybody */ +extern unsigned long pg0[1024]; + +/* + * BAD_PAGETABLE is used when we need a bogus page-table, while + * BAD_PAGE is used for a bogus page. + * + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern pte_t __bad_page(void); +extern pte_t * __bad_pagetable(void); + +extern unsigned long __zero_page(void); + +#define BAD_PAGETABLE __bad_pagetable() +#define BAD_PAGE __bad_page() +#define ZERO_PAGE __zero_page() + +/* number of bits that fit into a memory pointer */ +#define BITS_PER_PTR (8*sizeof(unsigned long)) + +/* to align the pointer to a pointer address */ +#define PTR_MASK (~(sizeof(void*)-1)) + +/* sizeof(void*)==1<>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) + +/* 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) + +extern unsigned long high_memory; + +extern inline int pte_none(pte_t pte) { return !pte_val(pte); } +extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } +extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } + +extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); } +extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE || pmd_val(pmd) > high_memory; } +extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_PRESENT; } +extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = 0; } + +extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); } +extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~PAGE_MASK) != _PAGE_TABLE || pgd_val(pgd) > high_memory; } +extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_PRESENT; } +extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; } + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } +extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } +extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } +extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } +extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } +extern inline int pte_cow(pte_t pte) { return pte_val(pte) & _PAGE_COW; } + +extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; } +extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } +extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } +extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } +extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } +extern inline pte_t pte_uncow(pte_t pte) { pte_val(pte) &= ~_PAGE_COW; return pte; } +extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; } +extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } +extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } +extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } +extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } +extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; } + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot) +{ pte_t pte; pte_val(pte) = page | pgprot_val(pgprot); return pte; } + +extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } + +extern inline unsigned long pte_page(pte_t pte) +{ return pte_val(pte) & PAGE_MASK; } + +extern inline unsigned long pmd_page(pmd_t pmd) +{ return pmd_val(pmd) & PAGE_MASK; } + +extern inline unsigned long pgd_page(pgd_t pgd) +{ return pgd_val(pgd) & PAGE_MASK; } + +extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep) +{ pgd_val(*pgdp) = _PAGE_TABLE | (unsigned long) ptep; } + +#define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address)) + +/* to find an entry in a page-table-directory */ +extern inline pgd_t * pgd_offset(struct task_struct * tsk, unsigned long address) +{ + return (pgd_t *) tsk->tss.cr3 + (address >> PGDIR_SHIFT); +} + +/* Find an entry in the second-level page table.. */ +extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) +{ + return (pmd_t *) dir; +} + +/* Find an entry in the third-level page table.. */ +extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address) +{ + return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); +} + +/* + * Allocate and free page tables. The xxx_kernel() versions are + * used to allocate a kernel page table - this turns on ASN bits + * if any, and marks the page tables reserved. + */ +extern inline void pte_free_kernel(pte_t * pte) +{ + mem_map[MAP_NR(pte)] = 1; + free_page((unsigned long) pte); +} + +extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + if (pmd_none(*pmd)) { + pte_t * page = (pte_t *) get_free_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (page) { + pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) page; + mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED; + return page + address; + } + pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE; + return NULL; + } + free_page((unsigned long) page); + } + if (pmd_bad(*pmd)) { + printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE; + return NULL; + } + return (pte_t *) pmd_page(*pmd) + address; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +extern inline void pmd_free_kernel(pmd_t * pmd) +{ +} + +extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address) +{ + return (pmd_t *) pgd; +} + +extern inline void pte_free(pte_t * pte) +{ + free_page((unsigned long) pte); +} + +extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + if (pmd_none(*pmd)) { + pte_t * page = (pte_t *) get_free_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (page) { + pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) page; + return page + address; + } + pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE; + return NULL; + } + free_page((unsigned long) page); + } + if (pmd_bad(*pmd)) { + printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE; + return NULL; + } + return (pte_t *) pmd_page(*pmd) + address; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +extern inline void pmd_free(pmd_t * pmd) +{ +} + +extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address) +{ + return (pmd_t *) pgd; +} + +extern pgd_t swapper_pg_dir[1024]; + +#endif /* _I386_PAGE_H */ diff -u --recursive --new-file v1.1.87/linux/include/asm-mips/page.h linux/include/asm-mips/page.h --- v1.1.87/linux/include/asm-mips/page.h Mon Jan 30 06:41:58 1995 +++ linux/include/asm-mips/page.h Tue Jan 31 09:36:21 1995 @@ -50,7 +50,7 @@ /* * Note that we shift the lower 32bits of each EntryLo[01] entry * 6 bits to the left. That way we can convert the PFN into the - * physical address by a single 'and' operation and gain 6 aditional + * physical address by a single 'and' operation and gain 6 additional * bits for storing information which isn't present in a normal * MIPS page table. */ diff -u --recursive --new-file v1.1.87/linux/include/asm-sparc/cprefix.h linux/include/asm-sparc/cprefix.h --- v1.1.87/linux/include/asm-sparc/cprefix.h Thu Jan 26 07:49:15 1995 +++ linux/include/asm-sparc/cprefix.h Tue Jan 31 09:39:00 1995 @@ -1,7 +1,7 @@ /* cprefix.h: This file is included by assembly source which needs * to know what the c-label prefixes are. The newer versions * of cpp that come with gcc predefine such things to help - * us out. The reason this stuff is neaded is to make + * us out. The reason this stuff is needed is to make * solaris compiles of the kernel work. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v1.1.87/linux/include/linux/aztcd.h linux/include/linux/aztcd.h --- v1.1.87/linux/include/linux/aztcd.h Sun Jan 22 23:03:59 1995 +++ linux/include/linux/aztcd.h Tue Jan 31 09:36:21 1995 @@ -19,7 +19,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History: W.Zimmermann adaption to Aztech CD268-01A Version 1.3 - * Oktober 1994 Email: zimmerma@rz.fht-esslingen.de + * October 1994 Email: zimmerma@rz.fht-esslingen.de */ /* *** change this to set the I/O port address */ diff -u --recursive --new-file v1.1.87/linux/include/linux/ipx.h linux/include/linux/ipx.h --- v1.1.87/linux/include/linux/ipx.h Mon Jan 30 06:41:58 1995 +++ linux/include/linux/ipx.h Tue Jan 31 09:36:21 1995 @@ -7,9 +7,9 @@ struct sockaddr_ipx { short sipx_family; + short sipx_port; unsigned long sipx_network; unsigned char sipx_node[IPX_NODE_LEN]; - short sipx_port; unsigned char sipx_type; unsigned char sipx_zero; /* 16 byte fill */ }; @@ -18,8 +18,10 @@ * So we can fit the extra info for SIOCSIFADDR into the address nicely */ -#define sipx_primary sipx_port -#define sipx_internal sipx_zero +#define sipx_special sipx_port +#define sipx_action sipx_zero +#define IPX_DLTITF 0 +#define IPX_CRTITF 1 typedef struct ipx_route_definition { @@ -32,14 +34,16 @@ { unsigned long ipx_network; unsigned char ipx_device[16]; - unsigned short ipx_dlink_type; + unsigned char ipx_dlink_type; #define IPX_FRAME_NONE 0 #define IPX_FRAME_SNAP 1 #define IPX_FRAME_8022 2 #define IPX_FRAME_ETHERII 3 #define IPX_FRAME_8023 4 - unsigned char ipx_primary; - unsigned char ipx_internal; + unsigned char ipx_special; +#define IPX_SPECIAL_NONE 0 +#define IPX_PRIMARY 1 +#define IPX_INTERNAL 2 unsigned char ipx_node[IPX_NODE_LEN]; } ipx_interface_definition; @@ -50,7 +54,7 @@ } ipx_config_data; /* - * OLD Route Definition for backware compatibility. + * OLD Route Definition for backward compatibility. */ struct ipx_route_def diff -u --recursive --new-file v1.1.87/linux/include/linux/mc146818rtc.h linux/include/linux/mc146818rtc.h --- v1.1.87/linux/include/linux/mc146818rtc.h Wed Dec 1 14:44:15 1993 +++ linux/include/linux/mc146818rtc.h Tue Jan 31 09:30:48 1995 @@ -12,13 +12,31 @@ #define _MC146818RTC_H #include +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ADDR(x) (0x80 | (x)) +#define RTC_ALWAYS_BCD 1 + +/* + * The Alpha Jensen hardware for some rather strange reason puts + * the RTC clock at 0x170 instead of 0x70. Probably due to some + * misguided idea about using 0x70 for NMI stuff. + */ +#ifdef __alpha__ +#undef RTC_PORT +#undef RTC_ADDR +#undef RTC_ALWAYS_BCD +#define RTC_PORT(x) (0x170+(x)) +#define RTC_ADDR(x) (x) +#define RTC_ALWAYS_BCD 0 +#endif + #define CMOS_READ(addr) ({ \ -outb_p(addr|0x80,0x70); \ -inb_p(0x71); \ +outb_p(RTC_ADDR(addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ }) #define CMOS_WRITE(val, addr) ({ \ -outb_p(addr|0x80,0x70); \ -outb_p(val,0x71); \ +outb_p(RTC_ADDR(addr),RTC_PORT(0)); \ +outb_p(val,RTC_PORT(1)); \ }) /********************************************************************** diff -u --recursive --new-file v1.1.87/linux/include/linux/mm.h linux/include/linux/mm.h --- v1.1.87/linux/include/linux/mm.h Thu Jan 26 07:49:15 1995 +++ linux/include/linux/mm.h Mon Jan 30 13:08:04 1995 @@ -13,8 +13,6 @@ #define VERIFY_READ 0 #define VERIFY_WRITE 1 -extern pgd_t swapper_pg_dir[1024]; - extern int verify_area(int, const void *, unsigned long); /* diff -u --recursive --new-file v1.1.87/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v1.1.87/linux/include/linux/proc_fs.h Mon Jan 30 06:41:58 1995 +++ linux/include/linux/proc_fs.h Tue Jan 31 14:36:24 1995 @@ -74,6 +74,9 @@ #ifdef CONFIG_IP_ACCT PROC_NET_IPACCT, #endif +#if defined(CONFIG_WAVELAN) + PROC_NET_WAVELAN, +#endif /* defined(CONFIG_WAVELAN) */ #endif #ifdef CONFIG_IPX PROC_NET_IPX_INTERFACE, diff -u --recursive --new-file v1.1.87/linux/include/linux/serial.h linux/include/linux/serial.h --- v1.1.87/linux/include/linux/serial.h Mon Dec 19 16:35:51 1994 +++ linux/include/linux/serial.h Tue Jan 31 09:39:02 1995 @@ -22,10 +22,19 @@ unsigned short close_delay; char reserved_char[2]; int hub6; - int reserved[5]; + unsigned short closing_wait; /* time to wait before rcvr shutdown */ + unsigned short closing_wait2; /* time to wait after rcvr shutdown */ + int reserved[4]; }; /* + * For the close wait times, 0 means wait forever for serial port to + * flush its output. 65535 means don't wait at all. + */ +#define ASYNC_CLOSING_WAIT_INF 0 +#define ASYNC_CLOSING_WAIT_NONE 65535 + +/* * These are the supported serial types. */ #define PORT_UNKNOWN 0 @@ -33,8 +42,9 @@ #define PORT_16450 2 #define PORT_16550 3 #define PORT_16550A 4 -#define PORT_CIRRUS 5 -#define PORT_MAX 5 +#define PORT_CIRRUS 5 /* Hey! Who put this there? */ +#define PORT_16650 6 +#define PORT_MAX 6 /* * Definitions for async_struct (and serial_struct) flags field @@ -96,6 +106,8 @@ int custom_divisor; int x_char; /* xon/xoff character */ int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ int MCR_noint; /* MCR with interrupts off */ diff -u --recursive --new-file v1.1.87/linux/include/linux/serial_reg.h linux/include/linux/serial_reg.h --- v1.1.87/linux/include/linux/serial_reg.h Wed Aug 10 19:26:44 1994 +++ linux/include/linux/serial_reg.h Tue Jan 31 09:39:02 1995 @@ -21,6 +21,8 @@ #define UART_IER 1 /* Out: Interrupt Enable Register */ #define UART_IIR 2 /* In: Interrupt ID Register */ #define UART_FCR 2 /* Out: FIFO Control Register */ +#define UART_EFR 2 /* I/O: Extended Features Register */ + /* (DLAB=1, 16C660 only) */ #define UART_LCR 3 /* Out: Line Control Register */ #define UART_MCR 4 /* Out: Modem Control Register */ #define UART_LSR 5 /* In: Line Status Register */ @@ -29,6 +31,7 @@ /* * These are the definitions for the FIFO Control Register + * (16650 only) */ #define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ @@ -39,6 +42,15 @@ #define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ #define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ #define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ +/* 16650 redefinitions */ +#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */ +#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */ +#define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */ +#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */ +#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */ +#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */ +#define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */ +#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */ /* * These are the definitions for the Line Control Register @@ -108,6 +120,18 @@ #define UART_MSR_DDSR 0x02 /* Delta DSR */ #define UART_MSR_DCTS 0x01 /* Delta CTS */ #define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ + +/* + * These are the definitions for the Extended Features Register + * (StarTech 16C660 only, when DLAB=1) + */ +#define UART_EFR_CTS 0x80 /* CTS flow control */ +#define UART_EFR_RTS 0x40 /* RTS flow control */ +#define UART_EFR_SCD 0x20 /* Special character detect */ +#define UART_EFR_ENI 0x10 /* Enhanced Interrupt */ +/* + * the low four bits control software flow control + */ #endif /* _LINUX_SERIAL_REG_H */ diff -u --recursive --new-file v1.1.87/linux/ipc/shm.c linux/ipc/shm.c --- v1.1.87/linux/ipc/shm.c Mon Jan 30 06:41:59 1995 +++ linux/ipc/shm.c Mon Jan 30 13:08:04 1995 @@ -6,13 +6,15 @@ */ #include -#include #include #include #include #include #include #include + +#include +#include extern int ipcperms (struct ipc_perm *ipcp, short shmflg); extern unsigned int get_swap_page (void); diff -u --recursive --new-file v1.1.87/linux/kernel/module.c linux/kernel/module.c --- v1.1.87/linux/kernel/module.c Thu Jan 26 07:49:16 1995 +++ linux/kernel/module.c Tue Jan 31 09:36:21 1995 @@ -32,7 +32,7 @@ * and ALSO from loadable modules. * The goal is to assist in modularizing the kernel even more, * and finally: reducing the number of entries in ksyms.c - * since every subsystem should now be able to decide amd + * since every subsystem should now be able to decide and * control exactly what symbols it wants to export, locally! */ diff -u --recursive --new-file v1.1.87/linux/kernel/sched.c linux/kernel/sched.c --- v1.1.87/linux/kernel/sched.c Thu Jan 26 07:49:16 1995 +++ linux/kernel/sched.c Mon Jan 30 13:08:05 1995 @@ -30,6 +30,7 @@ #include #include #include +#include #define TIMER_IRQ 0 diff -u --recursive --new-file v1.1.87/linux/kernel/time.c linux/kernel/time.c --- v1.1.87/linux/kernel/time.c Thu Jan 26 07:49:16 1995 +++ linux/kernel/time.c Tue Jan 31 09:30:48 1995 @@ -29,8 +29,6 @@ #include #include -#define RTC_ALWAYS_BCD 1 - #include /* converts date to days since 1/1/1970 diff -u --recursive --new-file v1.1.87/linux/mm/filemap.c linux/mm/filemap.c --- v1.1.87/linux/mm/filemap.c Sun Jan 22 23:04:00 1995 +++ linux/mm/filemap.c Mon Jan 30 13:08:05 1995 @@ -21,6 +21,7 @@ #include #include +#include /* * Shared mappings implemented 30.11.1994. It's not fully working yet, diff -u --recursive --new-file v1.1.87/linux/mm/memory.c linux/mm/memory.c --- v1.1.87/linux/mm/memory.c Thu Jan 26 07:49:16 1995 +++ linux/mm/memory.c Mon Jan 30 13:08:05 1995 @@ -47,6 +47,7 @@ #include #include +#include unsigned long high_memory = 0; diff -u --recursive --new-file v1.1.87/linux/mm/mmap.c linux/mm/mmap.c --- v1.1.87/linux/mm/mmap.c Thu Jan 26 07:49:16 1995 +++ linux/mm/mmap.c Mon Jan 30 13:08:05 1995 @@ -15,6 +15,7 @@ #include #include +#include static int anon_map(struct inode *, struct file *, struct vm_area_struct *); diff -u --recursive --new-file v1.1.87/linux/mm/mprotect.c linux/mm/mprotect.c --- v1.1.87/linux/mm/mprotect.c Thu Jan 26 07:49:16 1995 +++ linux/mm/mprotect.c Mon Jan 30 13:08:05 1995 @@ -15,6 +15,7 @@ #include #include +#include static void change_protection(unsigned long start, unsigned long end, pgprot_t newprot) { diff -u --recursive --new-file v1.1.87/linux/mm/swap.c linux/mm/swap.c --- v1.1.87/linux/mm/swap.c Mon Jan 30 06:41:59 1995 +++ linux/mm/swap.c Mon Jan 30 13:08:05 1995 @@ -22,6 +22,7 @@ #include #include /* for cli()/sti() */ #include +#include #define MAX_SWAPFILES 8 diff -u --recursive --new-file v1.1.87/linux/mm/vmalloc.c linux/mm/vmalloc.c --- v1.1.87/linux/mm/vmalloc.c Thu Jan 26 07:49:16 1995 +++ linux/mm/vmalloc.c Tue Jan 31 09:30:48 1995 @@ -16,6 +16,7 @@ #include #include +#include struct vm_struct { unsigned long flags; @@ -26,122 +27,143 @@ static struct vm_struct * vmlist = NULL; -static inline void set_pgdir(unsigned long dindex, pte_t * page_table) +static inline void set_pgdir(unsigned long address, pgd_t entry) { struct task_struct * p; - p = &init_task; - do { - pgd_set(PAGE_DIR_OFFSET(p,0) + dindex, page_table); - p = p->next_task; - } while (p != &init_task); + for_each_task(p) + *PAGE_DIR_OFFSET(p,address) = entry; } -static inline void clear_pgdir(unsigned long dindex) +static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned long size) { - struct task_struct * p; + pte_t * pte; + unsigned long end; - p = &init_task; - do { - pgd_clear(PAGE_DIR_OFFSET(p,0) + dindex); - p = p->next_task; - } while (p != &init_task); + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + printk("free_area_pte: bad pmd (%08lx)\n", pmd_val(*pmd)); + pmd_clear(pmd); + return; + } + pte = pte_offset(pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + while (address < end) { + pte_t page = *pte; + pte_clear(pte); + address += PAGE_SIZE; + pte++; + if (pte_none(page)) + continue; + if (pte_present(page)) { + free_page(pte_page(page)); + continue; + } + printk("Whee.. Swapped out page in kernel page table\n"); + } } -static int free_area_pages(unsigned long dindex, unsigned long index, unsigned long nr) +static inline void free_area_pmd(pgd_t * dir, unsigned long address, unsigned long size) { - pgd_t * dir; - pte_t * page_table; - unsigned long page; + pmd_t * pmd; + unsigned long end; - dir = swapper_pg_dir + dindex; if (pgd_none(*dir)) - return 0; + return; if (pgd_bad(*dir)) { - printk("bad page directory entry in free_area_pages: %08lx\n", pgd_val(*dir)); + printk("free_area_pmd: bad pgd (%08lx)\n", pgd_val(*dir)); pgd_clear(dir); - return 0; + return; + } + pmd = pmd_offset(dir, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + while (address < end) { + free_area_pte(pmd, address, end - address); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } +} + +static void free_area_pages(unsigned long address, unsigned long size) +{ + pgd_t * dir; + unsigned long end = address + size; + + dir = pgd_offset(&init_task, address); + while (address < end) { + free_area_pmd(dir, address, end - address); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; } - page = pgd_page(*dir); - page_table = index + (pte_t *) page; - do { - pte_t pte = *page_table; - pte_clear(page_table); - if (pte_present(pte)) - free_page(pte_page(pte)); - page_table++; - } while (--nr); - page_table = (pte_t *) page; - for (nr = 0 ; nr < PTRS_PER_PAGE ; nr++, page_table++) - if (!pte_none(*page_table)) - return 0; - clear_pgdir(dindex); - mem_map[MAP_NR(page)] = 1; - free_page(page); invalidate(); - return 0; } -static int alloc_area_pages(unsigned long dindex, unsigned long index, unsigned long nr) +static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned long size) { - pgd_t *dir; - pte_t *page_table; + unsigned long end; - dir = swapper_pg_dir + dindex; - if (pgd_none(*dir)) { - unsigned long page = get_free_page(GFP_KERNEL); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + while (address < end) { + unsigned long page; + if (!pte_none(*pte)) + printk("alloc_area_pte: page already exists\n"); + page = __get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; - if (!pgd_none(*dir)) { - free_page(page); - } else { - mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED; - set_pgdir(dindex, (pte_t *) page); - } - } - if (pgd_bad(*dir)) { - printk("Bad page dir entry in alloc_area_pages (%08lx)\n", pgd_val(*dir)); - return -ENOMEM; + *pte = mk_pte(page, PAGE_KERNEL); + address += PAGE_SIZE; + pte++; } - page_table = index + (pte_t *) pgd_page(*dir); - /* - * use a tempotary page-table entry to remove a race with - * vfree(): it mustn't free the page table from under us - * if we sleep in get_free_page() - */ - *page_table = BAD_PAGE; - do { - unsigned long pg = get_free_page(GFP_KERNEL); + return 0; +} + +static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size) +{ + unsigned long end; - if (!pg) + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + while (address < end) { + pte_t * pte = pte_alloc_kernel(pmd, address); + if (!pte) return -ENOMEM; - *page_table = mk_pte(pg, PAGE_KERNEL); - page_table++; - } while (--nr); - invalidate(); + if (alloc_area_pte(pte, address, end - address)) + return -ENOMEM; + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } return 0; } -static int do_area(void * addr, unsigned long size, - int (*area_fn)(unsigned long,unsigned long,unsigned long)) +static int alloc_area_pages(unsigned long address, unsigned long size) { - unsigned long nr, dindex, index; + pgd_t * dir; + unsigned long end = address + size; - nr = size >> PAGE_SHIFT; - dindex = VMALLOC_VMADDR(addr); - index = (dindex >> PAGE_SHIFT) & (PTRS_PER_PAGE-1); - dindex = (dindex >> PGDIR_SHIFT) & (PTRS_PER_PAGE-1); - while (nr > 0) { - unsigned long i = PTRS_PER_PAGE - index; - - if (i > nr) - i = nr; - nr -= i; - if (area_fn(dindex, index, i)) - return -1; - index = 0; - dindex++; + dir = PAGE_DIR_OFFSET(&init_task, address); + while (address < end) { + pmd_t *pmd = pmd_alloc_kernel(dir, address); + if (!pmd) + return -ENOMEM; + if (alloc_area_pmd(pmd, address, end - address)) + return -ENOMEM; + set_pgdir(address, *dir); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; } + invalidate(); return 0; } @@ -158,7 +180,7 @@ for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { if (tmp->addr == addr) { *p = tmp->next; - do_area(tmp->addr, tmp->size, free_area_pages); + free_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size); kfree(tmp); return; } @@ -188,7 +210,7 @@ area->addr = addr; area->next = *p; *p = area; - if (do_area(addr, size, alloc_area_pages)) { + if (alloc_area_pages(VMALLOC_VMADDR(addr), size)) { vfree(addr); return NULL; } diff -u --recursive --new-file v1.1.87/linux/net/inet/dev.c linux/net/inet/dev.c --- v1.1.87/linux/net/inet/dev.c Wed Jan 11 21:14:29 1995 +++ linux/net/inet/dev.c Mon Jan 30 13:10:06 1995 @@ -388,7 +388,12 @@ { for (nitcount= dev_nit, ptype = ptype_base; nitcount > 0 && ptype != NULL; ptype = ptype->next) { - if (ptype->type == htons(ETH_P_ALL) && (ptype->dev==dev || !ptype->dev)) + /* Never send packets back to the socket + * they originated from - MvS (miquels@drinkel.ow.org) + */ + if (ptype->type == htons(ETH_P_ALL) && + (ptype->dev == dev || !ptype->dev) && + ((struct sock *)ptype->data != skb->sk)) { struct sk_buff *skb2; if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) diff -u --recursive --new-file v1.1.87/linux/net/inet/ipx.c linux/net/inet/ipx.c --- v1.1.87/linux/net/inet/ipx.c Mon Jan 30 06:41:59 1995 +++ linux/net/inet/ipx.c Tue Jan 31 09:39:01 1995 @@ -346,7 +346,7 @@ /* * We need to check if there is a primary net and if * this is addressed to one of the *SPECIAL* sockets because - * these need to be propogated to the primary net. + * these need to be propagated to the primary net. * The *SPECIAL* socket list contains: 0x452(SAP), 0x453(RIP) and * 0x456(Diagnostic). */ @@ -482,7 +482,7 @@ } } - /* if the orginating net is not equal to our net; this is routed */ + /* if the originating net is not equal to our net; this is routed */ if (ipx->ipx_source.net != intrfc->if_netnum) { if (++(ipx->ipx_tctrl) > ipxcfg_max_hops) send_to_wire = 0; @@ -621,6 +621,18 @@ return ipxitf_add_local_route(intrfc); } +static int +ipx_map_frame_type(unsigned char type) +{ + switch (type) { + case IPX_FRAME_ETHERII: return htons(ETH_P_IPX); + case IPX_FRAME_8022: return htons(ETH_P_802_2); + case IPX_FRAME_SNAP: return htons(ETH_P_SNAP); + case IPX_FRAME_8023: return htons(ETH_P_802_3); + } + return 0; +} + static int ipxitf_create(ipx_interface_definition *idef) { @@ -629,10 +641,10 @@ struct datalink_proto *datalink = NULL; ipx_interface *intrfc; - if (idef->ipx_internal) + if (idef->ipx_special == IPX_INTERNAL) return ipxitf_create_internal(idef); - if (idef->ipx_primary && (ipx_primary_net != NULL)) + if ((idef->ipx_special == IPX_PRIMARY) && (ipx_primary_net != NULL)) return -EEXIST; if ((idef->ipx_network != 0L) && @@ -665,9 +677,12 @@ return -EPROTONOSUPPORT; dev=dev_get(idef->ipx_device); - if(dev==NULL) + if (dev==NULL) return -ENODEV; + if (!(dev->flags & IFF_UP)) + return -ENETDOWN; + /* Check addresses are suitable */ if(dev->addr_len>IPX_NODE_LEN) return -EINVAL; @@ -688,7 +703,8 @@ intrfc->if_sklist = NULL; intrfc->if_sknum = IPX_MIN_EPHEMERAL_SOCKET; /* Setup primary if necessary */ - if (idef->ipx_primary) ipx_primary_net = intrfc; + if ((idef->ipx_special == IPX_PRIMARY)) + ipx_primary_net = intrfc; intrfc->if_internal = 0; intrfc->if_ipx_offset = dev->hard_header_len + datalink->header_length; memset(intrfc->if_node, 0, IPX_NODE_LEN); @@ -711,7 +727,7 @@ unsigned short dlink_type = 0; ipx_interface *intrfc; - if (idef->ipx_internal) { + if (idef->ipx_special == IPX_INTERNAL) { if (ipx_internal_net != NULL) { ipxitf_down(ipx_internal_net); return 0; @@ -719,24 +735,9 @@ return -ENOENT; } - switch (idef->ipx_dlink_type) { - case IPX_FRAME_ETHERII: - dlink_type = htons(ETH_P_IPX); - break; - case IPX_FRAME_8022: - dlink_type = htons(ETH_P_802_2); - break; - case IPX_FRAME_SNAP: - dlink_type = htons(ETH_P_SNAP); - break; - case IPX_FRAME_8023: - dlink_type = htons(ETH_P_802_3); - break; - case IPX_FRAME_NONE: - default: + dlink_type = ipx_map_frame_type(idef->ipx_dlink_type); + if (dlink_type == 0) return -EPROTONOSUPPORT; - break; - } dev=dev_get(idef->ipx_device); if(dev==NULL) return -ENODEV; @@ -811,10 +812,10 @@ return -EINVAL; f.ipx_network=sipx->sipx_network; memcpy(f.ipx_device, ifr.ifr_name, sizeof(f.ipx_device)); + memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN); f.ipx_dlink_type=sipx->sipx_type; - f.ipx_primary=sipx->sipx_primary; - f.ipx_internal=sipx->sipx_internal; - if(sipx->sipx_network==0) + f.ipx_special=sipx->sipx_special; + if(sipx->sipx_action==IPX_DLTITF) return ipxitf_delete(&f); else return ipxitf_create(&f); @@ -833,12 +834,13 @@ dev=dev_get(ifr.ifr_name); if(!dev) return -ENODEV; - ipxif=ipxitf_find_using_phys(dev, sipx->sipx_type); + ipxif=ipxitf_find_using_phys(dev, ipx_map_frame_type(sipx->sipx_type)); if(ipxif==NULL) return -EADDRNOTAVAIL; sipx->sipx_network=ipxif->if_netnum; memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node)); - + memcpy_tofs(arg,&ifr,sizeof(ifr)); + return 0; } case SIOCAIPXITFCRT: err=verify_area(VERIFY_READ,arg,sizeof(char)); @@ -1054,7 +1056,7 @@ switch(cmd) { case SIOCDELRT: - return ipxrtr_delete(sg->sipx_network); + return ipxrtr_delete(st->sipx_network); case SIOCADDRT: { struct ipx_route_definition f; diff -u --recursive --new-file v1.1.87/linux/net/inet/psnap.c linux/net/inet/psnap.c --- v1.1.87/linux/net/inet/psnap.c Mon Jan 30 06:42:00 1995 +++ linux/net/inet/psnap.c Mon Jan 30 13:10:06 1995 @@ -2,6 +2,7 @@ * SNAP data link layer. Derived from 802.2 * * Alan Cox , from the 802.2 layer by Greg Page. + * Merged in additions from Greg Page's psnap.c. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -38,6 +39,15 @@ int snap_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) { + static struct packet_type psnap_packet_type = + { + 0, + NULL, /* All Devices */ + snap_rcv, + NULL, + NULL, + }; + struct datalink_proto *proto; proto = find_snap_client(skb->h.raw); @@ -49,7 +59,9 @@ skb->h.raw += 5; skb->len -= 5; - return proto->rcvfunc(skb, dev, pt); + if (psnap_packet_type.type == 0) + psnap_packet_type.type=htons(ETH_P_SNAP); + return proto->rcvfunc(skb, dev, &psnap_packet_type); } skb->sk = NULL; kfree_skb(skb, FREE_READ); diff -u --recursive --new-file v1.1.87/linux/net/inet/tcp.c linux/net/inet/tcp.c --- v1.1.87/linux/net/inet/tcp.c Mon Jan 30 08:53:06 1995 +++ linux/net/inet/tcp.c Tue Jan 31 15:44:36 1995 @@ -157,7 +157,7 @@ * Change the receive queue to assemble as it goes. This lets us * dispose of most of tcp_sequence, half of tcp_ack and chunks of * tcp_data/tcp_read as well as the window shrink crud. - * Seperate out duplicated code - tcp_alloc_skb, tcp_build_ack + * Separate out duplicated code - tcp_alloc_skb, tcp_build_ack * tcp_queue_skb seem obvious routines to extract. * * This program is free software; you can redistribute it and/or @@ -582,7 +582,7 @@ } /* - * A write timeout has occured. Process the after effects. + * A write timeout has occurred. Process the after effects. */ static int tcp_write_timeout(struct sock *sk) @@ -675,8 +675,7 @@ /* Window probing */ case TIME_PROBE0: tcp_send_probe0(sk); - if(tcp_write_timeout(sk)) - release_sock (sk); + tcp_write_timeout(sk); break; /* Retransmitting */ case TIME_WRITE: @@ -704,7 +703,6 @@ { reset_xmit_timer (sk, TIME_WRITE, skb->when + sk->rto - jiffies); restore_flags(flags); - release_sock (sk); break; } restore_flags(flags); @@ -712,10 +710,8 @@ * Retransmission */ sk->prot->retransmit (sk, 0); - if(!tcp_write_timeout(sk)) - break; + tcp_write_timeout(sk); } - release_sock (sk); break; } /* Sending Keepalives */ @@ -730,14 +726,13 @@ if (sk->prot->write_wakeup) sk->prot->write_wakeup (sk); sk->retransmits++; - if(tcp_write_timeout(sk)) - release_sock (sk); + tcp_write_timeout(sk); break; default: printk ("rexmit_timer: timer expired - reason unknown\n"); - release_sock (sk); break; } + release_sock(sk); } /* @@ -2017,7 +2012,7 @@ struct wait_queue wait = { current, NULL }; int copied = 0; unsigned long peek_seq; - volatile unsigned long *seq; /* So gcc doesnt overoptimise */ + volatile unsigned long *seq; /* So gcc doesn't overoptimise */ unsigned long used; /* @@ -2600,8 +2595,9 @@ { case TCPOPT_EOL: return; - case TCPOPT_NOP: - length-=2; + case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */ + length--; + ptr--; /* the opsize=*ptr++ above was a mistake */ continue; default: