Commit 275d3262 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.85

parent 9ba95981
...@@ -730,6 +730,16 @@ S: 36 Mudtown Road ...@@ -730,6 +730,16 @@ S: 36 Mudtown Road
S: Wantage, New Jersey 07461 S: Wantage, New Jersey 07461
S: USA S: USA
N: Harald Hoyer
E: HarryH@Royal.Net
W: http://hot.spotline.de/
W: http://home.pages.de/~saturn
D: ip_masq_quake
D: md boot support
S: Alleenstrasse 27
S: D-71679 Asperg
S: Germany
N: Miguel de Icaza Amozurrutia N: Miguel de Icaza Amozurrutia
E: miguel@nuclecu.unam.mx E: miguel@nuclecu.unam.mx
D: Linux/SPARC team, Midnight Commander maintainer D: Linux/SPARC team, Midnight Commander maintainer
...@@ -1361,8 +1371,9 @@ S: 79098 Freiburg ...@@ -1361,8 +1371,9 @@ S: 79098 Freiburg
S: Germany S: Germany
N: Joerg Reuter N: Joerg Reuter
E: jreuter@lykos.oche.de E: jreuter@poboxes.com
E: dl1bke@db0pra.ampr.org W: http://www.rat.de/jr/
W: http://qsl.net/dl1bke/
D: Generic Z8530 driver, AX.25 DAMA slave implementation D: Generic Z8530 driver, AX.25 DAMA slave implementation
D: Several AX.25 hacks D: Several AX.25 hacks
......
...@@ -658,6 +658,11 @@ CONFIG_MD_RAID5 ...@@ -658,6 +658,11 @@ CONFIG_MD_RAID5
want to compile it as a module, say M here and read want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say Y. Documentation/modules.txt. If unsure, say Y.
Boot support (linear, striped)
CONFIG_MD_BOOT
To boot with an initial linear or striped md device you have to
select this. For lilo and loadlin options see Documentation/md.txt.
Support for Deskstation RPC44 Support for Deskstation RPC44
CONFIG_DESKSTATION_RPC44 CONFIG_DESKSTATION_RPC44
This is a machine with a R4400 100 MHz CPU. To compile a Linux This is a machine with a R4400 100 MHz CPU. To compile a Linux
...@@ -2737,29 +2742,54 @@ CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT ...@@ -2737,29 +2742,54 @@ CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
IBMMCA SCSI support IBMMCA SCSI support
CONFIG_SCSI_IBMMCA CONFIG_SCSI_IBMMCA
If your computer sports an MCA bus system architecture (IBM PS/2) This is support for the IBM SCSI adapter found in many of the PS/2
with an SCSI harddrive, say Y here. Please read series. CONFIG_MCA must be set for this to work. If the adapter
Documentation/mca.txt. This driver is also available as a module ( = isn't found during boot (a common problem for models 56, 57, 76, and
code which can be inserted in and removed from the running kernel 77) you'll need to use the 'ibmmcascsi=<pun>', where <pun> is the id
whenever you want). The module will be called ibmmca.o. If you want of the SCSI subsystem (usually 7, but if that doesn't work check your
to compile it as a module, say M here and read reference diskette). Owners of model 95 with a LED-matrix-display
Documentation/modules.txt. can in addition activate some activity info like under OS/2, but more
Normally, all IBM MCA SCSI adapters are automatically detected. If informative, by setting 'ibmmcascsi=display' as additional kernel-
that doesn't work right however, you can completely override parameter.
auto-detection by specifying "ibmmcascsi=io1,io2,..." at the boot
loader's command prompt or "io_port=io1,io2,... scsi_id=id1,id2,..." Standard SCSI-order
as a parameter of insmod. "io" and "id" are the I/O base address CONFIG_IBMMCA_SCSI_ORDER_STANDARD
and the SCSI ID of each adapter, respectively. In the PC-world and in most modern SCSI-BIOS-setups, SCSI-harddisks
If you want to compile this driver as a module ( = code which can be are assigned to the driveletters, starting with the lowest SCSI-id
inserted in and removed from the running kernel whenever you want), (physical number - pun) to be drive C:, as seen from DOS and similar
say M here and read Documentation/modules.txt. The module will be operating systems. When looking into papers, describing the
called ibmmca.o. ANSI-SCSI-standard, this assignment of drives appears to be wrong.
The SCSI-standard follows a hardware-hierarchy which says, that
reset SCSI-devices while booting id 7 has the highest priority and id 0 the lowest. Therefore, the
CONFIG_SCSI_IBMMCA_DEV_RESET hostadapters are still today everywhere placed as SCSI-id 7 by
If you say Y here, each connected SCSI device will get a reset default. In the SCSI-standard, the driveletters express the priority
command at boot time. This can be necessary for some special SCSI of the disk. C: should be the harddisk or a partition on it, with the
devices. If unsure, say N. highest priority. This must therefore be the disk with the highest
SCSI-id (e.g. 6) and not the one with the lowest! IBM-BIOS kept the
original definition of the SCSI-standard as also industrial- and
process-control-machines, like VME-CPUs running under realtime-OSs
(e.g. LynxOS, OS9) do.
If you like to run Linux on your MCA-machine with the same assignment,
of harddisks, as seen from e.g. DOS or OS/2 on your machine, which
is in addition conform to the SCSI-standard, you must say 'y' here.
This is also necessary for MCA-Linux-users who want to keep downward-
compatibility to older releases of the IBM-MCA-SCSI-driver (older than
driver-release 2.00 and older than June 1997).
If you like to have the lowest SCSI-id assigned as drive C:, as modern
SCSI-BIOS do, which is not conform to the standard, but widely spread
and common in the PC-world of today, you must say 'n' here.
Reset SCSI-devices at boottime
CONFIG_IBMMCA_SCSI_DEV_RESET
By default, SCSI-devices are reset, when the machine is powered on.
However, some devices exist, like special-control-devices,
SCSI-CNC-machines, SCSI-printer or scanners of older type, that
do not reset, when switched on. If you say 'y' here, each device
along your SCSI-bus will get a reset-command after it has been
probed, while the kernel is booting. Say always 'n' here, if you
have no such strange SCSI-devices on your bus. If you say 'y' and
some more modern devices, like harddisks, do not like too much
resets, your system will hang when booting.
Always IN2000 SCSI support Always IN2000 SCSI support
CONFIG_SCSI_IN2000 CONFIG_SCSI_IN2000
......
most (all) Intel SMP boards have the so-called 'IO-APIC', which is
an enhanced interrupt controller, able to route hardware interrupts
to multiple CPUs, or to CPU groups.
Linux supports the IO-APIC, but unfortunately there are broken boards
out there which make it unsafe to enable the IO-APIC unconditionally.
The Linux policy thus is to enable the IO-APIC only if it's 100% safe, ie.:
- the board is on the 'whitelist'
or - the board does not have PCI pins connected to the IO-APIC
or - the user has overriden blacklisted settings with the
pirq= boot option line.
Kernel messages tell you wether the board is 'safe'. If your box
boots with enabled IO-APIC IRQs, then you have nothing else to do. Your
/proc/interrupts will look like this one:
---------------------------->
hell:~> cat /proc/interrupts
CPU0 CPU1
0: 90782 0 XT PIC timer
1: 4135 2375 IO-APIC keyboard
2: 0 0 XT PIC cascade
3: 851 807 IO-APIC serial
9: 6 22 IO-APIC ncr53c8xx
11: 307 154 IO-APIC NE2000
13: 4 0 XT PIC fpu
14: 56000 30610 IO-APIC ide0
NMI: 0
IPI: 0
<----------------------------
some interrupts will still be 'XT PIC', but this is not a problem, none
of those IRQ sources is 'heavy'.
If one of your boot messages says 'unlisted/blacklisted board, DISABLING
IO-APIC IRQs', then you should do this to get multi-CPU IO-APIC IRQs
running:
A) if your board is unlisted, then mail to linux-smp to get
it into either the white or the blacklist
B) if your board is blacklisted, then figure out the apropriate
pirq= option to get your system boot
pirq= lines look like the following in /etc/lilo.conf:
append="pirq=15,11,10"
the actual numbers depend on your system, on your PCI cards and on their
PCI slot position. Usually PCI slots are 'daisy chained' before they are
connected to the PCI chipset irq routing facility (the incoming PIRQ1-4
lines):
,-. ,-. ,-. ,-. ,-.
PIRQ4 ----| |-. ,-| |-. ,-| |-. ,-| |--------| |
|S| \ / |S| \ / |S| \ / |S| |S|
PIRQ3 ----|l|-. `/---|l|-. `/---|l|-. `/---|l|--------|l|
|o| \/ |o| \/ |o| \/ |o| |o|
PIRQ2 ----|t|-./`----|t|-./`----|t|-./`----|t|--------|t|
|1| /\ |2| /\ |3| /\ |4| |5|
PIRQ1 ----| |- `----| |- `----| |- `----| |--------| |
`-' `-' `-' `-' `-'
every PCI card emits a PCI IRQ, which can be INTA,INTB,INTC,INTD:
,-.
INTD--| |
|S|
INTC--|l|
|o|
INTB--|t|
|x|
INTA--| |
`-'
These INTA-D PCI IRQs are always 'local to the card', their real meaning
depends on which slot they are in. If you look at the daisy chaining diagram,
a card in slot4, issuing INTA IRQ, it will end up as a signal on PIRQ2 of
the PCI chipset. Most cards issue INTA, this creates optimal distibution
between the PIRQ lines. (distributing IRQ sources properly is not a
necessity, PCI IRQs can be shared at will, but it's a good for performance
to have non shared interrupts). Slot5 should be used for videocards, they
dont use interrupts normally, thus they are not daisy chained either.
so if you have your SCSI card (IRQ11) in Slot1, Tulip card (IRQ9) in
Slot2, then you'll have to specify this pirq= line:
append="pirq=11,9"
the following script tries to figure out such a default pirq= line from
your PCI configuration:
echo -n pirq=; echo `scanpci | grep T_L | cut -c56-` | sed 's/ /,/g'
note that this script wont work if you have skipped a few slots or if your
board does not do default daisy-chaining. (or the IO-APIC has the PIRQ pins
connected in some strange way). Eg. if in the above case you have your SCSI
card (IRQ11) in Slot3, and have Slot1 empty:
append="pirq=0,9,11"
[value '0' is a generic 'placeholder', reserved for empty (or non-IRQ emitting)
slots.]
generally, it's always possible to find out the correct pirq= settings, just
permutate all IRQ numbers properly ... it will take some time though. An
'incorrect' pirq line will cause the booting process to hang, or a device
wont function properly (if it's inserted as eg. a module).
If you have 2 PCI buses, then you can use up to 8 pirq values. Although such
boards tend to have a good configuration and will be included in the
whitelist.
Be prepared that it might happen that you need some strange pirq line:
append="pirq=0,0,0,0,0,0,9,11"
use smart try-and-err techniques to find out the correct pirq line ...
the following pirq line can be used to force a board into the whitelist:
append="pirq=0"
[if your system works with no problems after this, then it should be added
to the official whitelist, contact us]
good luck and mail to linux-smp@vger.rutgers.edu or
linux-kernel@vger.rutger.edu if you have any problems that are not covered
by this document.
-- mingo
Mount options that are the same as for msdos and vfat partitions.
conv=binary Data is returned exactly as is, with CRLF's. [default]
conv=text (Carriage return, line feed) is replaced with newline.
conv=mtext (Carriage return, line feed) is returned as is (?).
conv=auto Chooses, file by file, conv=binary or conv=text (by guessing)
gid=nnn All files in the partition will be in group nnn.
uid=nnn All files in the partition will be owned by user id nnn.
umask=nnn The permission mask (see umask(1)) for the partition.
Mount options that are the same as vfat partitions. These are only useful
when using discs encoded using Microsoft's Joliet extensions.
iocharset=name Character set to use for converting from Unicode to
ASCII. Joliet filenames are stored in Unicode format, but
Unix for the most part doesn't know how to deal with Unicode.
There is also an option of doing UTF8 translations with the
utf8 option.
utf8 Encode Unicode names in UTF8 format. Default is no.
Mount options that are unique to the isofs filesystem.
block=512 Set the block size for the disk to 512 bytes
block=1024 Set the block size for the disk to 1024 bytes
block=2048 Set the block size for the disk to 2048 bytes
check=relaxed Matches filenames with different cases
check=strict Matches only filenames with the exact same case
cruft Try to handle badly formatted CDs.
map=off Do not map non-rockridge filenames to lowercase
map=normal Map rockridge filenames to lowercase
mode=xxx Sets the permissions on files to xxx
nojoliet Ignore Joliet extensions if they are present.
norock Ignore rockridge extensions if they are present.
unhide Show hidden files.
Tools that manage md devices can be found at sweet-smoke.ufr-info-p7.ibp.fr
in public/Linux/md035.tar.gz.
Marc ZYNGIER <zyngier@ufr-info-p7.ibp.fr>
--
You can boot (if you selected boot support in the configuration) with your md
device with the following kernel command line:
md=<md device no.>,<raid level>,<chunk size factor>,<fault level>,dev0,dev1,...,devn
md device no. = the number of the md device ...
0 means md0,
1 md1,
2 md2,
3 md3,
4 md4
raid level = -1 linear mode
0 striped mode
other modes are currently unsupported.
chunk size factor = (raid-0 and raid-1 only)
Set the chunk size as PAGE_SIZE << n.
fault level = (raid-1 only)
Set the maximum fault number as n.
Currently unsupported due to lack of boot support for raid1.
dev0-devn: e.g. /dev/hda1,/dev/hdc1,/dev/sda1,/dev/sdb1
my loadlin line looks like this:
e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro
Harald Hoyer <HarryH@Royal.Net>
You will find subset of the documentation in
linux/Documentation/networking/z8530drv.txt
To use this driver you MUST have the full package from:
Internet:
=========
1. db0bm.automation.fh-aachen.de/incoming/dl1bke/z8530drv-utils-3.0.tar.gz
2. ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-utils-3.0.tar.gz
If you can't find it there, try .../tcpip/linux/z8530drv-utils-3.0.tar.gz
and various mirrors (i.e. nic.switch.ch)
The package includes the utilities necessary to initialize and
control the driver.
Joerg Reuter ampr-net: dl1bke@db0pra.ampr.org
AX-25 : DL1BKE @ DB0ACH.#NRW.DEU.EU
Internet: jreuter@lykos.oche.de
...@@ -4,9 +4,9 @@ full package from: ...@@ -4,9 +4,9 @@ full package from:
Internet: Internet:
========= =========
1. ftp://db0bm.automation.fh-aachen.de/incoming/z8530drv/z8530drv-utils-3.0.tar.gz 1. ftp://ftp.ccac.rwth-aachen.de/pub/jr/z8530drv-utils-3.0-1.tar.gz
2. ftp://ftp.pspt.fi/pub/ham/linux/ax25/z8530drv-utils-3.0.tar.gz 2. ftp://ftp.pspt.fi/pub/ham/linux/ax25/z8530drv-utils-3.0-1.tar.gz
3. ftp://ftp.ucsd.edu/hamradio/packet/tcpip/incoming/z8530drv-utils-3.0.tar.gz 3. ftp://ftp.ucsd.edu/hamradio/packet/tcpip/incoming/z8530drv-utils-3.0.tar.gz
If you can't find it there, try .../tcpip/linux/z8530drv-utils-3.0.tar.gz If you can't find it there, try .../tcpip/linux/z8530drv-utils-3.0.tar.gz
...@@ -23,7 +23,7 @@ http://www.rat.de/jr ...@@ -23,7 +23,7 @@ http://www.rat.de/jr
******************************************************************** ********************************************************************
(c) 1993,1997 by Joerg Reuter DL1BKE <jreuter@poboxes.com> (c) 1993,1998 by Joerg Reuter DL1BKE <jreuter@poboxes.com>
portions (c) 1993 Guido ten Dolle PE1NNZ portions (c) 1993 Guido ten Dolle PE1NNZ
......
...@@ -156,7 +156,9 @@ S: Supported ...@@ -156,7 +156,9 @@ S: Supported
DAMA SLAVE for AX.25 DAMA SLAVE for AX.25
P: Joerg Reuter P: Joerg Reuter
M: jreuter@lykos.oche.de M: jreuter@poboxes.com
W: http://www.rat.de/jr/
W: http://qsl.net/dl1bke/
L: linux-hams@vger.rutgers.edu L: linux-hams@vger.rutgers.edu
S: Maintained S: Maintained
...@@ -602,7 +604,9 @@ S: Maintained ...@@ -602,7 +604,9 @@ S: Maintained
Z8530 DRIVER FOR AX.25 Z8530 DRIVER FOR AX.25
P: Joerg Reuter P: Joerg Reuter
M: jreuter@lykos.oche.de M: jreuter@poboxes.com
W: http://www.rat.de/jr/
W: http://qsl.net/dl1bke/
L: linux-hams@vger.rutgers.edu L: linux-hams@vger.rutgers.edu
S: Maintained S: Maintained
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 84 SUBLEVEL = 85
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
......
...@@ -191,7 +191,7 @@ if [ "$CONFIG_NET" = "y" ]; then ...@@ -191,7 +191,7 @@ if [ "$CONFIG_NET" = "y" ]; then
endmenu endmenu
fi fi
source drivers/net/hamradio/Config.in source net/ax25/Config.in
mainmenu_option next_comment mainmenu_option next_comment
comment 'ISDN subsystem' comment 'ISDN subsystem'
......
...@@ -40,7 +40,7 @@ extern void __remlu (void); ...@@ -40,7 +40,7 @@ extern void __remlu (void);
extern void __divqu (void); extern void __divqu (void);
extern void __remqu (void); extern void __remqu (void);
EXPORT_SYMBOL(__alpha_bh_counter); EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(local_irq_count);
/* platform dependent support */ /* platform dependent support */
......
...@@ -524,7 +524,7 @@ static inline void handle_nmi(struct pt_regs * regs) ...@@ -524,7 +524,7 @@ static inline void handle_nmi(struct pt_regs * regs)
} }
unsigned int local_irq_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS];
atomic_t __alpha_bh_counter; unsigned int local_bh_count[NR_CPUS];
#ifdef __SMP__ #ifdef __SMP__
#error "Me no hablo Alpha SMP" #error "Me no hablo Alpha SMP"
......
...@@ -23,7 +23,9 @@ OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S ...@@ -23,7 +23,9 @@ OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
LDFLAGS=-e stext LDFLAGS=-e stext
LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS) LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS)
CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce CFLAGS_PIPE := -pipe
CFLAGS_NSR := -fno-strength-reduce
CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) $(CFLAGS_NSR)
ifdef CONFIG_M386 ifdef CONFIG_M386
CFLAGS := $(CFLAGS) -m386 -DCPU=386 CFLAGS := $(CFLAGS) -m386 -DCPU=386
......
...@@ -93,7 +93,7 @@ if [ "$CONFIG_NET" = "y" ]; then ...@@ -93,7 +93,7 @@ if [ "$CONFIG_NET" = "y" ]; then
endmenu endmenu
fi fi
source drivers/net/hamradio/Config.in source net/ax25/Config.in
mainmenu_option next_comment mainmenu_option next_comment
comment 'ISDN subsystem' comment 'ISDN subsystem'
......
...@@ -78,6 +78,13 @@ ...@@ -78,6 +78,13 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
#include <linux/smp_lock.h>
#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/smp.h>
#include "irq.h"
/* /*
* Generic PCI access -- indirect calls according to detected HW. * Generic PCI access -- indirect calls according to detected HW.
*/ */
...@@ -133,7 +140,39 @@ int pcibios_find_device (unsigned short vendor, unsigned short device_id, ...@@ -133,7 +140,39 @@ int pcibios_find_device (unsigned short vendor, unsigned short device_id,
int pcibios_read_config_byte (unsigned char bus, int pcibios_read_config_byte (unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned char *value) unsigned char device_fn, unsigned char where, unsigned char *value)
{ {
return access_pci->read_config_byte(bus, device_fn, where, value); int res;
res = access_pci->read_config_byte(bus, device_fn, where, value);
#ifdef __SMP__
/*
* IOAPICs can take PCI IRQs directly, lets first check the mptable:
*/
if (where == PCI_INTERRUPT_LINE) {
int irq;
char pin;
/*
* get the PCI IRQ INT _physical pin_ for this device
*/
access_pci->read_config_byte(bus, device_fn,
PCI_INTERRUPT_PIN, &pin);
/*
* subtle, PCI pins are numbered starting from 1 ...
*/
pin--;
irq = IO_APIC_get_PCI_irq_vector (bus,PCI_SLOT(device_fn),pin);
if (irq != -1)
*value = (unsigned char) irq;
printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
bus,PCI_SLOT(device_fn), pin, irq);
}
#endif
return res;
} }
int pcibios_read_config_word (unsigned char bus, int pcibios_read_config_word (unsigned char bus,
......
...@@ -109,7 +109,7 @@ void io_apic_write (unsigned int reg, unsigned int value) ...@@ -109,7 +109,7 @@ void io_apic_write (unsigned int reg, unsigned int value)
*(io_apic_reg+4) = value; *(io_apic_reg+4) = value;
} }
void enable_IO_APIC_irq (int irq) void enable_IO_APIC_irq (unsigned int irq)
{ {
struct IO_APIC_route_entry entry; struct IO_APIC_route_entry entry;
...@@ -121,7 +121,11 @@ void enable_IO_APIC_irq (int irq) ...@@ -121,7 +121,11 @@ void enable_IO_APIC_irq (int irq)
io_apic_write(0x10+2*irq, *(((int *)&entry)+0)); io_apic_write(0x10+2*irq, *(((int *)&entry)+0));
} }
void disable_IO_APIC_irq (int irq) /*
* this function is just here to make things complete, otherwise it's
* unused
*/
void disable_IO_APIC_irq (unsigned int irq)
{ {
struct IO_APIC_route_entry entry; struct IO_APIC_route_entry entry;
...@@ -133,7 +137,7 @@ void disable_IO_APIC_irq (int irq) ...@@ -133,7 +137,7 @@ void disable_IO_APIC_irq (int irq)
io_apic_write(0x10+2*irq, *(((int *)&entry)+0)); io_apic_write(0x10+2*irq, *(((int *)&entry)+0));
} }
void clear_IO_APIC_irq (int irq) void clear_IO_APIC_irq (unsigned int irq)
{ {
struct IO_APIC_route_entry entry; struct IO_APIC_route_entry entry;
...@@ -151,8 +155,9 @@ void clear_IO_APIC_irq (int irq) ...@@ -151,8 +155,9 @@ void clear_IO_APIC_irq (int irq)
* specific CPU-side IRQs. * specific CPU-side IRQs.
*/ */
#define MAX_PIRQS 4 #define MAX_PIRQS 8
int pirq_entries [MAX_PIRQS]; int pirq_entries [MAX_PIRQS];
int pirqs_enabled;
void ioapic_pirq_setup(char *str, int *ints) void ioapic_pirq_setup(char *str, int *ints)
{ {
...@@ -161,9 +166,12 @@ void ioapic_pirq_setup(char *str, int *ints) ...@@ -161,9 +166,12 @@ void ioapic_pirq_setup(char *str, int *ints)
for (i=0; i<MAX_PIRQS; i++) for (i=0; i<MAX_PIRQS; i++)
pirq_entries[i]=-1; pirq_entries[i]=-1;
if (!ints) if (!ints) {
pirqs_enabled=0;
printk("PIRQ redirection SETUP, trusting MP-BIOS.\n"); printk("PIRQ redirection SETUP, trusting MP-BIOS.\n");
else {
} else {
pirqs_enabled=1;
printk("PIRQ redirection SETUP, working around broken MP-BIOS.\n"); printk("PIRQ redirection SETUP, working around broken MP-BIOS.\n");
max = MAX_PIRQS; max = MAX_PIRQS;
if (ints[0] < MAX_PIRQS) if (ints[0] < MAX_PIRQS)
...@@ -229,9 +237,10 @@ void setup_IO_APIC_irqs (void) ...@@ -229,9 +237,10 @@ void setup_IO_APIC_irqs (void)
} }
case MP_BUS_PCI: /* PCI pin */ case MP_BUS_PCI: /* PCI pin */
{ {
irq = mp_irqs[idx].mpc_srcbusirq >> 2; /*
if (irq>=16) * PCI IRQs are 'directly mapped'
printk("WARNING: MP BIOS says PIRQ%d is redirected to %d, suspicious.\n",idx-16, irq); */
irq = i;
break; break;
} }
default: default:
...@@ -358,7 +367,7 @@ void setup_IO_APIC_irqs (void) ...@@ -358,7 +367,7 @@ void setup_IO_APIC_irqs (void)
printk(" not connected.\n"); printk(" not connected.\n");
} }
void setup_IO_APIC_irq_ISA_default (int irq) void setup_IO_APIC_irq_ISA_default (unsigned int irq)
{ {
struct IO_APIC_route_entry entry; struct IO_APIC_route_entry entry;
...@@ -381,8 +390,23 @@ void setup_IO_APIC_irq_ISA_default (int irq) ...@@ -381,8 +390,23 @@ void setup_IO_APIC_irq_ISA_default (int irq)
io_apic_write(0x11+2*irq, *(((int *)&entry)+1)); io_apic_write(0x11+2*irq, *(((int *)&entry)+1));
} }
void setup_IO_APIC_irq (int irq) int IO_APIC_get_PCI_irq_vector (int bus, int slot, int pci_pin)
{ {
int i;
for (i=0; i<mp_irq_entries; i++) {
int lbus = mp_irqs[i].mpc_srcbus;
if (IO_APIC_IRQ(i) &&
(mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
!mp_irqs[i].mpc_irqtype &&
(bus == mp_irqs[i].mpc_srcbus) &&
(slot == (mp_irqs[i].mpc_srcbusirq >> 2)) &&
(pci_pin == (mp_irqs[i].mpc_srcbusirq & 3)))
return mp_irqs[i].mpc_dstirq;
}
return -1;
} }
void print_IO_APIC (void) void print_IO_APIC (void)
...@@ -471,6 +495,47 @@ void init_sym_mode (void) ...@@ -471,6 +495,47 @@ void init_sym_mode (void)
printk("...done.\n"); printk("...done.\n");
} }
char ioapic_OEM_ID [16];
char ioapic_Product_ID [16];
struct ioapic_list_entry {
char * oem_id;
char * product_id;
};
struct ioapic_list_entry ioapic_whitelist [] = {
{ "INTEL " , "PR440FX " },
{ 0 , 0 }
};
struct ioapic_list_entry ioapic_blacklist [] = {
{ "OEM00000" , "PROD00000000" },
{ 0 , 0 }
};
static int in_ioapic_list (struct ioapic_list_entry * table)
{
for (;table->oem_id; table++)
if ((!strcmp(table->oem_id,ioapic_OEM_ID)) &&
(!strcmp(table->product_id,ioapic_Product_ID)))
return 1;
return 0;
}
static int ioapic_whitelisted (void)
{
return in_ioapic_list(ioapic_whitelist);
}
static int ioapic_blacklisted (void)
{
return in_ioapic_list(ioapic_blacklist);
}
void setup_IO_APIC (void) void setup_IO_APIC (void)
{ {
int i; int i;
...@@ -490,8 +555,6 @@ void setup_IO_APIC (void) ...@@ -490,8 +555,6 @@ void setup_IO_APIC (void)
nr_ioapic_registers = reg_01.entries+1; nr_ioapic_registers = reg_01.entries+1;
} }
init_IO_APIC_traps();
/* /*
* do not trust the IO-APIC being empty at bootup * do not trust the IO-APIC being empty at bootup
*/ */
...@@ -504,6 +567,30 @@ void setup_IO_APIC (void) ...@@ -504,6 +567,30 @@ void setup_IO_APIC (void)
setup_IO_APIC_irq_ISA_default (i); setup_IO_APIC_irq_ISA_default (i);
#endif #endif
/*
* the following IO-APIC's can be enabled:
*
* - whitelisted ones
* - those which have no PCI pins connected
* - those for which the user has specified a pirq= parameter
*/
if ( ioapic_whitelisted() ||
(nr_ioapic_registers == 16) ||
pirqs_enabled)
{
printk("ENABLING IO-APIC IRQs\n");
io_apic_irqs = ~((1<<0)|(1<<2)|(1<<13));
} else {
if (ioapic_blacklisted())
printk(" blacklisted board, DISABLING IO-APIC IRQs\n");
else
printk(" unlisted board, DISABLING IO-APIC IRQs\n");
printk(" see Documentation/IO-APIC.txt to enable them\n");
io_apic_irqs = 0;
}
init_IO_APIC_traps();
setup_IO_APIC_irqs (); setup_IO_APIC_irqs ();
printk("nr of MP irq sources: %d.\n", mp_irq_entries); printk("nr of MP irq sources: %d.\n", mp_irq_entries);
......
/* /*
* linux/arch/i386/kernel/irq.c * linux/arch/i386/kernel/irq.c
* *
* Copyright (C) 1992 Linus Torvalds * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
* *
* This file contains the code used by various IRQ handling routines: * This file contains the code used by various IRQ handling routines:
* asking for different IRQ's should be done through these routines * asking for different IRQ's should be done through these routines
...@@ -41,33 +41,6 @@ ...@@ -41,33 +41,6 @@
#include "irq.h" #include "irq.h"
/*
* I had a lockup scenario where a tight loop doing
* spin_unlock()/spin_lock() on CPU#1 was racing with
* spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but
* apparently the spin_unlock() information did not make it
* through to CPU#0 ... nasty, is this by design, do we haveto limit
* 'memory update oscillation frequency' artificially like here?
*
* Such 'high frequency update' races can be avoided by careful design, but
* some of our major constructs like spinlocks use similar techniques,
* it would be nice to clarify this issue. Set this define to 0 if you
* want to check wether your system freezes. I suspect the delay done
* by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but
* i thought that such things are guaranteed by design, since we use
* the 'LOCK' prefix.
*/
#define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 1
#if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND
# define SYNC_OTHER_CORES(x) udelay(x+1)
#else
/*
* We have to allow irqs to arrive between __sti and __cli
*/
# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
#endif
unsigned int local_bh_count[NR_CPUS]; unsigned int local_bh_count[NR_CPUS];
unsigned int local_irq_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS];
...@@ -96,11 +69,8 @@ static unsigned int cached_irq_mask = (1<<NR_IRQS)-1; ...@@ -96,11 +69,8 @@ static unsigned int cached_irq_mask = (1<<NR_IRQS)-1;
spinlock_t irq_controller_lock; spinlock_t irq_controller_lock;
static int irq_events [NR_IRQS] = { -1, }; static unsigned int irq_events [NR_IRQS] = { -1, };
static int disabled_irq [NR_IRQS] = { 0, }; static int disabled_irq [NR_IRQS] = { 0, };
#ifdef __SMP__
static int irq_owner [NR_IRQS] = { NO_PROC_ID, };
#endif
/* /*
* Not all IRQs can be routed through the IO-APIC, eg. on certain (older) * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
...@@ -125,10 +95,54 @@ static int irq_owner [NR_IRQS] = { NO_PROC_ID, }; ...@@ -125,10 +95,54 @@ static int irq_owner [NR_IRQS] = { NO_PROC_ID, };
* - explicitly use irq 16-19 depending on which PCI irq * - explicitly use irq 16-19 depending on which PCI irq
* line your PCI controller uses. * line your PCI controller uses.
*/ */
unsigned int io_apic_irqs = 0xff0000; unsigned int io_apic_irqs = 0;
#endif
struct hw_interrupt_type {
void (*handle)(unsigned int irq, int cpu, struct pt_regs * regs);
void (*enable)(unsigned int irq);
void (*disable)(unsigned int irq);
};
static void do_8259A_IRQ (unsigned int irq, int cpu, struct pt_regs * regs);
static void enable_8259A_irq (unsigned int irq);
static void disable_8259A_irq (unsigned int irq);
static struct hw_interrupt_type i8259A_irq_type = {
do_8259A_IRQ,
enable_8259A_irq,
disable_8259A_irq
};
#ifdef __SMP__
static void do_ioapic_IRQ (unsigned int irq, int cpu, struct pt_regs * regs);
static void enable_ioapic_irq (unsigned int irq);
static void disable_ioapic_irq (unsigned int irq);
static struct hw_interrupt_type ioapic_irq_type = {
do_ioapic_IRQ,
enable_ioapic_irq,
disable_ioapic_irq
};
#endif #endif
static inline void mask_8259A(int irq) struct hw_interrupt_type *irq_handles[NR_IRQS] =
{
[0 ... 15] = &i8259A_irq_type /* standard ISA IRQs */
#ifdef __SMP__
, [16 ... NR_IRQS-1] = &ioapic_irq_type /* 'high' PCI IRQs */
#endif
};
/*
* These have to be protected by the irq controller spinlock
* before being called.
*/
static inline void mask_8259A(unsigned int irq)
{ {
cached_irq_mask |= 1 << irq; cached_irq_mask |= 1 << irq;
if (irq & 8) { if (irq & 8) {
...@@ -138,7 +152,7 @@ static inline void mask_8259A(int irq) ...@@ -138,7 +152,7 @@ static inline void mask_8259A(int irq)
} }
} }
static inline void unmask_8259A(int irq) static inline void unmask_8259A(unsigned int irq)
{ {
cached_irq_mask &= ~(1 << irq); cached_irq_mask &= ~(1 << irq);
if (irq & 8) { if (irq & 8) {
...@@ -148,7 +162,7 @@ static inline void unmask_8259A(int irq) ...@@ -148,7 +162,7 @@ static inline void unmask_8259A(int irq)
} }
} }
void set_8259A_irq_mask(int irq) void set_8259A_irq_mask(unsigned int irq)
{ {
/* /*
* (it might happen that we see IRQ>15 on a UP box, with SMP * (it might happen that we see IRQ>15 on a UP box, with SMP
...@@ -163,21 +177,7 @@ void set_8259A_irq_mask(int irq) ...@@ -163,21 +177,7 @@ void set_8259A_irq_mask(int irq)
} }
} }
/* void unmask_generic_irq(unsigned int irq)
* These have to be protected by the spinlock
* before being called.
*/
void mask_irq(unsigned int irq)
{
if (IO_APIC_IRQ(irq))
disable_IO_APIC_irq(irq);
else {
cached_irq_mask |= 1 << irq;
set_8259A_irq_mask(irq);
}
}
void unmask_irq(unsigned int irq)
{ {
if (IO_APIC_IRQ(irq)) if (IO_APIC_IRQ(irq))
enable_IO_APIC_irq(irq); enable_IO_APIC_irq(irq);
...@@ -218,8 +218,8 @@ BUILD_IRQ(12) BUILD_IRQ(13) BUILD_IRQ(14) BUILD_IRQ(15) ...@@ -218,8 +218,8 @@ BUILD_IRQ(12) BUILD_IRQ(13) BUILD_IRQ(14) BUILD_IRQ(15)
BUILD_IRQ(16) BUILD_IRQ(17) BUILD_IRQ(18) BUILD_IRQ(19) BUILD_IRQ(16) BUILD_IRQ(17) BUILD_IRQ(18) BUILD_IRQ(19)
/* /*
* [FIXME: anyone with 2 separate PCI buses and 2 IO-APICs, * [FIXME: anyone with 2 separate PCI buses and 2 IO-APICs, please
* please speak up and request experimental patches. * speak up if problems and request experimental patches.
* --mingo ] * --mingo ]
*/ */
...@@ -417,6 +417,33 @@ static inline void wait_on_bh(void) ...@@ -417,6 +417,33 @@ static inline void wait_on_bh(void)
} while (atomic_read(&global_bh_count) != 0); } while (atomic_read(&global_bh_count) != 0);
} }
/*
* I had a lockup scenario where a tight loop doing
* spin_unlock()/spin_lock() on CPU#1 was racing with
* spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but
* apparently the spin_unlock() information did not make it
* through to CPU#0 ... nasty, is this by design, do we have to limit
* 'memory update oscillation frequency' artificially like here?
*
* Such 'high frequency update' races can be avoided by careful design, but
* some of our major constructs like spinlocks use similar techniques,
* it would be nice to clarify this issue. Set this define to 0 if you
* want to check wether your system freezes. I suspect the delay done
* by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but
* i thought that such things are guaranteed by design, since we use
* the 'LOCK' prefix.
*/
#define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 1
#if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND
# define SYNC_OTHER_CORES(x) udelay(x+1)
#else
/*
* We have to allow irqs to arrive between __sti and __cli
*/
# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
#endif
static inline void wait_on_irq(int cpu) static inline void wait_on_irq(int cpu)
{ {
int count = MAXCOUNT; int count = MAXCOUNT;
...@@ -563,7 +590,7 @@ void __global_restore_flags(unsigned long flags) ...@@ -563,7 +590,7 @@ void __global_restore_flags(unsigned long flags)
#endif #endif
static int handle_IRQ_event(int irq, struct pt_regs * regs) static int handle_IRQ_event(unsigned int irq, struct pt_regs * regs)
{ {
struct irqaction * action; struct irqaction * action;
int status; int status;
...@@ -591,43 +618,118 @@ static int handle_IRQ_event(int irq, struct pt_regs * regs) ...@@ -591,43 +618,118 @@ static int handle_IRQ_event(int irq, struct pt_regs * regs)
} }
/*
* disable/enable_irq() wait for all irq contexts to finish
* executing. Also it's recursive.
*/
void disable_irq(unsigned int irq) void disable_irq(unsigned int irq)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags); spin_lock_irqsave(&irq_controller_lock, flags);
disabled_irq[irq]++; irq_handles[irq]->disable(irq);
mask_irq(irq);
spin_unlock_irqrestore(&irq_controller_lock, flags); spin_unlock_irqrestore(&irq_controller_lock, flags);
synchronize_irq(); synchronize_irq();
} }
void enable_irq(unsigned int irq) /*
* disable/enable_irq() wait for all irq contexts to finish
* executing. Also it's recursive.
*/
static void disable_8259A_irq(unsigned int irq)
{ {
unsigned long flags; disabled_irq[irq]++;
cached_irq_mask |= 1 << irq;
set_8259A_irq_mask(irq);
}
#ifdef __SMP__
static void disable_ioapic_irq(unsigned int irq)
{
disabled_irq[irq]++;
/*
* We do not disable IO-APIC irqs in hardware ...
*/
}
#endif
void enable_8259A_irq (unsigned int irq)
{
unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags); spin_lock_irqsave(&irq_controller_lock, flags);
disabled_irq[irq]--; if (disabled_irq[irq])
unmask_irq(irq); disabled_irq[irq]--;
else {
spin_unlock_irqrestore(&irq_controller_lock, flags);
return;
}
cached_irq_mask &= ~(1 << irq);
set_8259A_irq_mask(irq);
spin_unlock_irqrestore(&irq_controller_lock, flags); spin_unlock_irqrestore(&irq_controller_lock, flags);
} }
#ifdef __SMP__
void enable_ioapic_irq (unsigned int irq)
{
unsigned long flags;
int cpu = smp_processor_id(), should_handle_irq;
spin_lock_irqsave(&irq_controller_lock, flags);
if (disabled_irq[irq])
disabled_irq[irq]--;
else {
spin_unlock_irqrestore(&irq_controller_lock, flags);
return;
}
/*
* In the SMP+IOAPIC case it might happen that there are an unspecified
* number of pending IRQ events unhandled. We protect against multiple
* enable_irq()'s executing them via disable_irq[irq]++
*/
if (!disabled_irq[irq] && irq_events[irq]) {
struct pt_regs regs; /* FIXME: these are fake currently */
disabled_irq[irq]++;
spin_unlock(&irq_controller_lock);
release_irqlock(cpu);
irq_enter(cpu, irq);
again:
handle_IRQ_event(irq, &regs);
spin_lock(&irq_controller_lock);
disabled_irq[irq]--;
should_handle_irq=0;
if (--irq_events[irq] && !disabled_irq[irq]) {
should_handle_irq=1;
disabled_irq[irq]++;
}
spin_unlock(&irq_controller_lock);
if (should_handle_irq)
goto again;
irq_exit(cpu, irq);
__restore_flags(flags);
} else {
enable_IO_APIC_irq(irq);
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
}
#endif
void enable_irq(unsigned int irq)
{
irq_handles[irq]->enable(irq);
}
/* /*
* Careful! The 8259A is a fragile beast, it pretty * Careful! The 8259A is a fragile beast, it pretty
* much _has_ to be done exactly like this (mask it * much _has_ to be done exactly like this (mask it
* first, _then_ send the EOI, and the order of EOI * first, _then_ send the EOI, and the order of EOI
* to the two 8259s is important! * to the two 8259s is important!
*/ */
static inline void mask_and_ack_8259A(int irq_nr) static inline void mask_and_ack_8259A(unsigned int irq)
{ {
spin_lock(&irq_controller_lock); spin_lock(&irq_controller_lock);
cached_irq_mask |= 1 << irq_nr; cached_irq_mask |= 1 << irq;
if (irq_nr & 8) { if (irq & 8) {
inb(0xA1); /* DUMMY */ inb(0xA1); /* DUMMY */
outb(cached_A1,0xA1); outb(cached_A1,0xA1);
outb(0x62,0x20); /* Specific EOI to cascade */ outb(0x62,0x20); /* Specific EOI to cascade */
...@@ -640,7 +742,7 @@ static inline void mask_and_ack_8259A(int irq_nr) ...@@ -640,7 +742,7 @@ static inline void mask_and_ack_8259A(int irq_nr)
spin_unlock(&irq_controller_lock); spin_unlock(&irq_controller_lock);
} }
static void do_8259A_IRQ(int irq, int cpu, struct pt_regs * regs) static void do_8259A_IRQ(unsigned int irq, int cpu, struct pt_regs * regs)
{ {
mask_and_ack_8259A(irq); mask_and_ack_8259A(irq);
...@@ -656,45 +758,36 @@ static void do_8259A_IRQ(int irq, int cpu, struct pt_regs * regs) ...@@ -656,45 +758,36 @@ static void do_8259A_IRQ(int irq, int cpu, struct pt_regs * regs)
} }
#ifdef __SMP__ #ifdef __SMP__
/* static void do_ioapic_IRQ(unsigned int irq, int cpu, struct pt_regs * regs)
* FIXME! This is completely broken.
*/
static void do_ioapic_IRQ(int irq, int cpu, struct pt_regs * regs)
{ {
int should_handle_irq; int should_handle_irq = 0;
ack_APIC_irq();
spin_lock(&irq_controller_lock); spin_lock(&irq_controller_lock);
should_handle_irq = 0;
if (!irq_events[irq]++ && !disabled_irq[irq]) {
should_handle_irq = 1;
irq_owner[irq] = cpu;
hardirq_enter(cpu);
}
ack_APIC_irq(); if (!irq_events[irq]++ && !disabled_irq[irq])
should_handle_irq = 1;
spin_unlock(&irq_controller_lock); spin_unlock(&irq_controller_lock);
if (should_handle_irq) {
again:
if (!handle_IRQ_event(irq, regs))
disabled_irq[irq] = 1;
} irq_enter(cpu, irq);
spin_lock(&irq_controller_lock); if (should_handle_irq) {
release_irqlock(cpu); again:
handle_IRQ_event(irq, regs);
if ((--irq_events[irq]) && (!disabled_irq[irq]) && should_handle_irq) { spin_lock(&irq_controller_lock);
should_handle_irq=0;
if (--irq_events[irq] && !disabled_irq[irq])
should_handle_irq=1;
spin_unlock(&irq_controller_lock); spin_unlock(&irq_controller_lock);
goto again;
}
irq_owner[irq] = NO_PROC_ID; if (should_handle_irq)
hardirq_exit(cpu); goto again;
spin_unlock(&irq_controller_lock); }
enable_IO_APIC_irq(irq); irq_exit(cpu, irq);
} }
#endif #endif
...@@ -714,8 +807,6 @@ static void do_ioapic_IRQ(int irq, int cpu, struct pt_regs * regs) ...@@ -714,8 +807,6 @@ static void do_ioapic_IRQ(int irq, int cpu, struct pt_regs * regs)
*/ */
asmlinkage void do_IRQ(struct pt_regs regs) asmlinkage void do_IRQ(struct pt_regs regs)
{ {
void (*do_lowlevel_IRQ)(int, int, struct pt_regs *);
/* /*
* We ack quickly, we don't want the irq controller * We ack quickly, we don't want the irq controller
* thinking we're snobs just because some other CPU has * thinking we're snobs just because some other CPU has
...@@ -726,18 +817,11 @@ asmlinkage void do_IRQ(struct pt_regs regs) ...@@ -726,18 +817,11 @@ asmlinkage void do_IRQ(struct pt_regs regs)
* 0 return value means that this irq is already being * 0 return value means that this irq is already being
* handled by some other CPU. (or is disabled) * handled by some other CPU. (or is disabled)
*/ */
int irq = regs.orig_eax & 0xff; unsigned int irq = regs.orig_eax & 0xff;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
kstat.irqs[cpu][irq]++; kstat.irqs[cpu][irq]++;
irq_handles[irq]->handle(irq, cpu, &regs);
do_lowlevel_IRQ = do_8259A_IRQ;
#ifdef __SMP__
if (IO_APIC_IRQ(irq))
do_lowlevel_IRQ = do_ioapic_IRQ;
#endif
do_lowlevel_IRQ(irq, cpu, &regs);
/* /*
* This should be conditional: we should really get * This should be conditional: we should really get
...@@ -751,7 +835,7 @@ asmlinkage void do_IRQ(struct pt_regs regs) ...@@ -751,7 +835,7 @@ asmlinkage void do_IRQ(struct pt_regs regs)
} }
} }
int setup_x86_irq(int irq, struct irqaction * new) int setup_x86_irq(unsigned int irq, struct irqaction * new)
{ {
int shared = 0; int shared = 0;
struct irqaction *old, **p; struct irqaction *old, **p;
...@@ -780,16 +864,18 @@ int setup_x86_irq(int irq, struct irqaction * new) ...@@ -780,16 +864,18 @@ int setup_x86_irq(int irq, struct irqaction * new)
if (!shared) { if (!shared) {
spin_lock(&irq_controller_lock); spin_lock(&irq_controller_lock);
#ifdef __SMP__
if (IO_APIC_IRQ(irq)) { if (IO_APIC_IRQ(irq)) {
irq_handles[irq] = &ioapic_irq_type;
/* /*
* First disable it in the 8259A: * First disable it in the 8259A:
*/ */
cached_irq_mask |= 1 << irq; cached_irq_mask |= 1 << irq;
if (irq < 16) if (irq < 16)
set_8259A_irq_mask(irq); set_8259A_irq_mask(irq);
setup_IO_APIC_irq(irq);
} }
unmask_irq(irq); #endif
unmask_generic_irq(irq);
spin_unlock(&irq_controller_lock); spin_unlock(&irq_controller_lock);
} }
restore_flags(flags); restore_flags(flags);
...@@ -873,10 +959,11 @@ unsigned long probe_irq_on (void) ...@@ -873,10 +959,11 @@ unsigned long probe_irq_on (void)
*/ */
for (i = NR_IRQS-1; i > 0; i--) { for (i = NR_IRQS-1; i > 0; i--) {
if (!irq_action[i]) { if (!irq_action[i]) {
spin_lock(&irq_controller_lock); unsigned long flags;
unmask_irq(i); spin_lock_irqsave(&irq_controller_lock, flags);
unmask_generic_irq(i);
irqs |= (1 << i); irqs |= (1 << i);
spin_unlock(&irq_controller_lock); spin_unlock_irqrestore(&irq_controller_lock, flags);
} }
} }
...@@ -921,6 +1008,7 @@ int probe_irq_off (unsigned long irqs) ...@@ -921,6 +1008,7 @@ int probe_irq_off (unsigned long irqs)
return irq_found; return irq_found;
} }
#ifdef __SMP__
void init_IO_APIC_traps(void) void init_IO_APIC_traps(void)
{ {
int i; int i;
...@@ -938,16 +1026,17 @@ void init_IO_APIC_traps(void) ...@@ -938,16 +1026,17 @@ void init_IO_APIC_traps(void)
for (i = 0; i < NR_IRQS ; i++) for (i = 0; i < NR_IRQS ; i++)
if (IO_APIC_GATE_OFFSET+(i<<3) <= 0xfe) /* HACK */ { if (IO_APIC_GATE_OFFSET+(i<<3) <= 0xfe) /* HACK */ {
if (IO_APIC_IRQ(i)) { if (IO_APIC_IRQ(i)) {
irq_handles[i] = &ioapic_irq_type;
/* /*
* First disable it in the 8259A: * First disable it in the 8259A:
*/ */
cached_irq_mask |= 1 << i; cached_irq_mask |= 1 << i;
if (i < 16) if (i < 16)
set_8259A_irq_mask(i); set_8259A_irq_mask(i);
setup_IO_APIC_irq(i);
} }
} }
} }
#endif
__initfunc(void init_IRQ(void)) __initfunc(void init_IRQ(void))
{ {
...@@ -961,9 +1050,6 @@ __initfunc(void init_IRQ(void)) ...@@ -961,9 +1050,6 @@ __initfunc(void init_IRQ(void))
printk("INIT IRQ\n"); printk("INIT IRQ\n");
for (i=0; i<NR_IRQS; i++) { for (i=0; i<NR_IRQS; i++) {
irq_events[i] = 0; irq_events[i] = 0;
#ifdef __SMP__
irq_owner[i] = NO_PROC_ID;
#endif
disabled_irq[i] = 0; disabled_irq[i] = 0;
} }
/* /*
......
...@@ -9,15 +9,15 @@ ...@@ -9,15 +9,15 @@
#define IO_APIC_GATE_OFFSET 0x51 #define IO_APIC_GATE_OFFSET 0x51
void mask_irq(unsigned int irq_nr); void mask_irq(unsigned int irq);
void unmask_irq(unsigned int irq_nr); void unmask_irq(unsigned int irq);
void enable_IO_APIC_irq (int irq); void enable_IO_APIC_irq (unsigned int irq);
void disable_IO_APIC_irq (int irq); void disable_IO_APIC_irq (unsigned int irq);
void set_8259A_irq_mask(int irq_nr); void set_8259A_irq_mask(unsigned int irq);
void setup_IO_APIC_irq (int irq);
void ack_APIC_irq (void); void ack_APIC_irq (void);
void setup_IO_APIC (void); void setup_IO_APIC (void);
void init_IO_APIC_traps(void); void init_IO_APIC_traps(void);
int IO_APIC_get_PCI_irq_vector (int bus, int slot, int fn);
#ifdef __SMP__ #ifdef __SMP__
extern unsigned int io_apic_irqs; extern unsigned int io_apic_irqs;
...@@ -34,6 +34,8 @@ enum mp_bustype { ...@@ -34,6 +34,8 @@ enum mp_bustype {
MP_BUS_PCI MP_BUS_PCI
}; };
extern int mp_bus_id_to_type [MAX_MP_BUSSES]; extern int mp_bus_id_to_type [MAX_MP_BUSSES];
extern char ioapic_OEM_ID [16];
extern char ioapic_Product_ID [16];
extern spinlock_t irq_controller_lock; /* extern spinlock_t irq_controller_lock; /*
* Protects both the 8259 and the * Protects both the 8259 and the
...@@ -44,7 +46,7 @@ extern spinlock_t irq_controller_lock; /* ...@@ -44,7 +46,7 @@ extern spinlock_t irq_controller_lock; /*
#include <asm/atomic.h> #include <asm/atomic.h>
static inline void irq_enter(int cpu, int irq) static inline void irq_enter(int cpu, unsigned int irq)
{ {
hardirq_enter(cpu); hardirq_enter(cpu);
while (test_bit(0,&global_irq_lock)) { while (test_bit(0,&global_irq_lock)) {
...@@ -52,7 +54,7 @@ static inline void irq_enter(int cpu, int irq) ...@@ -52,7 +54,7 @@ static inline void irq_enter(int cpu, int irq)
} }
} }
static inline void irq_exit(int cpu, int irq) static inline void irq_exit(int cpu, unsigned int irq)
{ {
hardirq_exit(cpu); hardirq_exit(cpu);
release_irqlock(cpu); release_irqlock(cpu);
......
...@@ -331,8 +331,9 @@ struct cpu_model_info { ...@@ -331,8 +331,9 @@ struct cpu_model_info {
static struct cpu_model_info cpu_models[] __initdata = { static struct cpu_model_info cpu_models[] __initdata = {
{ X86_VENDOR_INTEL, 4, { X86_VENDOR_INTEL, 4,
{ "486 DX-25/33", "486 DX-50", "486 SX", "487 DX", "486 DX/2", "486 SL", "486 SX/2", { "486 DX-25/33", "486 DX-50", "486 SX", "486 DX/2", "486 SL", "486 SX/2",
NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL }}, NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL,
NULL, NULL }},
{ X86_VENDOR_INTEL, 5, { X86_VENDOR_INTEL, 5,
{ "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75+", { "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75+",
"OverDrive PODP5V83", "Pentium MMX", NULL, NULL, "OverDrive PODP5V83", "Pentium MMX", NULL, NULL,
......
...@@ -258,10 +258,14 @@ __initfunc(static int smp_read_mpc(struct mp_config_table *mpc)) ...@@ -258,10 +258,14 @@ __initfunc(static int smp_read_mpc(struct mp_config_table *mpc))
} }
memcpy(str,mpc->mpc_oem,8); memcpy(str,mpc->mpc_oem,8);
str[8]=0; str[8]=0;
memcpy(ioapic_OEM_ID,str,9);
printk("OEM ID: %s ",str); printk("OEM ID: %s ",str);
memcpy(str,mpc->mpc_productid,12); memcpy(str,mpc->mpc_productid,12);
str[12]=0; str[12]=0;
memcpy(ioapic_Product_ID,str,13);
printk("Product ID: %s ",str); printk("Product ID: %s ",str);
printk("APIC at: 0x%lX\n",mpc->mpc_lapic); printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
/* set the local APIC address */ /* set the local APIC address */
...@@ -367,14 +371,6 @@ __initfunc(static int smp_read_mpc(struct mp_config_table *mpc)) ...@@ -367,14 +371,6 @@ __initfunc(static int smp_read_mpc(struct mp_config_table *mpc))
--mp_irq_entries; --mp_irq_entries;
} }
printk(" Itype:%d Iflag:%d srcbus:%d srcbusI:%d dstapic:%d dstI:%d.\n",
m->mpc_irqtype,
m->mpc_irqflag,
m->mpc_srcbus,
m->mpc_srcbusirq,
m->mpc_dstapic,
m->mpc_dstirq);
mpt+=sizeof(*m); mpt+=sizeof(*m);
count+=sizeof(*m); count+=sizeof(*m);
break; break;
...@@ -1372,10 +1368,13 @@ void smp_local_timer_interrupt(struct pt_regs * regs) ...@@ -1372,10 +1368,13 @@ void smp_local_timer_interrupt(struct pt_regs * regs)
p->counter = 0; p->counter = 0;
need_resched = 1; need_resched = 1;
} }
if (p->priority < DEF_PRIORITY) if (p->priority < DEF_PRIORITY) {
kstat.cpu_nice += user; kstat.cpu_nice += user;
else kstat.per_cpu_nice[cpu] += user;
} else {
kstat.cpu_user += user; kstat.cpu_user += user;
kstat.per_cpu_user[cpu] += user;
}
kstat.cpu_system += system; kstat.cpu_system += system;
kstat.per_cpu_system[cpu] += system; kstat.per_cpu_system[cpu] += system;
......
...@@ -129,7 +129,7 @@ if [ "$CONFIG_NET" = "y" ]; then ...@@ -129,7 +129,7 @@ if [ "$CONFIG_NET" = "y" ]; then
endmenu endmenu
fi fi
source drivers/net/hamradio/Config.in source net/ax25/Config.in
mainmenu_option next_comment mainmenu_option next_comment
comment 'ISDN subsystem' comment 'ISDN subsystem'
......
...@@ -65,6 +65,9 @@ if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then ...@@ -65,6 +65,9 @@ if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5
fi fi
if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then
bool ' Boot support (linear, striped)' CONFIG_MD_BOOT
fi
tristate 'RAM disk support' CONFIG_BLK_DEV_RAM tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
......
...@@ -1093,6 +1093,9 @@ __initfunc(void device_setup(void)) ...@@ -1093,6 +1093,9 @@ __initfunc(void device_setup(void))
extern void console_map_init(void); extern void console_map_init(void);
#ifdef CONFIG_PARPORT #ifdef CONFIG_PARPORT
extern int parport_init(void); extern int parport_init(void);
#endif
#ifdef CONFIG_MD_BOOT
extern void md_setup_drive(void) __init;
#endif #endif
struct gendisk *p; struct gendisk *p;
int nr=0; int nr=0;
...@@ -1124,4 +1127,7 @@ __initfunc(void device_setup(void)) ...@@ -1124,4 +1127,7 @@ __initfunc(void device_setup(void))
#endif #endif
rd_load(); rd_load();
#endif #endif
#ifdef CONFIG_MD_BOOT
md_setup_drive();
#endif
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
A lot of inspiration came from hd.c ... A lot of inspiration came from hd.c ...
kerneld support by Boris Tobotras <boris@xtalk.msk.su> kerneld support by Boris Tobotras <boris@xtalk.msk.su>
boot support for linear and striped mode by Harald Hoyer <HarryH@Royal.Net>
RAID-1/RAID-5 extensions by: RAID-1/RAID-5 extensions by:
Ingo Molnar, Miguel de Icaza, Gadi Oxman Ingo Molnar, Miguel de Icaza, Gadi Oxman
...@@ -59,6 +60,10 @@ ...@@ -59,6 +60,10 @@
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#ifdef CONFIG_MD_BOOT
extern dev_t name_to_dev_t(char *line) __init;
#endif
static struct hd_struct md_hd_struct[MAX_MD_DEV]; static struct hd_struct md_hd_struct[MAX_MD_DEV];
static int md_blocksizes[MAX_MD_DEV]; static int md_blocksizes[MAX_MD_DEV];
int md_maxreadahead[MAX_MD_DEV]; int md_maxreadahead[MAX_MD_DEV];
...@@ -988,10 +993,13 @@ int md_thread(void * arg) ...@@ -988,10 +993,13 @@ int md_thread(void * arg)
cli(); cli();
if (!test_bit(THREAD_WAKEUP, &thread->flags)) { if (!test_bit(THREAD_WAKEUP, &thread->flags)) {
do { do {
spin_lock_irq(&current->sigmask_lock); spin_lock(&current->sigmask_lock);
flush_signals(current); flush_signals(current);
spin_unlock_irq(&current->sigmask_lock); spin_unlock(&current->sigmask_lock);
interruptible_sleep_on(&thread->wqueue); interruptible_sleep_on(&thread->wqueue);
cli();
if (test_bit(THREAD_WAKEUP, &thread->flags))
break;
} while (signal_pending(current)); } while (signal_pending(current));
} }
} }
...@@ -1055,7 +1063,7 @@ int md_do_sync(struct md_dev *mddev) ...@@ -1055,7 +1063,7 @@ int md_do_sync(struct md_dev *mddev)
*/ */
curr_bsize = blksize_size[major][minor]; curr_bsize = blksize_size[major][minor];
if (curr_bsize != blocksize) { if (curr_bsize != blocksize) {
diff_blocksize: diff_blocksize:
if (curr_bsize > blocksize) if (curr_bsize > blocksize)
/* /*
* this is safe, rounds downwards. * this is safe, rounds downwards.
...@@ -1163,6 +1171,102 @@ void mdsyncd (void *data) ...@@ -1163,6 +1171,102 @@ void mdsyncd (void *data)
} }
#ifdef CONFIG_MD_BOOT
struct {
int set;
int ints[100];
char str[100];
} md_setup_args __initdata = {
0,{0},{0}
};
/* called from init/main.c */
__initfunc(void md_setup(char *str,int *ints))
{
int i;
for(i=0;i<=ints[0];i++) {
md_setup_args.ints[i] = ints[i];
strcpy(md_setup_args.str, str);
/* printk ("md: ints[%d]=%d.\n", i, ints[i]);*/
}
md_setup_args.set=1;
return;
}
__initfunc(void do_md_setup(char *str,int *ints))
{
int minor, pers, factor, fault;
dev_t dev;
int i=1;
if(ints[0] < 4) {
printk ("md: Too few Arguments (%d).\n", ints[0]);
return;
}
minor=ints[i++];
if (minor >= MAX_MD_DEV) {
printk ("md: Minor device number too high.\n");
return;
}
pers = 0;
switch(ints[i++]) { /* Raidlevel */
case -1:
#ifdef CONFIG_MD_LINEAR
pers = LINEAR;
printk ("md: Setting up md%d as linear device.\n",minor);
#else
printk ("md: Linear mode not configured."
"Recompile the kernel with linear mode enabled!\n");
#endif
break;
case 0:
pers = STRIPED;
#ifdef CONFIG_MD_STRIPED
printk ("md: Setting up md%d as a striped device.\n",minor);
#else
printk ("md: Striped mode not configured."
"Recompile the kernel with striped mode enabled!\n");
#endif
break;
/* not supported yet
case 1:
pers = RAID1;
printk ("md: Setting up md%d as a raid1 device.\n",minor);
break;
case 5:
pers = RAID5;
printk ("md: Setting up md%d as a raid5 device.\n",minor);
break;
*/
default:
printk ("md: Unknown or not supported raid level %d.\n", ints[--i]);
return;
}
if(pers) {
factor=ints[i++]; /* Chunksize */
fault =ints[i++]; /* Faultlevel */
pers=pers | factor | (fault << FAULT_SHIFT);
while( str && (dev = name_to_dev_t(str))) {
do_md_add (minor, dev);
if(str = strchr (str, ','))
str++;
}
do_md_run (minor, pers);
printk ("md: Loading md%d.\n",minor);
}
}
#endif
void linear_init (void); void linear_init (void);
void raid0_init (void); void raid0_init (void);
void raid1_init (void); void raid1_init (void);
...@@ -1216,6 +1320,13 @@ __initfunc(int md_init (void)) ...@@ -1216,6 +1320,13 @@ __initfunc(int md_init (void))
#ifdef CONFIG_MD_RAID5 #ifdef CONFIG_MD_RAID5
raid5_init (); raid5_init ();
#endif #endif
return (0); return (0);
} }
#ifdef CONFIG_MD_BOOT
__initfunc(void md_setup_drive(void))
{
if(md_setup_args.set)
do_md_setup(md_setup_args.str, md_setup_args.ints);
}
#endif
comment 'Misc. hamradio protocols'
tristate 'Shortwave radio modem driver' CONFIG_HFMODEM
if [ "$CONFIG_HFMODEM" != "n" ]; then
bool ' HFmodem support for Soundblaster and compatible cards' CONFIG_HFMODEM_SBC
bool ' HFmodem support for WSS and Crystal cards' CONFIG_HFMODEM_WSS
fi
...@@ -54,6 +54,8 @@ static const char *version = ...@@ -54,6 +54,8 @@ static const char *version =
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h>
#include <asm/delay.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/in.h> #include <linux/in.h>
...@@ -185,10 +187,12 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -185,10 +187,12 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
/* Mask interrupts from the ethercard. */ /* Mask interrupts from the ethercard. */
outb_p(0x00, e8390_base + EN0_IMR); outb_p(0x00, e8390_base + EN0_IMR);
disable_irq(dev->irq);
synchronize_irq(); synchronize_irq();
if (dev->interrupt) { if (dev->interrupt) {
printk("%s: Tx request while isr active.\n",dev->name); printk("%s: Tx request while isr active.\n",dev->name);
outb_p(ENISR_ALL, e8390_base + EN0_IMR); outb_p(ENISR_ALL, e8390_base + EN0_IMR);
enable_irq(dev->irq);
ei_local->stat.tx_errors++; ei_local->stat.tx_errors++;
dev_kfree_skb(skb, FREE_WRITE); dev_kfree_skb(skb, FREE_WRITE);
return 0; return 0;
...@@ -226,6 +230,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -226,6 +230,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
ei_local->irqlock = 0; ei_local->irqlock = 0;
dev->tbusy = 1; dev->tbusy = 1;
outb_p(ENISR_ALL, e8390_base + EN0_IMR); outb_p(ENISR_ALL, e8390_base + EN0_IMR);
enable_irq(dev->irq);
ei_local->stat.tx_errors++; ei_local->stat.tx_errors++;
return 1; return 1;
} }
...@@ -272,6 +277,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -272,6 +277,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
/* Turn 8390 interrupts back on. */ /* Turn 8390 interrupts back on. */
ei_local->irqlock = 0; ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR); outb_p(ENISR_ALL, e8390_base + EN0_IMR);
enable_irq(dev->irq);
dev_kfree_skb (skb, FREE_WRITE); dev_kfree_skb (skb, FREE_WRITE);
ei_local->stat.tx_bytes += send_length; ei_local->stat.tx_bytes += send_length;
...@@ -608,7 +614,6 @@ static void ei_receive(struct device *dev) ...@@ -608,7 +614,6 @@ static void ei_receive(struct device *dev)
static void ei_rx_overrun(struct device *dev) static void ei_rx_overrun(struct device *dev)
{ {
int e8390_base = dev->base_addr; int e8390_base = dev->base_addr;
unsigned long wait_start_time;
unsigned char was_txing, must_resend = 0; unsigned char was_txing, must_resend = 0;
struct ei_device *ei_local = (struct ei_device *) dev->priv; struct ei_device *ei_local = (struct ei_device *) dev->priv;
...@@ -629,9 +634,7 @@ static void ei_rx_overrun(struct device *dev) ...@@ -629,9 +634,7 @@ static void ei_rx_overrun(struct device *dev)
* it "is not a reliable indicator and subsequently should be ignored." * it "is not a reliable indicator and subsequently should be ignored."
* We wait at least 10ms. * We wait at least 10ms.
*/ */
wait_start_time = jiffies; udelay(10*1000);
while (jiffies - wait_start_time <= 1*HZ/100)
barrier();
/* /*
* Reset RBCR[01] back to zero as per magic incantation. * Reset RBCR[01] back to zero as per magic incantation.
......
...@@ -2216,7 +2216,7 @@ pci_probe(struct device *dev, u_long ioaddr)) ...@@ -2216,7 +2216,7 @@ pci_probe(struct device *dev, u_long ioaddr))
__initfunc(static void __initfunc(static void
srom_search(int index)) srom_search(int index))
{ {
u_char pb, dev_fn; u_char pb, dev_fn, tirq;
u_short dev_id, dev_num, vendor, status; u_short dev_id, dev_num, vendor, status;
u_int tmp, irq = 0, device, class = DE4X5_CLASS_CODE; u_int tmp, irq = 0, device, class = DE4X5_CLASS_CODE;
u_long iobase = 0; /* Clear upper 32 bits in Alphas */ u_long iobase = 0; /* Clear upper 32 bits in Alphas */
...@@ -2266,8 +2266,8 @@ srom_search(int index)) ...@@ -2266,8 +2266,8 @@ srom_search(int index))
/* Fetch the IRQ to be used */ /* Fetch the IRQ to be used */
#ifndef __sparc_v9__ #ifndef __sparc_v9__
pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
(char *)&irq); irq = tirq;
#else #else
irq = pdev->irq; irq = pdev->irq;
#endif #endif
......
# comment 'AX.25 network device drivers'
# Amateur Radio protocols and AX.25 device configuration
#
# 19971130 Now in an own category to make correct compilation of the
# AX.25 stuff easier...
# Joerg Reuter DL1BKE <jreuter@poboxes.com>
mainmenu_option next_comment dep_tristate 'Serial port KISS driver' CONFIG_MKISS $CONFIG_AX25
comment 'Amateur Radio support' # dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
bool 'Amateur Radio support' CONFIG_HAMRADIO dep_tristate 'BPQ Ethernet driver' CONFIG_BPQETHER $CONFIG_AX25
if [ "$CONFIG_HAMRADIO" != "n" ] ; then
if [ "$CONFIG_NET" != "n" ] ; then
comment 'Packet Radio protocols'
tristate 'Amateur Radio AX.25 Level 2 protocol' CONFIG_AX25
if [ "$CONFIG_AX25" != "n" ]; then
bool ' AX.25 DAMA Slave support' CONFIG_AX25_DAMA_SLAVE
# bool ' AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER
dep_tristate ' Amateur Radio NET/ROM protocol' CONFIG_NETROM $CONFIG_AX25
dep_tristate ' Amateur Radio X.25 PLP (Rose)' CONFIG_ROSE $CONFIG_AX25
fi
if [ "$CONFIG_AX25" != "n" ]; then
comment 'AX.25 network device drivers'
tristate 'Serial port KISS driver' CONFIG_MKISS
# tristate 'Serial port 6PACK driver' CONFIG_6PACK
tristate 'BPQ Ethernet driver' CONFIG_BPQETHER
dep_tristate 'High-speed (DMA) SCC driver for AX.25' CONFIG_DMASCC $CONFIG_AX25
tristate 'Z8530 SCC driver' CONFIG_SCC
if [ "$CONFIG_SCC" != "n" ]; then
bool ' additional delay for PA0HZP OptoSCC compatible boards' CONFIG_SCC_DELAY
bool ' support for TRX that feedback the tx signal to rx' CONFIG_SCC_TRXECHO
fi
tristate 'BAYCOM ser12 fullduplex driver for AX.25' CONFIG_BAYCOM_SER_FDX dep_tristate 'High-speed (DMA) SCC driver for AX.25' CONFIG_DMASCC $CONFIG_AX25
tristate 'BAYCOM ser12 halfduplex driver for AX.25' CONFIG_BAYCOM_SER_HDX dep_tristate 'Z8530 SCC driver' CONFIG_SCC $CONFIG_AX25
tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR if [ "$CONFIG_SCC" != "n" ]; then
bool ' additional delay for PA0HZP OptoSCC compatible boards' CONFIG_SCC_DELAY
tristate 'Soundcard modem driver' CONFIG_SOUNDMODEM bool ' support for TRX that feedback the tx signal to rx' CONFIG_SCC_TRXECHO
if [ "$CONFIG_SOUNDMODEM" != "n" ]; then
bool ' soundmodem support for Soundblaster and compatible cards' CONFIG_SOUNDMODEM_SBC
bool ' soundmodem support for WSS and Crystal cards' CONFIG_SOUNDMODEM_WSS
bool ' soundmodem support for 1200 baud AFSK modulation' CONFIG_SOUNDMODEM_AFSK1200
bool ' soundmodem support for 2400 baud AFSK modulation (7.3728MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_7
bool ' soundmodem support for 2400 baud AFSK modulation (8MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_8
bool ' soundmodem support for 4800 baud HAPN-1 modulation' CONFIG_SOUNDMODEM_HAPN4800
bool ' soundmodem support for 9600 baud FSK G3RUH modulation' CONFIG_SOUNDMODEM_FSK9600
fi
fi
fi
comment 'Misc. hamradio protocols'
tristate 'Shortwave radio modem driver' CONFIG_HFMODEM
if [ "$CONFIG_HFMODEM" != "n" ]; then
bool ' HFmodem support for Soundblaster and compatible cards' CONFIG_HFMODEM_SBC
bool ' HFmodem support for WSS and Crystal cards' CONFIG_HFMODEM_WSS
fi
fi fi
dep_tristate 'BAYCOM ser12 fullduplex driver for AX.25' CONFIG_BAYCOM_SER_FDX $CONFIG_AX25
dep_tristate 'BAYCOM ser12 halfduplex driver for AX.25' CONFIG_BAYCOM_SER_HDX $CONFIG_AX25
dep_tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR $CONFIG_AX25
endmenu dep_tristate 'Soundcard modem driver' CONFIG_SOUNDMODEM $CONFIG_AX25
if [ "$CONFIG_SOUNDMODEM" != "n" ]; then
bool ' soundmodem support for Soundblaster and compatible cards' CONFIG_SOUNDMODEM_SBC
bool ' soundmodem support for WSS and Crystal cards' CONFIG_SOUNDMODEM_WSS
bool ' soundmodem support for 1200 baud AFSK modulation' CONFIG_SOUNDMODEM_AFSK1200
bool ' soundmodem support for 2400 baud AFSK modulation (7.3728MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_7
bool ' soundmodem support for 2400 baud AFSK modulation (8MHz crystal)' CONFIG_SOUNDMODEM_AFSK2400_8
bool ' soundmodem support for 4800 baud HAPN-1 modulation' CONFIG_SOUNDMODEM_HAPN4800
bool ' soundmodem support for 9600 baud FSK G3RUH modulation' CONFIG_SOUNDMODEM_FSK9600
fi
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
* call. * call.
* Fixed to match Linux networking * Fixed to match Linux networking
* changes - 2.1.15. * changes - 2.1.15.
* BPQ 004 Joerg(DL1BKE) Fixed to not lock up on ifconfig.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -78,6 +79,7 @@ ...@@ -78,6 +79,7 @@
#include <linux/firewall.h> #include <linux/firewall.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/rtnetlink.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/arp.h> #include <net/arp.h>
...@@ -186,7 +188,11 @@ static int bpq_check_devices(struct device *dev) ...@@ -186,7 +188,11 @@ static int bpq_check_devices(struct device *dev)
if (&bpq->axdev == dev) if (&bpq->axdev == dev)
result = 1; result = 1;
unregister_netdev(&bpq->axdev); /* We should be locked, call
* unregister_netdevice directly
*/
unregister_netdevice(&bpq->axdev);
kfree(bpq); kfree(bpq);
} }
...@@ -531,7 +537,9 @@ static int bpq_new_device(struct device *dev) ...@@ -531,7 +537,9 @@ static int bpq_new_device(struct device *dev)
dev->name = buf; dev->name = buf;
dev->init = bpq_dev_init; dev->init = bpq_dev_init;
if (register_netdev(dev) != 0) { /* We should be locked, call register_netdevice() directly. */
if (register_netdevice(dev) != 0) {
kfree(bpq); kfree(bpq);
return -EIO; return -EIO;
} }
......
#define RCS_ID "$Id: scc.c,v 1.71 1997/11/29 19:59:20 jreuter Exp jreuter $" #define RCS_ID "$Id: scc.c,v 1.73 1998/01/29 17:38:51 jreuter Exp jreuter $"
#define VERSION "3.0" #define VERSION "3.0"
#define BANNER "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n" #define BANNER "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n"
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
/* /*
* Please use z8530drv-utils-3.0 with this version. * Please use z8530drv-utils-3.0 with this version.
* ------------------ * ------------------
*
* You can find a subset of the documentation in
* linux/Documentation/networking/z8530drv.txt.
*/ */
/* /*
...@@ -16,7 +19,7 @@ ...@@ -16,7 +19,7 @@
******************************************************************** ********************************************************************
Copyright (c) 1993, 1997 Joerg Reuter DL1BKE Copyright (c) 1993, 1998 Joerg Reuter DL1BKE
portions (c) 1993 Guido ten Dolle PE1NNZ portions (c) 1993 Guido ten Dolle PE1NNZ
...@@ -89,7 +92,8 @@ ...@@ -89,7 +92,8 @@
970108 - Fixed the remaining problems. 970108 - Fixed the remaining problems.
970402 - Hopefully fixed the problems with the new *_timer() 970402 - Hopefully fixed the problems with the new *_timer()
routines, added calibration code. routines, added calibration code.
971012 - made SCC_DELAY a CONFIG option, added CONFIG_SCC_TRXECHO 971012 - Made SCC_DELAY a CONFIG option, added CONFIG_SCC_TRXECHO
980129 - Small fix to avoid lock-up on initialization
Thanks to all who contributed to this driver with ideas and bug Thanks to all who contributed to this driver with ideas and bug
reports! reports!
...@@ -195,7 +199,7 @@ static void scc_key_trx (struct scc_channel *scc, char tx); ...@@ -195,7 +199,7 @@ static void scc_key_trx (struct scc_channel *scc, char tx);
static void scc_isr(int irq, void *dev_id, struct pt_regs *regs); static void scc_isr(int irq, void *dev_id, struct pt_regs *regs);
static void scc_init_timer(struct scc_channel *scc); static void scc_init_timer(struct scc_channel *scc);
static int scc_net_setup(struct scc_channel *scc, unsigned char *name); static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev);
static int scc_net_init(struct device *dev); static int scc_net_init(struct device *dev);
static int scc_net_open(struct device *dev); static int scc_net_open(struct device *dev);
static int scc_net_close(struct device *dev); static int scc_net_close(struct device *dev);
...@@ -1529,7 +1533,7 @@ static void z8530_init(void) ...@@ -1529,7 +1533,7 @@ static void z8530_init(void)
* Allocate device structure, err, instance, and register driver * Allocate device structure, err, instance, and register driver
*/ */
static int scc_net_setup(struct scc_channel *scc, unsigned char *name) static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev)
{ {
unsigned char *buf; unsigned char *buf;
struct device *dev; struct device *dev;
...@@ -1553,11 +1557,11 @@ static int scc_net_setup(struct scc_channel *scc, unsigned char *name) ...@@ -1553,11 +1557,11 @@ static int scc_net_setup(struct scc_channel *scc, unsigned char *name)
dev->name = buf; dev->name = buf;
dev->init = scc_net_init; dev->init = scc_net_init;
if (register_netdev(dev) != 0) if ((addev? register_netdevice(dev) : register_netdev(dev)) != 0)
{ {
kfree(dev); kfree(dev);
return -EIO; return -EIO;
} }
return 0; return 0;
} }
...@@ -1868,7 +1872,7 @@ static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd) ...@@ -1868,7 +1872,7 @@ static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl"); request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data"); request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
if (Nchips+chan != 0) if (Nchips+chan != 0)
scc_net_setup(&SCC_Info[2*Nchips+chan], device_name); scc_net_setup(&SCC_Info[2*Nchips+chan], device_name, 1);
} }
} }
...@@ -2178,7 +2182,7 @@ __initfunc(int scc_init (void)) ...@@ -2178,7 +2182,7 @@ __initfunc(int scc_init (void))
sprintf(devname,"%s0", SCC_DriverName); sprintf(devname,"%s0", SCC_DriverName);
result = scc_net_setup(SCC_Info, devname); result = scc_net_setup(SCC_Info, devname, 0);
if (result) if (result)
{ {
printk(KERN_ERR "z8530drv: cannot initialize module\n"); printk(KERN_ERR "z8530drv: cannot initialize module\n");
...@@ -2203,7 +2207,7 @@ int init_module(void) ...@@ -2203,7 +2207,7 @@ int init_module(void)
result = scc_init(); result = scc_init();
if (result == 0) if (result == 0)
printk(KERN_INFO "Copyright 1993,1997 Joerg Reuter DL1BKE (jreuter@poboxes.com)\n"); printk(KERN_INFO "Copyright 1993,1998 Joerg Reuter DL1BKE (jreuter@poboxes.com)\n");
return result; return result;
} }
......
...@@ -84,10 +84,11 @@ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_NCR53C7xx" != "y" ]; then ...@@ -84,10 +84,11 @@ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_NCR53C7xx" != "y" ]; then
fi fi
fi fi
if [ "$CONFIG_MCA" = "y" ]; then if [ "$CONFIG_MCA" = "y" ]; then
dep_tristate 'IBMMCA SCSI support' CONFIG_SCSI_IBMMCA $CONFIG_SCSI bool 'IBMMCA SCSI support' CONFIG_SCSI_IBMMCA
if [ "$CONFIG_SCSI_IBMMCA" != "n" ]; then if [ "$CONFIG_SCSI_IBMMCA" = "y" ]; then
bool ' reset SCSI-devices while booting' CONFIG_SCSI_IBMMCA_DEV_RESET bool ' Standard SCSI-order' CONFIG_IBMMCA_SCSI_ORDER_STANDARD
fi bool ' Reset SCSI-devices at boottime' CONFIG_IBMMCA_SCSI_DEV_RESET
fi
fi fi
if [ "$CONFIG_PARPORT" != "n" ]; then if [ "$CONFIG_PARPORT" != "n" ]; then
dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
......
...@@ -199,10 +199,11 @@ ...@@ -199,10 +199,11 @@
5) Magneto-Optical drives and medium-changers are also recognized, now. 5) Magneto-Optical drives and medium-changers are also recognized, now.
Therefore, we have a completely gapfree recognition of all SCSI- Therefore, we have a completely gapfree recognition of all SCSI-
device-types, that are known by Linux up to kernel 2.1.31. device-types, that are known by Linux up to kernel 2.1.31.
6) The flag CONFIG_SCSI_IBMMCA_DEV_RESET has been inserted. If it is set 6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
within the configuration, each connected SCSI-device will get a reset the configuration, each connected SCSI-device will get a reset command
command during boottime. This can be necessary for some special during boottime. This can be necessary for some special SCSI-devices.
SCSI-devices. (See also the new Config.in file.) This flag should be included in Config.in.
(See also the new Config.in file.)
Probable next improvement: bad disk handler. Probable next improvement: bad disk handler.
- Michael Lang - Michael Lang
...@@ -210,8 +211,64 @@ ...@@ -210,8 +211,64 @@
1) Some debugging and speed optimization applied. 1) Some debugging and speed optimization applied.
- Michael Lang - Michael Lang
Dec 15, 1997
- chrisb@truespectra.com
- made the front panel display thingy optional, specified from the
command-line via ibmmcascsi=display. Along the lines of the /LED
option for the OS/2 driver.
- fixed small bug in the LED display that would hang some machines.
- reversed ordering of the drives (using the
IBMMCA_SCSI_ORDER_STANDARD define). This is necessary for two main
reasons:
- users who've already installed Linux won't be screwed. Keep
in mind that not everyone is a kernel hacker.
- be consistent with the BIOS ordering of the drives. In the
BIOS, id 6 is C:, id 0 might be D:. With this scheme, they'd be
backwards. This confuses the crap out of those heathens who've
got a impure Linux installation (which, <wince>, I'm one of).
This whole problem arises because IBM is actually non-standard with
the id to BIOS mappings. You'll find, in fdomain.c, a similar
comment about a few FD BIOS revisions. The Linux (and apparently
industry) standard is that C: maps to scsi id (0,0). Let's stick
with that standard.
- Since this is technically a branch of my own, I changed the
version number to 3.0e-cpb.
Jan 17, 1998: (v3.0f)
1) Addition of some statistical info for /proc in proc_info.
2) Taking care of the SCSI-assignment problem, dealed by Chris at Dec 15
1997. In fact, IBM is right, concerning the assignment of SCSI-devices
to driveletters. It is conform to the ANSI-definition of the SCSI-
standard to assign drive C: to SCSI-id 6, because it is the highest
hardware priority after the hostadapter (that has still today by
default everywhere id 7). Also realtime-operating systems that I use,
like LynxOS and OS9, which are quite industrial systems use top-down
numbering of the harddisks, that is also starting at id 6. Now, one
sits a bit between two chairs. On one hand side, using the define
IBMMCA_SCSI_ORDER_STANDARD makes Linux assigning disks conform to
the IBM- and ANSI-SCSI-standard and keeps this driver downward
compatible to older releases, on the other hand side, people is quite
habituated in believing that C: is assigned to (0,0) and much other
SCSI-BIOS do so. Therefore, I moved the IBMMCA_SCSI_ORDER_STANDARD
define out of the driver and put it into Config.in as subitem of
'IBM SCSI support'. A help, added to Documentation/Configure.help
explains the differences between saying 'y' or 'n' to the user, when
IBMMCA_SCSI_ORDER_STANDARD prompts, so the ordinary user is enabled to
choose the way of assignment, depending on his own situation and gusto.
3) Adapted SCSI_IBMMCA_DEV_RESET to the local naming convention, so it is
now called IBMMCA_SCSI_DEV_RESET.
4) Optimization of proc_info and its subroutines.
5) Added more in-source-comments and extended the driver description by
some explanation about the SCSI-device-assignment problem.
- Michael Lang
Jan 18, 1998: (v3.0g)
1) Correcting names to be absolutely conform to the later 2.1.x releases.
This is necessary for
IBMMCA_SCSI_DEV_RESET -> CONFIG_IBMMCA_SCSI_DEV_RESET
IBMMCA_SCSI_ORDER_STANDARD -> CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- Michael Lang
TODO: TODO:
- It seems that the handling of bad disks is really bad - - It seems that the handling of bad disks is really bad -
...@@ -252,7 +309,12 @@ ...@@ -252,7 +309,12 @@
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
/* current version of this driver-source: */ /* current version of this driver-source: */
#define IBMMCA_SCSI_DRIVER_VERSION "3.0d" #define IBMMCA_SCSI_DRIVER_VERSION "3.0f"
/* use standard Linux ordering, where C: maps to (0,0), unlike the IBM
standard which seems to like C: => (6,0) */
/* #define IBMMCA_SCSI_ORDER_STANDARD is defined/undefined in Config.in
* now, while configuring the kernel. */
/* /*
Driver Description Driver Description
...@@ -341,8 +403,23 @@ ...@@ -341,8 +403,23 @@
If your boot-partition is not coming up, also edit the /etc/lilo.conf-file If your boot-partition is not coming up, also edit the /etc/lilo.conf-file
in a Linux session booted on old kernel and run lilo before reboot. Check in a Linux session booted on old kernel and run lilo before reboot. Check
lilo.conf anyway to get boot on other partitions with foreign OSes right lilo.conf anyway to get boot on other partitions with foreign OSes right
again. again.
The problem is, that Linux does not assign the SCSI-devices in the
way as described in the ANSI-SCSI-standard. Linux assigns /dev/sda to
the device with at minimum id 0. But the first drive should be at id 6,
because for historical reasons, drive at id 6 has, by hardware, the highest
priority and a drive at id 0 the lowest. IBM was one of the rare producers,
where the BIOS assigns drives belonging to the ANSI-SCSI-standard. Most
other producers' BIOS does not (I think even Adaptec-BIOS). The
IBMMCA_SCSI_ORDER_STANDARD flag helps to be able to choose the preferred
way of SCSI-device-assignment. Defining this flag would result in Linux
determining the devices in the same order as DOS and OS/2 does on your
MCA-machine. This is also standard on most industrial computers. Leaving
this flag undefined will get your devices ordered in the default way of
Linux. See also the remarks of Chris Beauregard from Dec 15, 1997 and
the followups.
(C) Regular Processing (C) Regular Processing
Only three functions get involved: ibmmca_queuecommand(), issue_cmd(), Only three functions get involved: ibmmca_queuecommand(), issue_cmd(),
and interrupt_handler(). and interrupt_handler().
...@@ -443,7 +520,7 @@ ...@@ -443,7 +520,7 @@
/* basic I/O-port of first adapter */ /* basic I/O-port of first adapter */
#define IM_IO_PORT 0x3540 #define IM_IO_PORT 0x3540
/* maximum number of hosts that can be find */ /* maximum number of hosts that can be found */
#define IM_N_IO_PORT 8 #define IM_N_IO_PORT 8
/*requests going into the upper nibble of the Attention register */ /*requests going into the upper nibble of the Attention register */
...@@ -589,16 +666,19 @@ struct im_tsb ...@@ -589,16 +666,19 @@ struct im_tsb
interest, debugging or just for having fun. The left number gives the interest, debugging or just for having fun. The left number gives the
host-adapter number and the right shows the accessed SCSI-ID. */ host-adapter number and the right shows the accessed SCSI-ID. */
/* use_display is set by the ibmmcascsi=display command line arg */
static int use_display = 0;
#define PS2_DISK_LED_ON(ad,id) {\ #define PS2_DISK_LED_ON(ad,id) {\
if( machine_id == 0xf8 ) { outb((char)(id+48), MOD95_LED_PORT ); \ if( use_display ) { outb((char)(id+48), MOD95_LED_PORT ); \
outb((char)(ad+48), MOD95_LED_PORT+1); } \ outb((char)(ad+48), MOD95_LED_PORT+1); } \
else outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); \ else outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); \
} }
/* bug fixed, Dec 15, 1997, where | was replaced by & here */
#define PS2_DISK_LED_OFF() {\ #define PS2_DISK_LED_OFF() {\
if( machine_id == 0xf8 ) { outb( ' ', MOD95_LED_PORT ); \ if( use_display ) { outb( ' ', MOD95_LED_PORT ); \
outb(' ', MOD95_LED_PORT+1); } \ outb(' ', MOD95_LED_PORT+1); } \
else outb(inb(PS2_SYS_CTR) | 0x3f, PS2_SYS_CTR); \ else outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); \
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
...@@ -609,6 +689,8 @@ struct subsys_list_struct ...@@ -609,6 +689,8 @@ struct subsys_list_struct
unsigned short mca_id; unsigned short mca_id;
char *description; char *description;
}; };
/* List of possible IBM-SCSI-adapters */
struct subsys_list_struct subsys_list[] = struct subsys_list_struct subsys_list[] =
{ {
{0x8efc, "IBM Fast SCSI-2 Adapter"}, {0x8efc, "IBM Fast SCSI-2 Adapter"},
...@@ -632,14 +714,14 @@ of the adapter itself. */ ...@@ -632,14 +714,14 @@ of the adapter itself. */
/*local data for a logical device */ /*local data for a logical device */
struct logical_device struct logical_device
{ {
struct im_scb scb; struct im_scb scb; /* SCSI-subsystem-control-block structure */
struct im_tsb tsb; struct im_tsb tsb;
struct im_sge sge[16]; struct im_sge sge[16];
Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */ Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */
int device_type; /* type of the SCSI-device. See include/scsi/scsi.h int device_type; /* type of the SCSI-device. See include/scsi/scsi.h
for interpreation of the possible values */ for interpretation of the possible values */
int block_length; int block_length;/* blocksize of a particular logical SCSI-device */
}; };
/* statistics of the driver during operations (for proc_info) */ /* statistics of the driver during operations (for proc_info) */
...@@ -649,6 +731,8 @@ struct Driver_Statistics ...@@ -649,6 +731,8 @@ struct Driver_Statistics
int ldn_access[MAX_LOG_DEV+1]; /* total accesses on a ldn */ int ldn_access[MAX_LOG_DEV+1]; /* total accesses on a ldn */
int ldn_read_access[MAX_LOG_DEV+1]; /* total read-access on a ldn */ int ldn_read_access[MAX_LOG_DEV+1]; /* total read-access on a ldn */
int ldn_write_access[MAX_LOG_DEV+1]; /* total write-access on a ldn */ int ldn_write_access[MAX_LOG_DEV+1]; /* total write-access on a ldn */
int ldn_inquiry_access[MAX_LOG_DEV+1]; /* total inquiries on a ldn */
int ldn_modeselect_access[MAX_LOG_DEV+1]; /* total mode selects on ldn */
int total_accesses; /* total accesses on all ldns */ int total_accesses; /* total accesses on all ldns */
int total_interrupts; /* total interrupts (should be int total_interrupts; /* total interrupts (should be
same as total_accesses) */ same as total_accesses) */
...@@ -663,26 +747,28 @@ struct Driver_Statistics ...@@ -663,26 +747,28 @@ struct Driver_Statistics
/* data structure for each host adapter */ /* data structure for each host adapter */
struct ibmmca_hostdata struct ibmmca_hostdata
{ {
/* array of logical devices */ /* array of logical devices: */
struct logical_device _ld[MAX_LOG_DEV]; struct logical_device _ld[MAX_LOG_DEV];
/* array to convert (pun, lun) into logical device number */ /* array to convert (pun, lun) into logical device number: */
unsigned char _get_ldn[8][8]; unsigned char _get_ldn[8][8];
/*array that contains the information about the physical SCSI-devices /*array that contains the information about the physical SCSI-devices
attached to this host adapter */ attached to this host adapter: */
unsigned char _get_scsi[8][8]; unsigned char _get_scsi[8][8];
/* used only when checking logical devices */ /* used only when checking logical devices: */
int _local_checking_phase_flag; int _local_checking_phase_flag;
/* report received interrupt: */
int _got_interrupt; int _got_interrupt;
/* report termination-status of SCSI-command: */
int _stat_result; int _stat_result;
/* reset status (used only when doing reset) */ /* reset status (used only when doing reset): */
int _reset_status; int _reset_status;
/* code of the last SCSI command (needed for panic info) */ /* code of the last SCSI command (needed for panic info): */
int _last_scsi_command; int _last_scsi_command;
/* counter that points on next reassignable ldn for dynamical remapping */ /* Counter that points on the next reassignable ldn for dynamical
/* The default value is 7, that is the first reassignable number in remapping. The default value is 7, that is the first reassignable
the list on startup. */ number in the list at boottime: */
int _next_ldn; int _next_ldn;
/* Statistics for this IBM-SCSI-host */ /* Statistics-structure for this IBM-SCSI-host: */
struct Driver_Statistics _IBM_DS; struct Driver_Statistics _IBM_DS;
}; };
...@@ -701,21 +787,21 @@ struct ibmmca_hostdata ...@@ -701,21 +787,21 @@ struct ibmmca_hostdata
#define IBM_DS (HOSTDATA(shpnt)->_IBM_DS) #define IBM_DS (HOSTDATA(shpnt)->_IBM_DS)
/* Define a arbitrary number as subsystem-marker-type. This number is, as /* Define a arbitrary number as subsystem-marker-type. This number is, as
described in the SCSI-Standard, not occupied by other device-types. */ described in the ANSI-SCSI-standard, not occupied by other device-types. */
#define TYPE_IBM_SCSI_ADAPTER 0x2F #define TYPE_IBM_SCSI_ADAPTER 0x2F
/* Define 0xFF for no device type, because this type is not defined within /* Define 0xFF for no device type, because this type is not defined within
the SCSI-standard, therefore, it can be used and should not cause any the ANSI-SCSI-standard, therefore, it can be used and should not cause any
harm. */ harm. */
#define TYPE_NO_DEVICE 0xFF #define TYPE_NO_DEVICE 0xFF
/* define medium-changer. If this is not defined previously, define /* define medium-changer. If this is not defined previously, e.g. Linux
this type here. */ 2.0.x, define this type here. */
#ifndef TYPE_MEDIUM_CHANGER #ifndef TYPE_MEDIUM_CHANGER
#define TYPE_MEDIUM_CHANGER 0x08 #define TYPE_MEDIUM_CHANGER 0x08
#endif #endif
/* define operations for immediate_assign */ /* define possible operations for the immediate_assign command */
#define SET_LDN 0 #define SET_LDN 0
#define REMOVE_LDN 1 #define REMOVE_LDN 1
...@@ -732,7 +818,7 @@ static int io_port[IM_MAX_HOSTS] = { 0, 0, 0, 0, 0, 0, 0, 0 }; ...@@ -732,7 +818,7 @@ static int io_port[IM_MAX_HOSTS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static int scsi_id[IM_MAX_HOSTS] = { 7, 7, 7, 7, 7, 7, 7, 7 }; static int scsi_id[IM_MAX_HOSTS] = { 7, 7, 7, 7, 7, 7, 7, 7 };
/* fill module-parameters only, when this define is present. /* fill module-parameters only, when this define is present.
(that is kernel >=2.1.0) */ (that is kernel version 2.1.x) */
#ifdef MODULE_PARM #ifdef MODULE_PARM
MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
...@@ -1036,24 +1122,19 @@ static char *ti_p(int value) ...@@ -1036,24 +1122,19 @@ static char *ti_p(int value)
return("-"); return("-");
} }
/* type-interpreter for logical devices /* interpreter for logical device numbers (ldn) */
(A bit stupid, but it was necessary to get the '-' and the Hex-codes
into one type.) */
static char *ti_l(int value) static char *ti_l(int value)
{ {
switch (value) const char hex[16] = ("0123456789abcdef");
{ static char answer[2];
case 0: return("0"); break; case 1: return("1"); break;
case 2: return("2"); break; case 3: return("3"); break; answer[1] = (char)(0x0);
case 4: return("4"); break; case 5: return("5"); break; if (value<=MAX_LOG_DEV)
case 6: return("6"); break; case 7: return("7"); break; answer[0] = hex[value];
case 8: return("8"); break; case 9: return("9"); break; else
case 10: return("a"); break; case 11: return("b"); break; answer[0] = '-';
case 12: return("c"); break; case 13: return("d"); break;
case 14: return("e"); break; case 15: return("f"); break; return (char *)&answer;
default: return("-"); break;
}
return("-");
} }
/* /*
...@@ -1093,7 +1174,7 @@ static void check_devices (struct Scsi_Host *shpnt) ...@@ -1093,7 +1174,7 @@ static void check_devices (struct Scsi_Host *shpnt)
memset (get_ldn, TYPE_NO_DEVICE, sizeof get_ldn); /* this is essential ! */ memset (get_ldn, TYPE_NO_DEVICE, sizeof get_ldn); /* this is essential ! */
memset (get_scsi, TYPE_NO_DEVICE, sizeof get_scsi); /* this is essential ! */ memset (get_scsi, TYPE_NO_DEVICE, sizeof get_scsi); /* this is essential ! */
for (lun=0; lun<=7; lun++) /* mark the adapter at its pun on all luns*/ for (lun=0; lun<8; lun++) /* mark the adapter at its pun on all luns*/
{ {
get_scsi[subsystem_pun][lun] = TYPE_IBM_SCSI_ADAPTER; get_scsi[subsystem_pun][lun] = TYPE_IBM_SCSI_ADAPTER;
get_ldn[subsystem_pun][lun] = MAX_LOG_DEV; /* make sure, the subsystem get_ldn[subsystem_pun][lun] = MAX_LOG_DEV; /* make sure, the subsystem
...@@ -1111,13 +1192,13 @@ static void check_devices (struct Scsi_Host *shpnt) ...@@ -1111,13 +1192,13 @@ static void check_devices (struct Scsi_Host *shpnt)
immediate_assign(shpnt,0,0,ldn,REMOVE_LDN); /* remove ldn (wherever)*/ immediate_assign(shpnt,0,0,ldn,REMOVE_LDN); /* remove ldn (wherever)*/
} }
lun = 0; lun = 0; /* default lun is 0 */
/* STEP 2: */ /* STEP 2: */
printk("\nIBM MCA SCSI: Probing SCSI-devices."); printk("\nIBM MCA SCSI: Probing SCSI-devices.");
for (id=0; id<=7; id++) for (id=0; id<8; id++)
#ifdef CONFIG_SCSI_MULTI_LUN #ifdef CONFIG_SCSI_MULTI_LUN
for (lun=0; lun<=7; lun++) for (lun=0; lun<8; lun++)
#endif #endif
{ {
#ifdef IM_DEBUG_PROBE #ifdef IM_DEBUG_PROBE
...@@ -1137,16 +1218,16 @@ static void check_devices (struct Scsi_Host *shpnt) ...@@ -1137,16 +1218,16 @@ static void check_devices (struct Scsi_Host *shpnt)
} }
} }
/* STEP 3: */ /* STEP 3: */
printk("\nIBM MCA SCSI: Mapping SCSI-devices."); printk("\nIBM MCA SCSI: Mapping SCSI-devices.");
ldn = 0; ldn = 0;
lun = 0; lun = 0;
#ifdef CONFIG_SCSI_MULTI_LUN #ifdef CONFIG_SCSI_MULTI_LUN
for (lun=0; lun<=7 && ldn<MAX_LOG_DEV; lun++) for (lun=0; lun<8 && ldn<MAX_LOG_DEV; lun++)
#endif #endif
for (id=0; id<=7 && ldn<MAX_LOG_DEV; id++) for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
{ {
#ifdef IM_DEBUG_PROBE #ifdef IM_DEBUG_PROBE
printk("."); printk(".");
...@@ -1163,7 +1244,7 @@ static void check_devices (struct Scsi_Host *shpnt) ...@@ -1163,7 +1244,7 @@ static void check_devices (struct Scsi_Host *shpnt)
if (device_exists (shpnt, ldn, &ld[ldn].block_length, if (device_exists (shpnt, ldn, &ld[ldn].block_length,
&ld[ldn].device_type)) &ld[ldn].device_type))
{ {
#ifdef CONFIG_SCSI_IBMMCA_DEV_RESET #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
int ticks; int ticks;
printk("(resetting)"); printk("(resetting)");
ticks = IM_RESET_DELAY*HZ; ticks = IM_RESET_DELAY*HZ;
...@@ -1211,8 +1292,8 @@ static void check_devices (struct Scsi_Host *shpnt) ...@@ -1211,8 +1292,8 @@ static void check_devices (struct Scsi_Host *shpnt)
/* STEP 4: */ /* STEP 4: */
/* map remaining ldns to non-existing devices */ /* map remaining ldns to non-existing devices */
for (lun=1; lun<=7 && ldn<MAX_LOG_DEV; lun++) for (lun=1; lun<8 && ldn<MAX_LOG_DEV; lun++)
for (id=0; id<=7 && ldn<MAX_LOG_DEV; id++) for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
{ {
if (get_scsi[id][lun] == TYPE_NO_LUN || if (get_scsi[id][lun] == TYPE_NO_LUN ||
get_scsi[id][lun] == TYPE_NO_DEVICE) get_scsi[id][lun] == TYPE_NO_DEVICE)
...@@ -1228,24 +1309,29 @@ static void check_devices (struct Scsi_Host *shpnt) ...@@ -1228,24 +1309,29 @@ static void check_devices (struct Scsi_Host *shpnt)
} }
printk("\n"); printk("\n");
#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
printk("IBM MCA SCSI: SCSI-access-order: IBM/ANSI.\n");
#else
printk("IBM MCA SCSI: SCSI-access-order: Linux.\n");
#endif
#ifdef IM_DEBUG_PROBE #ifdef IM_DEBUG_PROBE
/* Show the physical and logical mapping during boot. */ /* Show the physical and logical mapping during boot. */
printk("IBM MCA SCSI: Determined SCSI-device-mapping:\n"); printk("IBM MCA SCSI: Determined SCSI-device-mapping:\n");
printk(" Physical SCSI-Device Map Logical SCSI-Device Map\n"); printk(" Physical SCSI-Device Map Logical SCSI-Device Map\n");
printk("ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n"); printk("ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n");
for (id=0; id<=7; id++) for (id=0; id<8; id++)
{ {
printk("%2d %2s %2s %2s %2s %2s %2s %2s %2s", printk("%2d %2s %2s %2s %2s %2s %2s %2s %2s",
id, ti_p(get_scsi[id][0]), ti_p(get_scsi[id][1]), id, ti_p(get_scsi[id][0]), ti_p(get_scsi[id][1]),
ti_p(get_scsi[id][2]), ti_p(get_scsi[id][3]), ti_p(get_scsi[id][2]), ti_p(get_scsi[id][3]),
ti_p(get_scsi[id][4]), ti_p(get_scsi[id][5]), ti_p(get_scsi[id][4]), ti_p(get_scsi[id][5]),
ti_p(get_scsi[id][6]), ti_p(get_scsi[id][7])); ti_p(get_scsi[id][6]), ti_p(get_scsi[id][7]));
printk(" %2d %2s %2s %2s %2s %2s %2s %2s %2s\n",
id, ti_l(get_ldn[id][0]), ti_l(get_ldn[id][1]), printk(" %2d ",id);
ti_l(get_ldn[id][2]), ti_l(get_ldn[id][3]), for (lun=0; lun<8; lun++)
ti_l(get_ldn[id][4]), ti_l(get_ldn[id][5]), printk("%2s ",ti_l(get_ldn[id][lun]));
ti_l(get_ldn[id][6]), ti_l(get_ldn[id][7])); printk("\n");
} }
#endif #endif
...@@ -1270,6 +1356,8 @@ static void check_devices (struct Scsi_Host *shpnt) ...@@ -1270,6 +1356,8 @@ static void check_devices (struct Scsi_Host *shpnt)
memset (IBM_DS.ldn_access, 0x0, sizeof (IBM_DS.ldn_access)); memset (IBM_DS.ldn_access, 0x0, sizeof (IBM_DS.ldn_access));
memset (IBM_DS.ldn_read_access, 0x0, sizeof (IBM_DS.ldn_read_access)); memset (IBM_DS.ldn_read_access, 0x0, sizeof (IBM_DS.ldn_read_access));
memset (IBM_DS.ldn_write_access, 0x0, sizeof (IBM_DS.ldn_write_access)); memset (IBM_DS.ldn_write_access, 0x0, sizeof (IBM_DS.ldn_write_access));
memset (IBM_DS.ldn_inquiry_access, 0x0, sizeof (IBM_DS.ldn_inquiry_access));
memset (IBM_DS.ldn_modeselect_access, 0x0, sizeof (IBM_DS.ldn_modeselect_access));
memset (IBM_DS.ldn_assignments, 0x0, sizeof (IBM_DS.ldn_assignments)); memset (IBM_DS.ldn_assignments, 0x0, sizeof (IBM_DS.ldn_assignments));
return; return;
...@@ -1412,10 +1500,14 @@ device_exists (struct Scsi_Host *shpnt, int ldn, int *block_length, ...@@ -1412,10 +1500,14 @@ device_exists (struct Scsi_Host *shpnt, int ldn, int *block_length,
void void
ibmmca_scsi_setup (char *str, int *ints) ibmmca_scsi_setup (char *str, int *ints)
{ {
int i; if( str && !strcmp( str, "display" ) ) {
use_display = 1;
for (i = 0; i < IM_MAX_HOSTS && i < ints[0]; i++) } else if( ints ) {
io_port[i] = ints[i+1]; int i;
for (i = 0; i < IM_MAX_HOSTS && i < ints[0]; i++) {
io_port[i] = ints[i+1];
}
}
} }
#endif #endif
...@@ -1597,9 +1689,16 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1597,9 +1689,16 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
int current_ldn; int current_ldn;
int id,lun; int id,lun;
/* use industry standard ordering of the IDs */
#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
int target = 6 - cmd->target;
#else
int target = cmd->target;
#endif
/*if (target,lun) is NO LUN or not existing at all, return error */ /*if (target,lun) is NO LUN or not existing at all, return error */
if ((get_scsi[cmd->target][cmd->lun] == TYPE_NO_LUN)|| if ((get_scsi[target][cmd->lun] == TYPE_NO_LUN)||
(get_scsi[cmd->target][cmd->lun] == TYPE_NO_DEVICE)) (get_scsi[target][cmd->lun] == TYPE_NO_DEVICE))
{ {
cmd->result = DID_NO_CONNECT << 16; cmd->result = DID_NO_CONNECT << 16;
done (cmd); done (cmd);
...@@ -1607,7 +1706,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1607,7 +1706,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
} }
/*if (target,lun) unassigned, do further checks... */ /*if (target,lun) unassigned, do further checks... */
ldn = get_ldn[cmd->target][cmd->lun]; ldn = get_ldn[target][cmd->lun];
if (ldn >= MAX_LOG_DEV) /* on invalid ldn do special stuff */ if (ldn >= MAX_LOG_DEV) /* on invalid ldn do special stuff */
{ {
if (ldn > MAX_LOG_DEV) /* dynamical remapping if ldn unassigned */ if (ldn > MAX_LOG_DEV) /* dynamical remapping if ldn unassigned */
...@@ -1623,7 +1722,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1623,7 +1722,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n"); printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n");
printk(" On ldn 7-14 SCSI-commands everywhere in progress.\n"); printk(" On ldn 7-14 SCSI-commands everywhere in progress.\n");
printk(" Reporting DID_NO_CONNECT for device (%d,%d).\n", printk(" Reporting DID_NO_CONNECT for device (%d,%d).\n",
cmd->target, cmd->lun); target, cmd->lun);
cmd->result = DID_NO_CONNECT << 16;/* return no connect*/ cmd->result = DID_NO_CONNECT << 16;/* return no connect*/
done (cmd); done (cmd);
return 0; return 0;
...@@ -1631,8 +1730,8 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1631,8 +1730,8 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
} }
/* unmap non-processing ldn */ /* unmap non-processing ldn */
for (id=0; id<=7; id ++) for (id=0; id<8; id ++)
for (lun=0; lun<=7; lun++) for (lun=0; lun<8; lun++)
{ {
if (get_ldn[id][lun] == next_ldn) if (get_ldn[id][lun] == next_ldn)
{ {
...@@ -1645,9 +1744,9 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1645,9 +1744,9 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
/* unassign found ldn (pun,lun does not matter for remove) */ /* unassign found ldn (pun,lun does not matter for remove) */
immediate_assign(shpnt,0,0,next_ldn,REMOVE_LDN); immediate_assign(shpnt,0,0,next_ldn,REMOVE_LDN);
/* assign found ldn to aimed pun,lun */ /* assign found ldn to aimed pun,lun */
immediate_assign(shpnt,cmd->target,cmd->lun,next_ldn,SET_LDN); immediate_assign(shpnt,target,cmd->lun,next_ldn,SET_LDN);
/* map found ldn to pun,lun */ /* map found ldn to pun,lun */
get_ldn[cmd->target][cmd->lun] = next_ldn; get_ldn[target][cmd->lun] = next_ldn;
/* change ldn to the right value, that is now next_ldn */ /* change ldn to the right value, that is now next_ldn */
ldn = next_ldn; ldn = next_ldn;
/* set reduced interrupt_handler-mode for checking */ /* set reduced interrupt_handler-mode for checking */
...@@ -1668,19 +1767,19 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1668,19 +1767,19 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
/* panic here, because a device, found at boottime has /* panic here, because a device, found at boottime has
vanished */ vanished */
panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n",
ldn, cmd->target, cmd->lun); ldn, target, cmd->lun);
/* set back to normal interrupt_handling */ /* set back to normal interrupt_handling */
local_checking_phase_flag = 0; local_checking_phase_flag = 0;
/* Information on syslog terminal */ /* Information on syslog terminal */
printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n",
ldn, cmd->target, cmd->lun); ldn, target, cmd->lun);
/* increase next_ldn for next dynamical assignment */ /* increase next_ldn for next dynamical assignment */
next_ldn ++; next_ldn ++;
if (next_ldn>=MAX_LOG_DEV) next_ldn = 7; if (next_ldn>=MAX_LOG_DEV) next_ldn = 7;
} }
else else
{ /* wall against Linux accesses to the subsystem adapter */ { /* wall against Linux accesses to the subsystem adapter */
cmd->result = DID_NO_CONNECT << 16; cmd->result = DID_NO_CONNECT << 16;
...@@ -1729,7 +1828,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1729,7 +1828,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn); printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn);
#endif #endif
/* for specific device debugging: */ /* for specific device-type debugging: */
#ifdef IM_DEBUG_CMD_SPEC_DEV #ifdef IM_DEBUG_CMD_SPEC_DEV
if (ld[ldn].device_type==IM_DEBUG_CMD_DEVICE) if (ld[ldn].device_type==IM_DEBUG_CMD_DEVICE)
printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n",
...@@ -1794,7 +1893,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1794,7 +1893,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
} }
scb->u2.blk.length = ld[ldn].block_length; scb->u2.blk.length = ld[ldn].block_length;
if (++disk_rw_in_progress == 1) if (++disk_rw_in_progress == 1)
PS2_DISK_LED_ON (shpnt->host_no, cmd->target); PS2_DISK_LED_ON (shpnt->host_no, target);
break; break;
/* for other devices, enter here. Other types are not known by /* for other devices, enter here. Other types are not known by
...@@ -1830,11 +1929,12 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1830,11 +1929,12 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
/* Read/write on this non-disk devices is also displayworthy, /* Read/write on this non-disk devices is also displayworthy,
so flash-up the LED/display. */ so flash-up the LED/display. */
if (++disk_rw_in_progress == 1) if (++disk_rw_in_progress == 1)
PS2_DISK_LED_ON (shpnt->host_no, cmd->target); PS2_DISK_LED_ON (shpnt->host_no, target);
break; break;
} }
break; break;
case INQUIRY: case INQUIRY:
IBM_DS.ldn_inquiry_access[ldn]++;
scb->command = IM_DEVICE_INQUIRY_CMD; scb->command = IM_DEVICE_INQUIRY_CMD;
scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
break; break;
...@@ -1856,6 +1956,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) ...@@ -1856,6 +1956,7 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
/* Commands that need write-only-mode (system -> device): */ /* Commands that need write-only-mode (system -> device): */
case MODE_SELECT: case MODE_SELECT:
case MODE_SELECT_10: case MODE_SELECT_10:
IBM_DS.ldn_modeselect_access[ldn]++;
scb->command = IM_OTHER_SCSI_CMD_CMD; scb->command = IM_OTHER_SCSI_CMD_CMD;
scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /*Select needs WRITE-enabled*/ scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /*Select needs WRITE-enabled*/
scb->u1.scsi_cmd_length = cmd->cmd_len; scb->u1.scsi_cmd_length = cmd->cmd_len;
...@@ -1892,10 +1993,16 @@ ibmmca_abort (Scsi_Cmnd * cmd) ...@@ -1892,10 +1993,16 @@ ibmmca_abort (Scsi_Cmnd * cmd)
unsigned int ldn; unsigned int ldn;
void (*saved_done) (Scsi_Cmnd *); void (*saved_done) (Scsi_Cmnd *);
#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
int target = 6 - cmd->target;
#else
int target = cmd->target;
#endif
/*get logical device number, and disable system interrupts */ /*get logical device number, and disable system interrupts */
printk ("IBM MCA SCSI: sending abort to device id=%d lun=%d.\n", printk ("IBM MCA SCSI: sending abort to device id=%d lun=%d.\n",
cmd->target, cmd->lun); target, cmd->lun);
ldn = get_ldn[cmd->target][cmd->lun]; ldn = get_ldn[target][cmd->lun];
cli (); cli ();
/*if cmd for this ldn has already finished, no need to abort */ /*if cmd for this ldn has already finished, no need to abort */
...@@ -2027,12 +2134,32 @@ static int ldn_access_total_read_write(struct Scsi_Host *shpnt) ...@@ -2027,12 +2134,32 @@ static int ldn_access_total_read_write(struct Scsi_Host *shpnt)
return(a); return(a);
} }
static int ldn_access_total_inquiry(struct Scsi_Host *shpnt)
{
int a = 0;
int i;
for (i=0; i<=MAX_LOG_DEV; i++)
a+=IBM_DS.ldn_inquiry_access[i];
return(a);
}
static int ldn_access_total_modeselect(struct Scsi_Host *shpnt)
{
int a = 0;
int i;
for (i=0; i<=MAX_LOG_DEV; i++)
a+=IBM_DS.ldn_modeselect_access[i];
return(a);
}
/* routine to display info in the proc-fs-structure (a deluxe feature) */ /* routine to display info in the proc-fs-structure (a deluxe feature) */
int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length, int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
int hostno, int inout) int hostno, int inout)
{ {
int len=0; int len=0;
int i,id; int i,id,lun;
struct Scsi_Host *shpnt; struct Scsi_Host *shpnt;
for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++); for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++);
...@@ -2047,6 +2174,11 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length, ...@@ -2047,6 +2174,11 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
len += sprintf(buffer+len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", len += sprintf(buffer+len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n",
IBMMCA_SCSI_DRIVER_VERSION); IBMMCA_SCSI_DRIVER_VERSION);
len += sprintf(buffer+len, " SCSI Access-Statistics:\n"); len += sprintf(buffer+len, " SCSI Access-Statistics:\n");
#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
len += sprintf(buffer+len, " ANSI-SCSI-standard order.: Yes\n");
#else
len += sprintf(buffer+len, " ANSI-SCSI-standard order.: No\n");
#endif
#ifdef CONFIG_SCSI_MULTI_LUN #ifdef CONFIG_SCSI_MULTI_LUN
len += sprintf(buffer+len, " Multiple LUN probing.....: Yes\n"); len += sprintf(buffer+len, " Multiple LUN probing.....: Yes\n");
#else #else
...@@ -2064,8 +2196,14 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length, ...@@ -2064,8 +2196,14 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
IBM_DS.total_accesses); IBM_DS.total_accesses);
len += sprintf(buffer+len, " Total SCSI READ/WRITE..: %d\n", len += sprintf(buffer+len, " Total SCSI READ/WRITE..: %d\n",
ldn_access_total_read_write(shpnt)); ldn_access_total_read_write(shpnt));
len += sprintf(buffer+len, " Total SCSI Inquiries...: %d\n",
ldn_access_total_inquiry(shpnt));
len += sprintf(buffer+len, " Total SCSI Modeselects.: %d\n",
ldn_access_total_modeselect(shpnt));
len += sprintf(buffer+len, " Total SCSI other cmds..: %d\n\n", len += sprintf(buffer+len, " Total SCSI other cmds..: %d\n\n",
IBM_DS.total_accesses - ldn_access_total_read_write(shpnt)); IBM_DS.total_accesses - ldn_access_total_read_write(shpnt)
- ldn_access_total_modeselect(shpnt)
- ldn_access_total_inquiry(shpnt));
len += sprintf(buffer+len, " Logical-Device-Number (LDN) Access-Statistics:\n"); len += sprintf(buffer+len, " Logical-Device-Number (LDN) Access-Statistics:\n");
len += sprintf(buffer+len, " LDN | Accesses [%%] | READ | WRITE | ASSIGNMENTS\n"); len += sprintf(buffer+len, " LDN | Accesses [%%] | READ | WRITE | ASSIGNMENTS\n");
...@@ -2096,11 +2234,11 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length, ...@@ -2096,11 +2234,11 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
ti_p(get_scsi[id][2]), ti_p(get_scsi[id][3]), ti_p(get_scsi[id][2]), ti_p(get_scsi[id][3]),
ti_p(get_scsi[id][4]), ti_p(get_scsi[id][5]), ti_p(get_scsi[id][4]), ti_p(get_scsi[id][5]),
ti_p(get_scsi[id][6]), ti_p(get_scsi[id][7])); ti_p(get_scsi[id][6]), ti_p(get_scsi[id][7]));
len += sprintf(buffer+len, " %2d %2s %2s %2s %2s %2s %2s %2s %2s\n",
id, ti_l(get_ldn[id][0]), ti_l(get_ldn[id][1]), len += sprintf(buffer+len, " %2d ",id);
ti_l(get_ldn[id][2]), ti_l(get_ldn[id][3]), for (lun=0; lun<8; lun++)
ti_l(get_ldn[id][4]), ti_l(get_ldn[id][5]), len += sprintf(buffer+len,"%2s ",ti_l(get_ldn[id][lun]));
ti_l(get_ldn[id][6]), ti_l(get_ldn[id][7])); len += sprintf(buffer+len,"\n");
} }
len += sprintf(buffer+len, "(A = IBM-Subsystem, D = Harddisk, T = Tapedrive, P = Processor, W = WORM,\n"); len += sprintf(buffer+len, "(A = IBM-Subsystem, D = Harddisk, T = Tapedrive, P = Processor, W = WORM,\n");
...@@ -2125,3 +2263,6 @@ Scsi_Host_Template driver_template = IBMMCA; ...@@ -2125,3 +2263,6 @@ Scsi_Host_Template driver_template = IBMMCA;
#endif #endif
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
...@@ -19,22 +19,30 @@ int ibmmca_biosparam (Disk *, kdev_t, int *); ...@@ -19,22 +19,30 @@ int ibmmca_biosparam (Disk *, kdev_t, int *);
extern struct proc_dir_entry proc_scsi_ibmmca; extern struct proc_dir_entry proc_scsi_ibmmca;
/*initialization for Scsi_host_template type */ /*initialization for Scsi_host_template type */
#define IBMMCA { \ #define IBMMCA { \
proc_dir: &proc_scsi_ibmmca, /*proc_dir*/ \ NULL, /*next*/ \
proc_info: ibmmca_proc_info, /*proc info fn*/ \ NULL, /*usage_count*/ \
name: "IBMMCA", /*name*/ \ &proc_scsi_ibmmca, /*proc_dir*/ \
detect: ibmmca_detect, /*detect fn*/ \ ibmmca_proc_info, /*proc info fn*/ \
release: ibmmca_release, /*release fn*/ \ "IBMMCA", /*name*/ \
command: ibmmca_command, /*command fn*/ \ ibmmca_detect, /*detect fn*/ \
queuecommand: ibmmca_queuecommand, /*queuecommand fn*/ \ ibmmca_release, /*release fn*/ \
abort: ibmmca_abort, /*abort fn*/ \ NULL, /*info fn*/ \
reset: ibmmca_reset, /*reset fn*/ \ ibmmca_command, /*command fn*/ \
bios_param: ibmmca_biosparam, /*bios fn*/ \ ibmmca_queuecommand, /*queuecommand fn*/ \
can_queue: 16, /*can_queue*/ \ ibmmca_abort, /*abort fn*/ \
this_id: 7, /*set by detect*/ \ ibmmca_reset, /*reset fn*/ \
sg_tablesize: 16, /*sg_tablesize*/ \ NULL, /*slave_attach fn*/ \
cmd_per_lun: 1, /*cmd_per_lun*/ \ ibmmca_biosparam, /*bios fn*/ \
use_clustering: ENABLE_CLUSTERING /*use_clustering*/ \ 16, /*can_queue*/ \
7, /*set by detect*/ \
16, /*sg_tablesize*/ \
1, /*cmd_per_lun*/ \
0, /*present*/ \
0, /*unchecked_isa_dma*/ \
ENABLE_CLUSTERING /*use_clustering*/ \
} }
#endif /* _IBMMCA_H */ #endif /* _IBMMCA_H */
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* *
* linux/fs/autofs/dirhash.c * linux/fs/autofs/dirhash.c
* *
* Copyright 1997 Transmeta Corporation -- All Rights Reserved * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
* *
* This file is part of the Linux kernel and is made available under * This file is part of the Linux kernel and is made available under
* the terms of the GNU General Public License, version 2, or at your * the terms of the GNU General Public License, version 2, or at your
...@@ -84,11 +84,15 @@ void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent) ...@@ -84,11 +84,15 @@ void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent)
ent->next = *dhnp; ent->next = *dhnp;
ent->back = dhnp; ent->back = dhnp;
*dhnp = ent; *dhnp = ent;
if ( ent->next )
ent->next->back = &(ent->next);
} }
void autofs_hash_delete(struct autofs_dir_ent *ent) void autofs_hash_delete(struct autofs_dir_ent *ent)
{ {
*(ent->back) = ent->next; *(ent->back) = ent->next;
if ( ent->next )
ent->next->back = ent->back;
autofs_delete_usage(ent); autofs_delete_usage(ent);
......
...@@ -757,6 +757,30 @@ char * d_path(struct dentry *dentry, char *buffer, int buflen) ...@@ -757,6 +757,30 @@ char * d_path(struct dentry *dentry, char *buffer, int buflen)
return retval; return retval;
} }
/*
* Test whether new_dentry is a subdirectory of old_dentry.
*
* Trivially implemented using the dcache structure
*/
int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry)
{
int result;
result = 0;
for (;;) {
if (new_dentry != old_dentry) {
struct dentry * parent = new_dentry->d_parent;
if (parent == new_dentry)
break;
new_dentry = parent;
continue;
}
result = 1;
break;
}
return result;
}
/* /*
* Check whether a dentry already exists for the given name, * Check whether a dentry already exists for the given name,
* and return the inode number if it has an inode. * and return the inode number if it has an inode.
......
...@@ -621,13 +621,6 @@ static struct proc_dir_entry proc_root_slab = { ...@@ -621,13 +621,6 @@ static struct proc_dir_entry proc_root_slab = {
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations 0, &proc_array_inode_operations
}; };
#ifdef CONFIG_OMIRR
static struct proc_dir_entry proc_root_omirr = {
PROC_OMIRR, 5, "omirr",
S_IFREG | S_IRUSR, 1, 0, 0,
0, &proc_omirr_inode_operations
};
#endif
#ifdef __powerpc__ #ifdef __powerpc__
static struct proc_dir_entry proc_root_ppc_htab = { static struct proc_dir_entry proc_root_ppc_htab = {
PROC_PPC_HTAB, 8, "ppc_htab", PROC_PPC_HTAB, 8, "ppc_htab",
......
...@@ -7,3 +7,10 @@ Fri Jan 23 1998 Krzysztof G. Baranowski <kgb@manjak.knm.org.pl> ...@@ -7,3 +7,10 @@ Fri Jan 23 1998 Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
in detected_[xenix,sysv4,sysv2,coherent]. Thanks in detected_[xenix,sysv4,sysv2,coherent]. Thanks
to Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl> to Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
for identifying the problem. for identifying the problem.
Tue Jan 27 1998 Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
* inode.c: added 2048-byte block support to SystemV FS.
Merged detected_bs[512,1024,2048] into one function:
void detected_bs (u_char type, struct super_block *sb).
Thanks to Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
for the patch.
...@@ -18,7 +18,7 @@ These filesystems are rather similar. Here is a comparison with Minix FS: ...@@ -18,7 +18,7 @@ These filesystems are rather similar. Here is a comparison with Minix FS:
* Size of a block or zone (data allocation unit on disk) * Size of a block or zone (data allocation unit on disk)
- Minix FS 1024 - Minix FS 1024
- Xenix FS 1024 (also 512 ??) - Xenix FS 1024 (also 512 ??)
- SystemV FS 1024 (also 512) - SystemV FS 1024 (also 512 and 2048)
- Coherent FS 512 - Coherent FS 512
* General layout: all have one boot block, one super block and * General layout: all have one boot block, one super block and
...@@ -180,4 +180,3 @@ and not the disk driver's notion of "block". ...@@ -180,4 +180,3 @@ and not the disk driver's notion of "block".
Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de> Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de>
...@@ -34,6 +34,27 @@ ...@@ -34,6 +34,27 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#if 0
void sysv_print_inode(struct inode * inode)
{
printk("ino %lu mode 0%6.6o lk %d uid %d gid %d"
" sz %lu blks %lu cnt %u\n",
inode->i_ino, inode->i_mode, inode->i_nlink, inode->i_uid,
inode->i_gid, inode->i_size, inode->i_blocks, inode->i_count);
printk(" db <0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx"
" 0x%lx 0x%lx>\n",
inode->u.sysv_i.i_data[0], inode->u.sysv_i.i_data[1],
inode->u.sysv_i.i_data[2], inode->u.sysv_i.i_data[3],
inode->u.sysv_i.i_data[4], inode->u.sysv_i.i_data[5],
inode->u.sysv_i.i_data[6], inode->u.sysv_i.i_data[7],
inode->u.sysv_i.i_data[8], inode->u.sysv_i.i_data[9]);
printk(" ib <0x%lx 0x%lx 0x%lx>\n",
inode->u.sysv_i.i_data[10],
inode->u.sysv_i.i_data[11],
inode->u.sysv_i.i_data[12]);
}
#endif
void sysv_put_inode(struct inode *inode) void sysv_put_inode(struct inode *inode)
{ {
if (inode->i_nlink) if (inode->i_nlink)
...@@ -65,58 +86,35 @@ static struct super_operations sysv_sops = { ...@@ -65,58 +86,35 @@ static struct super_operations sysv_sops = {
* the time stamp is not < 01-01-1980. * the time stamp is not < 01-01-1980.
*/ */
static void detected_bs512 (struct super_block *sb) static void detected_bs (u_char type, struct super_block *sb)
{ {
sb->sv_block_size = 512; u_char n_bits = type+8;
sb->sv_block_size_1 = 512-1; int bsize = 1 << n_bits;
sb->sv_block_size_bits = 9; int bsize_4 = bsize >> 2;
sb->sv_block_size_ratio = 2;
sb->sv_block_size_ratio_bits = 1; sb->sv_block_size = bsize;
sb->sv_inodes_per_block = 512/64; sb->sv_block_size_1 = bsize-1;
sb->sv_inodes_per_block_1 = 512/64-1; sb->sv_block_size_bits = n_bits;
sb->sv_inodes_per_block_bits = 9-6; sb->sv_block_size_dec_bits = (bsize==512) ? 1 : 0;
sb->sv_toobig_block = 10 + sb->sv_block_size_inc_bits = (bsize==2048) ? 1 : 0;
(sb->sv_ind_per_block = 512/4) + sb->sv_inodes_per_block = bsize >> 6;
(sb->sv_ind_per_block_2 = (512/4)*(512/4)) + sb->sv_inodes_per_block_1 = (bsize >> 6)-1;
(sb->sv_ind_per_block_3 = (512/4)*(512/4)*(512/4)); sb->sv_inodes_per_block_bits = n_bits-6;
sb->sv_ind_per_block_1 = 512/4-1;
sb->sv_ind_per_block_2_1 = (512/4)*(512/4)-1;
sb->sv_ind_per_block_2_bits = 2 *
(sb->sv_ind_per_block_bits = 9-2);
sb->sv_ind_per_block_block_size_1 = (512/4)*512-1;
sb->sv_ind_per_block_block_size_bits = (9-2)+9;
sb->sv_ind_per_block_2_block_size_1 = (512/4)*(512/4)*512-1;
sb->sv_ind_per_block_2_block_size_bits = (9-2)+(9-2)+9;
sb->sv_ind0_size = 10 * 512;
sb->sv_ind1_size = (10 + (512/4))* 512;
sb->sv_ind2_size = (10 + (512/4) + (512/4)*(512/4)) * 512;
}
static void detected_bs1024 (struct super_block *sb)
{
sb->sv_block_size = 1024;
sb->sv_block_size_1 = 1024-1;
sb->sv_block_size_bits = 10;
sb->sv_block_size_ratio = 1;
sb->sv_block_size_ratio_bits = 0;
sb->sv_inodes_per_block = 1024/64;
sb->sv_inodes_per_block_1 = 1024/64-1;
sb->sv_inodes_per_block_bits = 10-6;
sb->sv_toobig_block = 10 + sb->sv_toobig_block = 10 +
(sb->sv_ind_per_block = 1024/4) + (sb->sv_ind_per_block = bsize_4) +
(sb->sv_ind_per_block_2 = (1024/4)*(1024/4)) + (sb->sv_ind_per_block_2 = bsize_4*bsize_4) +
(sb->sv_ind_per_block_3 = (1024/4)*(1024/4)*(1024/4)); (sb->sv_ind_per_block_3 = bsize_4*bsize_4*bsize_4);
sb->sv_ind_per_block_1 = 1024/4-1; sb->sv_ind_per_block_1 = bsize_4-1;
sb->sv_ind_per_block_2_1 = (1024/4)*(1024/4)-1; sb->sv_ind_per_block_2_1 = bsize_4*bsize_4-1;
sb->sv_ind_per_block_2_bits = 2 * sb->sv_ind_per_block_2_bits = 2 *
(sb->sv_ind_per_block_bits = 10-2); (sb->sv_ind_per_block_bits = n_bits-2);
sb->sv_ind_per_block_block_size_1 = (1024/4)*1024-1; sb->sv_ind_per_block_block_size_1 = bsize_4*bsize-1;
sb->sv_ind_per_block_block_size_bits = (10-2)+10; sb->sv_ind_per_block_block_size_bits = 2*n_bits-2;
sb->sv_ind_per_block_2_block_size_1 = (1024/4)*(1024/4)*1024-1; sb->sv_ind_per_block_2_block_size_1 = bsize_4*bsize_4*bsize-1;
sb->sv_ind_per_block_2_block_size_bits = (10-2)+(10-2)+10; sb->sv_ind_per_block_2_block_size_bits = 3*n_bits-4;
sb->sv_ind0_size = 10 * 1024; sb->sv_ind0_size = 10 * bsize;
sb->sv_ind1_size = (10 + (1024/4))* 1024; sb->sv_ind1_size = (10 + bsize_4)* bsize;
sb->sv_ind2_size = (10 + (1024/4) + (1024/4)*(1024/4)) * 1024; sb->sv_ind2_size = (10 + bsize_4 + bsize_4*bsize_4) * bsize;
} }
static const char* detect_xenix (struct super_block *sb, struct buffer_head *bh) static const char* detect_xenix (struct super_block *sb, struct buffer_head *bh)
...@@ -126,11 +124,9 @@ static const char* detect_xenix (struct super_block *sb, struct buffer_head *bh) ...@@ -126,11 +124,9 @@ static const char* detect_xenix (struct super_block *sb, struct buffer_head *bh)
sbd = (struct xenix_super_block *) bh->b_data; sbd = (struct xenix_super_block *) bh->b_data;
if (sbd->s_magic != 0x2b5544) if (sbd->s_magic != 0x2b5544)
return NULL; return NULL;
switch (sbd->s_type) { if (sbd->s_type > 2 || sbd->s_type < 1)
case 1: detected_bs512(sb); break; return NULL;
case 2: detected_bs1024(sb); break; detected_bs(sbd->s_type, sb);
default: return NULL;
}
sb->sv_type = FSTYPE_XENIX; sb->sv_type = FSTYPE_XENIX;
return "Xenix"; return "Xenix";
} }
...@@ -139,8 +135,8 @@ static struct super_block * detected_xenix (struct super_block *sb, struct buffe ...@@ -139,8 +135,8 @@ static struct super_block * detected_xenix (struct super_block *sb, struct buffe
struct xenix_super_block * sbd1; struct xenix_super_block * sbd1;
struct xenix_super_block * sbd2; struct xenix_super_block * sbd2;
if (sb->sv_block_size == BLOCK_SIZE) if (sb->sv_block_size >= BLOCK_SIZE)
/* block size = 1024, so bh1 = bh2 */ /* block size >= 1024, so bh1 = bh2 */
sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data; sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data;
else { else {
/* block size = 512, so bh1 != bh2 */ /* block size = 512, so bh1 != bh2 */
...@@ -184,11 +180,9 @@ static const char* detect_sysv4 (struct super_block *sb, struct buffer_head *bh) ...@@ -184,11 +180,9 @@ static const char* detect_sysv4 (struct super_block *sb, struct buffer_head *bh)
return NULL; return NULL;
if (sbd->s_time < 315532800) /* this is likely to happen on SystemV2 FS */ if (sbd->s_time < 315532800) /* this is likely to happen on SystemV2 FS */
return NULL; return NULL;
switch (sbd->s_type) { if (sbd->s_type > 3 || sbd->s_type < 1)
case 1: detected_bs512(sb); break; return NULL;
case 2: detected_bs1024(sb); break; detected_bs(sbd->s_type, sb);
default: return NULL;
}
sb->sv_type = FSTYPE_SYSV4; sb->sv_type = FSTYPE_SYSV4;
return "SystemV"; return "SystemV";
} }
...@@ -196,7 +190,7 @@ static struct super_block * detected_sysv4 (struct super_block *sb, struct buffe ...@@ -196,7 +190,7 @@ static struct super_block * detected_sysv4 (struct super_block *sb, struct buffe
{ {
struct sysv4_super_block * sbd; struct sysv4_super_block * sbd;
if (sb->sv_block_size == BLOCK_SIZE) if (sb->sv_block_size >= BLOCK_SIZE)
sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2); sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2);
else { else {
sbd = (struct sysv4_super_block *) bh->b_data; sbd = (struct sysv4_super_block *) bh->b_data;
...@@ -241,11 +235,9 @@ static const char* detect_sysv2 (struct super_block *sb, struct buffer_head *bh) ...@@ -241,11 +235,9 @@ static const char* detect_sysv2 (struct super_block *sb, struct buffer_head *bh)
return NULL; return NULL;
if (sbd->s_time < 315532800) /* this is likely to happen on SystemV4 FS */ if (sbd->s_time < 315532800) /* this is likely to happen on SystemV4 FS */
return NULL; return NULL;
switch (sbd->s_type) { if (sbd->s_type > 3 || sbd->s_type < 1)
case 1: detected_bs512(sb); break; return NULL;
case 2: detected_bs1024(sb); break; detected_bs(sbd->s_type, sb);
default: return NULL;
}
sb->sv_type = FSTYPE_SYSV2; sb->sv_type = FSTYPE_SYSV2;
return "SystemV Release 2"; return "SystemV Release 2";
} }
...@@ -253,7 +245,7 @@ static struct super_block * detected_sysv2 (struct super_block *sb, struct buffe ...@@ -253,7 +245,7 @@ static struct super_block * detected_sysv2 (struct super_block *sb, struct buffe
{ {
struct sysv2_super_block * sbd; struct sysv2_super_block * sbd;
if (sb->sv_block_size == BLOCK_SIZE) if (sb->sv_block_size >= BLOCK_SIZE)
sbd = (struct sysv2_super_block *) (bh->b_data + BLOCK_SIZE/2); sbd = (struct sysv2_super_block *) (bh->b_data + BLOCK_SIZE/2);
else { else {
sbd = (struct sysv2_super_block *) bh->b_data; sbd = (struct sysv2_super_block *) bh->b_data;
...@@ -297,7 +289,7 @@ static const char* detect_coherent (struct super_block *sb, struct buffer_head * ...@@ -297,7 +289,7 @@ static const char* detect_coherent (struct super_block *sb, struct buffer_head *
if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6)) if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6))
|| (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6))) || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6)))
return NULL; return NULL;
detected_bs512(sb); detected_bs(1, sb);
sb->sv_type = FSTYPE_COH; sb->sv_type = FSTYPE_COH;
return "Coherent"; return "Coherent";
} }
...@@ -342,7 +334,8 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, ...@@ -342,7 +334,8 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
const char *found; const char *found;
kdev_t dev = sb->s_dev; kdev_t dev = sb->s_dev;
struct inode *root_inode; struct inode *root_inode;
unsigned long blocknr;
if (1024 != sizeof (struct xenix_super_block)) if (1024 != sizeof (struct xenix_super_block))
panic("Xenix FS: bad super-block size"); panic("Xenix FS: bad super-block size");
if ((512 != sizeof (struct sysv4_super_block)) if ((512 != sizeof (struct sysv4_super_block))
...@@ -376,22 +369,29 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, ...@@ -376,22 +369,29 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
} }
/* Try to recognize SystemV superblock */ /* Try to recognize SystemV superblock */
/* Offset by 1 track, i.e. most probably 9, 15, or 18 kilobytes. */ /* Offset by 1 track, i.e. most probably 9, 15, or 18 kilobytes. */
/* 2kB blocks with offset of 9 and 15 kilobytes are not supported. */
/* Maybe we should also check the device geometry ? */
{ static int offsets[] = { 9, 15, 18, }; { static int offsets[] = { 9, 15, 18, };
int i; int i;
for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++) for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++)
if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) { if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) {
/* Try to recognize SystemV superblock */ /* Try to recognize SystemV superblock */
if ((found = detect_sysv4(sb,bh)) != NULL) { if ((found = detect_sysv4(sb,bh)) != NULL) {
sb->sv_block_base = offsets[i] << sb->sv_block_size_ratio_bits; if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2))
goto bad_shift;
sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
goto ok; goto ok;
} }
if ((found = detect_sysv2(sb,bh)) != NULL) { if ((found = detect_sysv2(sb,bh)) != NULL) {
sb->sv_block_base = offsets[i] << sb->sv_block_size_ratio_bits; if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2))
goto bad_shift;
sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
goto ok; goto ok;
} }
brelse(bh); brelse(bh);
} }
} }
bad_shift:
sb->s_dev = 0; sb->s_dev = 0;
unlock_super(sb); unlock_super(sb);
if (!silent) if (!silent)
...@@ -402,7 +402,14 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, ...@@ -402,7 +402,14 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
return NULL; return NULL;
ok: ok:
if (sb->sv_block_size == BLOCK_SIZE) { if (sb->sv_block_size >= BLOCK_SIZE) {
if (sb->sv_block_size != BLOCK_SIZE) {
brelse(bh);
set_blocksize(dev, sb->sv_block_size);
blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
if ((bh = bread(dev, blocknr, sb->sv_block_size)) == NULL)
goto bad_superblock;
}
switch (sb->sv_type) { switch (sb->sv_type) {
case FSTYPE_XENIX: case FSTYPE_XENIX:
if (!detected_xenix(sb,bh,bh)) if (!detected_xenix(sb,bh,bh))
...@@ -416,19 +423,21 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data, ...@@ -416,19 +423,21 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
if (!detected_sysv2(sb,bh)) if (!detected_sysv2(sb,bh))
goto bad_superblock; goto bad_superblock;
break; break;
default: default: goto bad_superblock;
bad_superblock: goto superblock_ok;
brelse(bh); bad_superblock:
sb->s_dev = 0; brelse(bh);
unlock_super(sb); sb->s_dev = 0;
printk("SysV FS: cannot read superblock in 1024 byte mode\n"); unlock_super(sb);
goto failed; printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size);
goto failed;
superblock_ok:
} }
} else { } else {
/* Switch to another block size. Unfortunately, we have to /* Switch to 512 block size. Unfortunately, we have to
release the 1 KB block bh and read it in two parts again. */ release the block bh and read it again. */
struct buffer_head *bh1, *bh2; struct buffer_head *bh1, *bh2;
unsigned long blocknr = bh->b_blocknr << sb->sv_block_size_ratio_bits; unsigned long blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits;
brelse(bh); brelse(bh);
set_blocksize(dev,sb->sv_block_size); set_blocksize(dev,sb->sv_block_size);
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
* *
* sysv/namei.c * sysv/namei.c
* Copyright (C) 1993 Bruno Haible * Copyright (C) 1993 Bruno Haible
*
*/ */
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include <linux/tasks.h> #include <linux/tasks.h>
extern unsigned int local_irq_count[NR_CPUS]; extern unsigned int local_irq_count[NR_CPUS];
#define in_interrupt() (local_irq_count[smp_processor_id()] != 0)
#ifndef __SMP__ #ifndef __SMP__
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* is entirely private to an implementation, it should not be * is entirely private to an implementation, it should not be
* referenced at all outside of this file. * referenced at all outside of this file.
*/ */
extern atomic_t __alpha_bh_counter; extern unsigned int local_bh_count[NR_CPUS];
#define get_active_bhs() (bh_mask & bh_active) #define get_active_bhs() (bh_mask & bh_active)
...@@ -42,52 +42,50 @@ extern inline void mark_bh(int nr) ...@@ -42,52 +42,50 @@ extern inline void mark_bh(int nr)
set_bit(nr, &bh_active); set_bit(nr, &bh_active);
} }
/*
* These use a mask count to correctly handle
* nested disable/enable calls
*/
extern inline void disable_bh(int nr)
{
bh_mask &= ~(1 << nr);
bh_mask_count[nr]++;
}
extern inline void enable_bh(int nr)
{
if (!--bh_mask_count[nr])
bh_mask |= 1 << nr;
}
/* /*
* start_bh_atomic/end_bh_atomic also nest * start_bh_atomic/end_bh_atomic also nest
* naturally by using a counter * naturally by using a counter
*/ */
extern inline void start_bh_atomic(void) extern inline void start_bh_atomic(void)
{ {
#ifdef __SMP__ local_bh_count[smp_processor_id()]++;
atomic_inc(&__alpha_bh_counter); barrier();
synchronize_irq();
#else
atomic_inc(&__alpha_bh_counter);
#endif
} }
extern inline void end_bh_atomic(void) extern inline void end_bh_atomic(void)
{ {
atomic_dec(&__alpha_bh_counter); barrier();
local_bh_count[smp_processor_id()]--;
} }
#ifndef __SMP__ #ifndef __SMP__
/* These are for the irq's testing the lock */ /* These are for the irq's testing the lock */
#define softirq_trylock(cpu) (atomic_read(&__alpha_bh_counter) ? \ #define softirq_trylock(cpu) \
0 : \ (local_bh_count[cpu] ? 0 : (local_bh_count[cpu] = 1))
((atomic_set(&__alpha_bh_counter,1)),1)) #define softirq_endlock(cpu) \
#define softirq_endlock(cpu) (atomic_set(&__alpha_bh_counter, 0)) (local_bh_count[cpu] = 0)
#else #else
#error FIXME #error FIXME
#endif /* __SMP__ */ #endif /* __SMP__ */
/*
* These use a mask count to correctly handle
* nested disable/enable calls
*/
extern inline void disable_bh(int nr)
{
bh_mask &= ~(1 << nr);
bh_mask_count[nr]++;
}
extern inline void enable_bh(int nr)
{
if (!--bh_mask_count[nr])
bh_mask |= 1 << nr;
}
#endif /* _ALPHA_SOFTIRQ_H */ #endif /* _ALPHA_SOFTIRQ_H */
...@@ -728,6 +728,9 @@ extern void put_write_access(struct inode *inode); ...@@ -728,6 +728,9 @@ extern void put_write_access(struct inode *inode);
extern struct dentry * open_namei(const char * pathname, int flag, int mode); extern struct dentry * open_namei(const char * pathname, int flag, int mode);
extern struct dentry * do_mknod(const char * filename, int mode, dev_t dev); extern struct dentry * do_mknod(const char * filename, int mode, dev_t dev);
extern int do_pipe(int *); extern int do_pipe(int *);
/* fs/dcache.c -- generic fs support functions */
extern int is_subdir(struct dentry *, struct dentry *);
extern ino_t find_inode_number(struct dentry *, struct qstr *); extern ino_t find_inode_number(struct dentry *, struct qstr *);
/* /*
......
...@@ -48,7 +48,6 @@ enum root_directory_inos { ...@@ -48,7 +48,6 @@ enum root_directory_inos {
PROC_HARDWARE, PROC_HARDWARE,
PROC_SLABINFO, PROC_SLABINFO,
PROC_PARPORT, PROC_PARPORT,
PROC_OMIRR, /* whether enabled or not */
PROC_PPC_HTAB, PROC_PPC_HTAB,
PROC_SOUND PROC_SOUND
}; };
......
...@@ -15,8 +15,8 @@ struct sysv_sb_info { ...@@ -15,8 +15,8 @@ struct sysv_sb_info {
unsigned int s_block_size; /* zone size, = 512 or = 1024 */ unsigned int s_block_size; /* zone size, = 512 or = 1024 */
unsigned int s_block_size_1; /* block_size - 1 */ unsigned int s_block_size_1; /* block_size - 1 */
unsigned int s_block_size_bits; /* log2(block_size) */ unsigned int s_block_size_bits; /* log2(block_size) */
unsigned int s_block_size_ratio; /* BLOCK_SIZE / block_size */ unsigned int s_block_size_inc_bits; /* log2(block_size/BLOCK_SIZE) if >0 */
unsigned int s_block_size_ratio_bits; /* log2(block_size_ratio) */ unsigned int s_block_size_dec_bits; /* log2(BLOCK_SIZE/block_size) if >0 */
char s_convert; /* flag whether byte ordering requires conversion */ char s_convert; /* flag whether byte ordering requires conversion */
char s_kludge_symlinks; /* flag whether symlinks have a kludgey mode */ char s_kludge_symlinks; /* flag whether symlinks have a kludgey mode */
char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */ char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */
...@@ -66,15 +66,15 @@ struct sysv_sb_info { ...@@ -66,15 +66,15 @@ struct sysv_sb_info {
unsigned long s_ndatazones; /* total number of data zones */ unsigned long s_ndatazones; /* total number of data zones */
unsigned long s_nzones; /* same as s_sbd->s_fsize */ unsigned long s_nzones; /* same as s_sbd->s_fsize */
}; };
/* The fields s_block_size_ratio, s_ind_per_block_2_1, s_toobig_block are currently unused. */ /* The fields s_ind_per_block_2_1, s_toobig_block are currently unused. */
/* sv_ == u.sysv_sb.s_ */ /* sv_ == u.sysv_sb.s_ */
#define sv_type u.sysv_sb.s_type #define sv_type u.sysv_sb.s_type
#define sv_block_size u.sysv_sb.s_block_size #define sv_block_size u.sysv_sb.s_block_size
#define sv_block_size_1 u.sysv_sb.s_block_size_1 #define sv_block_size_1 u.sysv_sb.s_block_size_1
#define sv_block_size_bits u.sysv_sb.s_block_size_bits #define sv_block_size_bits u.sysv_sb.s_block_size_bits
#define sv_block_size_ratio u.sysv_sb.s_block_size_ratio #define sv_block_size_inc_bits u.sysv_sb.s_block_size_inc_bits
#define sv_block_size_ratio_bits u.sysv_sb.s_block_size_ratio_bits #define sv_block_size_dec_bits u.sysv_sb.s_block_size_dec_bits
#define sv_convert u.sysv_sb.s_convert #define sv_convert u.sysv_sb.s_convert
#define sv_kludge_symlinks u.sysv_sb.s_kludge_symlinks #define sv_kludge_symlinks u.sysv_sb.s_kludge_symlinks
#define sv_truncate u.sysv_sb.s_truncate #define sv_truncate u.sysv_sb.s_truncate
......
...@@ -2,58 +2,26 @@ ...@@ -2,58 +2,26 @@
#define _LINUX_TIMER_H #define _LINUX_TIMER_H
/* /*
* DON'T CHANGE THESE!! Most of them are hardcoded into some assembly language * Old-style timers. Please don't use for any new code.
* as well as being defined here.
*/
/*
* The timers are:
*
* BLANK_TIMER console screen-saver timer
*
* BEEP_TIMER console beep timer
*
* RS_TIMER timer for the RS-232 ports
*
* SWAP_TIMER timer for the background pageout daemon
*
* HD_TIMER harddisk timer
*
* HD_TIMER2 (atdisk2 patches)
*
* FLOPPY_TIMER floppy disk timer (not used right now)
*
* NET_TIMER tcp/ip timeout timer
*
* COPRO_TIMER 387 timeout for buggy hardware..
*
* QIC02_TAPE_TIMER timer for QIC-02 tape driver (it's not hardcoded)
*
* MCD_TIMER Mitsumi CD-ROM Timer
*
* GSCD_TIMER Goldstar CD-ROM Timer
* *
* Numbering of these timers should be consecutive to minimize
* processing delays. [MJ]
*/ */
#define BLANK_TIMER 0 #define BLANK_TIMER 0 /* Console screen-saver */
#define BEEP_TIMER 1 #define BEEP_TIMER 1 /* Console beep */
#define RS_TIMER 2 #define RS_TIMER 2 /* RS-232 ports */
#define SWAP_TIMER 3 #define SWAP_TIMER 3 /* Background pageout */
#define BACKGR_TIMER 4 /* io_request background I/O */
#define HD_TIMER 16 #define HD_TIMER 5 /* Old IDE driver */
#define FLOPPY_TIMER 17 #define FLOPPY_TIMER 6 /* Floppy */
#define NET_TIMER 19 #define QIC02_TAPE_TIMER 7 /* QIC 02 tape */
#define SOUND_TIMER 20 #define MCD_TIMER 8 /* Mitsumi CDROM */
#define COPRO_TIMER 21 #define GSCD_TIMER 9 /* Goldstar CDROM */
#define COMTROL_TIMER 10 /* Comtrol serial */
#define QIC02_TAPE_TIMER 22 /* hhb */ #define DIGI_TIMER 11 /* Digi serial */
#define MCD_TIMER 23
#define HD_TIMER2 24
#define GSCD_TIMER 25
#define COMTROL_TIMER 26
#define DIGI_TIMER 29 #define COPRO_TIMER 31 /* 387 timeout for buggy hardware (boot only) */
struct timer_struct { struct timer_struct {
unsigned long expires; unsigned long expires;
......
...@@ -282,6 +282,10 @@ extern void ftape_setup(char *str, int *ints); ...@@ -282,6 +282,10 @@ extern void ftape_setup(char *str, int *ints);
extern void ipc_init(void); extern void ipc_init(void);
#endif #endif
#ifdef CONFIG_MD_BOOT
extern void md_setup(char *str,int *ints) __init;
#endif
#ifdef __sparc__ #ifdef __sparc__
extern int serial_console; extern int serial_console;
#endif #endif
...@@ -378,6 +382,9 @@ static struct dev_name_struct { ...@@ -378,6 +382,9 @@ static struct dev_name_struct {
#ifdef CONFIG_BLK_DEV_FD #ifdef CONFIG_BLK_DEV_FD
{ "fd", 0x0200 }, { "fd", 0x0200 },
#endif #endif
#ifdef CONFIG_MD_BOOT
{ "md", 0x0900 },
#endif
#ifdef CONFIG_BLK_DEV_XD #ifdef CONFIG_BLK_DEV_XD
{ "xda", 0x0d00 }, { "xda", 0x0d00 },
{ "xdb", 0x0d40 }, { "xdb", 0x0d40 },
...@@ -419,7 +426,7 @@ static struct dev_name_struct { ...@@ -419,7 +426,7 @@ static struct dev_name_struct {
{ NULL, 0 } { NULL, 0 }
}; };
__initfunc(static void root_dev_setup(char *line, int *num)) __initfunc(dev_t name_to_dev_t(char *line))
{ {
int base = 0; int base = 0;
if (strncmp(line,"/dev/",5) == 0) { if (strncmp(line,"/dev/",5) == 0) {
...@@ -435,7 +442,12 @@ __initfunc(static void root_dev_setup(char *line, int *num)) ...@@ -435,7 +442,12 @@ __initfunc(static void root_dev_setup(char *line, int *num))
dev++; dev++;
} while (dev->name); } while (dev->name);
} }
ROOT_DEV = to_kdev_t(base + simple_strtoul(line,NULL,base?10:16)); return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
}
__initfunc(static void root_dev_setup(char *line, int *num))
{
ROOT_DEV = name_to_dev_t(line);
} }
/* /*
...@@ -713,6 +725,9 @@ static struct kernel_param cooked_params[] __initdata = { ...@@ -713,6 +725,9 @@ static struct kernel_param cooked_params[] __initdata = {
#endif #endif
#ifdef CONFIG_FTAPE #ifdef CONFIG_FTAPE
{ "ftape=", ftape_setup}, { "ftape=", ftape_setup},
#endif
#ifdef CONFIG_MD_BOOT
{ "md=", md_setup},
#endif #endif
{ 0, 0 } { 0, 0 }
}; };
......
...@@ -143,6 +143,7 @@ EXPORT_SYMBOL(update_vm_cache); ...@@ -143,6 +143,7 @@ EXPORT_SYMBOL(update_vm_cache);
EXPORT_SYMBOL(vmtruncate); EXPORT_SYMBOL(vmtruncate);
/* filesystem internal functions */ /* filesystem internal functions */
EXPORT_SYMBOL(update_atime);
EXPORT_SYMBOL(get_super); EXPORT_SYMBOL(get_super);
EXPORT_SYMBOL(getname); EXPORT_SYMBOL(getname);
EXPORT_SYMBOL(putname); EXPORT_SYMBOL(putname);
...@@ -203,6 +204,7 @@ EXPORT_SYMBOL(prune_dcache); ...@@ -203,6 +204,7 @@ EXPORT_SYMBOL(prune_dcache);
EXPORT_SYMBOL(shrink_dcache_sb); EXPORT_SYMBOL(shrink_dcache_sb);
EXPORT_SYMBOL(shrink_dcache_parent); EXPORT_SYMBOL(shrink_dcache_parent);
EXPORT_SYMBOL(find_inode_number); EXPORT_SYMBOL(find_inode_number);
EXPORT_SYMBOL(is_subdir);
#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE) #if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
EXPORT_SYMBOL(do_nfsservctl); EXPORT_SYMBOL(do_nfsservctl);
......
#
# Amateur Radio protocols and AX.25 device configuration
#
# 19971130 Now in an own category to make correct compilation of the
# AX.25 stuff easier...
# Joerg Reuter DL1BKE <jreuter@poboxes.com>
# 19980129 Moved to net/ax25/Config.in, sourcing device drivers.
mainmenu_option next_comment
comment 'Amateur Radio support'
bool 'Amateur Radio support' CONFIG_HAMRADIO
if [ "$CONFIG_HAMRADIO" != "n" ] ; then
if [ "$CONFIG_NET" != "n" ] ; then
comment 'Packet Radio protocols'
tristate 'Amateur Radio AX.25 Level 2 protocol' CONFIG_AX25
if [ "$CONFIG_AX25" != "n" ]; then
bool ' AX.25 DAMA Slave support' CONFIG_AX25_DAMA_SLAVE
# bool ' AX.25 DAMA Master support' CONFIG_AX25_DAMA_MASTER
dep_tristate ' Amateur Radio NET/ROM protocol' CONFIG_NETROM $CONFIG_AX25
dep_tristate ' Amateur Radio X.25 PLP (Rose)' CONFIG_ROSE $CONFIG_AX25
fi
if [ "$CONFIG_AX25" != "n" ]; then
source drivers/net/hamradio/Config.in
fi
fi
source drivers/char/hfmodem/Config.in
fi
endmenu
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
* Thomas Bogendoerfer : Return ENODEV for dev_open, if there * Thomas Bogendoerfer : Return ENODEV for dev_open, if there
* is no device open function. * is no device open function.
* Andi Kleen : Fix error reporting for SIOCGIFCONF * Andi Kleen : Fix error reporting for SIOCGIFCONF
* Rgis Duchesne : Fix the argument check in dev_ioctl()
* *
*/ */
...@@ -1534,7 +1535,6 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd) ...@@ -1534,7 +1535,6 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
return -EINVAL; return -EINVAL;
} }
/* /*
* This function handles all "interface"-type I/O control requests. The actual * This function handles all "interface"-type I/O control requests. The actual
* 'doing' part of this is dev_ifsioc above. * 'doing' part of this is dev_ifsioc above.
...@@ -1566,25 +1566,19 @@ int dev_ioctl(unsigned int cmd, void *arg) ...@@ -1566,25 +1566,19 @@ int dev_ioctl(unsigned int cmd, void *arg)
return dev_ifname((struct ifreq *)arg); return dev_ifname((struct ifreq *)arg);
} }
/*
* Fetch the interface name from the info block.
*/
if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
return -EFAULT; return -EFAULT;
ifr.ifr_name[IFNAMSIZ-1] = 0; ifr.ifr_name[IFNAMSIZ-1] = 0;
#ifdef CONFIG_NET_ALIAS #ifdef CONFIG_NET_ALIAS
colon = strchr(ifr.ifr_name, ':'); colon = strchr(ifr.ifr_name, ':');
if (colon) if (colon)
*colon = 0; *colon = 0;
#endif #endif
/*
* See which interface the caller is talking about.
*/
#ifdef CONFIG_KERNELD
dev_load(ifr.ifr_name);
#endif
switch(cmd) switch(cmd)
{ {
/* /*
...@@ -1602,6 +1596,9 @@ int dev_ioctl(unsigned int cmd, void *arg) ...@@ -1602,6 +1596,9 @@ int dev_ioctl(unsigned int cmd, void *arg)
case SIOCGIFMAP: case SIOCGIFMAP:
case SIOCGIFINDEX: case SIOCGIFINDEX:
case SIOCGIFTXQLEN: case SIOCGIFTXQLEN:
#ifdef CONFIG_KERNELD
dev_load(ifr.ifr_name);
#endif
ret = dev_ifsioc(&ifr, cmd); ret = dev_ifsioc(&ifr, cmd);
if (!ret) { if (!ret) {
#ifdef CONFIG_NET_ALIAS #ifdef CONFIG_NET_ALIAS
...@@ -1632,6 +1629,9 @@ int dev_ioctl(unsigned int cmd, void *arg) ...@@ -1632,6 +1629,9 @@ int dev_ioctl(unsigned int cmd, void *arg)
case SIOCSIFTXQLEN: case SIOCSIFTXQLEN:
if (!suser()) if (!suser())
return -EPERM; return -EPERM;
#ifdef CONFIG_KERNELD
dev_load(ifr.ifr_name);
#endif
rtnl_lock(); rtnl_lock();
ret = dev_ifsioc(&ifr, cmd); ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock(); rtnl_unlock();
...@@ -1652,6 +1652,9 @@ int dev_ioctl(unsigned int cmd, void *arg) ...@@ -1652,6 +1652,9 @@ int dev_ioctl(unsigned int cmd, void *arg)
default: default:
if (cmd >= SIOCDEVPRIVATE && if (cmd >= SIOCDEVPRIVATE &&
cmd <= SIOCDEVPRIVATE + 15) { cmd <= SIOCDEVPRIVATE + 15) {
#ifdef CONFIG_KERNELD
dev_load(ifr.ifr_name);
#endif
rtnl_lock(); rtnl_lock();
ret = dev_ifsioc(&ifr, cmd); ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock(); rtnl_unlock();
...@@ -1664,8 +1667,15 @@ int dev_ioctl(unsigned int cmd, void *arg) ...@@ -1664,8 +1667,15 @@ int dev_ioctl(unsigned int cmd, void *arg)
if (IW_IS_SET(cmd)) { if (IW_IS_SET(cmd)) {
if (!suser()) if (!suser())
return -EPERM; return -EPERM;
#ifdef CONFIG_KERNELD
dev_load(ifr.ifr_name);
#endif
rtnl_lock(); rtnl_lock();
} }
#ifdef CONFIG_KERNELD
else
dev_load(ifr.ifr_name);
#endif
ret = dev_ifsioc(&ifr, cmd); ret = dev_ifsioc(&ifr, cmd);
if (IW_IS_SET(cmd)) if (IW_IS_SET(cmd))
rtnl_unlock(); rtnl_unlock();
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/major.h> #include <linux/major.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/file.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
static __inline__ int scm_check_creds(struct ucred *creds) static __inline__ int scm_check_creds(struct ucred *creds)
{ {
/* N.B. The test for suser should follow the credential check */
if (suser()) if (suser())
return 0; return 0;
if (creds->pid != current->pid || if (creds->pid != current->pid ||
...@@ -58,11 +60,10 @@ static __inline__ int scm_check_creds(struct ucred *creds) ...@@ -58,11 +60,10 @@ static __inline__ int scm_check_creds(struct ucred *creds)
static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
{ {
int num; int *fdp = (int*)CMSG_DATA(cmsg);
struct scm_fp_list *fpl = *fplp; struct scm_fp_list *fpl = *fplp;
struct file **fpp; struct file **fpp;
int *fdp = (int*)CMSG_DATA(cmsg); int i, num;
int i;
num = (cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)))/sizeof(int); num = (cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)))/sizeof(int);
...@@ -86,41 +87,33 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) ...@@ -86,41 +87,33 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
return -EINVAL; return -EINVAL;
/* /*
* Verify the descriptors. * Verify the descriptors and increment the usage count.
*/ */
for (i=0; i< num; i++) for (i=0; i< num; i++)
{ {
int fd; int fd = fdp[i];
struct file *file;
fd = fdp[i];
if (fd < 0 || fd >= NR_OPEN) if (fd < 0 || !(file = fget(fd)))
return -EBADF;
if (current->files->fd[fd]==NULL)
return -EBADF; return -EBADF;
fpp[i] = current->files->fd[fd]; *fpp++ = file;
fpl->count++;
} }
/* add another reference to these files */
for (i=0; i< num; i++, fpp++)
(*fpp)->f_count++;
fpl->count += num;
return num; return num;
} }
void __scm_destroy(struct scm_cookie *scm) void __scm_destroy(struct scm_cookie *scm)
{ {
int i;
struct scm_fp_list *fpl = scm->fp; struct scm_fp_list *fpl = scm->fp;
int i;
if (!fpl) if (fpl) {
return; scm->fp = NULL;
for (i=fpl->count-1; i>=0; i--)
for (i=fpl->count-1; i>=0; i--) close_fp(fpl->fp[i]);
close_fp(fpl->fp[i]); kfree(fpl);
}
kfree(fpl);
} }
...@@ -223,14 +216,17 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data) ...@@ -223,14 +216,17 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
cmhdr.cmsg_level = level; cmhdr.cmsg_level = level;
cmhdr.cmsg_type = type; cmhdr.cmsg_type = type;
cmhdr.cmsg_len = cmlen; cmhdr.cmsg_len = cmlen;
err = copy_to_user(cm, &cmhdr, sizeof cmhdr);
if (!err) err = -EFAULT;
err = copy_to_user(CMSG_DATA(cm), data, cmlen - sizeof(struct cmsghdr)); if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
if (!err) { goto out;
cmlen = CMSG_SPACE(len); if (copy_to_user(CMSG_DATA(cm), data, cmlen - sizeof(struct cmsghdr)))
msg->msg_control += cmlen; goto out;
msg->msg_controllen -= cmlen; cmlen = CMSG_SPACE(len);
} msg->msg_control += cmlen;
msg->msg_controllen -= cmlen;
err = 0;
out:
return err; return err;
} }
...@@ -240,21 +236,28 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) ...@@ -240,21 +236,28 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
int fdmax = (msg->msg_controllen - sizeof(struct cmsghdr))/sizeof(int); int fdmax = (msg->msg_controllen - sizeof(struct cmsghdr))/sizeof(int);
int fdnum = scm->fp->count; int fdnum = scm->fp->count;
int *cmfptr;
int err = 0;
int i;
struct file **fp = scm->fp->fp; struct file **fp = scm->fp->fp;
int *cmfptr;
int err = 0, i;
if (fdnum < fdmax) if (fdnum < fdmax)
fdmax = fdnum; fdmax = fdnum;
for (i=0, cmfptr=(int*)CMSG_DATA(cm); i<fdmax; i++, cmfptr++) for (i=0, cmfptr=(int*)CMSG_DATA(cm); i<fdmax; i++, cmfptr++)
{ {
int new_fd = get_unused_fd(); int new_fd;
if (new_fd < 0) err = get_unused_fd();
if (err < 0)
break; break;
current->files->fd[new_fd] = fp[i]; new_fd = err;
err = put_user(new_fd, cmfptr); err = put_user(new_fd, cmfptr);
if (err) {
put_unused_fd(new_fd);
break;
}
/* Bump the usage count and install the file. */
fp[i]->f_count++;
current->files->fd[new_fd] = fp[i];
} }
if (i > 0) if (i > 0)
...@@ -272,38 +275,30 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) ...@@ -272,38 +275,30 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
msg->msg_controllen -= cmlen; msg->msg_controllen -= cmlen;
} }
} }
if (i < fdnum)
if (err) msg->msg_flags |= MSG_CTRUNC;
i = 0;
/* /*
* Dump those that don't fit. * All of the files that fit in the message have had their
* usage counts incremented, so we just free the list.
*/ */
for ( ; i < fdnum; i++) { __scm_destroy(scm);
msg->msg_flags |= MSG_CTRUNC;
close_fp(fp[i]);
}
kfree (scm->fp);
scm->fp = NULL;
} }
struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
{ {
int i;
struct scm_fp_list *new_fpl; struct scm_fp_list *new_fpl;
int i;
if (!fpl) if (!fpl)
return NULL; return NULL;
new_fpl = kmalloc(fpl->count*sizeof(int) + sizeof(*fpl), GFP_KERNEL); new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
if (!new_fpl) if (new_fpl) {
return NULL; memcpy(new_fpl, fpl, sizeof(*fpl));
memcpy(new_fpl, fpl, fpl->count*sizeof(int) + sizeof(*fpl));
for (i=fpl->count-1; i>=0; i--)
fpl->fp[i]->f_count++;
for (i=fpl->count-1; i>=0; i--)
fpl->fp[i]->f_count++;
}
return new_fpl; return new_fpl;
} }
...@@ -767,7 +767,7 @@ __initfunc(static int ic_bootp_string(char *dest, char *src, int len, int max)) ...@@ -767,7 +767,7 @@ __initfunc(static int ic_bootp_string(char *dest, char *src, int len, int max))
/* /*
* Process BOOTP extension. * Process BOOTP extension.
*/ */
__initfunc(static void ic_do_bootp_ext(struct bootp_pkt *b, u8 *ext)) __initfunc(static void ic_do_bootp_ext(u8 *ext))
{ {
#ifdef IPCONFIG_DEBUG #ifdef IPCONFIG_DEBUG
u8 *c; u8 *c;
...@@ -864,7 +864,7 @@ __initfunc(static void ic_bootp_recv(void)) ...@@ -864,7 +864,7 @@ __initfunc(static void ic_bootp_recv(void))
opt = ext; opt = ext;
ext += ext[1] + 2; ext += ext[1] + 2;
if (ext <= end) if (ext <= end)
ic_do_bootp_ext(b, opt); ic_do_bootp_ext(opt);
} }
} }
} }
......
#! /usr/bin/perl #! /usr/bin/perl
# #
# checkconfig: find uses of CONFIG_* names without matching definitions. # checkconfig: find uses of CONFIG_* names without matching definitions.
# Copyright abandoned, 1998, Michael Elizabeth Chastain <mailto:mec@shout.net>.
use integer; use integer;
$| = 1;
foreach $file (@ARGV) foreach $file (@ARGV)
{ {
# Open this file. # Open this file.
...@@ -24,15 +27,15 @@ foreach $file (@ARGV) ...@@ -24,15 +27,15 @@ foreach $file (@ARGV)
# Pick up definitions. # Pick up definitions.
if ( m/^#/o ) if ( m/^#/o )
{ {
$iLinuxConfig = $. if m/^#\s*include\s+<linux\/config\.h>/o; $iLinuxConfig = $. if m/^#\s*include\s*<linux\/config\.h>/o;
$configList{uc $1} = 1 if m/^#\s*include\s+<config\/(\S*)\.h>/o; $configList{uc $1} = 1 if m/^#\s*include\s*<config\/(\S*)\.h>/o;
$configList{$1} = 1 if m/^#\s*define\s+CONFIG_(\w*)/o; $configList{$1} = 1 if m/^#\s*define\s+CONFIG_(\w*)/o;
$configList{$1} = 1 if m/^#\s*undef\s+CONFIG_(\w*)/o; $configList{$1} = 1 if m/^#\s*undef\s+CONFIG_(\w*)/o;
} }
# Look for usages. # Look for usages.
next unless m/CONFIG_/o; next unless m/CONFIG_/o;
WORD: while ( m/\bCONFIG_(\w*)/og ) WORD: while ( m/\bCONFIG_(\w+)/og )
{ {
$fUseConfig = 1; $fUseConfig = 1;
last LINE if $iLinuxConfig; last LINE if $iLinuxConfig;
......
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