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

Import 2.0.9

parent 2409324e
...@@ -1004,9 +1004,10 @@ S: Germany ...@@ -1004,9 +1004,10 @@ S: Germany
N: David C. Niemi N: David C. Niemi
E: niemi@erols.com 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: 2364 Old Trail Drive
S: Reston, Virginia 22091 S: Reston, Virginia 20191
S: USA S: USA
N: Michael O'Reilly N: Michael O'Reilly
...@@ -1449,7 +1450,7 @@ S: Fargo, ND 58122 ...@@ -1449,7 +1450,7 @@ S: Fargo, ND 58122
S: USA S: USA
N: Hans-Joachim Widmaier N: Hans-Joachim Widmaier
E: jbhr@sofal.tynet.sub.org E: hjw@zvw.de
D: AFFS rewrite D: AFFS rewrite
S: Eichenweg 16 S: Eichenweg 16
S: 73650 Winterbach S: 73650 Winterbach
......
...@@ -22,7 +22,11 @@ prefer a HTML-ized shopping list. ...@@ -22,7 +22,11 @@ prefer a HTML-ized shopping list.
documento, consultad la traduccion de Alfredo Sanjuan en documento, consultad la traduccion de Alfredo Sanjuan en
http://slug.ctv.es/~alfredo/Cambios.html. 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 Author: Chris Ricker (gt1355b@prism.gatech.edu).
Current Releases Current Releases
...@@ -40,7 +44,9 @@ Current Releases ...@@ -40,7 +44,9 @@ Current Releases
- Gpm 1.09 - Gpm 1.09
- SysVinit 2.64 - SysVinit 2.64
- Util-linux 2.5 - Util-linux 2.5
- Mount 2.5k
- Net-tools 1.32-alpha - Net-tools 1.32-alpha
- Kbd 0.91
Upgrade notes Upgrade notes
************* *************
...@@ -225,6 +231,15 @@ Kbd ...@@ -225,6 +231,15 @@ Kbd
For those of you needing non-ASCII character/font support, you should 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. 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 Console
======= =======
...@@ -318,7 +333,7 @@ ftp://louie.udel.edu/pub/ntp/xntp3.5f.tar.Z. ...@@ -318,7 +333,7 @@ ftp://louie.udel.edu/pub/ntp/xntp3.5f.tar.Z.
Sound driver 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 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 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 report that various other sound utils (cdd2wav-sbpcd, for example) need
...@@ -352,7 +367,7 @@ Loop device ...@@ -352,7 +367,7 @@ Loop device
file as a file system, which can allow for all sorts of cool things 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 like encrypted file systems and such. To use it, you'll need a
modified version of mount from 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 on encrypted file system support can be found in
ftp.funet.fi:/pub/OS/Linux/BETA/loop/des.1.tar.gz. ftp.funet.fi:/pub/OS/Linux/BETA/loop/des.1.tar.gz.
...@@ -463,7 +478,9 @@ groff ...@@ -463,7 +478,9 @@ groff
pages due to changes in groff. If your man pages display <AD> for - 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 when present at the end of a line, try setting an appropriate value
(many have reported success with "latin1", for example) for the (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 How to know the version of the installed programs
************************************************* *************************************************
......
Amiga filesystems Overview Amiga filesystems Overview
========================== ==========================
Not all varieties of the Amiga filesystems are supported. The Amiga Not all varieties of the Amiga filesystems are supported for reading and
currently knows 6 different filesystems: writing. The Amiga currently knows 6 different filesystems:
DOS\0 The old or original filesystem, not really suited for DOS\0 The old or original filesystem, not really suited for
hard disks and normally not used on them, either. 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 DOS\2 The old "international" filesystem. International means that
a bug has been fixed so that accented ("international") letters a bug has been fixed so that accented ("international") letters
in file names are case-insensitive, as they ought to be. 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 DOS\4 The original filesystem with directory cache. The directory
cache speeds up directory accesses on floppies considerably, cache speeds up directory accesses on floppies considerably,
but slows down file creation/deletion. Doesn't make much 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. 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 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 ...@@ -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. 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 mode=mode Sets the mode flags to the given (octal) value, regardless
of the original permissions. Directories will get an x of the original permissions. Directories will get an x
permission, if the corresponding r bit is set. permission, if the corresponding r bit is set.
...@@ -72,6 +71,13 @@ quiet The file system will not return an error for disallowed ...@@ -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 verbose The volume name, file system type and block size will
be written to the syslog. 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 Handling of the Users/Groups and protection flags
================================================= =================================================
...@@ -109,9 +115,33 @@ The Linux rwxrwxrwx file mode is handled as follows: ...@@ -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 Newly created files and directories will get the user and group id
of the current user and a mode according to the umask. of the current user and a mode according to the umask.
Command line example Symbolic links
==================== ==============
mount Archive/Amiga/Workbench3.1.adf /mnt -t affs -o loop,size=1760
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 mount /dev/sda3 /Amiga -t affs
/etc/fstab example /etc/fstab example
...@@ -151,7 +181,7 @@ Until then, you should do ...@@ -151,7 +181,7 @@ Until then, you should do
ln -s /bin/true /etc/fs/mkfs.affs ln -s /bin/true /etc/fs/mkfs.affs
It's not possible to read floppy disks with a normal PC or workstation 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 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). ...@@ -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 Interfaces beyond the first two are not normally probed for, but may be
specified using kernel "command line" options. For example, 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: 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: ...@@ -120,6 +120,9 @@ The standard port, and irq values are these:
ide2=0x1e8,0x3ee,11 ide2=0x1e8,0x3ee,11
ide3=0x168,0x36e,10 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 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 to the appropriate ide channel. Pass the parameter for the correct ide
channel to the kernel, as explained above. channel to the kernel, as explained above.
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 0 PATCHLEVEL = 0
SUBLEVEL = 8 SUBLEVEL = 9
ARCH = i386 ARCH = i386
......
...@@ -62,6 +62,7 @@ CONFIG_BLK_DEV_FD=y ...@@ -62,6 +62,7 @@ CONFIG_BLK_DEV_FD=y
CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM=y
# CONFIG_BLK_DEV_INITRD is not set # CONFIG_BLK_DEV_INITRD is not set
# CONFIG_BLK_DEV_XD is not set # CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_DEV_HD is not set
# #
# Networking options # Networking options
......
...@@ -40,7 +40,7 @@ CPP=$(CC) -E -D__ELF__ ...@@ -40,7 +40,7 @@ CPP=$(CC) -E -D__ELF__
OBJDUMP=$(CROSS_COMPILE)objdump OBJDUMP=$(CROSS_COMPILE)objdump
OBJDUMP_FLAGS=-k -q OBJDUMP_FLAGS=-k -q
ENCAPS=$(CROSS_COMPILE)encaps 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 ZLDFLAGS=-e startup_32
LDFLAGS=-e stext LDFLAGS=-e stext
ZIMAGE_OFFSET=0x1000 ZIMAGE_OFFSET=0x1000
......
...@@ -16,13 +16,13 @@ else ...@@ -16,13 +16,13 @@ else
bool ' Support removable IDE interfaces (PCMCIA)' CONFIG_BLK_DEV_IDE_PCMCIA bool ' Support removable IDE interfaces (PCMCIA)' CONFIG_BLK_DEV_IDE_PCMCIA
bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640 bool ' CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640
if [ "$CONFIG_PCI" = "y" ]; then 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 ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000
bool ' Intel 82371 PIIX (Triton I/II) DMA support' CONFIG_BLK_DEV_TRITON
fi fi
bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS
if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
comment 'Note: most of these also require special kernel boot parameters' 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 ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278
bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
...@@ -50,6 +50,8 @@ tristate 'XT harddisk support' CONFIG_BLK_DEV_XD ...@@ -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 if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then
define_bool CONFIG_BLK_DEV_HD y define_bool CONFIG_BLK_DEV_HD y
else
define_bool CONFIG_BLK_DEV_HD n
fi fi
endmenu endmenu
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
/* /*
* ALI M14xx chipset EIDE controller * 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 * Adapted from code developed by derekn@vw.ece.cmu.edu. -ml
* Derek's notes follow: * Derek's notes follow:
* *
...@@ -23,6 +25,16 @@ ...@@ -23,6 +25,16 @@
* *
* Derek Noonburg (derekn@ece.cmu.edu) * Derek Noonburg (derekn@ece.cmu.edu)
* 95-sep-26 * 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 */ #undef REALLY_SLOW_IO /* most systems can safely undef this */
...@@ -45,8 +57,8 @@ ...@@ -45,8 +57,8 @@
* from 25 to 50. Setting this too *low* will make the EIDE * from 25 to 50. Setting this too *low* will make the EIDE
* controller unable to communicate with the disks. * controller unable to communicate with the disks.
* *
* I suggest using a default of 50, since it should work ok with any * The value is 50 by default -- this should work ok with any system.
* system. (Low values cause problems because it multiplies by bus speed * (Low values cause problems because it multiplies by bus speed
* to get cycles, and thus gets a too-small cycle count and tries to * 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 * access the disks too fast. I tried this once under DOS and it locked
* up the system.) -- derekn@vw.ece.cmu.edu * up the system.) -- derekn@vw.ece.cmu.edu
...@@ -71,11 +83,13 @@ static RegInitializer initData[] = { ...@@ -71,11 +83,13 @@ static RegInitializer initData[] = {
}; };
/* default timing parameters for each PIO mode */ /* 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 */ {600, 165}, /* PIO 0 */
{383, 125}, /* PIO 1 */ {383, 125}, /* PIO 1 */
{240, 100}, /* PIO 2 */ {240, 100}, /* PIO 2 */
{180, 80} /* PIO 3 */ {180, 80}, /* PIO 3 */
{120, 70} /* PIO 4 */
}; };
/* timing parameter registers for each drive */ /* timing parameter registers for each drive */
...@@ -127,20 +141,20 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio) ...@@ -127,20 +141,20 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
if (pio == 255) if (pio == 255)
pio = ide_get_best_pio_mode(drive); pio = ide_get_best_pio_mode(drive);
if (pio > 3) if (pio > ALI_MAX_PIO)
pio = 3; pio = ALI_MAX_PIO;
/* calculate timing, according to PIO mode */ /* calculate timing, according to PIO mode */
time1 = timeTab[pio].time1; time1 = timeTab[pio].time1;
time2 = timeTab[pio].time2; time2 = timeTab[pio].time2;
if (pio == 3) { if (pio >= 3) {
time1a = (id->capability & 0x08) ? id->eide_pio_iordy : id->eide_pio; time1a = (id->capability & 0x08) ? id->eide_pio_iordy : id->eide_pio;
if (time1a != 0 && time1a < time1) if (time1a != 0 && time1a < time1)
time1 = time1a; time1 = time1a;
} }
param3 = param1 = (time2 * ALI_14xx_BUS_SPEED + 999) / 1000; param3 = param1 = (time2 * ALI_14xx_BUS_SPEED + 999) / 1000;
param4 = param2 = (time1 * ALI_14xx_BUS_SPEED + 999) / 1000 - param1; param4 = param2 = (time1 * ALI_14xx_BUS_SPEED + 999) / 1000 - param1;
if (pio != 3) { if (pio < 3) {
param3 += 8; param3 += 8;
param4 += 8; param4 += 8;
} }
......
This diff is collapsed.
...@@ -41,8 +41,8 @@ ...@@ -41,8 +41,8 @@
* *
* DTC2278S has only a single IDE interface. * DTC2278S has only a single IDE interface.
* DTC2278D has two IDE interfaces and is otherwise identical to the S version. * DTC2278D has two IDE interfaces and is otherwise identical to the S version.
* DTC2278E has onboard BIOS, while the others do not. * DTC2278E also has serial ports and a printer port
* DTC2278EB: "works like a charm" -- Kent Bradford <kent@theory.caltech.edu> * 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 * There may be a fourth controller type. The S and D versions use the
* Winbond chip, and I think the E version does also. * 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 ...@@ -551,6 +551,88 @@ static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sec
#endif /* CONFIG_SUN_PARTITION */ #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 void check_partition(struct gendisk *hd, kdev_t dev)
{ {
static int first_time = 1; static int first_time = 1;
...@@ -583,6 +665,10 @@ static void check_partition(struct gendisk *hd, kdev_t dev) ...@@ -583,6 +665,10 @@ static void check_partition(struct gendisk *hd, kdev_t dev)
#ifdef CONFIG_SUN_PARTITION #ifdef CONFIG_SUN_PARTITION
if(sun_partition(hd, dev, first_sector)) if(sun_partition(hd, dev, first_sector))
return; return;
#endif
#ifdef CONFIG_AMIGA_PARTITION
if(amiga_partition(hd, dev, first_sector))
return;
#endif #endif
printk(" unknown partition table\n"); 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) * Copyright (C) 1994-1996 Linus Torvalds & authors (see below)
*/ */
...@@ -238,6 +238,11 @@ ...@@ -238,6 +238,11 @@
* Version 5.42 simplify irq-masking after probe * Version 5.42 simplify irq-masking after probe
* fix NULL pointer deref in save_match() * fix NULL pointer deref in save_match()
* Version 5.43 Ugh.. unexpected_intr is back: try to exterminate it * 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 * Some additional driver compile-time options are in ide.h
* *
...@@ -284,7 +289,6 @@ ...@@ -284,7 +289,6 @@
#endif /* CONFIG_BLK_DEV_PROMISE */ #endif /* CONFIG_BLK_DEV_PROMISE */
static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR}; 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 unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10}; static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10};
...@@ -580,6 +584,8 @@ static void init_gendisk (ide_hwif_t *hwif) ...@@ -580,6 +584,8 @@ static void init_gendisk (ide_hwif_t *hwif)
gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL); gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
bs = kmalloc (minors*sizeof(int), 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 */ /* cdroms and msdos f/s are examples of non-1024 blocksizes */
blksize_size[hwif->major] = bs; blksize_size[hwif->major] = bs;
for (unit = 0; unit < minors; ++unit) for (unit = 0; unit < minors; ++unit)
...@@ -1619,6 +1625,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) ...@@ -1619,6 +1625,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
byte stat; byte stat;
unsigned int unit; unsigned int unit;
ide_hwif_t *hwif = hwgroup->hwif; ide_hwif_t *hwif = hwgroup->hwif;
static unsigned long last_time = 0;
/* /*
* handle the unexpected interrupt * handle the unexpected interrupt
...@@ -1630,8 +1637,12 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) ...@@ -1630,8 +1637,12 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
if (!drive->present) if (!drive->present)
continue; continue;
SELECT_DRIVE(hwif,drive); SELECT_DRIVE(hwif,drive);
if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT)) if (!OK_STAT(stat=GET_STAT(), drive->ready_stat, BAD_STAT)) {
(void) ide_dump_status(drive, "unexpected_intr", 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)) if ((stat & DRQ_STAT))
try_to_flush_leftover_data(drive); try_to_flush_leftover_data(drive);
} }
...@@ -1645,8 +1656,8 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) ...@@ -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) void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
{ {
ide_hwgroup_t *hwgroup = dev_id; ide_hwgroup_t *hwgroup = dev_id;
ide_handler_t *handler; ide_handler_t *handler;
if (irq == hwgroup->hwif->irq && (handler = hwgroup->handler) != NULL) { if (irq == hwgroup->hwif->irq && (handler = hwgroup->handler) != NULL) {
ide_drive_t *drive = hwgroup->drive; ide_drive_t *drive = hwgroup->drive;
...@@ -1658,7 +1669,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) ...@@ -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 */ cli(); /* this is necessary, as next rq may be different irq */
if (hwgroup->handler == NULL) { if (hwgroup->handler == NULL) {
SET_RECOVERY_TIMER(HWIF(drive)); SET_RECOVERY_TIMER(HWIF(drive));
ide_do_request(hwgroup); ide_do_request(hwgroup);
} }
} else { } else {
unexpected_intr(irq, hwgroup); unexpected_intr(irq, hwgroup);
...@@ -1899,8 +1910,13 @@ static int revalidate_disk(kdev_t i_rdev) ...@@ -1899,8 +1910,13 @@ static int revalidate_disk(kdev_t i_rdev)
}; };
drive->part[0].nr_sects = current_capacity(drive); drive->part[0].nr_sects = current_capacity(drive);
if (drive->media == ide_disk) if (drive->media != ide_disk)
resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit); 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; drive->busy = 0;
wake_up(&drive->wqueue); wake_up(&drive->wqueue);
...@@ -2194,7 +2210,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ...@@ -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 */ if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */
|| (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */ || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */
|| (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */ || (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->model, sizeof(id->model), bswap);
ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap);
...@@ -2367,10 +2383,15 @@ static void delay_10ms (void) ...@@ -2367,10 +2383,15 @@ static void delay_10ms (void)
*/ */
static int try_to_identify (ide_drive_t *drive, byte cmd) static int try_to_identify (ide_drive_t *drive, byte cmd)
{ {
int hd_status, rc; int irqs, rc;
unsigned long timeout; 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? */ if (!HWIF(drive)->irq) { /* already got an IRQ? */
probe_irq_off(probe_irq_on()); /* clear dangling irqs */ probe_irq_off(probe_irq_on()); /* clear dangling irqs */
irqs = probe_irq_on(); /* start monitoring irqs */ irqs = probe_irq_on(); /* start monitoring irqs */
...@@ -2428,16 +2449,28 @@ static int try_to_identify (ide_drive_t *drive, byte cmd) ...@@ -2428,16 +2449,28 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
irqs = probe_irq_on(); irqs = probe_irq_on();
OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */ OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
udelay(5); udelay(5);
(void) GET_STAT(); /* clear drive IRQ */
(void) probe_irq_off(irqs); (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 */ } else { /* Mmmm.. multiple IRQs.. don't know which was ours */
printk("%s: IRQ probe failed (%d)\n", drive->name, irqs); printk("%s: IRQ probe failed (%d)\n", drive->name, irqs);
#ifdef CONFIG_BLK_DEV_CMD640 #ifdef CONFIG_BLK_DEV_CMD640
if (HWIF(drive)->chipset == ide_cmd640) { if (HWIF(drive)->chipset == ide_cmd640) {
extern byte (*get_cmd640_reg)(int); extern byte (*get_cmd640_reg)(int);
byte reg9 = get_cmd640_reg(0x09);
printk("%s: Hmmm.. probably a driver problem.\n", drive->name); 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)); 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 */ #endif /* CONFIG_BLK_DEV_CMD640 */
} }
...@@ -2832,7 +2865,7 @@ void ide_setup (char *s) ...@@ -2832,7 +2865,7 @@ void ide_setup (char *s)
/* /*
* Cryptic check to ensure chipset not already set for hwif: * 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) if (hwif->chipset != ide_unknown)
goto bad_option; goto bad_option;
if (i < 0 && ide_hwifs[1].chipset != ide_unknown) if (i < 0 && ide_hwifs[1].chipset != ide_unknown)
...@@ -2841,7 +2874,7 @@ void ide_setup (char *s) ...@@ -2841,7 +2874,7 @@ void ide_setup (char *s)
/* /*
* Interface keywords work only for ide0: * Interface keywords work only for ide0:
*/ */
if (i <= -6 && hw != 0) if (i <= -5 && hw != 0)
goto bad_hwif; goto bad_hwif;
switch (i) { switch (i) {
...@@ -3058,7 +3091,9 @@ static void save_match (ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) ...@@ -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) static int init_irq (ide_hwif_t *hwif)
{ {
unsigned long flags; unsigned long flags;
#if MAX_HWIFS > 1
unsigned int index; unsigned int index;
#endif /* MAX_HWIFS > 1 */
ide_hwgroup_t *hwgroup; ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL; ide_hwif_t *match = NULL;
......
...@@ -135,7 +135,11 @@ typedef unsigned char byte; /* used everywhere */ ...@@ -135,7 +135,11 @@ typedef unsigned char byte; /* used everywhere */
* Timeouts for various operations: * Timeouts for various operations:
*/ */
#define WAIT_DRQ (5*HZ/100) /* 50msec - spec allows up to 20ms */ #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 */ #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_PIDENTIFY (1*HZ) /* 1sec - should be less than 3ms (?) */
#define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */ #define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */
#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */ #define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */
...@@ -292,6 +296,18 @@ typedef union { ...@@ -292,6 +296,18 @@ typedef union {
} b; } b;
} special_t; } 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 { typedef union {
unsigned all : 8; /* all of the bits together */ unsigned all : 8; /* all of the bits together */
struct { struct {
...@@ -302,6 +318,7 @@ typedef union { ...@@ -302,6 +318,7 @@ typedef union {
unsigned bit7 : 1; /* always 1 */ unsigned bit7 : 1; /* always 1 */
} b; } b;
} select_t; } select_t;
#endif /* __BIG_ENDIAN_BITFIELD */
typedef struct ide_drive_s { typedef struct ide_drive_s {
special_t special; /* special action flags */ special_t special; /* special action flags */
...@@ -315,6 +332,7 @@ typedef struct ide_drive_s { ...@@ -315,6 +332,7 @@ typedef struct ide_drive_s {
unsigned unmask : 1; /* flag: okay to unmask other irqs */ unsigned unmask : 1; /* flag: okay to unmask other irqs */
unsigned nobios : 1; /* flag: do not probe bios for drive */ unsigned nobios : 1; /* flag: do not probe bios for drive */
unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */ unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
unsigned ignore_unexp : 1; /* flag: ignore unexpected_intr's */
#if FAKE_FDISK_FOR_EZDRIVE #if FAKE_FDISK_FOR_EZDRIVE
unsigned remap_0_to_1 : 1; /* flag: partitioned with ezdrive */ unsigned remap_0_to_1 : 1; /* flag: partitioned with ezdrive */
#endif /* FAKE_FDISK_FOR_EZDRIVE */ #endif /* FAKE_FDISK_FOR_EZDRIVE */
...@@ -324,7 +342,7 @@ typedef struct ide_drive_s { ...@@ -324,7 +342,7 @@ typedef struct ide_drive_s {
byte ready_stat; /* min status value for drive ready */ byte ready_stat; /* min status value for drive ready */
byte mult_count; /* current multiple sector setting */ byte mult_count; /* current multiple sector setting */
byte mult_req; /* requested 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 io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
byte bad_wstat; /* used for ignoring WRERR_STAT */ byte bad_wstat; /* used for ignoring WRERR_STAT */
byte sect0; /* offset of first sector for DM6:DDO */ 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 * Copyright (c) 1995-1996 Mark Lord
* May be copied or modified under the terms of the GNU General Public License * 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) ...@@ -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 * 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 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. * 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) ...@@ -382,7 +382,7 @@ void ide_init_triton (byte bus, byte fn)
unsigned short pcicmd; unsigned short pcicmd;
unsigned int bmiba, timings; 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: * See if IDE and BM-DMA features are enabled:
*/ */
...@@ -439,14 +439,14 @@ void ide_init_triton (byte bus, byte fn) ...@@ -439,14 +439,14 @@ void ide_init_triton (byte bus, byte fn)
unsigned short time; unsigned short time;
if (hwif->io_base == 0x1f0) { if (hwif->io_base == 0x1f0) {
time = timings & 0xffff; time = timings & 0xffff;
if ((timings & 0x8000) == 0) /* interface enabled? */ if ((time & 0x8000) == 0) /* interface enabled? */
continue; continue;
hwif->chipset = ide_triton; hwif->chipset = ide_triton;
if (dma_enabled) if (dma_enabled)
init_triton_dma(hwif, bmiba); init_triton_dma(hwif, bmiba);
} else if (hwif->io_base == 0x170) { } else if (hwif->io_base == 0x170) {
time = timings >> 16; time = timings >> 16;
if ((timings & 0x8000) == 0) /* interface enabled? */ if ((time & 0x8000) == 0) /* interface enabled? */
continue; continue;
hwif->chipset = ide_triton; hwif->chipset = ide_triton;
if (dma_enabled) if (dma_enabled)
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
* Daniel v. Mosnenck (he sent me the Technical and Programming Reference) * Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
* Gerd Knorr (he lent me his PhotoCD) * Gerd Knorr (he lent me his PhotoCD)
* Nils Faerber and Roger E. Wolff (extensively tested the LU portion) * 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) * Heiko Eissfeldt (VERIFY_READ/WRITE)
* Marcin Dalecki (improved performance, shortened code) * Marcin Dalecki (improved performance, shortened code)
* ... somebody forgotten? * ... somebody forgotten?
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
#define KEYBOARD_IRQ 1 #define KEYBOARD_IRQ 1
#define DISABLE_KBD_DURING_INTERRUPTS 0
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -69,14 +70,6 @@ static int initialize_kbd(void); ...@@ -69,14 +70,6 @@ static int initialize_kbd(void);
#define KBD_DEFLOCK 0 #define KBD_DEFLOCK 0
#endif #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/io.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -337,48 +330,31 @@ int getkeycode(unsigned int scancode) ...@@ -337,48 +330,31 @@ int getkeycode(unsigned int scancode)
e0_keys[scancode - 128]; 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 */ static unsigned int prev_scancode = 0; /* remember E0, E1 */
char up_flag; /* 0 or 0200 */ char up_flag; /* 0 or 0200 */
char raw_mode; 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) { if (reply_expected) {
/* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */ /* 0xfa, 0xfe only mean "acknowledge", "resend" for most keyboards */
/* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */ /* but they are the key-up scancodes for PF6, PF10 on a FOCUS 9000 */
reply_expected = 0; reply_expected = 0;
if (scancode == 0xfa) { if (scancode == 0xfa) {
acknowledge = 1; acknowledge = 1;
goto end_kbd_intr; return;
} else if (scancode == 0xfe) { } else if (scancode == 0xfe) {
resend = 1; resend = 1;
goto end_kbd_intr; return;
} }
/* strange ... */ /* strange ... */
reply_expected = 1; reply_expected = 1;
...@@ -392,7 +368,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -392,7 +368,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_INFO "keyboard buffer overflow\n"); printk(KERN_INFO "keyboard buffer overflow\n");
#endif #endif
prev_scancode = 0; prev_scancode = 0;
goto end_kbd_intr; return;
} }
do_poke_blanked_console = 1; do_poke_blanked_console = 1;
mark_bh(CONSOLE_BH); mark_bh(CONSOLE_BH);
...@@ -417,12 +393,12 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -417,12 +393,12 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#endif #endif
#endif #endif
prev_scancode = 0; prev_scancode = 0;
goto end_kbd_intr; return;
} }
if (scancode == 0xe0 || scancode == 0xe1) { if (scancode == 0xe0 || scancode == 0xe1) {
prev_scancode = scancode; 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) ...@@ -439,7 +415,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (prev_scancode != 0xe0) { if (prev_scancode != 0xe0) {
if (prev_scancode == 0xe1 && scancode == 0x1d) { if (prev_scancode == 0xe1 && scancode == 0x1d) {
prev_scancode = 0x100; prev_scancode = 0x100;
goto end_kbd_intr; return;
} else if (prev_scancode == 0x100 && scancode == 0x45) { } else if (prev_scancode == 0x100 && scancode == 0x45) {
keycode = E1_PAUSE; keycode = E1_PAUSE;
prev_scancode = 0; prev_scancode = 0;
...@@ -449,7 +425,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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"); printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
#endif #endif
prev_scancode = 0; prev_scancode = 0;
goto end_kbd_intr; return;
} }
} else { } else {
prev_scancode = 0; prev_scancode = 0;
...@@ -467,7 +443,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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 * So, we should also ignore the latter. - aeb@cwi.nl
*/ */
if (scancode == 0x2a || scancode == 0x36) if (scancode == 0x2a || scancode == 0x36)
goto end_kbd_intr; return;
if (e0_keys[scancode]) if (e0_keys[scancode])
keycode = e0_keys[scancode]; keycode = e0_keys[scancode];
...@@ -477,7 +453,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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", printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
scancode); scancode);
#endif #endif
goto end_kbd_intr; return;
} }
} }
} else if (scancode >= SC_LIM) { } else if (scancode >= SC_LIM) {
...@@ -500,7 +476,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -500,7 +476,7 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
" - ignored\n", scancode); " - ignored\n", scancode);
#endif #endif
} }
goto end_kbd_intr; return;
} }
} else } else
keycode = scancode; keycode = scancode;
...@@ -526,12 +502,12 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -526,12 +502,12 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
rep = set_bit(keycode, key_down); rep = set_bit(keycode, key_down);
if (raw_mode) if (raw_mode)
goto end_kbd_intr; return;
if (kbd->kbdmode == VC_MEDIUMRAW) { if (kbd->kbdmode == VC_MEDIUMRAW) {
/* soon keycodes will require more than one byte */ /* soon keycodes will require more than one byte */
put_queue(keycode + up_flag); 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) ...@@ -592,9 +568,32 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#endif #endif
} }
} }
}
end_kbd_intr: static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
send_cmd(0xAE); /* enable keyboard */ {
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) static void put_queue(int ch)
......
...@@ -176,6 +176,8 @@ static int read_zero(struct inode * node, struct file * file, char * buf, int co ...@@ -176,6 +176,8 @@ static int read_zero(struct inode * node, struct file * file, char * buf, int co
for (left = count; left > 0; left--) { for (left = count; left > 0; left--) {
put_user(0,buf); put_user(0,buf);
buf++; buf++;
if (need_resched)
schedule();
} }
return count; return count;
} }
......
...@@ -25,10 +25,6 @@ ...@@ -25,10 +25,6 @@
* Rearranged SIGIO support to use code from tty_io. 9Sept95 ctm@ardi.com * Rearranged SIGIO support to use code from tty_io. 9Sept95 ctm@ardi.com
* *
* Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk> * 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. */ /* Uncomment the following line if your mouse needs initialization. */
...@@ -61,10 +57,8 @@ ...@@ -61,10 +57,8 @@
#define AUX_STATUS 0x64 /* Aux device status reg */ #define AUX_STATUS 0x64 /* Aux device status reg */
/* aux controller status bits */ /* 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_OBUF_FULL 0x21 /* output buffer (from device) full */
#define AUX_IBUF_FULL 0x02 /* input buffer (to device) full */ #define AUX_IBUF_FULL 0x02 /* input buffer (to device) full */
#define AUX_TIMEOUT 0x40 /* controller reports timeout */
/* aux controller commands */ /* aux controller commands */
#define AUX_CMD_WRITE 0x60 /* value to write to controller */ #define AUX_CMD_WRITE 0x60 /* value to write to controller */
...@@ -87,14 +81,6 @@ ...@@ -87,14 +81,6 @@
#define AUX_DISABLE_DEV 0xf5 /* disable aux device */ #define AUX_DISABLE_DEV 0xf5 /* disable aux device */
#define AUX_RESET 0xff /* reset 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*/ #define MAX_RETRIES 60 /* some aux operations take long time*/
#if defined(__alpha__) && !defined(CONFIG_PCI) #if defined(__alpha__) && !defined(CONFIG_PCI)
# define AUX_IRQ 9 /* Jensen is odd indeed */ # define AUX_IRQ 9 /* Jensen is odd indeed */
...@@ -135,6 +121,7 @@ static int aux_ready = 0; ...@@ -135,6 +121,7 @@ static int aux_ready = 0;
static int aux_count = 0; static int aux_count = 0;
static int aux_present = 0; static int aux_present = 0;
static int poll_aux_status(void); 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); static int fasync_aux(struct inode *inode, struct file *filp, int on);
#ifdef CONFIG_82C710_MOUSE #ifdef CONFIG_82C710_MOUSE
...@@ -149,70 +136,49 @@ static int probe_qp(void); ...@@ -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); poll_aux_status();
return 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) static int aux_write_ack(int val)
{ {
int rv, retries = 0, stat; int retries = 0;
repeat: poll_aux_status_nosleep();
if (poll_aux_status() < 0) outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
return -1; poll_aux_status_nosleep();
outb_p(AUX_MAGIC_WRITE, AUX_COMMAND); outb_p(val,AUX_OUTPUT_PORT);
if (poll_aux_status() < 0) poll_aux_status_nosleep();
return -1;
outb_p(val, AUX_OUTPUT_PORT); if ((inb(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
{
if ((rv = poll_aux_status()) < 0) return (inb(AUX_INPUT_PORT));
/* 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;
} }
return 0;
} }
#endif /* INITIALIZE_DEVICE */
/* /*
* Write aux device command * Write aux device command
*/ */
static int aux_write_cmd(int val) static void aux_write_cmd(int val)
{ {
if (poll_aux_status() < 0) poll_aux_status();
return -1; outb_p(AUX_CMD_WRITE,AUX_COMMAND);
outb_p(AUX_CMD_WRITE, AUX_COMMAND); poll_aux_status();
if (poll_aux_status() < 0) outb_p(val,AUX_OUTPUT_PORT);
return -1;
outb_p(val, AUX_OUTPUT_PORT);
if (poll_aux_status() < 0)
return -1;
return 0;
} }
...@@ -292,19 +258,10 @@ static void release_aux(struct inode * inode, struct file * file) ...@@ -292,19 +258,10 @@ static void release_aux(struct inode * inode, struct file * file)
fasync_aux(inode, file, 0); fasync_aux(inode, file, 0);
if (--aux_count) if (--aux_count)
return; 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(); 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); free_irq(AUX_IRQ, NULL);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
} }
...@@ -349,7 +306,7 @@ static int open_aux(struct inode * inode, struct file * file) ...@@ -349,7 +306,7 @@ static int open_aux(struct inode * inode, struct file * file)
return -ENODEV; return -ENODEV;
if (aux_count++) if (aux_count++)
return 0; return 0;
if (poll_aux_status() < 0) { if (!poll_aux_status()) {
aux_count--; aux_count--;
return -EBUSY; return -EBUSY;
} }
...@@ -360,27 +317,12 @@ static int open_aux(struct inode * inode, struct file * file) ...@@ -360,27 +317,12 @@ static int open_aux(struct inode * inode, struct file * file)
} }
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
poll_aux_status(); poll_aux_status();
/* disable keyboard to avoid clashes with multi-byte command sequences */ outb_p(AUX_ENABLE,AUX_COMMAND); /* Enable Aux */
if (aux_write_byte(KBD_DISABLE, AUX_COMMAND) < 0) aux_write_dev(AUX_ENABLE_DEV); /* enable aux device */
goto open_error; aux_write_cmd(AUX_INTS_ON); /* enable controller ints */
/* Enable Aux in kbd controller */ poll_aux_status();
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;
aux_ready = 0; aux_ready = 0;
return 0; return 0;
open_error:
printk( KERN_ERR "psaux: controller timeout\n" );
return -EIO;
} }
#ifdef CONFIG_82C710_MOUSE #ifdef CONFIG_82C710_MOUSE
...@@ -436,31 +378,17 @@ static int open_qp(struct inode * inode, struct file * file) ...@@ -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) static int write_aux(struct inode * inode, struct file * file, const char * buffer, int count)
{ {
int i = 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--) { while (i--) {
if (poll_aux_status() < 0) { if (!poll_aux_status())
rv = -EIO; return -EIO;
break;
}
outb_p(AUX_MAGIC_WRITE,AUX_COMMAND); outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
if (poll_aux_status() < 0) { if (!poll_aux_status())
rv = -EIO; return -EIO;
break;
}
outb_p(get_user(buffer++),AUX_OUTPUT_PORT); 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; inode->i_mtime = CURRENT_TIME;
return rv ? rv : count; return count;
} }
...@@ -591,11 +519,13 @@ int psaux_init(void) ...@@ -591,11 +519,13 @@ int psaux_init(void)
aux_write_ack(AUX_SET_RES); aux_write_ack(AUX_SET_RES);
aux_write_ack(3); /* 8 counts per mm */ aux_write_ack(3); /* 8 counts per mm */
aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */ aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
poll_aux_status_nosleep();
#endif /* INITIALIZE_DEVICE */ #endif /* INITIALIZE_DEVICE */
/* Disable Aux device and its interrupts on the controller */ outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */
if (aux_write_byte(AUX_DISABLE, AUX_COMMAND) < 0 || poll_aux_status_nosleep();
aux_write_cmd(AUX_INTS_OFF) < 0) outb_p(AUX_CMD_WRITE,AUX_COMMAND);
printk(KERN_ERR "psaux: controller timeout\n"); poll_aux_status_nosleep(); /* Disable interrupts */
outb_p(AUX_INTS_OFF, AUX_OUTPUT_PORT); /* on the controller */
} }
return 0; return 0;
} }
...@@ -603,7 +533,7 @@ int psaux_init(void) ...@@ -603,7 +533,7 @@ int psaux_init(void)
#ifdef MODULE #ifdef MODULE
int init_module(void) int init_module(void)
{ {
return psaux_init(); return psaux_init(); /*?? Bjorn */
} }
void cleanup_module(void) void cleanup_module(void)
...@@ -615,18 +545,28 @@ void cleanup_module(void) ...@@ -615,18 +545,28 @@ void cleanup_module(void)
static int poll_aux_status(void) static int poll_aux_status(void)
{ {
int retries=0; int retries=0;
int reply=0;
while ((inb(AUX_STATUS) & (AUX_KOBUF_FULL|AUX_IBUF_FULL)) && while ((inb(AUX_STATUS)&0x03) && retries < MAX_RETRIES) {
retries < MAX_RETRIES) {
if ((inb_p(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL) 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->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + (5*HZ + 99) / 100; current->timeout = jiffies + (5*HZ + 99) / 100;
schedule(); schedule();
retries++; 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 #ifdef CONFIG_82C710_MOUSE
......
...@@ -755,9 +755,48 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co ...@@ -755,9 +755,48 @@ static int tty_read(struct inode * inode, struct file * file, char * buf, int co
return i; 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) 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; struct tty_struct * tty;
is_console = (inode->i_rdev == CONSOLE_DEV); is_console = (inode->i_rdev == CONSOLE_DEV);
...@@ -781,14 +820,12 @@ static int tty_write(struct inode * inode, struct file * file, const char * buf, ...@@ -781,14 +820,12 @@ static int tty_write(struct inode * inode, struct file * file, const char * buf,
} }
} }
#endif #endif
if (tty->ldisc.write) if (!tty->ldisc.write)
/* XXX casts are for what kernel-wide prototypes should be. */ return -EIO;
i = (tty->ldisc.write)(tty,file,(const unsigned char *)buf,(unsigned int)count); return do_tty_write(tty->ldisc.write,
else inode, tty, file,
i = -EIO; (const unsigned char *)buf,
if (i > 0) (unsigned int)count);
inode->i_mtime = CURRENT_TIME;
return i;
} }
/* /*
......
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) Sun Jul 14 15:00 1996 Gerard Roudier (groudier@club-internet.fr)
* ncr53c8xx.c, Configure.help * ncr53c8xx.c, Configure.help
Memory mapped io donnot work under linux/Alpha for the driver. Memory mapped io donnot work under linux/Alpha for the driver.
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
*/ */
/* /*
** 23 June 1996, version 1.12 ** 21 July 1996, version 1.12b
** **
** Supported SCSI-II features: ** Supported SCSI-II features:
** Synchronous negotiation ** Synchronous negotiation
...@@ -424,6 +424,10 @@ static struct { ...@@ -424,6 +424,10 @@ static struct {
#define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f)) #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) #if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs); static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
#else #else
...@@ -3494,6 +3498,9 @@ printf("ncr_attach: unit=%d chip=%d base=%x, io_port=%x, irq=%d\n", unit, chip, ...@@ -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->io_port = io_port;
instance->n_io_port = 128; instance->n_io_port = 128;
instance->dma_channel = 0; 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 ** Patch script to physical addresses
...@@ -4786,7 +4793,7 @@ void ncr_init (ncb_p np, char * msg, u_long code) ...@@ -4786,7 +4793,7 @@ void ncr_init (ncb_p np, char * msg, u_long code)
else else
/** NCR53C815 **/ /** NCR53C815 **/
if (ChipDevice == PCI_DEVICE_ID_NCR_53C815) { if (ChipDevice == PCI_DEVICE_ID_NCR_53C815) {
OUTB(nc_dmode, 0x00); /* Set 2-transfer burst */ OUTB(nc_dmode, 0x80); /* Set 8-transfer burst */
} }
else else
/** NCR53C825 **/ /** NCR53C825 **/
...@@ -5874,7 +5881,7 @@ static void ncr_int_ma (ncb_p np) ...@@ -5874,7 +5881,7 @@ static void ncr_int_ma (ncb_p np)
if (cp != np->header.cp) { if (cp != np->header.cp) {
printf ("%s: SCSI phase error fixup: CCB address mismatch (0x%08lx != 0x%08lx)\n", 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); 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 ...@@ -7521,6 +7528,30 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, int unit, int board, int
(int) irq, bus, (uchar) device_fn); (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 ** Linux entry point of queuecommand() function
......
...@@ -196,7 +196,7 @@ int ncr53c8xx_release(struct Scsi_Host *); ...@@ -196,7 +196,7 @@ int ncr53c8xx_release(struct Scsi_Host *);
#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0) #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_release, /* info */ NULL, /* command, deprecated */ NULL, \
ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset, \ ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset, \
NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\ NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
...@@ -207,7 +207,7 @@ int ncr53c8xx_release(struct Scsi_Host *); ...@@ -207,7 +207,7 @@ int ncr53c8xx_release(struct Scsi_Host *);
#else #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_release, /* info */ NULL, /* command, deprecated */ NULL, \
ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset, \ ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset, \
NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\ NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
......
...@@ -2875,11 +2875,32 @@ static void resize_dma_pool(void) ...@@ -2875,11 +2875,32 @@ static void resize_dma_pool(void)
for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) { for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
host = SDpnt->host; 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 * new_dma_sectors += ((host->sg_tablesize *
sizeof(struct scatterlist) + 511) >> 9) * sizeof(struct scatterlist) + 511) >> 9) *
SDpnt->queue_depth; 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 && if(host->unchecked_isa_dma &&
scsi_need_isa_bounce_buffers && scsi_need_isa_bounce_buffers &&
SDpnt->type != TYPE_TAPE) { SDpnt->type != TYPE_TAPE) {
...@@ -2888,7 +2909,11 @@ static void resize_dma_pool(void) ...@@ -2888,7 +2909,11 @@ static void resize_dma_pool(void)
new_need_isa_buffer++; 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: */ /* limit DMA memory to 32MB: */
new_dma_sectors = (new_dma_sectors + 15) & 0xfff0; new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
...@@ -2945,6 +2970,12 @@ static void resize_dma_pool(void) ...@@ -2945,6 +2970,12 @@ static void resize_dma_pool(void)
dma_sectors = new_dma_sectors; dma_sectors = new_dma_sectors;
need_isa_buffer = new_need_isa_buffer; need_isa_buffer = new_need_isa_buffer;
restore_flags(flags); 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... */ #ifdef CONFIG_MODULES /* a big #ifdef block... */
......
...@@ -582,7 +582,7 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock) ...@@ -582,7 +582,7 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
if (!audio_devs[dev]->go) if (!audio_devs[dev]->go)
tmout = 0; tmout = 0;
else else
tmout = 2 * HZ; tmout = 10 * HZ;
{ {
......
...@@ -832,7 +832,9 @@ unload_pss (struct address_info *hw_config) ...@@ -832,7 +832,9 @@ unload_pss (struct address_info *hw_config)
void void
unload_pss_mpu (struct address_info *hw_config) unload_pss_mpu (struct address_info *hw_config)
{ {
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
unload_mpu401 (hw_config); unload_mpu401 (hw_config);
#endif
} }
void void
......
...@@ -44,16 +44,26 @@ affs_put_super(struct super_block *sb) ...@@ -44,16 +44,26 @@ affs_put_super(struct super_block *sb)
lock_super(sb); lock_super(sb);
for (i = 0; i < sb->u.affs_sb.s_bm_count; i++) for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh); 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); if (!(sb->s_flags & MS_RDONLY)) {
secs_to_datestamp(CURRENT_TIME,&ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered); ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1);
affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5); secs_to_datestamp(CURRENT_TIME,
mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1); &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) if (sb->u.affs_sb.s_flags & SF_PREFIX)
kfree(sb->u.affs_sb.s_prefix); kfree(sb->u.affs_sb.s_prefix);
kfree(sb->u.affs_sb.s_bitmap); kfree(sb->u.affs_sb.s_bitmap);
affs_brelse(sb->u.affs_sb.s_root_bh); 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); set_blocksize(sb->s_dev,BLOCK_SIZE);
sb->s_dev = 0; sb->s_dev = 0;
unlock_super(sb); unlock_super(sb);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
...@@ -63,13 +73,8 @@ affs_put_super(struct super_block *sb) ...@@ -63,13 +73,8 @@ affs_put_super(struct super_block *sb)
static void static void
affs_write_super(struct super_block *sb) 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)) { if (!(sb->s_flags & MS_RDONLY)) {
lock_super(sb); lock_super(sb);
for (i = 0, clean = 1; i < sb->u.affs_sb.s_bm_count; i++) { 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 ...@@ -149,13 +154,6 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i
} }
*mount_opts |= SF_IMMUTABLE; *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")) { else if (!strcmp(this_char,"verbose")) {
if (value) { if (value) {
printk("AFFS: option verbose does not take an argument\n"); 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) ...@@ -380,6 +378,16 @@ affs_read_super(struct super_block *s,void *data, int silent)
bb = affs_bread(dev,0,s->s_blocksize); bb = affs_bread(dev,0,s->s_blocksize);
if (bb) { if (bb) {
chksum = htonl(*(__u32 *)bb->b_data); 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) { switch (chksum) {
case MUFS_FS: case MUFS_FS:
case MUFS_INTLFFS: case MUFS_INTLFFS:
...@@ -388,9 +396,11 @@ affs_read_super(struct super_block *s,void *data, int silent) ...@@ -388,9 +396,11 @@ affs_read_super(struct super_block *s,void *data, int silent)
case FS_INTLFFS: case FS_INTLFFS:
s->u.affs_sb.s_flags |= SF_INTL; s->u.affs_sb.s_flags |= SF_INTL;
break; break;
case MUFS_DCFFS:
case MUFS_FFS: case MUFS_FFS:
s->u.affs_sb.s_flags |= SF_MUFS; s->u.affs_sb.s_flags |= SF_MUFS;
break; break;
case FS_DCFFS:
case FS_FFS: case FS_FFS:
break; break;
case MUFS_OFS: case MUFS_OFS:
...@@ -399,20 +409,13 @@ affs_read_super(struct super_block *s,void *data, int silent) ...@@ -399,20 +409,13 @@ affs_read_super(struct super_block *s,void *data, int silent)
case FS_OFS: case FS_OFS:
s->u.affs_sb.s_flags |= SF_OFS; s->u.affs_sb.s_flags |= SF_OFS;
break; break;
case MUFS_DCOFS:
case MUFS_INTLOFS: case MUFS_INTLOFS:
s->u.affs_sb.s_flags |= SF_MUFS; s->u.affs_sb.s_flags |= SF_MUFS;
/* fall thru */ case FS_DCOFS:
case FS_INTLOFS: case FS_INTLOFS:
s->u.affs_sb.s_flags |= SF_INTL | SF_OFS; s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;
break; 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: default:
printk("AFFS: Unknown filesystem on device %s: %08X\n", printk("AFFS: Unknown filesystem on device %s: %08X\n",
kdevname(dev),chksum); kdevname(dev),chksum);
...@@ -432,8 +435,8 @@ affs_read_super(struct super_block *s,void *data, int silent) ...@@ -432,8 +435,8 @@ affs_read_super(struct super_block *s,void *data, int silent)
(char *)&chksum,((char *)&chksum)[3] + '0',blocksize); (char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
} }
s->s_magic = AFFS_SUPER_MAGIC; s->s_magic = AFFS_SUPER_MAGIC;
s->s_flags = MS_NODEV | MS_NOSUID; s->s_flags |= MS_NODEV | MS_NOSUID;
/* Keep super block in cache */ /* Keep super block in cache */
if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) { 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) ...@@ -587,6 +590,7 @@ affs_read_super(struct super_block *s,void *data, int silent)
affs_brelse(s->u.affs_sb.s_root_bh); affs_brelse(s->u.affs_sb.s_root_bh);
if (s->u.affs_sb.s_bitmap) if (s->u.affs_sb.s_bitmap)
kfree(s->u.affs_sb.s_bitmap); kfree(s->u.affs_sb.s_bitmap);
set_blocksize(dev,BLOCK_SIZE);
s->s_dev = 0; s->s_dev = 0;
unlock_super(s); unlock_super(s);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
...@@ -787,7 +791,7 @@ affs_write_inode(struct inode *inode) ...@@ -787,7 +791,7 @@ affs_write_inode(struct inode *inode)
gid = inode->i_gid ^ ~0; gid = inode->i_gid ^ ~0;
} }
if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETUID)) 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)) if (!(inode->i_sb->u.affs_sb.s_flags & SF_SETGID))
file_end->owner_gid = ntohs(gid); file_end->owner_gid = ntohs(gid);
} }
......
...@@ -476,20 +476,11 @@ void iput(struct inode * inode) ...@@ -476,20 +476,11 @@ void iput(struct inode * inode)
return; 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) struct inode * get_empty_inode(void)
{ {
static int ino = 0; static int ino = 0;
struct inode * inode, * best; struct inode * inode, * best;
unsigned long badness = 1000; unsigned long badness;
int i; int i;
if (nr_inodes < max_inodes && nr_free_inodes < (nr_inodes >> 1)) if (nr_inodes < max_inodes && nr_free_inodes < (nr_inodes >> 1))
...@@ -497,50 +488,54 @@ struct inode * get_empty_inode(void) ...@@ -497,50 +488,54 @@ struct inode * get_empty_inode(void)
repeat: repeat:
inode = first_inode; inode = first_inode;
best = NULL; best = NULL;
badness = 1000;
for (i = nr_inodes/2; i > 0; i--,inode = inode->i_next) { for (i = nr_inodes/2; i > 0; i--,inode = inode->i_next) {
if (!inode->i_count) { 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) { if (i < badness) {
best = inode; best = inode;
if ((badness = i) == 0) if (!i)
break; goto found_good;
badness = i;
} }
} }
} }
if (badness) if (nr_inodes < max_inodes) {
if (nr_inodes < max_inodes) { if (grow_inodes() == 0)
if (grow_inodes() == 0) goto repeat;
goto repeat; best = NULL;
} }
inode = best; if (!best) {
if (!inode) {
printk("VFS: No free inodes - contact Linus\n"); printk("VFS: No free inodes - contact Linus\n");
sleep_on(&inode_wait); sleep_on(&inode_wait);
goto repeat; goto repeat;
} }
if (inode->i_lock) { if (best->i_lock) {
wait_on_inode(inode); wait_on_inode(best);
goto repeat; goto repeat;
} }
if (inode->i_dirt) { if (best->i_dirt) {
write_inode(inode); write_inode(best);
goto repeat; goto repeat;
} }
if (inode->i_count) if (best->i_count)
goto repeat; goto repeat;
clear_inode(inode); found_good:
inode->i_count = 1; clear_inode(best);
inode->i_nlink = 1; best->i_count = 1;
inode->i_version = ++event; best->i_nlink = 1;
inode->i_sem.count = 1; best->i_version = ++event;
inode->i_ino = ++ino; best->i_sem.count = 1;
inode->i_dev = 0; best->i_ino = ++ino;
best->i_dev = 0;
nr_free_inodes--; nr_free_inodes--;
if (nr_free_inodes < 0) { if (nr_free_inodes < 0) {
printk ("VFS: get_empty_inode: bad free inode count.\n"); printk ("VFS: get_empty_inode: bad free inode count.\n");
nr_free_inodes = 0; nr_free_inodes = 0;
} }
return inode; return best;
} }
struct inode * get_pipe_inode(void) struct inode * get_pipe_inode(void)
......
...@@ -5,9 +5,11 @@ ...@@ -5,9 +5,11 @@
* *
* (C) 1991 Linus Torvalds - minix filesystem * (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 * isofs directory handling functions
*/ */
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/iso_fs.h> #include <linux/iso_fs.h>
...@@ -133,9 +135,13 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, ...@@ -133,9 +135,13 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
#ifdef DEBUG #ifdef DEBUG
printk("Block, offset, f_pos: %x %x %x\n", printk("Block, offset, f_pos: %x %x %x\n",
block, offset, filp->f_pos); block, offset, filp->f_pos);
printk("inode->i_size = %x\n",inode->i_size);
#endif #endif
/* Next directory_record on next CDROM sector */ /* Next directory_record on next CDROM sector */
if (offset >= bufsize) { if (offset >= bufsize) {
#ifdef DEBUG
printk("offset >= bufsize\n");
#endif
brelse(bh); brelse(bh);
offset = 0; offset = 0;
block = isofs_bmap(inode, (filp->f_pos) >> bufbits); block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
...@@ -151,6 +157,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, ...@@ -151,6 +157,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
inode_number = (block << bufbits) + (offset & (bufsize - 1)); inode_number = (block << bufbits) + (offset & (bufsize - 1));
de_len = *(unsigned char *) de; 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 /* 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 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, ...@@ -175,15 +185,31 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
If not, put the two halves together in "tmpde" */ If not, put the two halves together in "tmpde" */
next_offset = offset + de_len; next_offset = offset + de_len;
if (next_offset > bufsize) { if (next_offset > bufsize) {
#ifdef DEBUG
printk("next_offset (%x) > bufsize (%x)\n",next_offset,bufsize);
#endif
next_offset &= (bufsize - 1); next_offset &= (bufsize - 1);
memcpy(tmpde, de, bufsize - offset); memcpy(tmpde, de, bufsize - offset);
brelse(bh); brelse(bh);
block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits); block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits);
if (!block) if (!block)
{
return 0; 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) 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; return 0;
}
memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset); memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset);
de = tmpde; de = tmpde;
} }
......
...@@ -189,7 +189,7 @@ static unsigned int isofs_get_last_session(kdev_t dev) ...@@ -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); printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
} }
#endif 0 #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; return vol_desc_start;
} }
......
...@@ -62,6 +62,31 @@ static void probe_m68k_ide (void); ...@@ -62,6 +62,31 @@ static void probe_m68k_ide (void);
#undef HD_DATA #undef HD_DATA
#define HD_DATA NULL #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 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) #define insl(data_reg, buffer, wcount) insw(data_reg, buffer, wcount<<1)
......
...@@ -64,7 +64,6 @@ struct affs_sb_info { ...@@ -64,7 +64,6 @@ struct affs_sb_info {
#define SF_SETUID 0x0010 /* Ignore Amiga uid */ #define SF_SETUID 0x0010 /* Ignore Amiga uid */
#define SF_SETGID 0x0020 /* Ignore Amiga gid */ #define SF_SETGID 0x0020 /* Ignore Amiga gid */
#define SF_SETMODE 0x0040 /* Ignore Amiga protection bits */ #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_MUFS 0x0100 /* Use MUFS uid/gid mapping */
#define SF_OFS 0x0200 /* Old filesystem */ #define SF_OFS 0x0200 /* Old filesystem */
#define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */ #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) ...@@ -467,6 +467,7 @@ asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
int err; int err;
unsigned int id; unsigned int id;
unsigned long addr; unsigned long addr;
unsigned long len;
if (shmid < 0) { if (shmid < 0) {
/* printk("shmat() -> EINVAL because shmid = %d < 0\n",shmid); */ /* 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) ...@@ -490,6 +491,12 @@ asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
else else
return -EINVAL; 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 * If shm segment goes below stack, make sure there is some
* space left for the stack to grow (presently 4 pages). * space left for the stack to grow (presently 4 pages).
......
...@@ -415,7 +415,7 @@ static void profile_readahead(int async, struct file *filp) ...@@ -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. * Reasonable means, in this context, not too large but not too small.
* The actual maximum value is: * The actual maximum value is:
* MAX_READAHEAD + PAGE_SIZE = 76k is CONFIG_READA_SMALL is undefined * 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: * Asynchronous read-ahead benefits:
* --------------------------------- * ---------------------------------
...@@ -442,15 +442,17 @@ static void profile_readahead(int async, struct file *filp) ...@@ -442,15 +442,17 @@ static void profile_readahead(int async, struct file *filp)
* - The total memory pool usage for the file access stream. * - The total memory pool usage for the file access stream.
* This maximum memory usage is implicitly 2 IO read chunks: * This maximum memory usage is implicitly 2 IO read chunks:
* 2*(MAX_READAHEAD + PAGE_SIZE) = 156K if CONFIG_READA_SMALL is undefined, * 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 PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
#define MAX_READAHEAD (PAGE_SIZE*7)
#define MIN_READAHEAD (PAGE_SIZE*2) #if 0 /* small readahead */
#else #define MAX_READAHEAD PageAlignSize(4096*7)
#define MAX_READAHEAD (PAGE_SIZE*18) #define MIN_READAHEAD PageAlignSize(4096*2)
#define MIN_READAHEAD (PAGE_SIZE*3) #else /* large readahead */
#define MAX_READAHEAD PageAlignSize(4096*18)
#define MIN_READAHEAD PageAlignSize(4096*3)
#endif #endif
static inline unsigned long generic_file_readahead(int reada_ok, struct file * filp, struct inode * inode, 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) ...@@ -756,26 +756,6 @@ int verify_area(int type, const void * addr, unsigned long size)
return -EFAULT; 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.. * 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, ...@@ -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 * tries to share with existing pages, but makes a separate copy if
* the "write_access" parameter is true in order to avoid the next * the "write_access" parameter is true in order to avoid the next
* page fault. * 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, void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma,
unsigned long address, int write_access) unsigned long address, int write_access)
...@@ -938,23 +921,31 @@ void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma, ...@@ -938,23 +921,31 @@ void do_no_page(struct task_struct * tsk, struct vm_area_struct * vma,
entry = pte_mkwrite(pte_mkdirty(entry)); entry = pte_mkwrite(pte_mkdirty(entry));
} else if (mem_map[MAP_NR(page)].count > 1 && !(vma->vm_flags & VM_SHARED)) } else if (mem_map[MAP_NR(page)].count > 1 && !(vma->vm_flags & VM_SHARED))
entry = pte_wrprotect(entry); entry = pte_wrprotect(entry);
flush_cache_page(vma, address);
put_page(page_table, entry); put_page(page_table, entry);
/* no need to invalidate: a not-present page shouldn't be cached */ /* no need to invalidate: a not-present page shouldn't be cached */
return; 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: sigbus:
force_sig(SIGBUS, current); force_sig(SIGBUS, current);
flush_cache_page(vma, address);
put_page(page_table, BAD_PAGE); put_page(page_table, BAD_PAGE);
/* no need to invalidate, wasn't present */ /* no need to invalidate, wasn't present */
return; return;
anonymous_page:
flush_cache_page(vma, address);
get_empty_page(tsk, vma, page_table, write_access);
return;
swap_page: swap_page:
do_swap_page(tsk, vma, address, page_table, entry, write_access); do_swap_page(tsk, vma, address, page_table, entry, write_access);
return; 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