Commit 57dabd37 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.34

parent 5079f36d
VERSION = 1 VERSION = 1
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 33 SUBLEVEL = 34
all: Version zImage all: Version zImage
...@@ -79,9 +79,21 @@ endif ...@@ -79,9 +79,21 @@ endif
AS86 =as86 -0 -a AS86 =as86 -0 -a
LD86 =ld86 -0 LD86 =ld86 -0
#
# Set these to indicate how to link it..
#
# -zmagic:
#
#LOWLDFLAGS = -Ttext 0x1000
#HIGHLDFLAGS = -Ttext 0x100000
#
# -qmagic (we need to remove the 32 byte header for bootup purposes)
#
LOWLDFLAGS =-qmagic -Ttext 0xfe0
HIGHLDFLAGS =-qmagic -Ttext 0xfffe0
AS =as AS =as
LD =ld LD =ld
LDFLAGS =#-qmagic
HOSTCC =gcc HOSTCC =gcc
CC =gcc -D__KERNEL__ -I$(TOPDIR)/include CC =gcc -D__KERNEL__ -I$(TOPDIR)/include
MAKE =make MAKE =make
...@@ -156,7 +168,7 @@ init/main.o: $(CONFIGURE) init/main.c ...@@ -156,7 +168,7 @@ init/main.o: $(CONFIGURE) init/main.c
$(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $< $(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $<
tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs
$(LD) $(LDFLAGS) -Ttext 1000 boot/head.o init/main.o tools/version.o \ $(LD) $(LOWLDFLAGS) boot/head.o init/main.o tools/version.o \
$(ARCHIVES) \ $(ARCHIVES) \
$(FILESYSTEMS) \ $(FILESYSTEMS) \
$(DRIVERS) \ $(DRIVERS) \
...@@ -201,7 +213,7 @@ zlilo: $(CONFIGURE) zImage ...@@ -201,7 +213,7 @@ zlilo: $(CONFIGURE) zImage
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs
$(LD) $(LDFLAGS) -Ttext 100000 boot/head.o init/main.o tools/version.o \ $(LD) $(HIGHLDFLAGS) boot/head.o init/main.o tools/version.o \
$(ARCHIVES) \ $(ARCHIVES) \
$(FILESYSTEMS) \ $(FILESYSTEMS) \
$(DRIVERS) \ $(DRIVERS) \
......
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
! Move PS/2 aux init code to psaux.c ! Move PS/2 aux init code to psaux.c
! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 ! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
! !
! some changes and additional features by Christoph Niemann, March 1993 ! some changes and additional features by Christoph Niemann,
! (niemann@rubdv15.ETDV.Ruhr-Uni-Bochum.De) ! March 1993/June 1994 (Christoph.Niemann@linux.org)
! !
! NOTE! These had better be the same as in bootsect.s! ! NOTE! These had better be the same as in bootsect.s!
...@@ -97,9 +97,11 @@ novga: mov [14],ax ...@@ -97,9 +97,11 @@ novga: mov [14],ax
mov ds,ax mov ds,ax
lds si,[4*0x41] lds si,[4*0x41]
mov ax,#INITSEG mov ax,#INITSEG
push ax
mov es,ax mov es,ax
mov di,#0x0080 mov di,#0x0080
mov cx,#0x10 mov cx,#0x10
push cx
cld cld
rep rep
movsb movsb
...@@ -109,11 +111,9 @@ novga: mov [14],ax ...@@ -109,11 +111,9 @@ novga: mov [14],ax
xor ax,ax ! clear ax xor ax,ax ! clear ax
mov ds,ax mov ds,ax
lds si,[4*0x46] lds si,[4*0x46]
mov ax,#INITSEG pop cx
mov es,ax pop es
mov di,#0x0090 mov di,#0x0090
mov cx,#0x10
cld
rep rep
movsb movsb
...@@ -159,7 +159,7 @@ no_psmouse: ...@@ -159,7 +159,7 @@ no_psmouse:
cld ! 'direction'=0, movs moves forward cld ! 'direction'=0, movs moves forward
do_move: do_move:
mov es,ax ! destination segment mov es,ax ! destination segment
add ax,#0x100 inc ah ! instead of add ax,#0x100
cmp ax,#0x9000 cmp ax,#0x9000
jz end_move jz end_move
mov ds,bx ! source segment mov ds,bx ! source segment
...@@ -246,7 +246,8 @@ end_move: ...@@ -246,7 +246,8 @@ end_move:
! Note that the short jump isn't strictly needed, althought there are ! Note that the short jump isn't strictly needed, althought there are
! reasons why it might be a good idea. It won't hurt in any case. ! reasons why it might be a good idea. It won't hurt in any case.
! !
mov ax,#0x0001 ! protected mode (PE) bit xor ax,ax
inc ax ! protected mode (PE) bit
lmsw ax ! This is it! lmsw ax ! This is it!
jmp flush_instr jmp flush_instr
flush_instr: flush_instr:
...@@ -394,33 +395,89 @@ vga28: ...@@ -394,33 +395,89 @@ vga28:
mov ax,#0x501c ! return 80x28 mov ax,#0x501c ! return 80x28
ret ret
/* svga modes */ /* svga modes */
!
! test for presence of an S3 VGA chip. The algorithm was taken
! from the SuperProbe package of XFree86 1.2.1
! report bugs to Christoph.Niemann@linux.org
!
svga: cld svga: cld
lea si,id9GXE ! Check for the #9GXE (jyanowit@orixa.mtholyoke.edu,thanks dlm40629@uxa.cso.uiuc.edu) mov cx,#0x0f35 ! we store some constants in cl/ch
mov di,#0x49 ! id string is at c000:049 mov dx,#0x03d4
mov cx,#0x11 ! length of "Graphics Power By" movb al,#0x38
repe call inidx
cmpsb mov bh,al ! store current value of CRT-register 0x38
jne of1280 mov ax,#0x0038
is9GXE: lea si,dsc9GXE ! table of descriptions of video modes for BIOS call outidx ! disable writing to special regs
lea di,mo9GXE ! table of sizes of video modes for my BIOS movb al,cl ! check wether we can write special reg 0x35
call inidx
movb bl,al ! save the current value of CRT reg 0x35
andb al,#0xf0 ! clear bits 0-3
movb ah,al
movb al,cl ! and write it to CRT reg 0x35
call outidx
call inidx ! now read it back
andb al,ch ! clear the upper 4 bits
jz s3_2 ! the first test failed. But we have a
movb ah,bl ! second chance
mov al,cl
call outidx
jmp s3_1 ! do the other tests
s3_2: mov ax,cx ! load ah with 0xf and al with 0x35
orb ah,bl ! set the upper 4 bits of ah with the orig value
call outidx ! write ...
call inidx ! ... and reread
andb al,cl ! turn off the upper 4 bits
push ax
movb ah,bl ! restore old value in register 0x35
movb al,cl
call outidx
pop ax
cmp al,ch ! setting lower 4 bits was successful => bad
je no_s3 ! writing is allowed => this is not an S3
s3_1: mov ax,#0x4838 ! allow writing to special regs by putting
call outidx ! magic number into CRT-register 0x38
movb al,cl ! check wether we can write special reg 0x35
call inidx
movb bl,al
andb al,#0xf0
movb ah,al
movb al,cl
call outidx
call inidx
andb al,ch
jnz no_s3 ! no, we can't write => no S3
mov ax,cx
orb ah,bl
call outidx
call inidx
andb al,ch
push ax
movb ah,bl ! restore old value in register 0x35
movb al,cl
call outidx
pop ax
cmp al,ch
jne no_s31 ! writing not possible => no S3
movb al,#0x30
call inidx ! now get the S3 id ...
lea di,idS3
mov cx,#0x10
repne
scasb
je no_s31
lea si,dsc_S3 ! table of descriptions of video modes for BIOS
lea di,mo_S3 ! table of sizes of video modes for my BIOS
movb ah,bh
movb al,#0x38
call outidx ! restore old value of CRT register 0x38
br selmod ! go ask for video mode br selmod ! go ask for video mode
of1280: cld no_s3: movb al,#0x35 ! restore CRT register 0x35
lea si,idf1280 ! Check for Orchid F1280 (dingbat@diku.dk) movb ah,bl
mov di,#0x10a ! id string is at c000:010a call outidx
mov cx,#0x21 ! length no_s31: movb ah,bh
repe movb al,#0x38
cmpsb call outidx ! restore old value of CRT register 0x38
jne nf1280
isVRAM: lea si,dscf1280
lea di,mof1280
br selmod
nf1280: lea si,idVRAM
mov di,#0x10a
mov cx,#0x0c
repe
cmpsb
je isVRAM
cld
lea si,idati ! Check ATI 'clues' lea si,idati ! Check ATI 'clues'
mov di,#0x31 mov di,#0x31
mov cx,#0x09 mov cx,#0x09
...@@ -710,6 +767,29 @@ gotmode: xor ah,ah ...@@ -710,6 +767,29 @@ gotmode: xor ah,ah
pop ds pop ds
ret ret
! Routine to write al into a VGA-register that is
! accessed via an index register
!
! dx contains the address of the index register
! al contains the index
! ah contains the value to write to the data register (dx + 1)
!
! no registers are changed
outidx: out dx,al
push ax
mov al,ah
inc dx
out dx,al
dec dx
pop ax
ret
inidx: out dx,al
inc dx
in al,dx
dec dx
ret
! Routine to print asciiz-string at DS:SI ! Routine to print asciiz-string at DS:SI
prtstr: lodsb prtstr: lodsb
...@@ -817,9 +897,8 @@ idcandt: .byte 0xa5 ...@@ -817,9 +897,8 @@ idcandt: .byte 0xa5
idgenoa: .byte 0x77, 0x00, 0x99, 0x66 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
idparadise: .ascii "VGA=" idparadise: .ascii "VGA="
idoakvga: .ascii "OAK VGA " idoakvga: .ascii "OAK VGA "
idf1280: .ascii "Orchid Technology Fahrenheit 1280" idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
id9GXE: .ascii "Graphics Power By" .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
idVRAM: .ascii "Stealth VRAM"
! Manufacturer: Numofmodes+2: Mode: ! Manufacturer: Numofmodes+2: Mode:
! Number of modes is the number of chip-specific svga modes plus the extended ! Number of modes is the number of chip-specific svga modes plus the extended
...@@ -836,8 +915,7 @@ motrident: .byte 0x09, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a ...@@ -836,8 +915,7 @@ motrident: .byte 0x09, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
motseng: .byte 0x07, 0x26, 0x2a, 0x23, 0x24, 0x22 motseng: .byte 0x07, 0x26, 0x2a, 0x23, 0x24, 0x22
movideo7: .byte 0x08, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45 movideo7: .byte 0x08, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
mooakvga: .byte 0x08, 0x00, 0x07, 0x4e, 0x4f, 0x50, 0x51 mooakvga: .byte 0x08, 0x00, 0x07, 0x4e, 0x4f, 0x50, 0x51
mo9GXE: .byte 0x04, 0x54, 0x55 mo_S3: .byte 0x04, 0x54, 0x55
mof1280: .byte 0x04, 0x54, 0x55
mounknown: .byte 0x02 mounknown: .byte 0x02
! msb = Cols lsb = Rows: ! msb = Cols lsb = Rows:
...@@ -855,8 +933,7 @@ dsctrident: .word 0x5032, 0x501c, 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842 ...@@ -855,8 +933,7 @@ dsctrident: .word 0x5032, 0x501c, 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842
dsctseng: .word 0x5032, 0x501c, 0x503c, 0x6428, 0x8419, 0x841c, 0x842c dsctseng: .word 0x5032, 0x501c, 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
dscvideo7: .word 0x5032, 0x501c, 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c dscvideo7: .word 0x5032, 0x501c, 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
dscoakvga: .word 0x5032, 0x501c, 0x2819, 0x5019, 0x503c, 0x843c, 0x8419, 0x842b dscoakvga: .word 0x5032, 0x501c, 0x2819, 0x5019, 0x503c, 0x843c, 0x8419, 0x842b
dscf1280: .word 0x5032, 0x501c, 0x842b, 0x8419 dsc_S3: .word 0x5032, 0x501c, 0x842b, 0x8419
dsc9GXE: .word 0x5032, 0x501c, 0x842b, 0x8419
dsunknown: .word 0x5032, 0x501c dsunknown: .word 0x5032, 0x501c
modesave: .word SVGA_MODE modesave: .word SVGA_MODE
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* and for "no-sound" interfaces like Lasermate and the * and for "no-sound" interfaces like Lasermate and the
* Panasonic CI-101P. * Panasonic CI-101P.
* *
* NOTE: This is release 2.3. * NOTE: This is release 2.4.
* It works with my SbPro & drive CR-521 V2.11 from 2/92 * It works with my SbPro & drive CR-521 V2.11 from 2/92
* and with the new CR-562-B V0.75 on a "naked" Panasonic * and with the new CR-562-B V0.75 on a "naked" Panasonic
* CI-101P interface. And vice versa. * CI-101P interface. And vice versa.
...@@ -117,6 +117,9 @@ ...@@ -117,6 +117,9 @@
* 2.3 Let "door lock" and "eject" live together. * 2.3 Let "door lock" and "eject" live together.
* Implemented "close tray" (done automatically during open). * Implemented "close tray" (done automatically during open).
* *
* 2.4 Use different names for device registering.
*
*
* TODO * TODO
* *
* disk change detection * disk change detection
...@@ -192,7 +195,7 @@ ...@@ -192,7 +195,7 @@
#include "blk.h" #include "blk.h"
#define VERSION "2.3 Eberhard Moenkeberg <emoenke@gwdg.de>" #define VERSION "2.4 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define SBPCD_DEBUG #define SBPCD_DEBUG
...@@ -397,6 +400,18 @@ static char *str_sb = "SoundBlaster"; ...@@ -397,6 +400,18 @@ static char *str_sb = "SoundBlaster";
static char *str_lm = "LaserMate"; static char *str_lm = "LaserMate";
static char *str_sp = "SPEA"; static char *str_sp = "SPEA";
char *type; char *type;
#if !(SBPCD_ISSUE-1)
static char *major_name="sbpcd";
#endif
#if !(SBPCD_ISSUE-2)
static char *major_name="sbpcd2";
#endif
#if !(SBPCD_ISSUE-3)
static char *major_name="sbpcd3";
#endif
#if !(SBPCD_ISSUE-4)
static char *major_name="sbpcd4";
#endif
/*==========================================================================*/ /*==========================================================================*/
...@@ -2840,7 +2855,6 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd, ...@@ -2840,7 +2855,6 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
/*==========================================================================*/ /*==========================================================================*/
/* /*
* Take care of the different block sizes between cdrom and Linux. * Take care of the different block sizes between cdrom and Linux.
* When Linux gets variable block sizes this will probably go away.
*/ */
static void sbp_transfer(void) static void sbp_transfer(void)
{ {
...@@ -3551,7 +3565,7 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end) ...@@ -3551,7 +3565,7 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
OUT(MIXER_data,0xCC); /* one nibble per channel */ OUT(MIXER_data,0xCC); /* one nibble per channel */
} }
if (register_blkdev(MAJOR_NR, "sbpcd", &sbpcd_fops) != 0) if (register_blkdev(MAJOR_NR, major_name, &sbpcd_fops) != 0)
{ {
printk("SBPCD: Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR); printk("SBPCD: Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR);
#if PRINTK_BUG #if PRINTK_BUG
......
...@@ -21,7 +21,7 @@ Space.o: Space.c ../../include/linux/autoconf.h ...@@ -21,7 +21,7 @@ Space.o: Space.c ../../include/linux/autoconf.h
net_init.o: ../../include/linux/autoconf.h net_init.o: ../../include/linux/autoconf.h
ifdef CONFIG_SK_G16 ifdef CONFIG_SK_G16
NETDRV_OBJS := $(NETDRV_OBJS) net.a(sk_g16.o) NETDRV_OBJS := $(NETDRV_OBJS) sk_g16.o
endif endif
ifdef CONFIG_WD80x3 ifdef CONFIG_WD80x3
...@@ -53,7 +53,7 @@ hp.o: hp.c CONFIG ...@@ -53,7 +53,7 @@ hp.o: hp.c CONFIG
endif endif
ifdef CONFIG_HPLAN_PLUS ifdef CONFIG_HPLAN_PLUS
NETDRV_OBJS := $(NETDRV_OBJS) net.a(hp-plus.o) NETDRV_OBJS := $(NETDRV_OBJS) hp-plus.o
CONFIG_8390 = CONFIG_8390 CONFIG_8390 = CONFIG_8390
endif endif
...@@ -104,7 +104,7 @@ de600.o: de600.c CONFIG ...@@ -104,7 +104,7 @@ de600.o: de600.c CONFIG
$(CC) $(CPPFLAGS) $(CFLAGS) $(DE600_OPTS) -c $< $(CC) $(CPPFLAGS) $(CFLAGS) $(DE600_OPTS) -c $<
ifdef CONFIG_DE620 ifdef CONFIG_DE620
NETDRV_OBJS := $(NETDRV_OBJS) net.a(de620.o) NETDRV_OBJS := $(NETDRV_OBJS) de620.o
endif endif
de620.o: de620.c CONFIG de620.o: de620.c CONFIG
$(CC) $(CPPFLAGS) $(CFLAGS) $(DE620_OPTS) -c $< $(CC) $(CPPFLAGS) $(CFLAGS) $(DE620_OPTS) -c $<
...@@ -155,7 +155,7 @@ NETDRV_OBJS := $(NETDRV_OBJS) ac3200.o ...@@ -155,7 +155,7 @@ NETDRV_OBJS := $(NETDRV_OBJS) ac3200.o
CONFIG_8390 = CONFIG_8390 CONFIG_8390 = CONFIG_8390
endif endif
ifdef CONFIG_APRICOT ifdef CONFIG_APRICOT
NETDRV_OBJS := $(NETDRV_OBJS) net.a(apricot.o) NETDRV_OBJS := $(NETDRV_OBJS) apricot.o
endif endif
ifdef CONFIG_8390 ifdef CONFIG_8390
......
/* e2100.c: A Cabletron E2100 series ethernet driver for linux. */ /* e2100.c: A Cabletron E2100 series ethernet driver for linux. */
/* /*
Written 1993 by Donald Becker. Written 1993-1994 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
distributed according to the terms of the GNU Public License,
incorporated herein by reference.
This is a driver for the Cabletron E2100 series ethercards. Copyright 1994 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
distributed according to the terms of the GNU Public License,
incorporated herein by reference.
The Author may be reached as becker@cesdis.gsfc.nasa.gov, or This is a driver for the Cabletron E2100 series ethercards.
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
The Author may be reached as becker@cesdis.gsfc.nasa.gov, or
C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
The E2100 series ethercard is a fairly generic shared memory 8390 The E2100 series ethercard is a fairly generic shared memory 8390
implementation. The only unusual aspect is the way the shared memory implementation. The only unusual aspect is the way the shared memory
registers are set: first you do an inb() in what is normally the registers are set: first you do an inb() in what is normally the
station address region, and the low four bits of next outb() is used station address region, and the low three bits of next outb() *address*
as the write value for that register. Either someone wasn't too used is used as the write value for that register. Either someone wasn't
to dem bit en bites, or they were trying to obfusicate the programming too used to dem bit en bites, or they were trying to obfusicate the
interface. programming interface.
There is an additional complication when setting the window on the packet There is an additional complication when setting the window on the packet
buffer. You must first do a read into the packet buffer region with the buffer. You must first do a read into the packet buffer region with the
...@@ -30,7 +32,7 @@ ...@@ -30,7 +32,7 @@
*/ */
static char *version = static char *version =
"e2100.c:v0.01 11/21/93 Donald Becker (becker@super.org)\n"; "e2100.c:v1.01 7/21/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -39,42 +41,29 @@ static char *version = ...@@ -39,42 +41,29 @@ static char *version =
#include <linux/string.h> #include <linux/string.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#ifndef PRE_PL13 #include <linux/ioport.h>
#include <linux/ioport.h> /* Delete if your kernel doesn't have it. */
#endif
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include "8390.h" #include "8390.h"
/* Compatibility definitions for earlier kernel versions. */ static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr, size) 0
#define snarf_region(ioaddr, size); do ; while (0)
#endif
#ifndef HAVE_AUTOIRQ
/* From auto_irq.c, in ioport.h for later versions. */
extern void autoirq_setup(int waittime);
extern int autoirq_report(int waittime);
/* The map from IRQ number (as passed to the interrupt handler) to
'struct device'. */
extern struct device *irq2dev_map[16];
#endif
/* Offsets from the base_addr. /* Offsets from the base_addr.
Read from the ASIC register, and the low 3(?) bits of the next outb() address Read from the ASIC register, and the low three bits of the next outb()
is used to set the cooresponding register. */ address is used to set the cooresponding register. */
#define E21_NIC_OFFSET 0 /* Offset to the 8390 NIC. */ #define E21_NIC_OFFSET 0 /* Offset to the 8390 NIC. */
#define E21_ASIC 0x10 #define E21_ASIC 0x10
#define E21_MEM_ENABLE 0x10 #define E21_MEM_ENABLE 0x10
#define E21_MEM_ON 0x05 /* Enable memory in 16 bit mode. */ #define E21_MEM_ON 0x05 /* Enable memory in 16 bit mode. */
#define E21_MEM_ON_8 0x07 /* Enable memory in 8 bit mode. */ #define E21_MEM_ON_8 0x07 /* Enable memory in 8 bit mode. */
#define E21_MEM_BASE 0x11 #define E21_MEM_BASE 0x11
#define E21_IRQ_LOW 0x12 /* The low three bits of the IRQ number. */ #define E21_IRQ_LOW 0x12 /* The low three bits of the IRQ number. */
#define E21_IRQ_HIGH 0x14 /* The high IRQ bit, and ... */ #define E21_IRQ_HIGH 0x14 /* The high IRQ bit and media select ... */
#define E21_MEDIA 0x14 /* (alias). */
#define E21_ALT_IFPORT 0x02 /* Set to use the other (BNC,AUI) port. */ #define E21_ALT_IFPORT 0x02 /* Set to use the other (BNC,AUI) port. */
#define E21_BIG_MEM 0x04 /* Use a bigger (64K) buffer (we don't) */ #define E21_BIG_MEM 0x04 /* Use a bigger (64K) buffer (we don't) */
#define E21_SAPROM 0x10 /* Offset to station address data. */ #define E21_SAPROM 0x10 /* Offset to station address data. */
#define ETHERCARD_TOTAL_SIZE 0x20 #define E21_IO_EXTENT 0x20
extern inline void mem_on(short port, volatile char *mem_base, extern inline void mem_on(short port, volatile char *mem_base,
unsigned char start_page ) unsigned char start_page )
...@@ -96,10 +85,10 @@ extern inline void mem_off(short port) ...@@ -96,10 +85,10 @@ extern inline void mem_off(short port)
is designed to have a 4K Tx region last. The windowing circuitry wraps the is designed to have a 4K Tx region last. The windowing circuitry wraps the
window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring
appear contiguously in the window. */ appear contiguously in the window. */
#define E21_RX_START_PG 0x00 /* First page of RX buffer */ #define E21_RX_START_PG 0x00 /* First page of RX buffer */
#define E21_RX_STOP_PG 0x30 /* Last page +1 of RX ring */ #define E21_RX_STOP_PG 0x30 /* Last page +1 of RX ring */
#define E21_BIG_RX_STOP_PG 0xF0 /* Last page +1 of RX ring */ #define E21_BIG_RX_STOP_PG 0xF0 /* Last page +1 of RX ring */
#define E21_TX_START_PG E21_RX_STOP_PG /* First page of TX buffer */ #define E21_TX_START_PG E21_RX_STOP_PG /* First page of TX buffer */
int e2100_probe(struct device *dev); int e2100_probe(struct device *dev);
int e21_probe1(struct device *dev, int ioaddr); int e21_probe1(struct device *dev, int ioaddr);
...@@ -107,9 +96,9 @@ int e21_probe1(struct device *dev, int ioaddr); ...@@ -107,9 +96,9 @@ int e21_probe1(struct device *dev, int ioaddr);
static int e21_open(struct device *dev); static int e21_open(struct device *dev);
static void e21_reset_8390(struct device *dev); static void e21_reset_8390(struct device *dev);
static int e21_block_input(struct device *dev, int count, static int e21_block_input(struct device *dev, int count,
char *buf, int ring_offset); char *buf, int ring_offset);
static void e21_block_output(struct device *dev, int count, static void e21_block_output(struct device *dev, int count,
const unsigned char *buf, const start_page); const unsigned char *buf, const start_page);
static int e21_close(struct device *dev); static int e21_close(struct device *dev);
...@@ -122,26 +111,22 @@ static int e21_close(struct device *dev); ...@@ -122,26 +111,22 @@ static int e21_close(struct device *dev);
int e2100_probe(struct device *dev) int e2100_probe(struct device *dev)
{ {
int *port, ports[] = {0x300, 0x280, 0x380, 0x220, 0}; int *port;
short base_addr = dev->base_addr; int base_addr = dev->base_addr;
if (base_addr > 0x1ff) /* Check a single specified location. */ if (base_addr > 0x1ff) /* Check a single specified location. */
return e21_probe1(dev, base_addr); return e21_probe1(dev, base_addr);
else if (base_addr > 0) /* Don't probe at all. */ else if (base_addr != 0) /* Don't probe at all. */
return ENXIO; return ENXIO;
for (port = &ports[0]; *port; port++) { for (port = e21_probe_list; *port; port++) {
ushort ioaddr = *port; if (check_region(*port, E21_IO_EXTENT))
continue;
if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE)) if (e21_probe1(dev, *port) == 0)
continue; return 0;
if (inb(ioaddr + E21_SAPROM + 0) == 0x00 }
&& inb(ioaddr + E21_SAPROM + 1) == 0x00
&& inb(ioaddr + E21_SAPROM + 2) == 0x1d return ENODEV;
&& e21_probe1(dev, ioaddr) == 0)
return 0;
}
return -ENODEV;
} }
int e21_probe1(struct device *dev, int ioaddr) int e21_probe1(struct device *dev, int ioaddr)
...@@ -149,29 +134,30 @@ int e21_probe1(struct device *dev, int ioaddr) ...@@ -149,29 +134,30 @@ int e21_probe1(struct device *dev, int ioaddr)
int i, status; int i, status;
unsigned char *station_addr = dev->dev_addr; unsigned char *station_addr = dev->dev_addr;
/* We've already checked the station address prefix, now verify by making /* First check the station address for the Ctron prefix. */
certain that there is a 8390 at the expected location. */ if (inb(ioaddr + E21_SAPROM + 0) != 0x00
|| inb(ioaddr + E21_SAPROM + 1) != 0x00
|| inb(ioaddr + E21_SAPROM + 2) != 0x1d)
return ENODEV;
/* Verify by making certain that there is a 8390 at there. */
outb(E8390_NODMA + E8390_STOP, ioaddr); outb(E8390_NODMA + E8390_STOP, ioaddr);
SLOW_DOWN_IO; SLOW_DOWN_IO;
status = inb(ioaddr); status = inb(ioaddr);
if (status != 0x21 && status != 0x23) if (status != 0x21 && status != 0x23)
return -ENODEV; return ENODEV;
#ifdef testing_only /* Grab the region so we can find a different board if IRQ select fails. */
printk("%s: E21xx at %#3x (PAXI backwards): ", dev->name, ioaddr); snarf_region(ioaddr, E21_IO_EXTENT);
for (i = 0; i < 16; i++)
printk(" %02X", inb(ioaddr + 0x1f - i));
printk("\n");
#endif
/* Read the station address PROM. */ /* Read the station address PROM. */
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
station_addr[i] = inb(ioaddr + E21_SAPROM + i); station_addr[i] = inb(ioaddr + E21_SAPROM + i);
/* Grab the region so we can find another board if needed . */ inb(ioaddr + E21_MEDIA); /* Point to media selection. */
snarf_region(ioaddr, ETHERCARD_TOTAL_SIZE); outb(0, ioaddr + E21_ASIC); /* and disable the secondary interface. */
printk("%s: E21xx at %#3x, ", dev->name, ioaddr); printk("%s: E21** at %#3x,", dev->name, ioaddr);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk(" %02X", station_addr[i]); printk(" %02X", station_addr[i]);
...@@ -182,15 +168,13 @@ int e21_probe1(struct device *dev, int ioaddr) ...@@ -182,15 +168,13 @@ int e21_probe1(struct device *dev, int ioaddr)
dev->irq = irqlist[i]; dev->irq = irqlist[i];
break; break;
} }
} else if (dev->irq == 2) /* Fixup bogosity: IRQ2 is really IRQ9 */ if (i >= 8) {
printk(" unable to get IRQ %d.\n", dev->irq);
return EAGAIN;
}
} else if (dev->irq == 2) /* Fixup luser bogosity: IRQ2 is really IRQ9 */
dev->irq = 9; dev->irq = 9;
/* Snarf the interrupt now. */
if (irqaction (dev->irq, &ei_sigaction)) {
printk (" unable to get IRQ %d.\n", dev->irq);
return -EBUSY;
}
/* The 8390 is at the base address. */ /* The 8390 is at the base address. */
dev->base_addr = ioaddr; dev->base_addr = ioaddr;
...@@ -201,6 +185,7 @@ int e21_probe1(struct device *dev, int ioaddr) ...@@ -201,6 +185,7 @@ int e21_probe1(struct device *dev, int ioaddr)
ei_status.tx_start_page = E21_TX_START_PG; ei_status.tx_start_page = E21_TX_START_PG;
ei_status.rx_start_page = E21_RX_START_PG; ei_status.rx_start_page = E21_RX_START_PG;
ei_status.stop_page = E21_RX_STOP_PG; ei_status.stop_page = E21_RX_STOP_PG;
ei_status.saved_irq = dev->irq;
/* Check the media port used. The port can be passed in on the /* Check the media port used. The port can be passed in on the
low mem_end bits. */ low mem_end bits. */
...@@ -208,10 +193,12 @@ int e21_probe1(struct device *dev, int ioaddr) ...@@ -208,10 +193,12 @@ int e21_probe1(struct device *dev, int ioaddr)
dev->if_port = dev->mem_end & 7; dev->if_port = dev->mem_end & 7;
else { else {
dev->if_port = 0; dev->if_port = 0;
inb_p(ioaddr + E21_IRQ_HIGH); /* Select if_port detect. */ inb(ioaddr + E21_MEDIA); /* Turn automatic media detection on. */
for(i = 0; i < 6; i++) for(i = 0; i < 6; i++)
if (station_addr[i] != inb(ioaddr + E21_SAPROM)) if (station_addr[i] != inb(ioaddr + E21_SAPROM + 8 + i)) {
dev->if_port = 1; dev->if_port = 1;
break;
}
} }
/* Never map in the E21 shared memory unless you are actively using it. /* Never map in the E21 shared memory unless you are actively using it.
...@@ -227,9 +214,8 @@ int e21_probe1(struct device *dev, int ioaddr) ...@@ -227,9 +214,8 @@ int e21_probe1(struct device *dev, int ioaddr)
dev->mem_end = dev->rmem_end = dev->mem_start + 2*1024; dev->mem_end = dev->rmem_end = dev->mem_start + 2*1024;
#endif #endif
printk(" IRQ %d, %s interface, memory at %#x-%#x.\n", dev->irq, printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
dev->if_port ? "secondary" : "primary", dev->mem_start, dev->if_port ? "secondary" : "primary", dev->mem_start);
dev->mem_start + 2*1024 - 1);
if (ei_debug > 0) if (ei_debug > 0)
printk(version); printk(version);
...@@ -247,16 +233,21 @@ int e21_probe1(struct device *dev, int ioaddr) ...@@ -247,16 +233,21 @@ int e21_probe1(struct device *dev, int ioaddr)
static int static int
e21_open(struct device *dev) e21_open(struct device *dev)
{ {
short ioaddr = dev->base_addr; short ioaddr = dev->base_addr;
if (irqaction (dev->irq, &ei_sigaction)) {
return EBUSY;
}
irq2dev_map[dev->irq] = dev;
/* Set the interrupt line and memory base on the hardware. */ /* Set the interrupt line and memory base on the hardware. */
inb_p(ioaddr + E21_IRQ_LOW); inb(ioaddr + E21_IRQ_LOW);
outb_p(0, ioaddr + E21_ASIC + (dev->irq & 7)); outb(0, ioaddr + E21_ASIC + (dev->irq & 7));
inb_p(ioaddr + E21_IRQ_HIGH); /* High IRQ bit, and if_port. */ inb(ioaddr + E21_IRQ_HIGH); /* High IRQ bit, and if_port. */
outb_p(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0) outb(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
+ (dev->if_port ? E21_ALT_IFPORT : 0)); + (dev->if_port ? E21_ALT_IFPORT : 0));
inb_p(ioaddr + E21_MEM_BASE); inb(ioaddr + E21_MEM_BASE);
outb_p(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7)); outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
return ei_open(dev); return ei_open(dev);
} }
...@@ -264,47 +255,47 @@ e21_open(struct device *dev) ...@@ -264,47 +255,47 @@ e21_open(struct device *dev)
static void static void
e21_reset_8390(struct device *dev) e21_reset_8390(struct device *dev)
{ {
short ioaddr = dev->base_addr; short ioaddr = dev->base_addr;
outb(0x01, ioaddr); outb(0x01, ioaddr);
if (ei_debug > 1) printk("resetting the E2180x3 t=%d...", jiffies); if (ei_debug > 1) printk("resetting the E2180x3 t=%ld...", jiffies);
ei_status.txing = 0; ei_status.txing = 0;
/* Set up the ASIC registers, just in case something changed them. */ /* Set up the ASIC registers, just in case something changed them. */
if (ei_debug > 1) printk("reset done\n"); if (ei_debug > 1) printk("reset done\n");
return; return;
} }
/* Block input and output are easy on shared memory ethercards. The E21xx makes /* Block input and output are easy on shared memory ethercards.
block_input() especially easy by wrapping the top ring buffer to the bottom The E21xx makes block_input() especially easy by wrapping the top
automatically. */ ring buffer to the bottom automatically. */
static int static int
e21_block_input(struct device *dev, int count, char *buf, int ring_offset) e21_block_input(struct device *dev, int count, char *buf, int ring_offset)
{ {
short ioaddr = dev->base_addr; short ioaddr = dev->base_addr;
char *shared_mem = (char *)dev->mem_start; char *shared_mem = (char *)dev->mem_start;
int start_page = (ring_offset>>8); int start_page = (ring_offset>>8);
mem_on(ioaddr, shared_mem, start_page); mem_on(ioaddr, shared_mem, start_page);
/* We'll always get a 4 byte header read first. */ /* We'll always get a 4 byte header read first. */
if (count == 4) if (count == 4)
((int*)buf)[0] = ((int*)shared_mem)[0]; ((int*)buf)[0] = ((int*)shared_mem)[0];
else else
memcpy(buf, shared_mem + (ring_offset & 0xff), count); memcpy(buf, shared_mem + (ring_offset & 0xff), count);
/* Turn off memory access: we would need to reprogram the window anyway. */ /* Turn off memory access: we would need to reprogram the window anyway. */
mem_off(ioaddr); mem_off(ioaddr);
return 0; return 0;
} }
static void static void
e21_block_output(struct device *dev, int count, const unsigned char *buf, e21_block_output(struct device *dev, int count, const unsigned char *buf,
int start_page) int start_page)
{ {
short ioaddr = dev->base_addr; short ioaddr = dev->base_addr;
volatile char *shared_mem = (char *)dev->mem_start; volatile char *shared_mem = (char *)dev->mem_start;
/* Set the shared memory window start by doing a read, with the low address /* Set the shared memory window start by doing a read, with the low address
...@@ -319,18 +310,37 @@ e21_block_output(struct device *dev, int count, const unsigned char *buf, ...@@ -319,18 +310,37 @@ e21_block_output(struct device *dev, int count, const unsigned char *buf,
static int static int
e21_close(struct device *dev) e21_close(struct device *dev)
{ {
short ioaddr = dev->base_addr; short ioaddr = dev->base_addr;
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
if (ei_debug > 1) free_irq(dev->irq);
printk("%s: Shutting down ethercard.\n", dev->name); dev->irq = ei_status.saved_irq;
NS8390_init(dev, 0);
/* Shut off the interrupt line and secondary interface. */
inb(ioaddr + E21_IRQ_LOW);
outb(0, ioaddr + E21_ASIC);
inb(ioaddr + E21_IRQ_HIGH); /* High IRQ bit, and if_port. */
outb(0, ioaddr + E21_ASIC);
irq2dev_map[dev->irq] = NULL;
NS8390_init(dev, 0);
/* Double-check that the memory has been turned off, because really
really bad things happen if it isn't. */
mem_off(ioaddr); mem_off(ioaddr);
return 0; return 0;
} }
#ifdef HAVE_DEVLIST
struct netdev_entry e21_drv =
{"e21", e21_probe1, E21_IO_EXTENT, e21_probe_list};
#endif
/* /*
* Local variables: * Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c e2100.c" * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c e2100.c"
......
...@@ -941,8 +941,8 @@ static int plip_config(struct device *dev, struct ifmap *map) ...@@ -941,8 +941,8 @@ static int plip_config(struct device *dev, struct ifmap *map)
static int plip_ioctl(struct device *dev, struct ifreq *rq) static int plip_ioctl(struct device *dev, struct ifreq *rq)
{ {
struct net_local *nl=(struct net_local *)dev->priv; struct net_local *nl = (struct net_local *) dev->priv;
struct plipconf *pc=(struct plipconf *)rq->ifr_data; struct plipconf *pc = (struct plipconf *) &rq->ifr_data;
switch(pc->pcmd) switch(pc->pcmd)
{ {
......
...@@ -1113,14 +1113,14 @@ __asm__ __volatile__("rep ; movsl": \ ...@@ -1113,14 +1113,14 @@ __asm__ __volatile__("rep ; movsl": \
* etc. This also allows us to optimize memory usage by sharing code pages * etc. This also allows us to optimize memory usage by sharing code pages
* and filesystem buffers.. * and filesystem buffers..
*/ */
unsigned long bread_page(unsigned long address, dev_t dev, int b[], int size, int share) unsigned long bread_page(unsigned long address, dev_t dev, int b[], int size, int no_share)
{ {
struct buffer_head * bh[8]; struct buffer_head * bh[8];
unsigned long where; unsigned long where;
int i, j; int i, j;
if (share) { if (!no_share) {
where = try_to_share_buffers(address,dev,b,size); where = try_to_share_buffers(address, dev, b, size);
if (where) if (where)
return where; return where;
} }
...@@ -1132,14 +1132,14 @@ unsigned long bread_page(unsigned long address, dev_t dev, int b[], int size, in ...@@ -1132,14 +1132,14 @@ unsigned long bread_page(unsigned long address, dev_t dev, int b[], int size, in
} }
read_buffers(bh,i); read_buffers(bh,i);
where = address; where = address;
for (i=0, j=0; j<PAGE_SIZE ; i++, j += size,address += size) { for (i=0, j=0; j<PAGE_SIZE ; i++, j += size, where += size) {
if (bh[i]) { if (bh[i]) {
if (bh[i]->b_uptodate) if (bh[i]->b_uptodate)
COPYBLK(size, (unsigned long) bh[i]->b_data,address); COPYBLK(size, (unsigned long) bh[i]->b_data, where);
brelse(bh[i]); brelse(bh[i]);
} }
} }
return where; return address;
} }
/* /*
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
* Fill in the supplied page for mmap * Fill in the supplied page for mmap
*/ */
static unsigned long nfs_file_mmap_nopage(struct vm_area_struct * area, static unsigned long nfs_file_mmap_nopage(struct vm_area_struct * area,
unsigned long address, unsigned long page, int error_code) unsigned long address, unsigned long page, int no_share)
{ {
struct inode * inode = area->vm_inode; struct inode * inode = area->vm_inode;
unsigned int clear; unsigned int clear;
......
...@@ -444,7 +444,7 @@ extern void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buff ...@@ -444,7 +444,7 @@ extern void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buff
extern void brelse(struct buffer_head * buf); extern void brelse(struct buffer_head * buf);
extern void set_blocksize(dev_t dev, int size); extern void set_blocksize(dev_t dev, int size);
extern struct buffer_head * bread(dev_t dev, int block, int size); extern struct buffer_head * bread(dev_t dev, int block, int size);
extern unsigned long bread_page(unsigned long addr,dev_t dev,int b[],int size,int share); extern unsigned long bread_page(unsigned long addr,dev_t dev,int b[],int size,int no_share);
extern struct buffer_head * breada(dev_t dev,int block, int size, extern struct buffer_head * breada(dev_t dev,int block, int size,
unsigned int pos, unsigned int filesize); unsigned int pos, unsigned int filesize);
extern void put_super(dev_t dev); extern void put_super(dev_t dev);
......
...@@ -228,9 +228,14 @@ extern void shm_no_page (ulong *); ...@@ -228,9 +228,14 @@ extern void shm_no_page (ulong *);
/* swap cache stuff (in swap.c) */ /* swap cache stuff (in swap.c) */
extern unsigned long * swap_cache; extern unsigned long * swap_cache;
extern inline unsigned long in_swap_cache (unsigned long addr) extern inline unsigned long in_swap_cache(unsigned long addr)
{ {
return swap_cache[addr >> PAGE_SHIFT]; return swap_cache[addr >> PAGE_SHIFT];
} }
extern inline void swap_cache_invalidate(unsigned long addr)
{
swap_cache[addr >> PAGE_SHIFT] = 0;
}
#endif #endif
...@@ -157,7 +157,7 @@ static struct vm_area_struct * find_vma(struct task_struct * tsk, unsigned long ...@@ -157,7 +157,7 @@ static struct vm_area_struct * find_vma(struct task_struct * tsk, unsigned long
struct vm_area_struct * vma; struct vm_area_struct * vma;
addr &= PAGE_MASK; addr &= PAGE_MASK;
for (vma = current->mm->mmap ; ; vma = vma->vm_next) { for (vma = tsk->mm->mmap ; ; vma = vma->vm_next) {
if (!vma) if (!vma)
return NULL; return NULL;
if (vma->vm_end > addr) if (vma->vm_end > addr)
......
...@@ -263,11 +263,17 @@ int copy_page_tables(struct task_struct * tsk) ...@@ -263,11 +263,17 @@ int copy_page_tables(struct task_struct * tsk)
*new_page_table = swap_duplicate(pg); *new_page_table = swap_duplicate(pg);
continue; continue;
} }
if ((pg & (PAGE_RW | PAGE_COW)) == (PAGE_RW | PAGE_COW)) if (pg > high_memory || (mem_map[MAP_NR(pg)] & MAP_PAGE_RESERVED)) {
*new_page_table = pg;
continue;
}
if (pg & PAGE_COW)
pg &= ~PAGE_RW; pg &= ~PAGE_RW;
if (in_swap_cache(pg)) {
swap_cache_invalidate(pg);
pg |= PAGE_DIRTY;
}
*new_page_table = pg; *new_page_table = pg;
if (mem_map[MAP_NR(pg)] & MAP_PAGE_RESERVED)
continue;
*old_page_table = pg; *old_page_table = pg;
mem_map[MAP_NR(pg)]++; mem_map[MAP_NR(pg)]++;
} }
...@@ -730,9 +736,6 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are ...@@ -730,9 +736,6 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
/* if it is private, it must be clean to be shared */ /* if it is private, it must be clean to be shared */
if ((from_area->vm_page_prot & PAGE_COW) && (from & PAGE_DIRTY)) if ((from_area->vm_page_prot & PAGE_COW) && (from & PAGE_DIRTY))
return 0; return 0;
/* the swap caching doesn't really handle shared pages.. */
if (in_swap_cache(from))
return 0;
/* is the page reasonable at all? */ /* is the page reasonable at all? */
if (from >= high_memory) if (from >= high_memory)
return 0; return 0;
...@@ -748,14 +751,26 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are ...@@ -748,14 +751,26 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
return 0; return 0;
/* do we copy? */ /* do we copy? */
if (newpage) { if (newpage) {
if (in_swap_cache(from)) { /* implies PAGE_DIRTY */
if (from_area->vm_page_prot & PAGE_COW)
return 0;
}
copy_page((from & PAGE_MASK), newpage); copy_page((from & PAGE_MASK), newpage);
*(unsigned long *) to_page = newpage | to_area->vm_page_prot; *(unsigned long *) to_page = newpage | to_area->vm_page_prot;
return 1; return 1;
} }
/* just share them.. */ /* do a final swap-cache test before sharing them.. */
if (in_swap_cache(from)) {
if (from_area->vm_page_prot & PAGE_COW)
return 0;
from |= PAGE_DIRTY;
*(unsigned long *) from_page = from;
swap_cache_invalidate(from);
invalidate();
}
mem_map[MAP_NR(from)]++; mem_map[MAP_NR(from)]++;
/* fill in the 'to' field, checking for COW-stuff */ /* fill in the 'to' field, checking for COW-stuff */
to = (from & PAGE_MASK) | to_area->vm_page_prot; to = (from & (PAGE_MASK | PAGE_DIRTY)) | to_area->vm_page_prot;
if (to & PAGE_COW) if (to & PAGE_COW)
to &= ~PAGE_RW; to &= ~PAGE_RW;
*(unsigned long *) to_page = to; *(unsigned long *) to_page = to;
...@@ -764,7 +779,7 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are ...@@ -764,7 +779,7 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
return 1; return 1;
if (!(from_area->vm_page_prot & PAGE_COW)) if (!(from_area->vm_page_prot & PAGE_COW))
return 1; return 1;
/* ok, need to mark it read-only, so invalidate aany possible old TB entry */ /* ok, need to mark it read-only, so invalidate any possible old TB entry */
from &= ~PAGE_RW; from &= ~PAGE_RW;
*(unsigned long *) from_page = from; *(unsigned long *) from_page = from;
invalidate(); invalidate();
...@@ -923,13 +938,24 @@ void do_no_page(struct vm_area_struct * vma, unsigned long address, ...@@ -923,13 +938,24 @@ void do_no_page(struct vm_area_struct * vma, unsigned long address,
} }
++vma->vm_task->mm->maj_flt; ++vma->vm_task->mm->maj_flt;
++vma->vm_task->mm->rss; ++vma->vm_task->mm->rss;
page = vma->vm_ops->nopage(vma, address, page, error_code); prot = vma->vm_page_prot;
/*
* The fourth argument is "no_share", which tells the low-level code
* to copy, not share the page even if sharing is possible. It's
* essentially an early COW detection ("moo at 5 AM").
*/
page = vma->vm_ops->nopage(vma, address, page, (error_code & PAGE_RW) && (prot & PAGE_COW));
if (share_page(vma, address, error_code, 0)) { if (share_page(vma, address, error_code, 0)) {
free_page(page); free_page(page);
return; return;
} }
prot = vma->vm_page_prot; /*
if ((prot & PAGE_COW) && mem_map[MAP_NR(page)] > 1) * This silly early PAGE_DIRTY setting removes a race
* due to the bad i386 page protection.
*/
if (error_code & PAGE_RW) {
prot |= PAGE_DIRTY; /* can't be COW-shared: see "no_share" above */
} else if ((prot & PAGE_COW) && mem_map[MAP_NR(page)] > 1)
prot &= ~PAGE_RW; prot &= ~PAGE_RW;
if (put_page(vma->vm_task, page, address, prot)) if (put_page(vma->vm_task, page, address, prot))
return; return;
...@@ -1251,25 +1277,29 @@ void si_meminfo(struct sysinfo *val) ...@@ -1251,25 +1277,29 @@ void si_meminfo(struct sysinfo *val)
} }
/* This handles a generic mmap of a disk file */ /*
* This handles a generic mmap of a disk file.
*/
static unsigned long file_mmap_nopage(struct vm_area_struct * area, unsigned long address, static unsigned long file_mmap_nopage(struct vm_area_struct * area, unsigned long address,
unsigned long page, int error_code) unsigned long page, int no_share)
{ {
struct inode * inode = area->vm_inode; struct inode * inode = area->vm_inode;
unsigned int block; unsigned int block;
int nr[8]; int nr[8];
int i, j; int i, *p;
int prot = area->vm_page_prot;
address &= PAGE_MASK; address &= PAGE_MASK;
block = address - area->vm_start + area->vm_offset; block = address - area->vm_start + area->vm_offset;
block >>= inode->i_sb->s_blocksize_bits; block >>= inode->i_sb->s_blocksize_bits;
i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
for (i=0, j=0; i< PAGE_SIZE ; j++, block++, i += inode->i_sb->s_blocksize) p = nr;
nr[j] = bmap(inode,block); do {
if (error_code & PAGE_RW) *p = bmap(inode,block);
prot |= PAGE_RW | PAGE_DIRTY; i--;
return bread_page(page, inode->i_dev, nr, inode->i_sb->s_blocksize, !(error_code & PAGE_RW)); block++;
p++;
} while (i > 0);
return bread_page(page, inode->i_dev, nr, inode->i_sb->s_blocksize, no_share);
} }
struct vm_operations_struct file_mmap = { struct vm_operations_struct file_mmap = {
......
...@@ -344,21 +344,13 @@ static inline int try_to_swap_out(unsigned long * table_ptr) ...@@ -344,21 +344,13 @@ static inline int try_to_swap_out(unsigned long * table_ptr)
} }
if ((entry = find_in_swap_cache(page))) { if ((entry = find_in_swap_cache(page))) {
*table_ptr |= PAGE_DIRTY;
if (mem_map[MAP_NR(page)] != 1) { if (mem_map[MAP_NR(page)] != 1) {
*table_ptr |= PAGE_DIRTY;
printk("Aiee.. duplicated cached swap-cache entry\n");
return 0; return 0;
} }
if (!entry) { *table_ptr = entry;
if (!(entry = get_swap_page())) { invalidate();
return 0;
}
*table_ptr = entry;
invalidate();
write_swap_page(entry, (char *) (page & PAGE_MASK));
} else {
*table_ptr = entry;
invalidate();
}
free_page(page & PAGE_MASK); free_page(page & PAGE_MASK);
return 1; return 1;
} }
...@@ -901,12 +893,14 @@ asmlinkage int sys_swapon(const char * specialfile) ...@@ -901,12 +893,14 @@ asmlinkage int sys_swapon(const char * specialfile)
error = namei(specialfile,&swap_inode); error = namei(specialfile,&swap_inode);
if (error) if (error)
goto bad_swap; goto bad_swap;
p->swap_file = swap_inode;
error = -EBUSY; error = -EBUSY;
if (swap_inode->i_count != 1) if (swap_inode->i_count != 1)
goto bad_swap; goto bad_swap;
error = -EINVAL; error = -EINVAL;
if (S_ISBLK(swap_inode->i_mode)) { if (S_ISBLK(swap_inode->i_mode)) {
p->swap_device = swap_inode->i_rdev; p->swap_device = swap_inode->i_rdev;
p->swap_file = NULL;
iput(swap_inode); iput(swap_inode);
error = -ENODEV; error = -ENODEV;
if (!p->swap_device) if (!p->swap_device)
...@@ -918,9 +912,7 @@ asmlinkage int sys_swapon(const char * specialfile) ...@@ -918,9 +912,7 @@ asmlinkage int sys_swapon(const char * specialfile)
if (p->swap_device == swap_info[i].swap_device) if (p->swap_device == swap_info[i].swap_device)
goto bad_swap; goto bad_swap;
} }
} else if (S_ISREG(swap_inode->i_mode)) } else if (!S_ISREG(swap_inode->i_mode))
p->swap_file = swap_inode;
else
goto bad_swap; goto bad_swap;
p->swap_lockmap = (unsigned char *) get_free_page(GFP_USER); p->swap_lockmap = (unsigned char *) get_free_page(GFP_USER);
if (!p->swap_lockmap) { if (!p->swap_lockmap) {
......
...@@ -32,7 +32,9 @@ ...@@ -32,7 +32,9 @@
#include <linux/a.out.h> #include <linux/a.out.h>
#define MINIX_HEADER 32 #define MINIX_HEADER 32
#define GCC_HEADER 1024
#define N_MAGIC_OFFSET 1024
static int GCC_HEADER = sizeof(struct exec);
#define SYS_SIZE DEF_SYSSIZE #define SYS_SIZE DEF_SYSSIZE
...@@ -188,7 +190,10 @@ int main(int argc, char ** argv) ...@@ -188,7 +190,10 @@ int main(int argc, char ** argv)
die("Unable to open 'system'"); die("Unable to open 'system'");
if (read(id,buf,GCC_HEADER) != GCC_HEADER) if (read(id,buf,GCC_HEADER) != GCC_HEADER)
die("Unable to read header of 'system'"); die("Unable to read header of 'system'");
if (N_MAGIC(*ex) != ZMAGIC) if (N_MAGIC(*ex) == ZMAGIC) {
GCC_HEADER = N_MAGIC_OFFSET;
lseek(id, GCC_HEADER, SEEK_SET);
} else if (N_MAGIC(*ex) != QMAGIC)
die("Non-GCC header of 'system'"); die("Non-GCC header of 'system'");
fprintf(stderr,"System is %d kB (%d kB code, %d kB data and %d kB bss)\n", fprintf(stderr,"System is %d kB (%d kB code, %d kB data and %d kB bss)\n",
(ex->a_text+ex->a_data+ex->a_bss)/1024, (ex->a_text+ex->a_data+ex->a_bss)/1024,
......
...@@ -11,14 +11,14 @@ CFLAGS = -O2 -DSTDC_HEADERS $(TEST) ...@@ -11,14 +11,14 @@ CFLAGS = -O2 -DSTDC_HEADERS $(TEST)
.c.s: .c.s:
$(CC) $(CFLAGS) -S -o $*.s $< $(CC) $(CFLAGS) -S -o $*.s $<
.s.o: .s.o:
$(AS) -c -o $*.o $< $(AS) -o $*.o $<
.c.o: .c.o:
$(CC) $(CFLAGS) -c -o $*.o $< $(CC) $(CFLAGS) -c -o $*.o $<
all: zSystem all: zSystem
zSystem: piggy.o $(zOBJECTS) zSystem: piggy.o $(zOBJECTS)
$(LD) $(LDFLAGS) -o zSystem -Ttext 1000 $(zOBJECTS) piggy.o $(LD) $(LOWLDFLAGS) -o zSystem $(zOBJECTS) piggy.o
head.o: head.s head.o: head.s
......
...@@ -18,7 +18,9 @@ ...@@ -18,7 +18,9 @@
#include <a.out.h> #include <a.out.h>
#include <linux/config.h> #include <linux/config.h>
#define GCC_HEADER 1024 #define N_MAGIC_OFFSET 1024
static int GCC_HEADER = sizeof(struct exec);
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
...@@ -49,7 +51,10 @@ int main(int argc, char ** argv) ...@@ -49,7 +51,10 @@ int main(int argc, char ** argv)
die("Unable to open 'system'"); die("Unable to open 'system'");
if (read(id,buf,GCC_HEADER) != GCC_HEADER) if (read(id,buf,GCC_HEADER) != GCC_HEADER)
die("Unable to read header of 'system'"); die("Unable to read header of 'system'");
if (N_MAGIC(*ex) != ZMAGIC) if (N_MAGIC(*ex) == ZMAGIC) {
GCC_HEADER = N_MAGIC_OFFSET;
lseek(id, GCC_HEADER, SEEK_SET);
} else if (N_MAGIC(*ex) != QMAGIC)
die("Non-GCC header of 'system'"); die("Non-GCC header of 'system'");
sz = N_SYMOFF(*ex) - GCC_HEADER + 4; /* +4 to get the same result than tools/build */ sz = N_SYMOFF(*ex) - GCC_HEADER + 4; /* +4 to get the same result than tools/build */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment