Commit 3495b6a6 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.0.9

parent 2409324e
......@@ -1004,9 +1004,10 @@ S: Germany
N: David C. Niemi
E: niemi@erols.com
D: Mtools/VFAT/floppy work, benchmarking, random kernel dilettante
D: Assistant maintainer of Mtools, fdutils, and floppy driver
D: Administrator of WAUUG Linux Server, http://linux.wauug.org
S: 2364 Old Trail Drive
S: Reston, Virginia 22091
S: Reston, Virginia 20191
S: USA
N: Michael O'Reilly
......@@ -1449,7 +1450,7 @@ S: Fargo, ND 58122
S: USA
N: Hans-Joachim Widmaier
E: jbhr@sofal.tynet.sub.org
E: hjw@zvw.de
D: AFFS rewrite
S: Eichenweg 16
S: 73650 Winterbach
......
......@@ -22,7 +22,11 @@ prefer a HTML-ized shopping list.
documento, consultad la traduccion de Alfredo Sanjuan en
http://slug.ctv.es/~alfredo/Cambios.html.
Last updated: July 13, 1996.
Akik magyarul szeretnenek olvasni az uj kernellel kapcsolatos
valtozasokrol, az alabbi cimen megtalaljak Nyitrai Tamas forditasat:
http://www.datanet.hu/generations/linux/newkernel.html.
Last updated: July 21, 1996.
Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
Current Releases
......@@ -40,7 +44,9 @@ Current Releases
- Gpm 1.09
- SysVinit 2.64
- Util-linux 2.5
- Mount 2.5k
- Net-tools 1.32-alpha
- Kbd 0.91
Upgrade notes
*************
......@@ -225,6 +231,15 @@ Kbd
For those of you needing non-ASCII character/font support, you should
upgrade to ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/kbd-0.91.tar.gz.
Mount
=====
The mount util is distributed as part of util-linux, which is
currently at release 2.5. Some may find, especially when using the
loop or xiafs file system, NFS, or automounting, that they need to
upgrade to the latest release of mount, available from
ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5k.tar.gz.
Console
=======
......@@ -318,7 +333,7 @@ ftp://louie.udel.edu/pub/ntp/xntp3.5f.tar.Z.
Sound driver
============
The sound driver was upgraded in the 1.3.x kernels, breaking vplay.
The sound driver was upgraded in the 2.0.x kernels, breaking vplay.
To fix this problem, get a new version of the sndkit from
ftp://ftp.best.com/pub/front/tasd/snd-util-3.5.tar.gz. Some users
report that various other sound utils (cdd2wav-sbpcd, for example) need
......@@ -352,7 +367,7 @@ Loop device
file as a file system, which can allow for all sorts of cool things
like encrypted file systems and such. To use it, you'll need a
modified version of mount from
ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5X.tar.gz; preliminary work
ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5k.tar.gz; preliminary work
on encrypted file system support can be found in
ftp.funet.fi:/pub/OS/Linux/BETA/loop/des.1.tar.gz.
......@@ -463,7 +478,9 @@ groff
pages due to changes in groff. If your man pages display <AD> for -
when present at the end of a line, try setting an appropriate value
(many have reported success with "latin1", for example) for the
environmental variable LESSCHARSET.
environmental variable LESSCHARSET. Another, and probably better,
solution is to edit the file /usr/lib/man.config and change all
`-Tlatin1' options to `-Tascii'.
How to know the version of the installed programs
*************************************************
......
Amiga filesystems Overview
==========================
Not all varieties of the Amiga filesystems are supported. The Amiga
currently knows 6 different filesystems:
Not all varieties of the Amiga filesystems are supported for reading and
writing. The Amiga currently knows 6 different filesystems:
DOS\0 The old or original filesystem, not really suited for
hard disks and normally not used on them, either.
Supported read/write.
DOS\1 The original Fast File System. Supported.
DOS\1 The original Fast File System. Supported read/write.
DOS\2 The old "international" filesystem. International means that
a bug has been fixed so that accented ("international") letters
in file names are case-insensitive, as they ought to be.
Supported read/write.
DOS\3 The "international" Fast File System. Supported.
DOS\3 The "international" Fast File System. Supported read/write.
DOS\4 The original filesystem with directory cache. The directory
cache speeds up directory accesses on floppies considerably,
but slows down file creation/deletion. Doesn't make much
sense on hard disks. Not supported.
sense on hard disks. Supported read only.
DOS\5 The Fast File System with directory cache. Not supported.
DOS\5 The Fast File System with directory cache. Supported read only.
All of the above filesystems allow block sizes from 512 to 32K bytes.
Supported block sizes are: 512, 1024, 2048 and 4096 bytes. Larger blocks
......@@ -47,9 +49,6 @@ setuid[=uid] This sets the owner of all files and directories in the file
setgid[=gid] Same as above, but for gid.
use_mp The uid and gid are taken from the now covered mount point
instead of the current user or value defined.
mode=mode Sets the mode flags to the given (octal) value, regardless
of the original permissions. Directories will get an x
permission, if the corresponding r bit is set.
......@@ -72,6 +71,13 @@ quiet The file system will not return an error for disallowed
verbose The volume name, file system type and block size will
be written to the syslog.
prefix=path Path will be prefixed to every absolute path name of
symbolic links on an AFFS partition. Default = /
volume=name When symbolic links with an absolute path are created
on an AFFS partition, volume will be prepended as the
volume name. Default = "" (empty string).
Handling of the Users/Groups and protection flags
=================================================
......@@ -109,9 +115,33 @@ The Linux rwxrwxrwx file mode is handled as follows:
Newly created files and directories will get the user and group id
of the current user and a mode according to the umask.
Command line example
====================
mount Archive/Amiga/Workbench3.1.adf /mnt -t affs -o loop,size=1760
Symbolic links
==============
Although the Amiga and Linux file systems resemble each other, there
are some, not always subtle, differences. One of them becomes apparent
with symbolic links. While Linux has a file system with exactly one
root directory, the Amiga has a seperate root directory for each
file system (i. e. partition, floppy disk, ...). With the Amiga,
these entities are called "volumes". They have symbolic names which
can be used to access them. Thus, symbolic links can point to a
different volume. AFFS turns the volume name into a directory name
and prepends the prefix path (see prefix option) to it.
Example:
You mount all your Amiga partitions under /amiga/<volume> (where
<volume> is the name of the volume), and you give the option
"prefix=/amiga/" when mounting all your AFFS partitions. (They
might be "User", "WB" and "Graphics", the mount points /amiga/User,
/amiga/WB and /amiga/Graphics). A symbolic link referring to
"User:sc/include/dos/dos.h" will be followed to
"/amiga/User/sc/include/dos/dos.h".
Examples
========
Command line
mount Archive/Amiga/Workbench3.1.adf /mnt -t affs -o loop,reserved=4
mount /dev/sda3 /Amiga -t affs
/etc/fstab example
......@@ -151,7 +181,7 @@ Until then, you should do
ln -s /bin/true /etc/fs/mkfs.affs
It's not possible to read floppy disks with a normal PC or workstation
due to an incompatibility to the Amiga floppy controller.
due to an incompatibility with the Amiga floppy controller.
If you are interested in an Amiga Emulator for Linux, look at
......
......@@ -107,7 +107,7 @@ IRQ numbers being used by the interfaces (normally IRQ14 & IRQ15).
Interfaces beyond the first two are not normally probed for, but may be
specified using kernel "command line" options. For example,
ide3=0x168,0x36e,10 /* ioports 0x1e8-0x1ef,0x3f0, irq 11 */
ide3=0x168,0x36e,10 /* ioports 0x168-0x16f,0x36e, irq 11 */
Normally the irq number need not be specified, as ide.c will probe for it:
......@@ -120,6 +120,9 @@ The standard port, and irq values are these:
ide2=0x1e8,0x3ee,11
ide3=0x168,0x36e,10
Note that the first parameter reserves 8 contiguous ioports, whereas the
second value denotes a single ioport. If in doubt, do a 'cat /proc/ioports'.
In all probability the device uses these ports and irqs if it is attached
to the appropriate ide channel. Pass the parameter for the correct ide
channel to the kernel, as explained above.
......
VERSION = 2
PATCHLEVEL = 0
SUBLEVEL = 8
SUBLEVEL = 9
ARCH = i386
......
......@@ -62,6 +62,7 @@ CONFIG_BLK_DEV_FD=y
CONFIG_BLK_DEV_RAM=y
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_DEV_HD is not set
#
# Networking options
......
......@@ -40,7 +40,7 @@ CPP=$(CC) -E -D__ELF__
OBJDUMP=$(CROSS_COMPILE)objdump
OBJDUMP_FLAGS=-k -q
ENCAPS=$(CROSS_COMPILE)encaps
OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment
OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -R .stab -R .stabstr
ZLDFLAGS=-e startup_32
LDFLAGS=-e stext
ZIMAGE_OFFSET=0x1000
......
......@@ -16,13 +16,13 @@ else
bool ' Support removable IDE interfaces (PCMCIA)' CONFIG_BLK_DEV_IDE_PCMCIA
bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640
if [ "$CONFIG_PCI" = "y" ]; then
bool ' Intel 430FX (Triton) chipset DMA support' CONFIG_BLK_DEV_TRITON
bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000
bool ' Intel 82371 PIIX (Triton I/II) DMA support' CONFIG_BLK_DEV_TRITON
fi
bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS
if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
comment 'Note: most of these also require special kernel boot parameters'
bool ' ALI M1439/M1445 support' CONFIG_BLK_DEV_ALI14XX
bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX
bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278
bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
......@@ -50,6 +50,8 @@ tristate 'XT harddisk support' CONFIG_BLK_DEV_XD
if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then
define_bool CONFIG_BLK_DEV_HD y
else
define_bool CONFIG_BLK_DEV_HD n
fi
endmenu
......@@ -7,6 +7,8 @@
/*
* ALI M14xx chipset EIDE controller
*
* Works for ALI M1439/1443/1445/1487/1489 chipsets.
*
* Adapted from code developed by derekn@vw.ece.cmu.edu. -ml
* Derek's notes follow:
*
......@@ -23,6 +25,16 @@
*
* Derek Noonburg (derekn@ece.cmu.edu)
* 95-sep-26
*
* Update 96-jul-13:
*
* I've since upgraded to two disks and a CD-ROM, with no trouble, and
* I've also heard from several others who have used it successfully.
* This driver appears to work with both the 1443/1445 and the 1487/1489
* chipsets. I've added support for PIO mode 4 for the 1487. This
* seems to work just fine on the 1443 also, although I'm not sure it's
* advertised as supporting mode 4. (I've been running a WDC AC21200 in
* mode 4 for a while now with no trouble.) -Derek
*/
#undef REALLY_SLOW_IO /* most systems can safely undef this */
......@@ -45,8 +57,8 @@
* from 25 to 50. Setting this too *low* will make the EIDE
* controller unable to communicate with the disks.
*
* I suggest using a default of 50, since it should work ok with any
* system. (Low values cause problems because it multiplies by bus speed
* The value is 50 by default -- this should work ok with any system.
* (Low values cause problems because it multiplies by bus speed
* to get cycles, and thus gets a too-small cycle count and tries to
* access the disks too fast. I tried this once under DOS and it locked
* up the system.) -- derekn@vw.ece.cmu.edu
......@@ -71,11 +83,13 @@ static RegInitializer initData[] = {
};
/* default timing parameters for each PIO mode */
static struct { int time1, time2; } timeTab[4] = {
#define ALI_MAX_PIO 4
static struct { int time1, time2; } timeTab[ALI_MAX_PIO+1] = {
{600, 165}, /* PIO 0 */
{383, 125}, /* PIO 1 */
{240, 100}, /* PIO 2 */
{180, 80} /* PIO 3 */
{180, 80}, /* PIO 3 */
{120, 70} /* PIO 4 */
};
/* timing parameter registers for each drive */
......@@ -127,20 +141,20 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
if (pio == 255)
pio = ide_get_best_pio_mode(drive);
if (pio > 3)
pio = 3;
if (pio > ALI_MAX_PIO)
pio = ALI_MAX_PIO;
/* calculate timing, according to PIO mode */
time1 = timeTab[pio].time1;
time2 = timeTab[pio].time2;
if (pio == 3) {
if (pio >= 3) {
time1a = (id->capability & 0x08) ? id->eide_pio_iordy : id->eide_pio;
if (time1a != 0 && time1a < time1)
time1 = time1a;
}
param3 = param1 = (time2 * ALI_14xx_BUS_SPEED + 999) / 1000;
param4 = param2 = (time1 * ALI_14xx_BUS_SPEED + 999) / 1000 - param1;
if (pio != 3) {
if (pio < 3) {
param3 += 8;
param4 += 8;
}
......
This diff is collapsed.
......@@ -41,8 +41,8 @@
*
* DTC2278S has only a single IDE interface.
* DTC2278D has two IDE interfaces and is otherwise identical to the S version.
* DTC2278E has onboard BIOS, while the others do not.
* DTC2278EB: "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
* DTC2278E also has serial ports and a printer port
* DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
*
* There may be a fourth controller type. The S and D versions use the
* Winbond chip, and I think the E version does also.
......
......@@ -551,6 +551,88 @@ static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sec
#endif /* CONFIG_SUN_PARTITION */
#ifdef CONFIG_AMIGA_PARTITION
#include <asm/byteorder.h>
#include <linux/affs_hardblocks.h>
static __inline__ __u32
checksum_block(__u32 *m, int size)
{
__u32 sum = 0;
while (size--)
sum += htonl(*m++);
return sum;
}
static int
amiga_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
{
struct buffer_head *bh;
struct RigidDiskBlock *rdb;
struct PartitionBlock *pb;
int start_sect;
int nr_sects;
int blk;
int part, res;
set_blocksize(dev,512);
res = 0;
for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
if(!(bh = bread(dev,blk,512))) {
printk("Dev %d: unable to read RDB block %d\n",dev,blk);
goto rdb_done;
}
if (*(__u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) {
rdb = (struct RigidDiskBlock *)bh->b_data;
if (checksum_block((__u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) {
printk("Dev %d: RDB in block %d has bad checksum\n",dev,blk);
brelse(bh);
continue;
}
printk(" RDSK");
blk = htonl(rdb->rdb_PartitionList);
brelse(bh);
for (part = 1; blk > 0 && part <= 16; part++) {
if (!(bh = bread(dev,blk,512))) {
printk("Dev %d: unable to read partition block %d\n",
dev,blk);
goto rdb_done;
}
pb = (struct PartitionBlock *)bh->b_data;
blk = htonl(pb->pb_Next);
if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block(
(__u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) {
/* Tell Kernel about it */
if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 -
htonl(pb->pb_Environment[9])) *
htonl(pb->pb_Environment[3]) *
htonl(pb->pb_Environment[5]))) {
continue;
}
start_sect = htonl(pb->pb_Environment[9]) *
htonl(pb->pb_Environment[3]) *
htonl(pb->pb_Environment[5]);
add_partition(hd,current_minor,start_sect,nr_sects);
current_minor++;
res = 1;
}
brelse(bh);
}
printk("\n");
break;
}
}
rdb_done:
set_blocksize(dev,BLOCK_SIZE);
return res;
}
#endif /* CONFIG_AMIGA_PARTITION */
static void check_partition(struct gendisk *hd, kdev_t dev)
{
static int first_time = 1;
......@@ -583,6 +665,10 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
#ifdef CONFIG_SUN_PARTITION
if(sun_partition(hd, dev, first_sector))
return;
#endif
#ifdef CONFIG_AMIGA_PARTITION
if(amiga_partition(hd, dev, first_sector))
return;
#endif
printk(" unknown partition table\n");
}
......
/*
* linux/drivers/block/ide.c Version 5.43 May 14, 1996
* linux/drivers/block/ide.c Version 5.45 Jul 22, 1996
*
* Copyright (C) 1994-1996 Linus Torvalds & authors (see below)
*/
......@@ -238,6 +238,11 @@
* Version 5.42 simplify irq-masking after probe
* fix NULL pointer deref in save_match()
* Version 5.43 Ugh.. unexpected_intr is back: try to exterminate it
* Version 5.44 Fix for "irq probe failed" on cmd640
* change path on message regarding MAKEDEV.ide
* add a throttle to the unexpected_intr() messages
* Version 5.45 fix ugly parameter parsing bugs (thanks Derek)
* include Gadi's magic fix for cmd640 unexpected_intr
*
* Some additional driver compile-time options are in ide.h
*
......@@ -284,7 +289,6 @@
#endif /* CONFIG_BLK_DEV_PROMISE */
static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10};
......@@ -580,6 +584,8 @@ static void init_gendisk (ide_hwif_t *hwif)
gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
bs = kmalloc (minors*sizeof(int), GFP_KERNEL);
memset(gd->part, 0, minors * sizeof(struct hd_struct));
/* cdroms and msdos f/s are examples of non-1024 blocksizes */
blksize_size[hwif->major] = bs;
for (unit = 0; unit < minors; ++unit)
......@@ -1619,6 +1625,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
byte stat;
unsigned int unit;
ide_hwif_t *hwif = hwgroup->hwif;
static unsigned long last_time = 0;
/*
* handle the unexpected interrupt
......@@ -1630,8 +1637,12 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
if (!drive->present)
continue;
SELECT_DRIVE(hwif,drive);
if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT))
(void) ide_dump_status(drive, "unexpected_intr", stat);
if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT)) {
if ((last_time + (HZ/2)) < jiffies && !drive->ignore_unexp) {
last_time = jiffies;
(void) ide_dump_status(drive, "unexpected_intr", stat);
}
}
if ((stat & DRQ_STAT))
try_to_flush_leftover_data(drive);
}
......@@ -1645,8 +1656,8 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
*/
void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
{
ide_hwgroup_t *hwgroup = dev_id;
ide_handler_t *handler;
ide_hwgroup_t *hwgroup = dev_id;
ide_handler_t *handler;
if (irq == hwgroup->hwif->irq && (handler = hwgroup->handler) != NULL) {
ide_drive_t *drive = hwgroup->drive;
......@@ -1658,7 +1669,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
cli(); /* this is necessary, as next rq may be different irq */
if (hwgroup->handler == NULL) {
SET_RECOVERY_TIMER(HWIF(drive));
ide_do_request(hwgroup);
ide_do_request(hwgroup);
}
} else {
unexpected_intr(irq, hwgroup);
......@@ -1899,8 +1910,13 @@ static int revalidate_disk(kdev_t i_rdev)
};
drive->part[0].nr_sects = current_capacity(drive);
if (drive->media == ide_disk)
resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
if (drive->media != ide_disk)
drive->part[0].start_sect = -1;
resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
#ifdef CONFIG_BLK_DEV_IDECD
if (drive->media == ide_cdrom)
ide_cdrom_setup(drive);
#endif /* CONFIG_BLK_DEV_IDECD */
drive->busy = 0;
wake_up(&drive->wqueue);
......@@ -2194,7 +2210,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */
|| (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */
|| (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
bswap = 0; /* Vertos drives may still be weird */
bswap ^= 1; /* Vertos drives may still be weird */
}
ide_fixstring (id->model, sizeof(id->model), bswap);
ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap);
......@@ -2367,10 +2383,15 @@ static void delay_10ms (void)
*/
static int try_to_identify (ide_drive_t *drive, byte cmd)
{
int hd_status, rc;
int irqs, rc;
unsigned long timeout;
int irqs = 0;
#ifdef CONFIG_BLK_DEV_CMD640
int retry = 0;
int hd_status;
try_again:
#endif /* CONFIG_BLK_DEV_CMD640 */
irqs = 0;
if (!HWIF(drive)->irq) { /* already got an IRQ? */
probe_irq_off(probe_irq_on()); /* clear dangling irqs */
irqs = probe_irq_on(); /* start monitoring irqs */
......@@ -2428,16 +2449,28 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
irqs = probe_irq_on();
OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
udelay(5);
(void) GET_STAT(); /* clear drive IRQ */
(void) probe_irq_off(irqs);
(void) probe_irq_off(probe_irq_on()); /* clear self-inflicted irq */
(void) GET_STAT(); /* clear drive IRQ */
} else { /* Mmmm.. multiple IRQs.. don't know which was ours */
printk("%s: IRQ probe failed (%d)\n", drive->name, irqs);
#ifdef CONFIG_BLK_DEV_CMD640
if (HWIF(drive)->chipset == ide_cmd640) {
extern byte (*get_cmd640_reg)(int);
byte reg9 = get_cmd640_reg(0x09);
printk("%s: Hmmm.. probably a driver problem.\n", drive->name);
printk("%s: cmd640 reg 09h == 0x%02x\n", drive->name, get_cmd640_reg(9));
printk("%s: cmd640 reg 09h == 0x%02x\n", drive->name, reg9);
printk("%s: cmd640 reg 51h == 0x%02x\n", drive->name, get_cmd640_reg(0x51));
if (reg9 == 0x0a) {
printk("%s: perhaps PCI INTA has not been set to IRQ15?\n", drive->name);
if (retry++ == 0) {
extern void (*put_cmd640_reg)(int, int);
printk("%s: switching secondary interface to legacy mode\n", drive->name);
put_cmd640_reg(0x09,0x00);
goto try_again;
}
}
}
#endif /* CONFIG_BLK_DEV_CMD640 */
}
......@@ -2832,7 +2865,7 @@ void ide_setup (char *s)
/*
* Cryptic check to ensure chipset not already set for hwif:
*/
if (i != -1 && i != -2) {
if (i >= 0 || i <= -5) {
if (hwif->chipset != ide_unknown)
goto bad_option;
if (i < 0 && ide_hwifs[1].chipset != ide_unknown)
......@@ -2841,7 +2874,7 @@ void ide_setup (char *s)
/*
* Interface keywords work only for ide0:
*/
if (i <= -6 && hw != 0)
if (i <= -5 && hw != 0)
goto bad_hwif;
switch (i) {
......@@ -3058,7 +3091,9 @@ static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
static int init_irq (ide_hwif_t *hwif)
{
unsigned long flags;
#if MAX_HWIFS > 1
unsigned int index;
#endif /* MAX_HWIFS > 1 */
ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL;
......
......@@ -135,7 +135,11 @@ typedef unsigned char byte; /* used everywhere */
* Timeouts for various operations:
*/
#define WAIT_DRQ (5*HZ/100) /* 50msec - spec allows up to 20ms */
#ifdef CONFIG_APM
#define WAIT_READY (5*HZ) /* 5sec - some laptops are very slow */
#else
#define WAIT_READY (3*HZ/100) /* 30msec - should be instantaneous */
#endif /* CONFIG_APM */
#define WAIT_PIDENTIFY (1*HZ) /* 1sec - should be less than 3ms (?) */
#define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */
#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */
......@@ -292,6 +296,18 @@ typedef union {
} b;
} special_t;
#ifdef __BIG_ENDIAN_BITFIELD
typedef union {
unsigned all : 8; /* all of the bits together */
struct {
unsigned bit7 : 1; /* always 1 */
unsigned lba : 1; /* using LBA instead of CHS */
unsigned bit5 : 1; /* always 1 */
unsigned unit : 1; /* drive select number, 0 or 1 */
unsigned head : 4; /* always zeros here */
} b;
} select_t;
#else /* __BIG_ENDIAN_BITFIELD */
typedef union {
unsigned all : 8; /* all of the bits together */
struct {
......@@ -302,6 +318,7 @@ typedef union {
unsigned bit7 : 1; /* always 1 */
} b;
} select_t;
#endif /* __BIG_ENDIAN_BITFIELD */
typedef struct ide_drive_s {
special_t special; /* special action flags */
......@@ -315,6 +332,7 @@ typedef struct ide_drive_s {
unsigned unmask : 1; /* flag: okay to unmask other irqs */
unsigned nobios : 1; /* flag: do not probe bios for drive */
unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
unsigned ignore_unexp : 1; /* flag: ignore unexpected_intr's */
#if FAKE_FDISK_FOR_EZDRIVE
unsigned remap_0_to_1 : 1; /* flag: partitioned with ezdrive */
#endif /* FAKE_FDISK_FOR_EZDRIVE */
......@@ -324,7 +342,7 @@ typedef struct ide_drive_s {
byte ready_stat; /* min status value for drive ready */
byte mult_count; /* current multiple sector setting */
byte mult_req; /* requested multiple sector setting */
byte pio_req; /* requested multiple sector setting */
byte pio_req; /* requested drive pio setting */
byte io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
byte bad_wstat; /* used for ignoring WRERR_STAT */
byte sect0; /* offset of first sector for DM6:DDO */
......
/*
* linux/drivers/block/triton.c Version 1.10 Apr 3, 1996
* linux/drivers/block/triton.c Version 1.12 Jul 24, 1996
*
* Copyright (c) 1995-1996 Mark Lord
* May be copied or modified under the terms of the GNU General Public License
......@@ -322,7 +322,7 @@ static int triton_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
/*
* print_triton_drive_flags() displays the currently programmed options
* in the 430FX (Triton) chipset for a given drive.
* in the 82371 (Triton) for a given drive.
*
* If fastDMA is "no", then slow ISA timings are used for DMA data xfers.
* If fastPIO is "no", then slow ISA timings are used for PIO data xfers.
......@@ -382,7 +382,7 @@ void ide_init_triton (byte bus, byte fn)
unsigned short pcicmd;
unsigned int bmiba, timings;
printk("ide: 430FX (Triton) on PCI bus %d function %d\n", bus, fn);
printk("ide: 82371 PIIX (Triton) on PCI bus %d function %d\n", bus, fn);
/*
* See if IDE and BM-DMA features are enabled:
*/
......@@ -439,14 +439,14 @@ void ide_init_triton (byte bus, byte fn)
unsigned short time;
if (hwif->io_base == 0x1f0) {
time = timings & 0xffff;
if ((timings & 0x8000) == 0) /* interface enabled? */
if ((time & 0x8000) == 0) /* interface enabled? */
continue;
hwif->chipset = ide_triton;
if (dma_enabled)
init_triton_dma(hwif, bmiba);
} else if (hwif->io_base == 0x170) {
time = timings >> 16;
if ((timings & 0x8000) == 0) /* interface enabled? */
if ((time & 0x8000) == 0) /* interface enabled? */
continue;
hwif->chipset = ide_triton;
if (dma_enabled)
......
......@@ -39,7 +39,7 @@
* Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
* Gerd Knorr (he lent me his PhotoCD)
* Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
* Andreas Kies (testing the mysterious hang up's)
* Andreas Kies (testing the mysterious hang-ups)
* Heiko Eissfeldt (VERIFY_READ/WRITE)
* Marcin Dalecki (improved performance, shortened code)
* ... somebody forgotten?
......
......@@ -18,6 +18,7 @@
*/
#define KEYBOARD_IRQ 1
#define DISABLE_KBD_DURING_INTERRUPTS 0
#include <linux/sched.h>
#include <linux/interrupt.h>
......@@ -69,14 +70,6 @@ static int initialize_kbd(void);
#define KBD_DEFLOCK 0
#endif
/*
* The default IO slowdown is doing 'inb()'s from 0x61, which should be
* safe. But as that is the keyboard controller chip address, we do our
* slowdowns here by doing short jumps: the keyboard controller should
* be able to keep up
*/
#define REALLY_SLOW_IO
#define SLOW_IO_BY_JUMPING
#include <asm/io.h>
#include <asm/system.h>
......@@ -337,48 +330,31 @@ int getkeycode(unsigned int scancode)
e0_keys[scancode - 128];
}
static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if DISABLE_KBD_DURING_INTERRUPTS
#define disable_keyboard() do { send_cmd(0xAD); kb_wait(); } while (0)
#define enable_keyboard() send_cmd(0xAE)
#else
#define disable_keyboard() /* nothing */
#define enable_keyboard() /* nothing */
#endif
static void handle_scancode(unsigned char scancode)
{
unsigned char scancode, keycode;
unsigned char keycode;
static unsigned int prev_scancode = 0; /* remember E0, E1 */
char up_flag; /* 0 or 0200 */
char raw_mode;
int status;
pt_regs = regs;
send_cmd(0xAD); /* disable keyboard */
kb_wait();
status = inb_p(0x64);
if ((status & kbd_read_mask) != 0x01) {
/*
* On some platforms (Alpha XL for one), the init code may leave
* an interrupt hanging, yet with status indicating no data.
* After making sure that there's no data indicated and its not a
* mouse interrupt, we will read the data register to clear it.
* If we don't do this, the data reg stays full and will not
* allow new data or interrupt from the keyboard. Sigh...
*/
if (!(status & 0x21)) { /* neither ODS nor OBF */
scancode = inb(0x60); /* read data anyway */
#if 0
printk(KERN_DEBUG "keyboard: status 0x%x mask 0x%x data 0x%x\n",
status, kbd_read_mask, scancode);
#endif
}
goto end_kbd_intr;
}
scancode = inb(0x60);
mark_bh(KEYBOARD_BH);
if (reply_expected) {
/* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
/* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
reply_expected = 0;
if (scancode == 0xfa) {
acknowledge = 1;
goto end_kbd_intr;
return;
} else if (scancode == 0xfe) {
resend = 1;
goto end_kbd_intr;
return;
}
/* strange ... */
reply_expected = 1;
......@@ -392,7 +368,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_INFO "keyboard buffer overflow\n");
#endif
prev_scancode = 0;
goto end_kbd_intr;
return;
}
do_poke_blanked_console = 1;
mark_bh(CONSOLE_BH);
......@@ -417,12 +393,12 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#endif
#endif
prev_scancode = 0;
goto end_kbd_intr;
return;
}
if (scancode == 0xe0 || scancode == 0xe1) {
prev_scancode = scancode;
goto end_kbd_intr;
return;
}
/*
......@@ -439,7 +415,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (prev_scancode != 0xe0) {
if (prev_scancode == 0xe1 && scancode == 0x1d) {
prev_scancode = 0x100;
goto end_kbd_intr;
return;
} else if (prev_scancode == 0x100 && scancode == 0x45) {
keycode = E1_PAUSE;
prev_scancode = 0;
......@@ -449,7 +425,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
#endif
prev_scancode = 0;
goto end_kbd_intr;
return;
}
} else {
prev_scancode = 0;
......@@ -467,7 +443,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* So, we should also ignore the latter. - aeb@cwi.nl
*/
if (scancode == 0x2a || scancode == 0x36)
goto end_kbd_intr;
return;
if (e0_keys[scancode])
keycode = e0_keys[scancode];
......@@ -477,7 +453,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
scancode);
#endif
goto end_kbd_intr;
return;
}
}
} else if (scancode >= SC_LIM) {
......@@ -500,7 +476,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
" - ignored\n", scancode);
#endif
}
goto end_kbd_intr;
return;
}
} else
keycode = scancode;
......@@ -526,12 +502,12 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
rep = set_bit(keycode, key_down);
if (raw_mode)
goto end_kbd_intr;
return;
if (kbd->kbdmode == VC_MEDIUMRAW) {
/* soon keycodes will require more than one byte */
put_queue(keycode + up_flag);
goto end_kbd_intr;
return;
}
/*
......@@ -592,9 +568,32 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#endif
}
}
}
end_kbd_intr:
send_cmd(0xAE); /* enable keyboard */
static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char status;
pt_regs = regs;
disable_keyboard();
status = inb_p(0x64);
do {
unsigned char scancode;
/* mouse data? */
if (status & kbd_read_mask & 0x20)
break;
scancode = inb(0x60);
if (status & 0x01)
handle_scancode(scancode);
status = inb(0x64);
} while (status & 0x01);
mark_bh(KEYBOARD_BH);
enable_keyboard();
}
static void put_queue(int ch)
......
......@@ -176,6 +176,8 @@ static int read_zero(struct inode * node, struct file * file, char * buf, int co
for (left = count; left > 0; left--) {
put_user(0,buf);
buf++;
if (need_resched)
schedule();
}
return count;
}
......
......@@ -25,10 +25,6 @@
* Rearranged SIGIO support to use code from tty_io. 9Sept95 ctm@ardi.com
*
* Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
*
* Fixed keyboard lockups at open time (intervening kbd interrupts), handle
* RESEND replies, better error checking
* 3-Jul-96 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
*/
/* Uncomment the following line if your mouse needs initialization. */
......@@ -61,10 +57,8 @@
#define AUX_STATUS 0x64 /* Aux device status reg */
/* aux controller status bits */
#define AUX_KOBUF_FULL 0x01 /* output buffer (from controller) full */
#define AUX_OBUF_FULL 0x21 /* output buffer (from device) full */
#define AUX_IBUF_FULL 0x02 /* input buffer (to device) full */
#define AUX_TIMEOUT 0x40 /* controller reports timeout */
/* aux controller commands */
#define AUX_CMD_WRITE 0x60 /* value to write to controller */
......@@ -87,14 +81,6 @@
#define AUX_DISABLE_DEV 0xf5 /* disable aux device */
#define AUX_RESET 0xff /* reset aux device */
/* kbd controller commands */
#define KBD_DISABLE 0xad
#define KBD_ENABLE 0xae
/* replies */
#define AUX_ACK 0xfa
#define AUX_RESEND 0xfe
#define MAX_RETRIES 60 /* some aux operations take long time*/
#if defined(__alpha__) && !defined(CONFIG_PCI)
# define AUX_IRQ 9 /* Jensen is odd indeed */
......@@ -135,6 +121,7 @@ static int aux_ready = 0;
static int aux_count = 0;
static int aux_present = 0;
static int poll_aux_status(void);
static int poll_aux_status_nosleep(void);
static int fasync_aux(struct inode *inode, struct file *filp, int on);
#ifdef CONFIG_82C710_MOUSE
......@@ -149,70 +136,49 @@ static int probe_qp(void);
/*
* Write a byte to the kbd controller and wait for it being processed
* Write to aux device
*/
static int aux_write_byte(int val,int port)
static void aux_write_dev(int val)
{
outb_p(val, port);
return poll_aux_status();
poll_aux_status();
outb_p(AUX_MAGIC_WRITE,AUX_COMMAND); /* write magic cookie */
poll_aux_status();
outb_p(val,AUX_OUTPUT_PORT); /* write data */
}
/*
* Write to device, handle returned resend requests and wait for ack
* Write to device & handle returned ack
*/
#if defined INITIALIZE_DEVICE
static int aux_write_ack(int val)
{
int rv, retries = 0, stat;
repeat:
if (poll_aux_status() < 0)
return -1;
outb_p(AUX_MAGIC_WRITE, AUX_COMMAND);
if (poll_aux_status() < 0)
return -1;
outb_p(val, AUX_OUTPUT_PORT);
if ((rv = poll_aux_status()) < 0)
/* timeout */
return -1;
else if (rv == AUX_RESEND)
/* controller needs last byte again... */
goto repeat;
else if (rv == AUX_ACK)
/* already got ACK */
return 0;
else {
/* wait for ACK from controller */
while (retries < MAX_RETRIES) {
stat = inb_p(AUX_STATUS);
if ((stat & AUX_OBUF_FULL) == AUX_OBUF_FULL &&
inb_p(AUX_INPUT_PORT) == AUX_ACK)
return 0;
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + (5*HZ + 99) / 100;
schedule();
retries++;
}
return -1;
int retries = 0;
poll_aux_status_nosleep();
outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
poll_aux_status_nosleep();
outb_p(val,AUX_OUTPUT_PORT);
poll_aux_status_nosleep();
if ((inb(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
{
return (inb(AUX_INPUT_PORT));
}
return 0;
}
#endif /* INITIALIZE_DEVICE */
/*
* Write aux device command
*/
static int aux_write_cmd(int val)
static void aux_write_cmd(int val)
{
if (poll_aux_status() < 0)
return -1;
outb_p(AUX_CMD_WRITE, AUX_COMMAND);
if (poll_aux_status() < 0)
return -1;
outb_p(val, AUX_OUTPUT_PORT);
if (poll_aux_status() < 0)
return -1;
return 0;
poll_aux_status();
outb_p(AUX_CMD_WRITE,AUX_COMMAND);
poll_aux_status();
outb_p(val,AUX_OUTPUT_PORT);
}
......@@ -292,19 +258,10 @@ static void release_aux(struct inode * inode, struct file * file)
fasync_aux(inode, file, 0);
if (--aux_count)
return;
/* disable keyboard to avoid clashes with multi-byte command sequences */
aux_write_cmd(AUX_INTS_OFF); /* disable controller ints */
poll_aux_status();
outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */
poll_aux_status();
if (aux_write_byte(KBD_DISABLE, AUX_COMMAND) < 0)
printk(KERN_ERR "psaux: controller timeout\n");
/* disable controller ints */
if (aux_write_cmd(AUX_INTS_OFF) < 0)
printk(KERN_ERR "psaux: controller timeout\n");
/* Disable Aux device */
if (aux_write_byte(AUX_DISABLE, AUX_COMMAND) < 0)
printk(KERN_ERR "psaux: controller timeout\n");
/* re-enable keyboard */
if (aux_write_byte(KBD_ENABLE, AUX_COMMAND) < 0)
printk(KERN_ERR "psaux: controller timeout\n");
free_irq(AUX_IRQ, NULL);
MOD_DEC_USE_COUNT;
}
......@@ -349,7 +306,7 @@ static int open_aux(struct inode * inode, struct file * file)
return -ENODEV;
if (aux_count++)
return 0;
if (poll_aux_status() < 0) {
if (!poll_aux_status()) {
aux_count--;
return -EBUSY;
}
......@@ -360,27 +317,12 @@ static int open_aux(struct inode * inode, struct file * file)
}
MOD_INC_USE_COUNT;
poll_aux_status();
/* disable keyboard to avoid clashes with multi-byte command sequences */
if (aux_write_byte(KBD_DISABLE, AUX_COMMAND) < 0)
goto open_error;
/* Enable Aux in kbd controller */
if (aux_write_byte(AUX_ENABLE, AUX_COMMAND) < 0)
goto open_error;
/* enable aux device */
if (aux_write_ack(AUX_ENABLE_DEV) < 0)
goto open_error;
/* enable controller ints */
if (aux_write_cmd(AUX_INTS_ON) < 0)
goto open_error;
/* re-enable keyboard */
if (aux_write_byte(KBD_ENABLE, AUX_COMMAND) < 0)
goto open_error;
outb_p(AUX_ENABLE,AUX_COMMAND); /* Enable Aux */
aux_write_dev(AUX_ENABLE_DEV); /* enable aux device */
aux_write_cmd(AUX_INTS_ON); /* enable controller ints */
poll_aux_status();
aux_ready = 0;
return 0;
open_error:
printk( KERN_ERR "psaux: controller timeout\n" );
return -EIO;
}
#ifdef CONFIG_82C710_MOUSE
......@@ -436,31 +378,17 @@ static int open_qp(struct inode * inode, struct file * file)
static int write_aux(struct inode * inode, struct file * file, const char * buffer, int count)
{
int i = count;
int rv = 0;
/* temporary disable keyboard to avoid clashes with multi-byte command
* sequence */
if (aux_write_byte(KBD_DISABLE, AUX_COMMAND) < 0)
return -EIO;
while (i--) {
if (poll_aux_status() < 0) {
rv = -EIO;
break;
}
if (!poll_aux_status())
return -EIO;
outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
if (poll_aux_status() < 0) {
rv = -EIO;
break;
}
if (!poll_aux_status())
return -EIO;
outb_p(get_user(buffer++),AUX_OUTPUT_PORT);
}
/* reenable keyboard */
if (poll_aux_status() < 0 || aux_write_byte(KBD_ENABLE, AUX_COMMAND) < 0)
rv = -EIO;
inode->i_mtime = CURRENT_TIME;
return rv ? rv : count;
return count;
}
......@@ -591,11 +519,13 @@ int psaux_init(void)
aux_write_ack(AUX_SET_RES);
aux_write_ack(3); /* 8 counts per mm */
aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
poll_aux_status_nosleep();
#endif /* INITIALIZE_DEVICE */
/* Disable Aux device and its interrupts on the controller */
if (aux_write_byte(AUX_DISABLE, AUX_COMMAND) < 0 ||
aux_write_cmd(AUX_INTS_OFF) < 0)
printk(KERN_ERR "psaux: controller timeout\n");
outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */
poll_aux_status_nosleep();
outb_p(AUX_CMD_WRITE,AUX_COMMAND);
poll_aux_status_nosleep(); /* Disable interrupts */
outb_p(AUX_INTS_OFF, AUX_OUTPUT_PORT); /* on the controller */
}
return 0;
}
......@@ -603,7 +533,7 @@ int psaux_init(void)
#ifdef MODULE
int init_module(void)
{
return psaux_init();
return psaux_init(); /*?? Bjorn */
}
void cleanup_module(void)
......@@ -615,18 +545,28 @@ void cleanup_module(void)
static int poll_aux_status(void)
{
int retries=0;
int reply=0;
while ((inb(AUX_STATUS) & (AUX_KOBUF_FULL|AUX_IBUF_FULL)) &&
retries < MAX_RETRIES) {
while ((inb(AUX_STATUS)&0x03) && retries < MAX_RETRIES) {
if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
reply = inb_p(AUX_INPUT_PORT);
inb_p(AUX_INPUT_PORT);
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + (5*HZ + 99) / 100;
schedule();
retries++;
}
return (retries==MAX_RETRIES) ? -1 : reply;
return !(retries==MAX_RETRIES);
}
static int poll_aux_status_nosleep(void)
{
int retries = 0;
while ((inb(AUX_STATUS)&0x03) && retries < 1000000) {
if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
inb_p(AUX_INPUT_PORT);
retries++;
}
return !(retries == 1000000);
}
#ifdef CONFIG_82C710_MOUSE
......
......@@ -755,9 +755,48 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
return i;
}
/*
* Split writes up in sane blocksizes to avoid
* denial-of-service type attacks
*/
static inline int do_tty_write(
int (*write)(struct tty_struct *, struct file *, const unsigned char *, unsigned int),
struct inode *inode,
struct tty_struct *tty,
struct file *file,
const unsigned char *buf,
unsigned int count)
{
int ret = 0, written = 0;
for (;;) {
unsigned int size = PAGE_SIZE*2;
if (size > count)
size = count;
ret = write(tty, file, buf, size);
if (ret <= 0)
break;
count -= ret;
written += ret;
if (!count)
break;
ret = -ERESTARTSYS;
if (current->signal & ~current->blocked)
break;
if (need_resched)
schedule();
}
if (written) {
inode->i_mtime = CURRENT_TIME;
ret = written;
}
return ret;
}
static int tty_write(struct inode * inode, struct file * file, const char * buf, int count)
{
int i, is_console;
int is_console;
struct tty_struct * tty;
is_console = (inode->i_rdev == CONSOLE_DEV);
......@@ -781,14 +820,12 @@ static int tty_write(struct inode * inode, struct file * file, const char * buf,
}
}
#endif
if (tty->ldisc.write)
/* XXX casts are for what kernel-wide prototypes should be. */
i = (tty->ldisc.write)(tty,file,(const unsigned char *)buf,(unsigned int)count);
else
i = -EIO;
if (i > 0)
inode->i_mtime = CURRENT_TIME;
return i;
if (!tty->ldisc.write)
return -EIO;
return do_tty_write(tty->ldisc.write,
inode, tty, file,
(const unsigned char *)buf,
(unsigned int)count);
}
/*
......
Sun Jul 21 00:00 1996 Gerard Roudier (groudier@club-internet.fr)
* ncr53c8xx.c, README.ncr53c8xx
Add the ncr53c8xx_select_queue_depths() function.
Set queue_depth to SCSI_NCR_MAX_TAGS (4 by default) for devices that
support tagged command queueing.
For other devices, set queue_depth to 1. No need to queue a command
to the driver if this command cannot be sent to the device.
Each time the driver hide io requests from the kernel and/or from the
driver, it may break a little (or a lot) optimization algorithms that
try to increase throughput by reordering io requests.
It is better to enable the disk write caching to reduce latencies for
write operations, and to trust asynchronous read ahead from the device
and from the kernel that can reduce latencies for read operations,
even when tagged command queuing is not supported or enabled.
Sat Jul 20 20:00 1996 Gerard Roudier (groudier@club-internet.fr)
* ncr53c8xx.c
Minor changes:
- Problem of "CCB address mismatch" that happens with the 3 versions
of the driver. The CCB is correct and Stefan Esser suggests a little
patch that seems to be a bypass.
Stefan says he will change that in a future version of the BSD driver.
- Set burst transfers to 8 for 815 chips.
Sun Jul 14 15:00 1996 Gerard Roudier (groudier@club-internet.fr)
* ncr53c8xx.c, Configure.help
Memory mapped io donnot work under linux/Alpha for the driver.
......
......@@ -40,7 +40,7 @@
*/
/*
** 23 June 1996, version 1.12
** 21 July 1996, version 1.12b
**
** Supported SCSI-II features:
** Synchronous negotiation
......@@ -424,6 +424,10 @@ static struct {
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f))
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0)
static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist);
#endif
#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
#else
......@@ -3494,6 +3498,9 @@ printf("ncr_attach: unit=%d chip=%d base=%x, io_port=%x, irq=%d\n", unit, chip,
instance->io_port = io_port;
instance->n_io_port = 128;
instance->dma_channel = 0;
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0)
instance->select_queue_depths = ncr53c8xx_select_queue_depths;
#endif
/*
** Patch script to physical addresses
......@@ -4786,7 +4793,7 @@ void ncr_init (ncb_p np, char * msg, u_long code)
else
/** NCR53C815 **/
if (ChipDevice == PCI_DEVICE_ID_NCR_53C815) {
OUTB(nc_dmode, 0x00); /* Set 2-transfer burst */
OUTB(nc_dmode, 0x80); /* Set 8-transfer burst */
}
else
/** NCR53C825 **/
......@@ -5874,7 +5881,7 @@ static void ncr_int_ma (ncb_p np)
if (cp != np->header.cp) {
printf ("%s: SCSI phase error fixup: CCB address mismatch (0x%08lx != 0x%08lx)\n",
ncr_name (np), (u_long) cp, (u_long) np->header.cp);
return;
/* return;*/
}
/*
......@@ -7521,6 +7528,30 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, int unit, int board, int
(int) irq, bus, (uchar) device_fn);
}
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,0,0)
/*
** Linux select queue depths function
*/
static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist)
{
struct scsi_device *device;
for (device = devlist; device; device = device->next) {
if (device->host == host) {
if (device->tagged_supported) {
device->queue_depth = SCSI_NCR_MAX_TAGS;
}
else {
device->queue_depth = 1;
}
#ifdef DEBUG
printk("ncr53c8xx_select_queue_depth: id=%d, lun=%d, queue_depth=%d\n",
device->id, device->lun, device->queue_depth);
#endif
}
}
}
#endif
/*
** Linux entry point of queuecommand() function
......
......@@ -196,7 +196,7 @@ int ncr53c8xx_release(struct Scsi_Host *);
#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0)
#define NCR53C8XX {NULL,NULL,NULL,NULL,"ncr53c8xx (rel 1.12a)", ncr53c8xx_detect,\
#define NCR53C8XX {NULL,NULL,NULL,NULL,"ncr53c8xx (rel 1.12b)", ncr53c8xx_detect,\
ncr53c8xx_release, /* info */ NULL, /* command, deprecated */ NULL, \
ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset, \
NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
......@@ -207,7 +207,7 @@ int ncr53c8xx_release(struct Scsi_Host *);
#else
#define NCR53C8XX {NULL, NULL, "ncr53c8xx (rel 1.12a)", ncr53c8xx_detect,\
#define NCR53C8XX {NULL, NULL, "ncr53c8xx (rel 1.12b)", ncr53c8xx_detect,\
ncr53c8xx_release, /* info */ NULL, /* command, deprecated */ NULL, \
ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset, \
NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
......
......@@ -2875,11 +2875,32 @@ static void resize_dma_pool(void)
for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
host = SDpnt->host;
if(SDpnt->type != TYPE_TAPE)
/*
* sd and sr drivers allocate scatterlists.
* sr drivers may allocate for each command 1x2048 or 2x1024 extra
* buffers for 2k sector size and 1k fs.
* sg driver allocates buffers < 4k.
* st driver does not need buffers from the dma pool.
* estimate 4k buffer/command for devices of unknown type (should panic).
*/
if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM ||
SDpnt->type == TYPE_DISK || SDpnt->type == TYPE_MOD) {
new_dma_sectors += ((host->sg_tablesize *
sizeof(struct scatterlist) + 511) >> 9) *
SDpnt->queue_depth;
if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM)
new_dma_sectors += (2048 >> 9) * SDpnt->queue_depth;
}
else if (SDpnt->type == TYPE_SCANNER || SDpnt->type == TYPE_PROCESSOR) {
new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
}
else {
if (SDpnt->type != TYPE_TAPE) {
printk("resize_dma_pool: unknown device type %d\n", SDpnt->type);
new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
}
}
if(host->unchecked_isa_dma &&
scsi_need_isa_bounce_buffers &&
SDpnt->type != TYPE_TAPE) {
......@@ -2888,7 +2909,11 @@ static void resize_dma_pool(void)
new_need_isa_buffer++;
}
}
#ifdef DEBUG_INIT
printk("resize_dma_pool: needed dma sectors = %d\n", new_dma_sectors);
#endif
/* limit DMA memory to 32MB: */
new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
......@@ -2945,6 +2970,12 @@ static void resize_dma_pool(void)
dma_sectors = new_dma_sectors;
need_isa_buffer = new_need_isa_buffer;
restore_flags(flags);
#ifdef DEBUG_INIT
printk("resize_dma_pool: dma free sectors = %d\n", dma_free_sectors);
printk("resize_dma_pool: dma sectors = %d\n", dma_sectors);
printk("resize_dma_pool: need isa buffers = %d\n", need_isa_buffer);
#endif
}
#ifdef CONFIG_MODULES /* a big #ifdef block... */
......
......@@ -582,7 +582,7 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
if (!audio_devs[dev]->go)
tmout = 0;
else
tmout = 2 * HZ;
tmout = 10 * HZ;
{
......
......@@ -832,7 +832,9 @@ unload_pss (struct address_info *hw_config)
void
unload_pss_mpu (struct address_info *hw_config)
{
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
unload_mpu401 (hw_config);
#endif
}
void
......
......@@ -44,16 +44,26 @@ affs_put_super(struct super_block *sb)
lock_super(sb);
for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);
ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1);
secs_to_datestamp(CURRENT_TIME,&ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);
if (!(sb->s_flags & MS_RDONLY)) {
ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1);
secs_to_datestamp(CURRENT_TIME,
&ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);
}
if (sb->u.affs_sb.s_flags & SF_PREFIX)
kfree(sb->u.affs_sb.s_prefix);
kfree(sb->u.affs_sb.s_bitmap);
affs_brelse(sb->u.affs_sb.s_root_bh);
/* I'm not happy with this. It would be better to save the previous
* value of this devices blksize_size[][] in the super block and
* restore it here, but with the affs superblock being quite large
* already ...
*/
set_blocksize(sb->s_dev,BLOCK_SIZE);
sb->s_dev = 0;
unlock_super(sb);
MOD_DEC_USE_COUNT;
......@@ -63,13 +73,8 @@ affs_put_super(struct super_block *sb)
static void
affs_write_super(struct super_block *sb)
{
int i, clean = 2;
int i, clean = 2;
if ((sb->u.affs_sb.s_flags & SF_USE_MP) && !sb->u.affs_sb.s_uid && sb->s_covered) {
sb->s_mounted->i_uid = sb->u.affs_sb.s_uid = sb->s_covered->i_uid;
sb->s_mounted->i_gid = sb->u.affs_sb.s_gid = sb->s_covered->i_gid;
sb->u.affs_sb.s_flags &= ~SF_USE_MP;
}
if (!(sb->s_flags & MS_RDONLY)) {
lock_super(sb);
for (i = 0, clean = 1; i < sb->u.affs_sb.s_bm_count; i++) {
......@@ -149,13 +154,6 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i
}
*mount_opts |= SF_IMMUTABLE;
}
if (!strcmp(this_char,"usemp")) {
if (value) {
printk("AFFS: option usemp does not take an argument\n");
return 0;
}
*mount_opts |= SF_USE_MP;
}
else if (!strcmp(this_char,"verbose")) {
if (value) {
printk("AFFS: option verbose does not take an argument\n");
......@@ -380,6 +378,16 @@ affs_read_super(struct super_block *s,void *data, int silent)
bb = affs_bread(dev,0,s->s_blocksize);
if (bb) {
chksum = htonl(*(__u32 *)bb->b_data);
/* Dircache filesystems are compatible with non-dircache ones
* when reading. As long as they aren't supported, writing is
* not recommended.
*/
if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
|| chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) {
printk("AFFS: Dircache FS - mounting %s read only.\n",kdevname(dev));
s->s_flags |= MS_RDONLY;
}
switch (chksum) {
case MUFS_FS:
case MUFS_INTLFFS:
......@@ -388,9 +396,11 @@ affs_read_super(struct super_block *s,void *data, int silent)
case FS_INTLFFS:
s->u.affs_sb.s_flags |= SF_INTL;
break;
case MUFS_DCFFS:
case MUFS_FFS:
s->u.affs_sb.s_flags |= SF_MUFS;
break;
case FS_DCFFS:
case FS_FFS:
break;
case MUFS_OFS:
......@@ -399,20 +409,13 @@ affs_read_super(struct super_block *s,void *data, int silent)
case FS_OFS:
s->u.affs_sb.s_flags |= SF_OFS;
break;
case MUFS_DCOFS:
case MUFS_INTLOFS:
s->u.affs_sb.s_flags |= SF_MUFS;
/* fall thru */
case FS_DCOFS:
case FS_INTLOFS:
s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;
break;
case FS_DCOFS:
case FS_DCFFS:
case MUFS_DCOFS:
case MUFS_DCFFS:
if (!silent)
printk("AFFS: Unsupported filesystem on device %s: %08X\n",
kdevname(dev),chksum);
if (0)
default:
printk("AFFS: Unknown filesystem on device %s: %08X\n",
kdevname(dev),chksum);
......@@ -432,8 +435,8 @@ affs_read_super(struct super_block *s,void *data, int silent)
(char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
}
s->s_magic = AFFS_SUPER_MAGIC;
s->s_flags = MS_NODEV | MS_NOSUID;
s->s_magic = AFFS_SUPER_MAGIC;
s->s_flags |= MS_NODEV | MS_NOSUID;
/* Keep super block in cache */
if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) {
......@@ -587,6 +590,7 @@ affs_read_super(struct super_block *s,void *data, int silent)
affs_brelse(s->u.affs_sb.s_root_bh);
if (s->u.affs_sb.s_bitmap)
kfree(s->u.affs_sb.s_bitmap);
set_blocksize(dev,BLOCK_SIZE);
s->s_dev = 0;
unlock_super(s);
MOD_DEC_USE_COUNT;
......@@ -787,7 +791,7 @@ affs_write_inode(struct inode *inode)
gid = inode->i_gid ^ ~0;
}
if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETUID))
file_end->owner_gid = ntohs(uid);
file_end->owner_uid = ntohs(uid);
if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETGID))
file_end->owner_gid = ntohs(gid);
}
......
......@@ -476,20 +476,11 @@ void iput(struct inode * inode)
return;
}
static inline unsigned long value(struct inode * inode)
{
if (inode->i_lock)
return 1000;
if (inode->i_dirt)
return 1000;
return inode->i_nrpages;
}
struct inode * get_empty_inode(void)
{
static int ino = 0;
struct inode * inode, * best;
unsigned long badness = 1000;
unsigned long badness;
int i;
if (nr_inodes < max_inodes && nr_free_inodes < (nr_inodes >> 1))
......@@ -497,50 +488,54 @@ struct inode * get_empty_inode(void)
repeat:
inode = first_inode;
best = NULL;
badness = 1000;
for (i = nr_inodes/2; i > 0; i--,inode = inode->i_next) {
if (!inode->i_count) {
unsigned long i = value(inode);
unsigned long i = 999;
if (!(inode->i_lock | inode->i_dirt))
i = inode->i_nrpages;
if (i < badness) {
best = inode;
if ((badness = i) == 0)
break;
if (!i)
goto found_good;
badness = i;
}
}
}
if (badness)
if (nr_inodes < max_inodes) {
if (grow_inodes() == 0)
goto repeat;
}
inode = best;
if (!inode) {
if (nr_inodes < max_inodes) {
if (grow_inodes() == 0)
goto repeat;
best = NULL;
}
if (!best) {
printk("VFS: No free inodes - contact Linus\n");
sleep_on(&inode_wait);
goto repeat;
}
if (inode->i_lock) {
wait_on_inode(inode);
if (best->i_lock) {
wait_on_inode(best);
goto repeat;
}
if (inode->i_dirt) {
write_inode(inode);
if (best->i_dirt) {
write_inode(best);
goto repeat;
}
if (inode->i_count)
if (best->i_count)
goto repeat;
clear_inode(inode);
inode->i_count = 1;
inode->i_nlink = 1;
inode->i_version = ++event;
inode->i_sem.count = 1;
inode->i_ino = ++ino;
inode->i_dev = 0;
found_good:
clear_inode(best);
best->i_count = 1;
best->i_nlink = 1;
best->i_version = ++event;
best->i_sem.count = 1;
best->i_ino = ++ino;
best->i_dev = 0;
nr_free_inodes--;
if (nr_free_inodes < 0) {
printk ("VFS: get_empty_inode: bad free inode count.\n");
nr_free_inodes = 0;
}
return inode;
return best;
}
struct inode * get_pipe_inode(void)
......
......@@ -5,9 +5,11 @@
*
* (C) 1991 Linus Torvalds - minix filesystem
*
* Steve Beynon : Missing last directory entries fixed
* (stephen@askone.demon.co.uk) : 21st June 1996
*
* isofs directory handling functions
*/
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/iso_fs.h>
......@@ -133,9 +135,13 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
#ifdef DEBUG
printk("Block, offset, f_pos: %x %x %x\n",
block, offset, filp->f_pos);
printk("inode->i_size = %x\n",inode->i_size);
#endif
/* Next directory_record on next CDROM sector */
if (offset >= bufsize) {
#ifdef DEBUG
printk("offset >= bufsize\n");
#endif
brelse(bh);
offset = 0;
block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
......@@ -151,6 +157,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
inode_number = (block << bufbits) + (offset & (bufsize - 1));
de_len = *(unsigned char *) de;
#ifdef DEBUG
printk("de_len = %ld\n", de_len);
#endif
/* If the length byte is zero, we should move on to the next
CDROM sector. If we are at the end of the directory, we
......@@ -175,15 +185,31 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
If not, put the two halves together in "tmpde" */
next_offset = offset + de_len;
if (next_offset > bufsize) {
#ifdef DEBUG
printk("next_offset (%x) > bufsize (%x)\n",next_offset,bufsize);
#endif
next_offset &= (bufsize - 1);
memcpy(tmpde, de, bufsize - offset);
memcpy(tmpde, de, bufsize - offset);
brelse(bh);
block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits);
if (!block)
{
return 0;
bh = breada(inode->i_dev, block, bufsize, filp->f_pos+de_len, inode->i_size);
}
bh = breada(inode->i_dev, block, bufsize,
filp->f_pos,
inode->i_size);
if (!bh)
{
#ifdef DEBUG
printk("!bh block=%ld, bufsize=%ld\n",block,bufsize);
printk("filp->f_pos = %ld\n",filp->f_pos);
printk("inode->i_size = %ld\n", inode->i_size);
#endif
return 0;
}
memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset);
de = tmpde;
}
......
......@@ -189,7 +189,7 @@ static unsigned int isofs_get_last_session(kdev_t dev)
printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
}
#endif 0
if ((i==0)&&(ms_info.xa_flag)) vol_desc_start=ms_info.addr.lba;
if (i==0) vol_desc_start=ms_info.addr.lba;
}
return vol_desc_start;
}
......
......@@ -62,6 +62,31 @@ static void probe_m68k_ide (void);
#undef HD_DATA
#define HD_DATA NULL
/* MSch: changed sti() to STI() wherever possible in ide.c; moved STI() def.
* to asm/ide.h
*/
/* The Atari interrupt structure strictly requires that the IPL isn't lowered
* uncontrolled in an interrupt handler. In the concrete case, the IDE
* interrupt is already a slow int, so the irq is already disabled at the time
* the handler is called, and the IPL has been lowered to the minimum value
* possible. To avoid going below that, STI() checks for being called inside
* an interrupt, and in that case it does nothing. Hope that is reasonable and
* works. (Roman)
*/
#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA)
#define STI() \
do { \
if (!intr_count) sti(); \
} while(0)
#elif defined(CONFIG_ATARI)
#define STI() \
do { \
if (!MACH_IS_ATARI || !intr_count) sti(); \
} while(0)
#else /* !defined(CONFIG_ATARI) */
#define STI() sti()
#endif
#define SELECT_DRIVE(hwif,drive) OUT_BYTE((drive)->select.all, hwif->io_base+IDE_SELECT_OFFSET);
#define insl(data_reg, buffer, wcount) insw(data_reg, buffer, wcount<<1)
......
......@@ -64,7 +64,6 @@ struct affs_sb_info {
#define SF_SETUID 0x0010 /* Ignore Amiga uid */
#define SF_SETGID 0x0020 /* Ignore Amiga gid */
#define SF_SETMODE 0x0040 /* Ignore Amiga protection bits */
#define SF_USE_MP 0x0080 /* Use uid and gid from mount point */
#define SF_MUFS 0x0100 /* Use MUFS uid/gid mapping */
#define SF_OFS 0x0200 /* Old filesystem */
#define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */
......
......@@ -467,6 +467,7 @@ asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
int err;
unsigned int id;
unsigned long addr;
unsigned long len;
if (shmid < 0) {
/* printk("shmat() -> EINVAL because shmid = %d < 0\n",shmid); */
......@@ -490,6 +491,12 @@ asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
else
return -EINVAL;
}
/*
* Check if addr exceeds TASK_SIZE (from do_mmap)
*/
len = PAGE_SIZE*shp->shm_npages;
if (addr >= TASK_SIZE || len > TASK_SIZE || addr > TASK_SIZE - len)
return -EINVAL;
/*
* If shm segment goes below stack, make sure there is some
* space left for the stack to grow (presently 4 pages).
......
......@@ -415,7 +415,7 @@ static void profile_readahead(int async, struct file *filp)
* Reasonable means, in this context, not too large but not too small.
* The actual maximum value is:
* MAX_READAHEAD + PAGE_SIZE = 76k is CONFIG_READA_SMALL is undefined
* and 32K if defined.
* and 32K if defined (4K page size assumed).
*
* Asynchronous read-ahead benefits:
* ---------------------------------
......@@ -442,15 +442,17 @@ static void profile_readahead(int async, struct file *filp)
* - The total memory pool usage for the file access stream.
* This maximum memory usage is implicitly 2 IO read chunks:
* 2*(MAX_READAHEAD + PAGE_SIZE) = 156K if CONFIG_READA_SMALL is undefined,
* 64k if defined.
* 64k if defined (4K page size assumed).
*/
#if 0 /* small readahead */
#define MAX_READAHEAD (PAGE_SIZE*7)
#define MIN_READAHEAD (PAGE_SIZE*2)
#else
#define MAX_READAHEAD (PAGE_SIZE*18)
#define MIN_READAHEAD (PAGE_SIZE*3)
#define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
#if 0 /* small readahead */
#define MAX_READAHEAD PageAlignSize(4096*7)
#define MIN_READAHEAD PageAlignSize(4096*2)
#else /* large readahead */
#define MAX_READAHEAD PageAlignSize(4096*18)
#define MIN_READAHEAD PageAlignSize(4096*3)
#endif
static inline unsigned long generic_file_readahead(int reada_ok, struct file * filp, struct inode * inode,
......
......@@ -756,26 +756,6 @@ int verify_area(int type, const void * addr, unsigned long size)
return -EFAULT;
}
static inline void get_empty_page(struct task_struct * tsk, struct vm_area_struct * vma,
pte_t * page_table, int write_access)
{
pte_t pte;
pte = pte_wrprotect(mk_pte(ZERO_PAGE, vma->vm_page_prot));
if (write_access) {
unsigned long page = get_free_page(GFP_KERNEL);
pte = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
vma->vm_mm->rss++;
tsk->min_flt++;
if (!page) {
oom(tsk);
pte = BAD_PAGE;
}
flush_page_to_ram(page);
}
put_page(page_table, pte);
}
/*
* This function zeroes out partial mmap'ed pages at truncation time..
*/
......@@ -886,6 +866,9 @@ static inline void do_swap_page(struct task_struct * tsk,
* tries to share with existing pages, but makes a separate copy if
* the "write_access" parameter is true in order to avoid the next
* page fault.
*
* As this is called only for pages that do not currently exist, we
* do not need to flush old virtual caches or the TLB.
*/
void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma,
unsigned long address, int write_access)
......@@ -938,23 +921,31 @@ void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma,
entry = pte_mkwrite(pte_mkdirty(entry));
} else if (mem_map[MAP_NR(page)].count > 1 && !(vma->vm_flags & VM_SHARED))
entry = pte_wrprotect(entry);
flush_cache_page(vma, address);
put_page(page_table, entry);
/* no need to invalidate: a not-present page shouldn't be cached */
return;
anonymous_page:
entry = pte_wrprotect(mk_pte(ZERO_PAGE, vma->vm_page_prot));
if (write_access) {
unsigned long page = __get_free_page(GFP_KERNEL);
if (!page)
goto sigbus;
memset((void *) page, 0, PAGE_SIZE);
entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
vma->vm_mm->rss++;
tsk->min_flt++;
flush_page_to_ram(page);
}
put_page(page_table, entry);
return;
sigbus:
force_sig(SIGBUS, current);
flush_cache_page(vma, address);
put_page(page_table, BAD_PAGE);
/* no need to invalidate, wasn't present */
return;
anonymous_page:
flush_cache_page(vma, address);
get_empty_page(tsk, vma, page_table, write_access);
return;
swap_page:
do_swap_page(tsk, vma, address, page_table, entry, write_access);
return;
......
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