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

Import 1.1.34

parent 5079f36d
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 33
SUBLEVEL = 34
all: Version zImage
......@@ -79,9 +79,21 @@ endif
AS86 =as86 -0 -a
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
LD =ld
LDFLAGS =#-qmagic
HOSTCC =gcc
CC =gcc -D__KERNEL__ -I$(TOPDIR)/include
MAKE =make
......@@ -156,7 +168,7 @@ init/main.o: $(CONFIGURE) init/main.c
$(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $<
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) \
$(FILESYSTEMS) \
$(DRIVERS) \
......@@ -201,7 +213,7 @@ zlilo: $(CONFIGURE) zImage
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
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) \
$(FILESYSTEMS) \
$(DRIVERS) \
......
......@@ -14,8 +14,8 @@
! Move PS/2 aux init code to psaux.c
! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
!
! some changes and additional features by Christoph Niemann, March 1993
! (niemann@rubdv15.ETDV.Ruhr-Uni-Bochum.De)
! some changes and additional features by Christoph Niemann,
! March 1993/June 1994 (Christoph.Niemann@linux.org)
!
! NOTE! These had better be the same as in bootsect.s!
......@@ -97,9 +97,11 @@ novga: mov [14],ax
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
push ax
mov es,ax
mov di,#0x0080
mov cx,#0x10
push cx
cld
rep
movsb
......@@ -109,11 +111,9 @@ novga: mov [14],ax
xor ax,ax ! clear ax
mov ds,ax
lds si,[4*0x46]
mov ax,#INITSEG
mov es,ax
pop cx
pop es
mov di,#0x0090
mov cx,#0x10
cld
rep
movsb
......@@ -159,7 +159,7 @@ no_psmouse:
cld ! 'direction'=0, movs moves forward
do_move:
mov es,ax ! destination segment
add ax,#0x100
inc ah ! instead of add ax,#0x100
cmp ax,#0x9000
jz end_move
mov ds,bx ! source segment
......@@ -246,7 +246,8 @@ end_move:
! 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.
!
mov ax,#0x0001 ! protected mode (PE) bit
xor ax,ax
inc ax ! protected mode (PE) bit
lmsw ax ! This is it!
jmp flush_instr
flush_instr:
......@@ -394,33 +395,89 @@ vga28:
mov ax,#0x501c ! return 80x28
ret
/* 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
lea si,id9GXE ! Check for the #9GXE (jyanowit@orixa.mtholyoke.edu,thanks dlm40629@uxa.cso.uiuc.edu)
mov di,#0x49 ! id string is at c000:049
mov cx,#0x11 ! length of "Graphics Power By"
repe
cmpsb
jne of1280
is9GXE: lea si,dsc9GXE ! table of descriptions of video modes for BIOS
lea di,mo9GXE ! table of sizes of video modes for my BIOS
mov cx,#0x0f35 ! we store some constants in cl/ch
mov dx,#0x03d4
movb al,#0x38
call inidx
mov bh,al ! store current value of CRT-register 0x38
mov ax,#0x0038
call outidx ! disable writing to special regs
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
of1280: cld
lea si,idf1280 ! Check for Orchid F1280 (dingbat@diku.dk)
mov di,#0x10a ! id string is at c000:010a
mov cx,#0x21 ! length
repe
cmpsb
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
no_s3: movb al,#0x35 ! restore CRT register 0x35
movb ah,bl
call outidx
no_s31: movb ah,bh
movb al,#0x38
call outidx ! restore old value of CRT register 0x38
lea si,idati ! Check ATI 'clues'
mov di,#0x31
mov cx,#0x09
......@@ -710,6 +767,29 @@ gotmode: xor ah,ah
pop ds
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
prtstr: lodsb
......@@ -817,9 +897,8 @@ idcandt: .byte 0xa5
idgenoa: .byte 0x77, 0x00, 0x99, 0x66
idparadise: .ascii "VGA="
idoakvga: .ascii "OAK VGA "
idf1280: .ascii "Orchid Technology Fahrenheit 1280"
id9GXE: .ascii "Graphics Power By"
idVRAM: .ascii "Stealth VRAM"
idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
.byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
! Manufacturer: Numofmodes+2: Mode:
! 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
motseng: .byte 0x07, 0x26, 0x2a, 0x23, 0x24, 0x22
movideo7: .byte 0x08, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
mooakvga: .byte 0x08, 0x00, 0x07, 0x4e, 0x4f, 0x50, 0x51
mo9GXE: .byte 0x04, 0x54, 0x55
mof1280: .byte 0x04, 0x54, 0x55
mo_S3: .byte 0x04, 0x54, 0x55
mounknown: .byte 0x02
! msb = Cols lsb = Rows:
......@@ -855,8 +933,7 @@ dsctrident: .word 0x5032, 0x501c, 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842
dsctseng: .word 0x5032, 0x501c, 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
dscvideo7: .word 0x5032, 0x501c, 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
dscoakvga: .word 0x5032, 0x501c, 0x2819, 0x5019, 0x503c, 0x843c, 0x8419, 0x842b
dscf1280: .word 0x5032, 0x501c, 0x842b, 0x8419
dsc9GXE: .word 0x5032, 0x501c, 0x842b, 0x8419
dsc_S3: .word 0x5032, 0x501c, 0x842b, 0x8419
dsunknown: .word 0x5032, 0x501c
modesave: .word SVGA_MODE
......
......@@ -5,7 +5,7 @@
* and for "no-sound" interfaces like Lasermate and the
* 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
* and with the new CR-562-B V0.75 on a "naked" Panasonic
* CI-101P interface. And vice versa.
......@@ -117,6 +117,9 @@
* 2.3 Let "door lock" and "eject" live together.
* Implemented "close tray" (done automatically during open).
*
* 2.4 Use different names for device registering.
*
*
* TODO
*
* disk change detection
......@@ -192,7 +195,7 @@
#include "blk.h"
#define VERSION "2.3 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define VERSION "2.4 Eberhard Moenkeberg <emoenke@gwdg.de>"
#define SBPCD_DEBUG
......@@ -397,6 +400,18 @@ static char *str_sb = "SoundBlaster";
static char *str_lm = "LaserMate";
static char *str_sp = "SPEA";
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,
/*==========================================================================*/
/*
* 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)
{
......@@ -3551,7 +3565,7 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
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);
#if PRINTK_BUG
......
......@@ -21,7 +21,7 @@ Space.o: Space.c ../../include/linux/autoconf.h
net_init.o: ../../include/linux/autoconf.h
ifdef CONFIG_SK_G16
NETDRV_OBJS := $(NETDRV_OBJS) net.a(sk_g16.o)
NETDRV_OBJS := $(NETDRV_OBJS) sk_g16.o
endif
ifdef CONFIG_WD80x3
......@@ -53,7 +53,7 @@ hp.o: hp.c CONFIG
endif
ifdef CONFIG_HPLAN_PLUS
NETDRV_OBJS := $(NETDRV_OBJS) net.a(hp-plus.o)
NETDRV_OBJS := $(NETDRV_OBJS) hp-plus.o
CONFIG_8390 = CONFIG_8390
endif
......@@ -104,7 +104,7 @@ de600.o: de600.c CONFIG
$(CC) $(CPPFLAGS) $(CFLAGS) $(DE600_OPTS) -c $<
ifdef CONFIG_DE620
NETDRV_OBJS := $(NETDRV_OBJS) net.a(de620.o)
NETDRV_OBJS := $(NETDRV_OBJS) de620.o
endif
de620.o: de620.c CONFIG
$(CC) $(CPPFLAGS) $(CFLAGS) $(DE620_OPTS) -c $<
......@@ -155,7 +155,7 @@ NETDRV_OBJS := $(NETDRV_OBJS) ac3200.o
CONFIG_8390 = CONFIG_8390
endif
ifdef CONFIG_APRICOT
NETDRV_OBJS := $(NETDRV_OBJS) net.a(apricot.o)
NETDRV_OBJS := $(NETDRV_OBJS) apricot.o
endif
ifdef CONFIG_8390
......
/* e2100.c: A Cabletron E2100 series ethernet driver for linux. */
/*
Written 1993 by Donald Becker.
Written 1993-1994 by Donald Becker.
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,
......@@ -9,15 +11,15 @@
This is a driver for the Cabletron E2100 series ethercards.
The Author may be reached as becker@cesdis.gsfc.nasa.gov, or
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
The E2100 series ethercard is a fairly generic shared memory 8390
implementation. The only unusual aspect is the way the shared memory
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
as the write value for that register. Either someone wasn't too used
to dem bit en bites, or they were trying to obfusicate the programming
interface.
station address region, and the low three bits of next outb() *address*
is used as the write value for that register. Either someone wasn't
too used to dem bit en bites, or they were trying to obfusicate the
programming interface.
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
......@@ -30,7 +32,7 @@
*/
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/kernel.h>
......@@ -39,30 +41,16 @@ static char *version =
#include <linux/string.h>
#include <asm/io.h>
#include <asm/system.h>
#ifndef PRE_PL13
#include <linux/ioport.h> /* Delete if your kernel doesn't have it. */
#endif
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include "8390.h"
/* Compatibility definitions for earlier kernel versions. */
#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
static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
/* Offsets from the base_addr.
Read from the ASIC register, and the low 3(?) bits of the next outb() address
is used to set the cooresponding register. */
Read from the ASIC register, and the low three bits of the next outb()
address is used to set the cooresponding register. */
#define E21_NIC_OFFSET 0 /* Offset to the 8390 NIC. */
#define E21_ASIC 0x10
#define E21_MEM_ENABLE 0x10
......@@ -70,11 +58,12 @@ extern struct device *irq2dev_map[16];
#define E21_MEM_ON_8 0x07 /* Enable memory in 8 bit mode. */
#define E21_MEM_BASE 0x11
#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_BIG_MEM 0x04 /* Use a bigger (64K) buffer (we don't) */
#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,
unsigned char start_page )
......@@ -122,26 +111,22 @@ static int e21_close(struct device *dev);
int e2100_probe(struct device *dev)
{
int *port, ports[] = {0x300, 0x280, 0x380, 0x220, 0};
short base_addr = dev->base_addr;
int *port;
int base_addr = dev->base_addr;
if (base_addr > 0x1ff) /* Check a single specified location. */
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;
for (port = &ports[0]; *port; port++) {
ushort ioaddr = *port;
if (check_region(ioaddr, ETHERCARD_TOTAL_SIZE))
for (port = e21_probe_list; *port; port++) {
if (check_region(*port, E21_IO_EXTENT))
continue;
if (inb(ioaddr + E21_SAPROM + 0) == 0x00
&& inb(ioaddr + E21_SAPROM + 1) == 0x00
&& inb(ioaddr + E21_SAPROM + 2) == 0x1d
&& e21_probe1(dev, ioaddr) == 0)
if (e21_probe1(dev, *port) == 0)
return 0;
}
return -ENODEV;
return ENODEV;
}
int e21_probe1(struct device *dev, int ioaddr)
......@@ -149,29 +134,30 @@ int e21_probe1(struct device *dev, int ioaddr)
int i, status;
unsigned char *station_addr = dev->dev_addr;
/* We've already checked the station address prefix, now verify by making
certain that there is a 8390 at the expected location. */
/* First check the station address for the Ctron prefix. */
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);
SLOW_DOWN_IO;
status = inb(ioaddr);
if (status != 0x21 && status != 0x23)
return -ENODEV;
return ENODEV;
#ifdef testing_only
printk("%s: E21xx at %#3x (PAXI backwards): ", dev->name, ioaddr);
for (i = 0; i < 16; i++)
printk(" %02X", inb(ioaddr + 0x1f - i));
printk("\n");
#endif
/* Grab the region so we can find a different board if IRQ select fails. */
snarf_region(ioaddr, E21_IO_EXTENT);
/* Read the station address PROM. */
for (i = 0; i < 6; i++)
station_addr[i] = inb(ioaddr + E21_SAPROM + i);
/* Grab the region so we can find another board if needed . */
snarf_region(ioaddr, ETHERCARD_TOTAL_SIZE);
inb(ioaddr + E21_MEDIA); /* Point to media selection. */
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++)
printk(" %02X", station_addr[i]);
......@@ -182,14 +168,12 @@ int e21_probe1(struct device *dev, int ioaddr)
dev->irq = irqlist[i];
break;
}
} else if (dev->irq == 2) /* Fixup bogosity: IRQ2 is really IRQ9 */
dev->irq = 9;
/* Snarf the interrupt now. */
if (irqaction (dev->irq, &ei_sigaction)) {
printk (" unable to get IRQ %d.\n", dev->irq);
return -EBUSY;
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;
/* The 8390 is at the base address. */
dev->base_addr = ioaddr;
......@@ -201,6 +185,7 @@ int e21_probe1(struct device *dev, int ioaddr)
ei_status.tx_start_page = E21_TX_START_PG;
ei_status.rx_start_page = E21_RX_START_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
low mem_end bits. */
......@@ -208,10 +193,12 @@ int e21_probe1(struct device *dev, int ioaddr)
dev->if_port = dev->mem_end & 7;
else {
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++)
if (station_addr[i] != inb(ioaddr + E21_SAPROM))
if (station_addr[i] != inb(ioaddr + E21_SAPROM + 8 + i)) {
dev->if_port = 1;
break;
}
}
/* 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)
dev->mem_end = dev->rmem_end = dev->mem_start + 2*1024;
#endif
printk(" IRQ %d, %s interface, memory at %#x-%#x.\n", dev->irq,
dev->if_port ? "secondary" : "primary", dev->mem_start,
dev->mem_start + 2*1024 - 1);
printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
dev->if_port ? "secondary" : "primary", dev->mem_start);
if (ei_debug > 0)
printk(version);
......@@ -249,14 +235,19 @@ e21_open(struct device *dev)
{
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. */
inb_p(ioaddr + E21_IRQ_LOW);
outb_p(0, ioaddr + E21_ASIC + (dev->irq & 7));
inb_p(ioaddr + E21_IRQ_HIGH); /* High IRQ bit, and if_port. */
outb_p(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
inb(ioaddr + E21_IRQ_LOW);
outb(0, ioaddr + E21_ASIC + (dev->irq & 7));
inb(ioaddr + E21_IRQ_HIGH); /* High IRQ bit, and if_port. */
outb(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
+ (dev->if_port ? E21_ALT_IFPORT : 0));
inb_p(ioaddr + E21_MEM_BASE);
outb_p(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
inb(ioaddr + E21_MEM_BASE);
outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
return ei_open(dev);
}
......@@ -267,7 +258,7 @@ e21_reset_8390(struct device *dev)
short ioaddr = dev->base_addr;
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;
/* Set up the ASIC registers, just in case something changed them. */
......@@ -276,9 +267,9 @@ e21_reset_8390(struct device *dev)
return;
}
/* Block input and output are easy on shared memory ethercards. The E21xx makes
block_input() especially easy by wrapping the top ring buffer to the bottom
automatically. */
/* Block input and output are easy on shared memory ethercards.
The E21xx makes block_input() especially easy by wrapping the top
ring buffer to the bottom automatically. */
static int
e21_block_input(struct device *dev, int count, char *buf, int ring_offset)
{
......@@ -323,14 +314,33 @@ e21_close(struct device *dev)
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
free_irq(dev->irq);
dev->irq = ei_status.saved_irq;
/* 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);
return 0;
}
#ifdef HAVE_DEVLIST
struct netdev_entry e21_drv =
{"e21", e21_probe1, E21_IO_EXTENT, e21_probe_list};
#endif
/*
* Local variables:
* 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)
static int plip_ioctl(struct device *dev, struct ifreq *rq)
{
struct net_local *nl=(struct net_local *)dev->priv;
struct plipconf *pc=(struct plipconf *)rq->ifr_data;
struct net_local *nl = (struct net_local *) dev->priv;
struct plipconf *pc = (struct plipconf *) &rq->ifr_data;
switch(pc->pcmd)
{
......
......@@ -1113,14 +1113,14 @@ __asm__ __volatile__("rep ; movsl": \
* etc. This also allows us to optimize memory usage by sharing code pages
* 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];
unsigned long where;
int i, j;
if (share) {
where = try_to_share_buffers(address,dev,b,size);
if (!no_share) {
where = try_to_share_buffers(address, dev, b, size);
if (where)
return where;
}
......@@ -1132,14 +1132,14 @@ unsigned long bread_page(unsigned long address, dev_t dev, int b[], int size, in
}
read_buffers(bh,i);
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]->b_uptodate)
COPYBLK(size, (unsigned long) bh[i]->b_data,address);
COPYBLK(size, (unsigned long) bh[i]->b_data, where);
brelse(bh[i]);
}
}
return where;
return address;
}
/*
......
......@@ -27,7 +27,7 @@
* Fill in the supplied page for mmap
*/
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;
unsigned int clear;
......
......@@ -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 set_blocksize(dev_t dev, 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,
unsigned int pos, unsigned int filesize);
extern void put_super(dev_t dev);
......
......@@ -228,9 +228,14 @@ extern void shm_no_page (ulong *);
/* swap cache stuff (in swap.c) */
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];
}
extern inline void swap_cache_invalidate(unsigned long addr)
{
swap_cache[addr >> PAGE_SHIFT] = 0;
}
#endif
......@@ -157,7 +157,7 @@ static struct vm_area_struct * find_vma(struct task_struct * tsk, unsigned long
struct vm_area_struct * vma;
addr &= PAGE_MASK;
for (vma = current->mm->mmap ; ; vma = vma->vm_next) {
for (vma = tsk->mm->mmap ; ; vma = vma->vm_next) {
if (!vma)
return NULL;
if (vma->vm_end > addr)
......
......@@ -263,11 +263,17 @@ int copy_page_tables(struct task_struct * tsk)
*new_page_table = swap_duplicate(pg);
continue;
}
if ((pg & (PAGE_RW | PAGE_COW)) == (PAGE_RW | PAGE_COW))
pg &= ~PAGE_RW;
if (pg > high_memory || (mem_map[MAP_NR(pg)] & MAP_PAGE_RESERVED)) {
*new_page_table = pg;
if (mem_map[MAP_NR(pg)] & MAP_PAGE_RESERVED)
continue;
}
if (pg & PAGE_COW)
pg &= ~PAGE_RW;
if (in_swap_cache(pg)) {
swap_cache_invalidate(pg);
pg |= PAGE_DIRTY;
}
*new_page_table = pg;
*old_page_table = 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
/* if it is private, it must be clean to be shared */
if ((from_area->vm_page_prot & PAGE_COW) && (from & PAGE_DIRTY))
return 0;
/* the swap caching doesn't really handle shared pages.. */
if (in_swap_cache(from))
return 0;
/* is the page reasonable at all? */
if (from >= high_memory)
return 0;
......@@ -748,14 +751,26 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
return 0;
/* do we copy? */
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);
*(unsigned long *) to_page = newpage | to_area->vm_page_prot;
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)]++;
/* 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)
to &= ~PAGE_RW;
*(unsigned long *) to_page = to;
......@@ -764,7 +779,7 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
return 1;
if (!(from_area->vm_page_prot & PAGE_COW))
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;
*(unsigned long *) from_page = from;
invalidate();
......@@ -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->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)) {
free_page(page);
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;
if (put_page(vma->vm_task, page, address, prot))
return;
......@@ -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,
unsigned long page, int error_code)
unsigned long page, int no_share)
{
struct inode * inode = area->vm_inode;
unsigned int block;
int nr[8];
int i, j;
int prot = area->vm_page_prot;
int i, *p;
address &= PAGE_MASK;
block = address - area->vm_start + area->vm_offset;
block >>= inode->i_sb->s_blocksize_bits;
for (i=0, j=0; i< PAGE_SIZE ; j++, block++, i += inode->i_sb->s_blocksize)
nr[j] = bmap(inode,block);
if (error_code & PAGE_RW)
prot |= PAGE_RW | PAGE_DIRTY;
return bread_page(page, inode->i_dev, nr, inode->i_sb->s_blocksize, !(error_code & PAGE_RW));
i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
p = nr;
do {
*p = bmap(inode,block);
i--;
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 = {
......
......@@ -344,21 +344,13 @@ static inline int try_to_swap_out(unsigned long * table_ptr)
}
if ((entry = find_in_swap_cache(page))) {
*table_ptr |= PAGE_DIRTY;
if (mem_map[MAP_NR(page)] != 1) {
*table_ptr |= PAGE_DIRTY;
printk("Aiee.. duplicated cached swap-cache entry\n");
return 0;
}
if (!entry) {
if (!(entry = get_swap_page())) {
return 0;
}
*table_ptr = entry;
invalidate();
write_swap_page(entry, (char *) (page & PAGE_MASK));
} else {
*table_ptr = entry;
invalidate();
}
free_page(page & PAGE_MASK);
return 1;
}
......@@ -901,12 +893,14 @@ asmlinkage int sys_swapon(const char * specialfile)
error = namei(specialfile,&swap_inode);
if (error)
goto bad_swap;
p->swap_file = swap_inode;
error = -EBUSY;
if (swap_inode->i_count != 1)
goto bad_swap;
error = -EINVAL;
if (S_ISBLK(swap_inode->i_mode)) {
p->swap_device = swap_inode->i_rdev;
p->swap_file = NULL;
iput(swap_inode);
error = -ENODEV;
if (!p->swap_device)
......@@ -918,9 +912,7 @@ asmlinkage int sys_swapon(const char * specialfile)
if (p->swap_device == swap_info[i].swap_device)
goto bad_swap;
}
} else if (S_ISREG(swap_inode->i_mode))
p->swap_file = swap_inode;
else
} else if (!S_ISREG(swap_inode->i_mode))
goto bad_swap;
p->swap_lockmap = (unsigned char *) get_free_page(GFP_USER);
if (!p->swap_lockmap) {
......
......@@ -32,7 +32,9 @@
#include <linux/a.out.h>
#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
......@@ -188,7 +190,10 @@ int main(int argc, char ** argv)
die("Unable to open 'system'");
if (read(id,buf,GCC_HEADER) != GCC_HEADER)
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'");
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,
......
......@@ -11,14 +11,14 @@ CFLAGS = -O2 -DSTDC_HEADERS $(TEST)
.c.s:
$(CC) $(CFLAGS) -S -o $*.s $<
.s.o:
$(AS) -c -o $*.o $<
$(AS) -o $*.o $<
.c.o:
$(CC) $(CFLAGS) -c -o $*.o $<
all: zSystem
zSystem: piggy.o $(zOBJECTS)
$(LD) $(LDFLAGS) -o zSystem -Ttext 1000 $(zOBJECTS) piggy.o
$(LD) $(LOWLDFLAGS) -o zSystem $(zOBJECTS) piggy.o
head.o: head.s
......
......@@ -18,7 +18,9 @@
#include <a.out.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
......@@ -49,7 +51,10 @@ int main(int argc, char ** argv)
die("Unable to open 'system'");
if (read(id,buf,GCC_HEADER) != GCC_HEADER)
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'");
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