S: Wantage, New Jersey 07461
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
E: miguel@nuclecu.unam.mx
D: Linux/SPARC team, Midnight Commander maintainer
S: Germany
N: Joerg Reuter
-E: jreuter@lykos.oche.de
-E: dl1bke@db0pra.ampr.org
+E: jreuter@poboxes.com
+W: http://www.rat.de/jr/
+W: http://qsl.net/dl1bke/
D: Generic Z8530 driver, AX.25 DAMA slave implementation
D: Several AX.25 hacks
want to compile it as a module, say M here and read
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
CONFIG_DESKSTATION_RPC44
This is a machine with a R4400 100 MHz CPU. To compile a Linux
IBMMCA SCSI support
CONFIG_SCSI_IBMMCA
- If your computer sports an MCA bus system architecture (IBM PS/2)
- with an SCSI harddrive, say Y here. Please read
- Documentation/mca.txt. This driver is also available as a module ( =
- code which can be inserted in and removed from the running kernel
- whenever you want). The module will be called ibmmca.o. If you want
- to compile it as a module, say M here and read
- Documentation/modules.txt.
- Normally, all IBM MCA SCSI adapters are automatically detected. If
- that doesn't work right however, you can completely override
- auto-detection by specifying "ibmmcascsi=io1,io2,..." at the boot
- loader's command prompt or "io_port=io1,io2,... scsi_id=id1,id2,..."
- as a parameter of insmod. "io" and "id" are the I/O base address
- and the SCSI ID of each adapter, respectively.
- If you want to compile this driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read Documentation/modules.txt. The module will be
- called ibmmca.o.
-
-reset SCSI-devices while booting
-CONFIG_SCSI_IBMMCA_DEV_RESET
- If you say Y here, each connected SCSI device will get a reset
- command at boot time. This can be necessary for some special SCSI
- devices. If unsure, say N.
+ This is support for the IBM SCSI adapter found in many of the PS/2
+ series. CONFIG_MCA must be set for this to work. If the adapter
+ isn't found during boot (a common problem for models 56, 57, 76, and
+ 77) you'll need to use the 'ibmmcascsi=<pun>', where <pun> is the id
+ of the SCSI subsystem (usually 7, but if that doesn't work check your
+ reference diskette). Owners of model 95 with a LED-matrix-display
+ can in addition activate some activity info like under OS/2, but more
+ informative, by setting 'ibmmcascsi=display' as additional kernel-
+ parameter.
+
+Standard SCSI-order
+CONFIG_IBMMCA_SCSI_ORDER_STANDARD
+ In the PC-world and in most modern SCSI-BIOS-setups, SCSI-harddisks
+ are assigned to the driveletters, starting with the lowest SCSI-id
+ (physical number - pun) to be drive C:, as seen from DOS and similar
+ operating systems. When looking into papers, describing the
+ ANSI-SCSI-standard, this assignment of drives appears to be wrong.
+ The SCSI-standard follows a hardware-hierarchy which says, that
+ id 7 has the highest priority and id 0 the lowest. Therefore, the
+ hostadapters are still today everywhere placed as SCSI-id 7 by
+ default. In the SCSI-standard, the driveletters express the priority
+ of the disk. C: should be the harddisk or a partition on it, with the
+ 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
CONFIG_SCSI_IN2000
--- /dev/null
+
+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
+
--- /dev/null
+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.
--- /dev/null
+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>
+++ /dev/null
-
-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
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
If you can't find it there, try .../tcpip/linux/z8530drv-utils-3.0.tar.gz
********************************************************************
- (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
DAMA SLAVE for AX.25
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
S: Maintained
Z8530 DRIVER FOR AX.25
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
S: Maintained
VERSION = 2
PATCHLEVEL = 1
-SUBLEVEL = 84
+SUBLEVEL = 85
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
endmenu
fi
-source drivers/net/hamradio/Config.in
+source net/ax25/Config.in
mainmenu_option next_comment
comment 'ISDN subsystem'
extern void __divqu (void);
extern void __remqu (void);
-EXPORT_SYMBOL(__alpha_bh_counter);
+EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count);
/* platform dependent support */
}
unsigned int local_irq_count[NR_CPUS];
-atomic_t __alpha_bh_counter;
+unsigned int local_bh_count[NR_CPUS];
#ifdef __SMP__
#error "Me no hablo Alpha SMP"
LDFLAGS=-e stext
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
CFLAGS := $(CFLAGS) -m386 -DCPU=386
endmenu
fi
-source drivers/net/hamradio/Config.in
+source net/ax25/Config.in
mainmenu_option next_comment
comment 'ISDN subsystem'
#include <asm/system.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.
*/
int pcibios_read_config_byte (unsigned char bus,
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,
*(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;
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;
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;
* specific CPU-side IRQs.
*/
-#define MAX_PIRQS 4
+#define MAX_PIRQS 8
int pirq_entries [MAX_PIRQS];
+int pirqs_enabled;
void ioapic_pirq_setup(char *str, int *ints)
{
for (i=0; i<MAX_PIRQS; i++)
pirq_entries[i]=-1;
- if (!ints)
+ if (!ints) {
+ pirqs_enabled=0;
printk("PIRQ redirection SETUP, trusting MP-BIOS.\n");
- else {
+
+ } else {
+ pirqs_enabled=1;
printk("PIRQ redirection SETUP, working around broken MP-BIOS.\n");
max = MAX_PIRQS;
if (ints[0] < MAX_PIRQS)
}
case MP_BUS_PCI: /* PCI pin */
{
- irq = mp_irqs[idx].mpc_srcbusirq >> 2;
- if (irq>=16)
- printk("WARNING: MP BIOS says PIRQ%d is redirected to %d, suspicious.\n",idx-16, irq);
+ /*
+ * PCI IRQs are 'directly mapped'
+ */
+ irq = i;
break;
}
default:
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;
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)
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)
{
int i;
nr_ioapic_registers = reg_01.entries+1;
}
- init_IO_APIC_traps();
-
/*
* do not trust the IO-APIC being empty at bootup
*/
setup_IO_APIC_irq_ISA_default (i);
#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 ();
printk("nr of MP irq sources: %d.\n", mp_irq_entries);
/*
* 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:
* asking for different IRQ's should be done through these routines
#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_irq_count[NR_CPUS];
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, };
-#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)
* - explicitly use irq 16-19 depending on which PCI irq
* 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
-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;
if (irq & 8) {
}
}
-static inline void unmask_8259A(int irq)
+static inline void unmask_8259A(unsigned int irq)
{
cached_irq_mask &= ~(1 << irq);
if (irq & 8) {
}
}
-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
}
}
-/*
- * 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)
+void unmask_generic_irq(unsigned int irq)
{
if (IO_APIC_IRQ(irq))
enable_IO_APIC_irq(irq);
BUILD_IRQ(16) BUILD_IRQ(17) BUILD_IRQ(18) BUILD_IRQ(19)
/*
- * [FIXME: anyone with 2 separate PCI buses and 2 IO-APICs,
- * please speak up and request experimental patches.
+ * [FIXME: anyone with 2 separate PCI buses and 2 IO-APICs, please
+ * speak up if problems and request experimental patches.
* --mingo ]
*/
} 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)
{
int count = MAXCOUNT;
#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;
int status;
}
-/*
- * disable/enable_irq() wait for all irq contexts to finish
- * executing. Also it's recursive.
- */
void disable_irq(unsigned int irq)
{
unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags);
- disabled_irq[irq]++;
- mask_irq(irq);
+ irq_handles[irq]->disable(irq);
spin_unlock_irqrestore(&irq_controller_lock, flags);
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);
- disabled_irq[irq]--;
- unmask_irq(irq);
+ if (disabled_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);
}
+#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, ®s);
+
+ 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
* much _has_ to be done exactly like this (mask it
* first, _then_ send the EOI, and the order of EOI
* 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);
- cached_irq_mask |= 1 << irq_nr;
- if (irq_nr & 8) {
+ cached_irq_mask |= 1 << irq;
+ if (irq & 8) {
inb(0xA1); /* DUMMY */
outb(cached_A1,0xA1);
outb(0x62,0x20); /* Specific EOI to cascade */
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);
}
#ifdef __SMP__
-/*
- * FIXME! This is completely broken.
- */
-static void do_ioapic_IRQ(int irq, int cpu, struct pt_regs * regs)
+static void do_ioapic_IRQ(unsigned 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);
- 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);
-
- if (should_handle_irq) {
-again:
- if (!handle_IRQ_event(irq, regs))
- disabled_irq[irq] = 1;
- }
+ irq_enter(cpu, irq);
- spin_lock(&irq_controller_lock);
- release_irqlock(cpu);
+ if (should_handle_irq) {
+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);
- goto again;
- }
- irq_owner[irq] = NO_PROC_ID;
- hardirq_exit(cpu);
- spin_unlock(&irq_controller_lock);
+ if (should_handle_irq)
+ goto again;
+ }
- enable_IO_APIC_irq(irq);
+ irq_exit(cpu, irq);
}
#endif
*/
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
* thinking we're snobs just because some other CPU has
* 0 return value means that this irq is already being
* 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();
kstat.irqs[cpu][irq]++;
-
- 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, ®s);
+ irq_handles[irq]->handle(irq, cpu, ®s);
/*
* This should be conditional: we should really get
}
}
-int setup_x86_irq(int irq, struct irqaction * new)
+int setup_x86_irq(unsigned int irq, struct irqaction * new)
{
int shared = 0;
struct irqaction *old, **p;
if (!shared) {
spin_lock(&irq_controller_lock);
+#ifdef __SMP__
if (IO_APIC_IRQ(irq)) {
+ irq_handles[irq] = &ioapic_irq_type;
/*
* First disable it in the 8259A:
*/
cached_irq_mask |= 1 << irq;
if (irq < 16)
set_8259A_irq_mask(irq);
- setup_IO_APIC_irq(irq);
}
- unmask_irq(irq);
+#endif
+ unmask_generic_irq(irq);
spin_unlock(&irq_controller_lock);
}
restore_flags(flags);
*/
for (i = NR_IRQS-1; i > 0; i--) {
if (!irq_action[i]) {
- spin_lock(&irq_controller_lock);
- unmask_irq(i);
+ unsigned long flags;
+ spin_lock_irqsave(&irq_controller_lock, flags);
+ unmask_generic_irq(i);
irqs |= (1 << i);
- spin_unlock(&irq_controller_lock);
+ spin_unlock_irqrestore(&irq_controller_lock, flags);
}
}
return irq_found;
}
+#ifdef __SMP__
void init_IO_APIC_traps(void)
{
int i;
for (i = 0; i < NR_IRQS ; i++)
if (IO_APIC_GATE_OFFSET+(i<<3) <= 0xfe) /* HACK */ {
if (IO_APIC_IRQ(i)) {
+ irq_handles[i] = &ioapic_irq_type;
/*
* First disable it in the 8259A:
*/
cached_irq_mask |= 1 << i;
if (i < 16)
set_8259A_irq_mask(i);
- setup_IO_APIC_irq(i);
}
}
}
+#endif
__initfunc(void init_IRQ(void))
{
printk("INIT IRQ\n");
for (i=0; i<NR_IRQS; i++) {
irq_events[i] = 0;
-#ifdef __SMP__
- irq_owner[i] = NO_PROC_ID;
-#endif
disabled_irq[i] = 0;
}
/*
#define IO_APIC_GATE_OFFSET 0x51
-void mask_irq(unsigned int irq_nr);
-void unmask_irq(unsigned int irq_nr);
-void enable_IO_APIC_irq (int irq);
-void disable_IO_APIC_irq (int irq);
-void set_8259A_irq_mask(int irq_nr);
-void setup_IO_APIC_irq (int irq);
+void mask_irq(unsigned int irq);
+void unmask_irq(unsigned int irq);
+void enable_IO_APIC_irq (unsigned int irq);
+void disable_IO_APIC_irq (unsigned int irq);
+void set_8259A_irq_mask(unsigned int irq);
void ack_APIC_irq (void);
void setup_IO_APIC (void);
void init_IO_APIC_traps(void);
+int IO_APIC_get_PCI_irq_vector (int bus, int slot, int fn);
#ifdef __SMP__
extern unsigned int io_apic_irqs;
MP_BUS_PCI
};
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; /*
* Protects both the 8259 and the
#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);
while (test_bit(0,&global_irq_lock)) {
}
}
-static inline void irq_exit(int cpu, int irq)
+static inline void irq_exit(int cpu, unsigned int irq)
{
hardirq_exit(cpu);
release_irqlock(cpu);
static struct cpu_model_info cpu_models[] __initdata = {
{ X86_VENDOR_INTEL, 4,
- { "486 DX-25/33", "486 DX-50", "486 SX", "487 DX", "486 DX/2", "486 SL", "486 SX/2",
- NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL }},
+ { "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, NULL }},
{ X86_VENDOR_INTEL, 5,
{ "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75+",
"OverDrive PODP5V83", "Pentium MMX", NULL, NULL,
}
memcpy(str,mpc->mpc_oem,8);
str[8]=0;
+ memcpy(ioapic_OEM_ID,str,9);
printk("OEM ID: %s ",str);
+
memcpy(str,mpc->mpc_productid,12);
str[12]=0;
+ memcpy(ioapic_Product_ID,str,13);
printk("Product ID: %s ",str);
+
printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
/* set the local APIC address */
--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);
count+=sizeof(*m);
break;
p->counter = 0;
need_resched = 1;
}
- if (p->priority < DEF_PRIORITY)
+ if (p->priority < DEF_PRIORITY) {
kstat.cpu_nice += user;
- else
+ kstat.per_cpu_nice[cpu] += user;
+ } else {
kstat.cpu_user += user;
+ kstat.per_cpu_user[cpu] += user;
+ }
kstat.cpu_system += system;
kstat.per_cpu_system[cpu] += system;
endmenu
fi
-source drivers/net/hamradio/Config.in
+source net/ax25/Config.in
mainmenu_option next_comment
comment 'ISDN subsystem'
tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5
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
if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
extern void console_map_init(void);
#ifdef CONFIG_PARPORT
extern int parport_init(void);
+#endif
+#ifdef CONFIG_MD_BOOT
+ extern void md_setup_drive(void) __init;
#endif
struct gendisk *p;
int nr=0;
#endif
rd_load();
#endif
+#ifdef CONFIG_MD_BOOT
+ md_setup_drive();
+#endif
}
A lot of inspiration came from hd.c ...
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:
Ingo Molnar, Miguel de Icaza, Gadi Oxman
#include <asm/bitops.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 int md_blocksizes[MAX_MD_DEV];
int md_maxreadahead[MAX_MD_DEV];
cli();
if (!test_bit(THREAD_WAKEUP, &thread->flags)) {
do {
- spin_lock_irq(¤t->sigmask_lock);
+ spin_lock(¤t->sigmask_lock);
flush_signals(current);
- spin_unlock_irq(¤t->sigmask_lock);
+ spin_unlock(¤t->sigmask_lock);
interruptible_sleep_on(&thread->wqueue);
+ cli();
+ if (test_bit(THREAD_WAKEUP, &thread->flags))
+ break;
} while (signal_pending(current));
}
}
*/
curr_bsize = blksize_size[major][minor];
if (curr_bsize != blocksize) {
-diff_blocksize:
+ diff_blocksize:
if (curr_bsize > blocksize)
/*
* this is safe, rounds downwards.
}
+#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 raid0_init (void);
void raid1_init (void);
#ifdef CONFIG_MD_RAID5
raid5_init ();
#endif
-
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
--- /dev/null
+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
#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/in.h>
/* Mask interrupts from the ethercard. */
outb_p(0x00, e8390_base + EN0_IMR);
+ disable_irq(dev->irq);
synchronize_irq();
if (dev->interrupt) {
printk("%s: Tx request while isr active.\n",dev->name);
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+ enable_irq(dev->irq);
ei_local->stat.tx_errors++;
dev_kfree_skb(skb, FREE_WRITE);
return 0;
ei_local->irqlock = 0;
dev->tbusy = 1;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+ enable_irq(dev->irq);
ei_local->stat.tx_errors++;
return 1;
}
/* Turn 8390 interrupts back on. */
ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+ enable_irq(dev->irq);
dev_kfree_skb (skb, FREE_WRITE);
ei_local->stat.tx_bytes += send_length;
static void ei_rx_overrun(struct device *dev)
{
int e8390_base = dev->base_addr;
- unsigned long wait_start_time;
unsigned char was_txing, must_resend = 0;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
* it "is not a reliable indicator and subsequently should be ignored."
* We wait at least 10ms.
*/
- wait_start_time = jiffies;
- while (jiffies - wait_start_time <= 1*HZ/100)
- barrier();
+ udelay(10*1000);
/*
* Reset RBCR[01] back to zero as per magic incantation.
__initfunc(static void
srom_search(int index))
{
- u_char pb, dev_fn;
+ u_char pb, dev_fn, tirq;
u_short dev_id, dev_num, vendor, status;
u_int tmp, irq = 0, device, class = DE4X5_CLASS_CODE;
u_long iobase = 0; /* Clear upper 32 bits in Alphas */
/* Fetch the IRQ to be used */
#ifndef __sparc_v9__
- pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE,
- (char *)&irq);
+ pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
+ irq = tirq;
#else
irq = pdev->irq;
#endif
-#
-# 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>
+comment 'AX.25 network 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
- 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
+dep_tristate 'Serial port KISS driver' CONFIG_MKISS $CONFIG_AX25
+# dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
+dep_tristate 'BPQ Ethernet driver' CONFIG_BPQETHER $CONFIG_AX25
- tristate 'BAYCOM ser12 fullduplex driver for AX.25' CONFIG_BAYCOM_SER_FDX
- tristate 'BAYCOM ser12 halfduplex driver for AX.25' CONFIG_BAYCOM_SER_HDX
- tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR
-
- tristate 'Soundcard modem driver' CONFIG_SOUNDMODEM
- 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
+dep_tristate 'High-speed (DMA) SCC driver for AX.25' CONFIG_DMASCC $CONFIG_AX25
+dep_tristate 'Z8530 SCC driver' CONFIG_SCC $CONFIG_AX25
+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
+
+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
* call.
* Fixed to match Linux networking
* changes - 2.1.15.
+ * BPQ 004 Joerg(DL1BKE) Fixed to not lock up on ifconfig.
*/
#include <linux/config.h>
#include <linux/firewall.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/rtnetlink.h>
#include <net/ip.h>
#include <net/arp.h>
if (&bpq->axdev == dev)
result = 1;
- unregister_netdev(&bpq->axdev);
+ /* We should be locked, call
+ * unregister_netdevice directly
+ */
+
+ unregister_netdevice(&bpq->axdev);
kfree(bpq);
}
dev->name = buf;
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);
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 BANNER "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n"
/*
* Please use z8530drv-utils-3.0 with this version.
* ------------------
+ *
+ * You can find a subset of the documentation in
+ * linux/Documentation/networking/z8530drv.txt.
*/
/*
********************************************************************
- Copyright (c) 1993, 1997 Joerg Reuter DL1BKE
+ Copyright (c) 1993, 1998 Joerg Reuter DL1BKE
portions (c) 1993 Guido ten Dolle PE1NNZ
970108 - Fixed the remaining problems.
970402 - Hopefully fixed the problems with the new *_timer()
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
reports!
static void scc_isr(int irq, void *dev_id, struct pt_regs *regs);
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_open(struct device *dev);
static int scc_net_close(struct device *dev);
* 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;
struct device *dev;
dev->name = buf;
dev->init = scc_net_init;
- if (register_netdev(dev) != 0)
+ if ((addev? register_netdevice(dev) : register_netdev(dev)) != 0)
{
kfree(dev);
- return -EIO;
- }
+ return -EIO;
+ }
return 0;
}
request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
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);
}
}
sprintf(devname,"%s0", SCC_DriverName);
- result = scc_net_setup(SCC_Info, devname);
+ result = scc_net_setup(SCC_Info, devname, 0);
if (result)
{
printk(KERN_ERR "z8530drv: cannot initialize module\n");
result = scc_init();
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;
}
fi
fi
if [ "$CONFIG_MCA" = "y" ]; then
- dep_tristate 'IBMMCA SCSI support' CONFIG_SCSI_IBMMCA $CONFIG_SCSI
- if [ "$CONFIG_SCSI_IBMMCA" != "n" ]; then
- bool ' reset SCSI-devices while booting' CONFIG_SCSI_IBMMCA_DEV_RESET
- fi
+ bool 'IBMMCA SCSI support' CONFIG_SCSI_IBMMCA
+ if [ "$CONFIG_SCSI_IBMMCA" = "y" ]; then
+ bool ' Standard SCSI-order' CONFIG_IBMMCA_SCSI_ORDER_STANDARD
+ bool ' Reset SCSI-devices at boottime' CONFIG_IBMMCA_SCSI_DEV_RESET
+ fi
fi
if [ "$CONFIG_PARPORT" != "n" ]; then
dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
5) Magneto-Optical drives and medium-changers are also recognized, now.
Therefore, we have a completely gapfree recognition of all SCSI-
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
- within the configuration, each connected SCSI-device will get a reset
- command during boottime. This can be necessary for some special
- SCSI-devices. (See also the new Config.in file.)
+ 6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
+ the configuration, each connected SCSI-device will get a reset command
+ during boottime. This can be necessary for some special SCSI-devices.
+ This flag should be included in Config.in.
+ (See also the new Config.in file.)
Probable next improvement: bad disk handler.
- Michael Lang
1) Some debugging and speed optimization applied.
- 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:
- It seems that the handling of bad disks is really bad -
/*--------------------------------------------------------------------*/
/* 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
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
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
Only three functions get involved: ibmmca_queuecommand(), issue_cmd(),
and interrupt_handler().
/* basic I/O-port of first adapter */
#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
/*requests going into the upper nibble of the Attention register */
interest, debugging or just for having fun. The left number gives the
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) {\
- 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); } \
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() {\
- if( machine_id == 0xf8 ) { outb( ' ', MOD95_LED_PORT ); \
+ if( use_display ) { outb( ' ', MOD95_LED_PORT ); \
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); \
}
/*--------------------------------------------------------------------*/
unsigned short mca_id;
char *description;
};
+
+/* List of possible IBM-SCSI-adapters */
struct subsys_list_struct subsys_list[] =
{
{0x8efc, "IBM Fast SCSI-2 Adapter"},
/*local data for a logical device */
struct logical_device
{
- struct im_scb scb;
+ struct im_scb scb; /* SCSI-subsystem-control-block structure */
struct im_tsb tsb;
struct im_sge sge[16];
Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */
int device_type; /* type of the SCSI-device. See include/scsi/scsi.h
- for interpreation of the possible values */
- int block_length;
+ for interpretation of the possible values */
+ int block_length;/* blocksize of a particular logical SCSI-device */
};
/* statistics of the driver during operations (for proc_info) */
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_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_interrupts; /* total interrupts (should be
same as total_accesses) */
/* data structure for each host adapter */
struct ibmmca_hostdata
{
- /* array of logical devices */
- struct logical_device _ld[MAX_LOG_DEV];
- /* array to convert (pun, lun) into logical device number */
+ /* array of logical devices: */
+ struct logical_device _ld[MAX_LOG_DEV];
+ /* array to convert (pun, lun) into logical device number: */
unsigned char _get_ldn[8][8];
/*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];
- /* used only when checking logical devices */
+ /* used only when checking logical devices: */
int _local_checking_phase_flag;
+ /* report received interrupt: */
int _got_interrupt;
+ /* report termination-status of SCSI-command: */
int _stat_result;
- /* reset status (used only when doing reset) */
+ /* reset status (used only when doing reset): */
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;
- /* counter that points on next reassignable ldn for dynamical remapping */
- /* The default value is 7, that is the first reassignable number in
- the list on startup. */
+ /* Counter that points on the next reassignable ldn for dynamical
+ remapping. The default value is 7, that is the first reassignable
+ number in the list at boottime: */
int _next_ldn;
- /* Statistics for this IBM-SCSI-host */
+ /* Statistics-structure for this IBM-SCSI-host: */
struct Driver_Statistics _IBM_DS;
};
#define IBM_DS (HOSTDATA(shpnt)->_IBM_DS)
/* 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 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. */
#define TYPE_NO_DEVICE 0xFF
-/* define medium-changer. If this is not defined previously, define
- this type here. */
+/* define medium-changer. If this is not defined previously, e.g. Linux
+ 2.0.x, define this type here. */
#ifndef TYPE_MEDIUM_CHANGER
#define TYPE_MEDIUM_CHANGER 0x08
#endif
-/* define operations for immediate_assign */
+/* define possible operations for the immediate_assign command */
#define SET_LDN 0
#define REMOVE_LDN 1
static int scsi_id[IM_MAX_HOSTS] = { 7, 7, 7, 7, 7, 7, 7, 7 };
/* 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
MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
return("-");
}
-/* type-interpreter for logical devices
- (A bit stupid, but it was necessary to get the '-' and the Hex-codes
- into one type.) */
+/* interpreter for logical device numbers (ldn) */
static char *ti_l(int value)
{
- switch (value)
- {
- case 0: return("0"); break; case 1: return("1"); break;
- case 2: return("2"); break; case 3: return("3"); break;
- case 4: return("4"); break; case 5: return("5"); break;
- case 6: return("6"); break; case 7: return("7"); break;
- case 8: return("8"); break; case 9: return("9"); break;
- case 10: return("a"); break; case 11: return("b"); break;
- case 12: return("c"); break; case 13: return("d"); break;
- case 14: return("e"); break; case 15: return("f"); break;
- default: return("-"); break;
- }
- return("-");
+ const char hex[16] = ("0123456789abcdef");
+ static char answer[2];
+
+ answer[1] = (char)(0x0);
+ if (value<=MAX_LOG_DEV)
+ answer[0] = hex[value];
+ else
+ answer[0] = '-';
+
+ return (char *)&answer;
}
/*
memset (get_ldn, TYPE_NO_DEVICE, sizeof get_ldn); /* 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_ldn[subsystem_pun][lun] = MAX_LOG_DEV; /* make sure, the subsystem
immediate_assign(shpnt,0,0,ldn,REMOVE_LDN); /* remove ldn (wherever)*/
}
- lun = 0;
+ lun = 0; /* default lun is 0 */
/* STEP 2: */
printk("\nIBM MCA SCSI: Probing SCSI-devices.");
- for (id=0; id<=7; id++)
+ for (id=0; id<8; id++)
#ifdef CONFIG_SCSI_MULTI_LUN
- for (lun=0; lun<=7; lun++)
+ for (lun=0; lun<8; lun++)
#endif
{
#ifdef IM_DEBUG_PROBE
}
}
- /* STEP 3: */
+ /* STEP 3: */
printk("\nIBM MCA SCSI: Mapping SCSI-devices.");
ldn = 0;
lun = 0;
#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
- for (id=0; id<=7 && ldn<MAX_LOG_DEV; id++)
+ for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
{
#ifdef IM_DEBUG_PROBE
printk(".");
if (device_exists (shpnt, ldn, &ld[ldn].block_length,
&ld[ldn].device_type))
{
-#ifdef CONFIG_SCSI_IBMMCA_DEV_RESET
+#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
int ticks;
printk("(resetting)");
ticks = IM_RESET_DELAY*HZ;
/* STEP 4: */
/* map remaining ldns to non-existing devices */
- for (lun=1; lun<=7 && ldn<MAX_LOG_DEV; lun++)
- for (id=0; id<=7 && ldn<MAX_LOG_DEV; id++)
+ for (lun=1; lun<8 && ldn<MAX_LOG_DEV; lun++)
+ for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
{
if (get_scsi[id][lun] == TYPE_NO_LUN ||
get_scsi[id][lun] == TYPE_NO_DEVICE)
}
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
/* Show the physical and logical mapping during boot. */
printk("IBM MCA SCSI: Determined SCSI-device-mapping:\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");
- for (id=0; id<=7; id++)
+ for (id=0; id<8; id++)
{
- printk("%2d %2s %2s %2s %2s %2s %2s %2s %2s",
- 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][4]), ti_p(get_scsi[id][5]),
- 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]),
- ti_l(get_ldn[id][2]), ti_l(get_ldn[id][3]),
- ti_l(get_ldn[id][4]), ti_l(get_ldn[id][5]),
- ti_l(get_ldn[id][6]), ti_l(get_ldn[id][7]));
+ printk("%2d %2s %2s %2s %2s %2s %2s %2s %2s",
+ 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][4]), ti_p(get_scsi[id][5]),
+ ti_p(get_scsi[id][6]), ti_p(get_scsi[id][7]));
+
+ printk(" %2d ",id);
+ for (lun=0; lun<8; lun++)
+ printk("%2s ",ti_l(get_ldn[id][lun]));
+ printk("\n");
}
#endif
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_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));
return;
void
ibmmca_scsi_setup (char *str, int *ints)
{
- int i;
-
- for (i = 0; i < IM_MAX_HOSTS && i < ints[0]; i++)
- io_port[i] = ints[i+1];
+ if( str && !strcmp( str, "display" ) ) {
+ use_display = 1;
+ } else if( ints ) {
+ int i;
+ for (i = 0; i < IM_MAX_HOSTS && i < ints[0]; i++) {
+ io_port[i] = ints[i+1];
+ }
+ }
}
#endif
int current_ldn;
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 ((get_scsi[cmd->target][cmd->lun] == TYPE_NO_LUN)||
- (get_scsi[cmd->target][cmd->lun] == TYPE_NO_DEVICE))
+ if ((get_scsi[target][cmd->lun] == TYPE_NO_LUN)||
+ (get_scsi[target][cmd->lun] == TYPE_NO_DEVICE))
{
cmd->result = DID_NO_CONNECT << 16;
done (cmd);
}
/*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) /* dynamical remapping if ldn unassigned */
printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n");
printk(" On ldn 7-14 SCSI-commands everywhere in progress.\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*/
done (cmd);
return 0;
}
/* unmap non-processing ldn */
- for (id=0; id<=7; id ++)
- for (lun=0; lun<=7; lun++)
+ for (id=0; id<8; id ++)
+ for (lun=0; lun<8; lun++)
{
if (get_ldn[id][lun] == next_ldn)
{
/* unassign found ldn (pun,lun does not matter for remove) */
immediate_assign(shpnt,0,0,next_ldn,REMOVE_LDN);
/* 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 */
- 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 */
ldn = next_ldn;
/* set reduced interrupt_handler-mode for checking */
/* panic here, because a device, found at boottime has
vanished */
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 */
local_checking_phase_flag = 0;
/* Information on syslog terminal */
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 */
next_ldn ++;
if (next_ldn>=MAX_LOG_DEV) next_ldn = 7;
- }
+ }
else
{ /* wall against Linux accesses to the subsystem adapter */
cmd->result = DID_NO_CONNECT << 16;
printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn);
#endif
- /* for specific device debugging: */
+ /* for specific device-type debugging: */
#ifdef IM_DEBUG_CMD_SPEC_DEV
if (ld[ldn].device_type==IM_DEBUG_CMD_DEVICE)
printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n",
}
scb->u2.blk.length = ld[ldn].block_length;
if (++disk_rw_in_progress == 1)
- PS2_DISK_LED_ON (shpnt->host_no, cmd->target);
+ PS2_DISK_LED_ON (shpnt->host_no, target);
break;
/* for other devices, enter here. Other types are not known by
/* Read/write on this non-disk devices is also displayworthy,
so flash-up the LED/display. */
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;
case INQUIRY:
+ IBM_DS.ldn_inquiry_access[ldn]++;
scb->command = IM_DEVICE_INQUIRY_CMD;
scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
break;
/* Commands that need write-only-mode (system -> device): */
case MODE_SELECT:
case MODE_SELECT_10:
+ IBM_DS.ldn_modeselect_access[ldn]++;
scb->command = IM_OTHER_SCSI_CMD_CMD;
scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /*Select needs WRITE-enabled*/
scb->u1.scsi_cmd_length = cmd->cmd_len;
unsigned int ldn;
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 */
printk ("IBM MCA SCSI: sending abort to device id=%d lun=%d.\n",
- cmd->target, cmd->lun);
- ldn = get_ldn[cmd->target][cmd->lun];
+ target, cmd->lun);
+ ldn = get_ldn[target][cmd->lun];
cli ();
/*if cmd for this ldn has already finished, no need to abort */
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) */
int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length,
int hostno, int inout)
{
int len=0;
- int i,id;
+ int i,id,lun;
struct Scsi_Host *shpnt;
for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++);
len += sprintf(buffer+len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n",
IBMMCA_SCSI_DRIVER_VERSION);
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
len += sprintf(buffer+len, " Multiple LUN probing.....: Yes\n");
#else
IBM_DS.total_accesses);
len += sprintf(buffer+len, " Total SCSI READ/WRITE..: %d\n",
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",
- 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, " LDN | Accesses [%%] | READ | WRITE | ASSIGNMENTS\n");
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][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]),
- ti_l(get_ldn[id][2]), ti_l(get_ldn[id][3]),
- ti_l(get_ldn[id][4]), ti_l(get_ldn[id][5]),
- ti_l(get_ldn[id][6]), ti_l(get_ldn[id][7]));
+
+ len += sprintf(buffer+len, " %2d ",id);
+ for (lun=0; lun<8; lun++)
+ len += sprintf(buffer+len,"%2s ",ti_l(get_ldn[id][lun]));
+ len += sprintf(buffer+len,"\n");
}
len += sprintf(buffer+len, "(A = IBM-Subsystem, D = Harddisk, T = Tapedrive, P = Processor, W = WORM,\n");
#endif
/*--------------------------------------------------------------------*/
+
+
+
extern struct proc_dir_entry proc_scsi_ibmmca;
/*initialization for Scsi_host_template type */
-#define IBMMCA { \
- proc_dir: &proc_scsi_ibmmca, /*proc_dir*/ \
- proc_info: ibmmca_proc_info, /*proc info fn*/ \
- name: "IBMMCA", /*name*/ \
- detect: ibmmca_detect, /*detect fn*/ \
- release: ibmmca_release, /*release fn*/ \
- command: ibmmca_command, /*command fn*/ \
- queuecommand: ibmmca_queuecommand, /*queuecommand fn*/ \
- abort: ibmmca_abort, /*abort fn*/ \
- reset: ibmmca_reset, /*reset fn*/ \
- bios_param: ibmmca_biosparam, /*bios fn*/ \
- can_queue: 16, /*can_queue*/ \
- this_id: 7, /*set by detect*/ \
- sg_tablesize: 16, /*sg_tablesize*/ \
- cmd_per_lun: 1, /*cmd_per_lun*/ \
- use_clustering: ENABLE_CLUSTERING /*use_clustering*/ \
+#define IBMMCA { \
+ NULL, /*next*/ \
+ NULL, /*usage_count*/ \
+ &proc_scsi_ibmmca, /*proc_dir*/ \
+ ibmmca_proc_info, /*proc info fn*/ \
+ "IBMMCA", /*name*/ \
+ ibmmca_detect, /*detect fn*/ \
+ ibmmca_release, /*release fn*/ \
+ NULL, /*info fn*/ \
+ ibmmca_command, /*command fn*/ \
+ ibmmca_queuecommand, /*queuecommand fn*/ \
+ ibmmca_abort, /*abort fn*/ \
+ ibmmca_reset, /*reset fn*/ \
+ NULL, /*slave_attach fn*/ \
+ ibmmca_biosparam, /*bios fn*/ \
+ 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 */
+
+
*
* 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
* the terms of the GNU General Public License, version 2, or at your
ent->next = *dhnp;
ent->back = dhnp;
*dhnp = ent;
+ if ( ent->next )
+ ent->next->back = &(ent->next);
}
void autofs_hash_delete(struct autofs_dir_ent *ent)
{
*(ent->back) = ent->next;
+ if ( ent->next )
+ ent->next->back = ent->back;
autofs_delete_usage(ent);
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,
* and return the inode number if it has an inode.
S_IFREG | S_IRUGO, 1, 0, 0,
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__
static struct proc_dir_entry proc_root_ppc_htab = {
PROC_PPC_HTAB, 8, "ppc_htab",
in detected_[xenix,sysv4,sysv2,coherent]. Thanks
to Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
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.
* Size of a block or zone (data allocation unit on disk)
- Minix FS 1024
- Xenix FS 1024 (also 512 ??)
- - SystemV FS 1024 (also 512)
+ - SystemV FS 1024 (also 512 and 2048)
- Coherent FS 512
* General layout: all have one boot block, one super block and
Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhe.de>
-
#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)
{
if (inode->i_nlink)
* the time stamp is not < 01-01-1980.
*/
-static void detected_bs512 (struct super_block *sb)
-{
- sb->sv_block_size = 512;
- sb->sv_block_size_1 = 512-1;
- sb->sv_block_size_bits = 9;
- sb->sv_block_size_ratio = 2;
- sb->sv_block_size_ratio_bits = 1;
- sb->sv_inodes_per_block = 512/64;
- sb->sv_inodes_per_block_1 = 512/64-1;
- sb->sv_inodes_per_block_bits = 9-6;
- sb->sv_toobig_block = 10 +
- (sb->sv_ind_per_block = 512/4) +
- (sb->sv_ind_per_block_2 = (512/4)*(512/4)) +
- (sb->sv_ind_per_block_3 = (512/4)*(512/4)*(512/4));
- 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;
+static void detected_bs (u_char type, struct super_block *sb)
+{
+ u_char n_bits = type+8;
+ int bsize = 1 << n_bits;
+ int bsize_4 = bsize >> 2;
+
+ sb->sv_block_size = bsize;
+ sb->sv_block_size_1 = bsize-1;
+ sb->sv_block_size_bits = n_bits;
+ sb->sv_block_size_dec_bits = (bsize==512) ? 1 : 0;
+ sb->sv_block_size_inc_bits = (bsize==2048) ? 1 : 0;
+ sb->sv_inodes_per_block = bsize >> 6;
+ sb->sv_inodes_per_block_1 = (bsize >> 6)-1;
+ sb->sv_inodes_per_block_bits = n_bits-6;
sb->sv_toobig_block = 10 +
- (sb->sv_ind_per_block = 1024/4) +
- (sb->sv_ind_per_block_2 = (1024/4)*(1024/4)) +
- (sb->sv_ind_per_block_3 = (1024/4)*(1024/4)*(1024/4));
- sb->sv_ind_per_block_1 = 1024/4-1;
- sb->sv_ind_per_block_2_1 = (1024/4)*(1024/4)-1;
+ (sb->sv_ind_per_block = bsize_4) +
+ (sb->sv_ind_per_block_2 = bsize_4*bsize_4) +
+ (sb->sv_ind_per_block_3 = bsize_4*bsize_4*bsize_4);
+ sb->sv_ind_per_block_1 = bsize_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_bits = 10-2);
- sb->sv_ind_per_block_block_size_1 = (1024/4)*1024-1;
- sb->sv_ind_per_block_block_size_bits = (10-2)+10;
- sb->sv_ind_per_block_2_block_size_1 = (1024/4)*(1024/4)*1024-1;
- sb->sv_ind_per_block_2_block_size_bits = (10-2)+(10-2)+10;
- sb->sv_ind0_size = 10 * 1024;
- sb->sv_ind1_size = (10 + (1024/4))* 1024;
- sb->sv_ind2_size = (10 + (1024/4) + (1024/4)*(1024/4)) * 1024;
+ (sb->sv_ind_per_block_bits = n_bits-2);
+ sb->sv_ind_per_block_block_size_1 = bsize_4*bsize-1;
+ sb->sv_ind_per_block_block_size_bits = 2*n_bits-2;
+ sb->sv_ind_per_block_2_block_size_1 = bsize_4*bsize_4*bsize-1;
+ sb->sv_ind_per_block_2_block_size_bits = 3*n_bits-4;
+ sb->sv_ind0_size = 10 * bsize;
+ sb->sv_ind1_size = (10 + bsize_4)* bsize;
+ 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)
sbd = (struct xenix_super_block *) bh->b_data;
if (sbd->s_magic != 0x2b5544)
return NULL;
- switch (sbd->s_type) {
- case 1: detected_bs512(sb); break;
- case 2: detected_bs1024(sb); break;
- default: return NULL;
- }
+ if (sbd->s_type > 2 || sbd->s_type < 1)
+ return NULL;
+ detected_bs(sbd->s_type, sb);
sb->sv_type = FSTYPE_XENIX;
return "Xenix";
}
struct xenix_super_block * sbd1;
struct xenix_super_block * sbd2;
- if (sb->sv_block_size == BLOCK_SIZE)
- /* block size = 1024, so bh1 = bh2 */
+ if (sb->sv_block_size >= BLOCK_SIZE)
+ /* block size >= 1024, so bh1 = bh2 */
sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data;
else {
/* block size = 512, so bh1 != bh2 */
return NULL;
if (sbd->s_time < 315532800) /* this is likely to happen on SystemV2 FS */
return NULL;
- switch (sbd->s_type) {
- case 1: detected_bs512(sb); break;
- case 2: detected_bs1024(sb); break;
- default: return NULL;
- }
+ if (sbd->s_type > 3 || sbd->s_type < 1)
+ return NULL;
+ detected_bs(sbd->s_type, sb);
sb->sv_type = FSTYPE_SYSV4;
return "SystemV";
}
{
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);
else {
sbd = (struct sysv4_super_block *) bh->b_data;
return NULL;
if (sbd->s_time < 315532800) /* this is likely to happen on SystemV4 FS */
return NULL;
- switch (sbd->s_type) {
- case 1: detected_bs512(sb); break;
- case 2: detected_bs1024(sb); break;
- default: return NULL;
- }
+ if (sbd->s_type > 3 || sbd->s_type < 1)
+ return NULL;
+ detected_bs(sbd->s_type, sb);
sb->sv_type = FSTYPE_SYSV2;
return "SystemV Release 2";
}
{
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);
else {
sbd = (struct sysv2_super_block *) bh->b_data;
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)))
return NULL;
- detected_bs512(sb);
+ detected_bs(1, sb);
sb->sv_type = FSTYPE_COH;
return "Coherent";
}
const char *found;
kdev_t dev = sb->s_dev;
struct inode *root_inode;
-
+ unsigned long blocknr;
+
if (1024 != sizeof (struct xenix_super_block))
panic("Xenix FS: bad super-block size");
if ((512 != sizeof (struct sysv4_super_block))
}
/* Try to recognize SystemV superblock */
/* 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, };
int i;
for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++)
if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) {
/* Try to recognize SystemV superblock */
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;
}
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;
}
brelse(bh);
}
}
+ bad_shift:
sb->s_dev = 0;
unlock_super(sb);
if (!silent)
return NULL;
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) {
case FSTYPE_XENIX:
if (!detected_xenix(sb,bh,bh))
if (!detected_sysv2(sb,bh))
goto bad_superblock;
break;
- default:
- bad_superblock:
- brelse(bh);
- sb->s_dev = 0;
- unlock_super(sb);
- printk("SysV FS: cannot read superblock in 1024 byte mode\n");
- goto failed;
+ default: goto bad_superblock;
+ goto superblock_ok;
+ bad_superblock:
+ brelse(bh);
+ sb->s_dev = 0;
+ unlock_super(sb);
+ printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size);
+ goto failed;
+ superblock_ok:
}
} else {
- /* Switch to another block size. Unfortunately, we have to
- release the 1 KB block bh and read it in two parts again. */
+ /* Switch to 512 block size. Unfortunately, we have to
+ release the block bh and read it again. */
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);
set_blocksize(dev,sb->sv_block_size);
*
* sysv/namei.c
* Copyright (C) 1993 Bruno Haible
- *
*/
#include <linux/tasks.h>
extern unsigned int local_irq_count[NR_CPUS];
-#define in_interrupt() (local_irq_count[smp_processor_id()] != 0)
#ifndef __SMP__
* is entirely private to an implementation, it should not be
* 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)
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
* naturally by using a counter
*/
extern inline void start_bh_atomic(void)
{
-#ifdef __SMP__
- atomic_inc(&__alpha_bh_counter);
- synchronize_irq();
-#else
- atomic_inc(&__alpha_bh_counter);
-#endif
+ local_bh_count[smp_processor_id()]++;
+ barrier();
}
extern inline void end_bh_atomic(void)
{
- atomic_dec(&__alpha_bh_counter);
+ barrier();
+ local_bh_count[smp_processor_id()]--;
}
#ifndef __SMP__
/* These are for the irq's testing the lock */
-#define softirq_trylock(cpu) (atomic_read(&__alpha_bh_counter) ? \
- 0 : \
- ((atomic_set(&__alpha_bh_counter,1)),1))
-#define softirq_endlock(cpu) (atomic_set(&__alpha_bh_counter, 0))
+#define softirq_trylock(cpu) \
+ (local_bh_count[cpu] ? 0 : (local_bh_count[cpu] = 1))
+#define softirq_endlock(cpu) \
+ (local_bh_count[cpu] = 0)
#else
#error FIXME
#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 */
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 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 *);
/*
PROC_HARDWARE,
PROC_SLABINFO,
PROC_PARPORT,
- PROC_OMIRR, /* whether enabled or not */
PROC_PPC_HTAB,
PROC_SOUND
};
unsigned int s_block_size; /* zone size, = 512 or = 1024 */
unsigned int s_block_size_1; /* block_size - 1 */
unsigned int s_block_size_bits; /* log2(block_size) */
- unsigned int s_block_size_ratio; /* BLOCK_SIZE / block_size */
- unsigned int s_block_size_ratio_bits; /* log2(block_size_ratio) */
+ unsigned int s_block_size_inc_bits; /* log2(block_size/BLOCK_SIZE) if >0 */
+ 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_kludge_symlinks; /* flag whether symlinks have a kludgey mode */
char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */
unsigned long s_ndatazones; /* total number of data zones */
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_ */
#define sv_type u.sysv_sb.s_type
#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_bits u.sysv_sb.s_block_size_bits
-#define sv_block_size_ratio u.sysv_sb.s_block_size_ratio
-#define sv_block_size_ratio_bits u.sysv_sb.s_block_size_ratio_bits
+#define sv_block_size_inc_bits u.sysv_sb.s_block_size_inc_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_kludge_symlinks u.sysv_sb.s_kludge_symlinks
#define sv_truncate u.sysv_sb.s_truncate
#define _LINUX_TIMER_H
/*
- * DON'T CHANGE THESE!! Most of them are hardcoded into some assembly language
- * 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
+ * Old-style timers. Please don't use for any new code.
*
+ * Numbering of these timers should be consecutive to minimize
+ * processing delays. [MJ]
*/
-#define BLANK_TIMER 0
-#define BEEP_TIMER 1
-#define RS_TIMER 2
-#define SWAP_TIMER 3
-
-#define HD_TIMER 16
-#define FLOPPY_TIMER 17
-#define NET_TIMER 19
-#define SOUND_TIMER 20
-#define COPRO_TIMER 21
-
-#define QIC02_TAPE_TIMER 22 /* hhb */
-#define MCD_TIMER 23
-
-#define HD_TIMER2 24
-#define GSCD_TIMER 25
-#define COMTROL_TIMER 26
+#define BLANK_TIMER 0 /* Console screen-saver */
+#define BEEP_TIMER 1 /* Console beep */
+#define RS_TIMER 2 /* RS-232 ports */
+#define SWAP_TIMER 3 /* Background pageout */
+#define BACKGR_TIMER 4 /* io_request background I/O */
+#define HD_TIMER 5 /* Old IDE driver */
+#define FLOPPY_TIMER 6 /* Floppy */
+#define QIC02_TAPE_TIMER 7 /* QIC 02 tape */
+#define MCD_TIMER 8 /* Mitsumi CDROM */
+#define GSCD_TIMER 9 /* Goldstar CDROM */
+#define COMTROL_TIMER 10 /* Comtrol serial */
+#define DIGI_TIMER 11 /* Digi serial */
-#define DIGI_TIMER 29
+#define COPRO_TIMER 31 /* 387 timeout for buggy hardware (boot only) */
struct timer_struct {
unsigned long expires;
extern void ipc_init(void);
#endif
+#ifdef CONFIG_MD_BOOT
+extern void md_setup(char *str,int *ints) __init;
+#endif
+
#ifdef __sparc__
extern int serial_console;
#endif
#ifdef CONFIG_BLK_DEV_FD
{ "fd", 0x0200 },
#endif
+#ifdef CONFIG_MD_BOOT
+ { "md", 0x0900 },
+#endif
#ifdef CONFIG_BLK_DEV_XD
{ "xda", 0x0d00 },
{ "xdb", 0x0d40 },
{ NULL, 0 }
};
-__initfunc(static void root_dev_setup(char *line, int *num))
+__initfunc(dev_t name_to_dev_t(char *line))
{
int base = 0;
if (strncmp(line,"/dev/",5) == 0) {
dev++;
} 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);
}
/*
#endif
#ifdef CONFIG_FTAPE
{ "ftape=", ftape_setup},
+#endif
+#ifdef CONFIG_MD_BOOT
+ { "md=", md_setup},
#endif
{ 0, 0 }
};
EXPORT_SYMBOL(vmtruncate);
/* filesystem internal functions */
+EXPORT_SYMBOL(update_atime);
EXPORT_SYMBOL(get_super);
EXPORT_SYMBOL(getname);
EXPORT_SYMBOL(putname);
EXPORT_SYMBOL(shrink_dcache_sb);
EXPORT_SYMBOL(shrink_dcache_parent);
EXPORT_SYMBOL(find_inode_number);
+EXPORT_SYMBOL(is_subdir);
#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
EXPORT_SYMBOL(do_nfsservctl);
--- /dev/null
+#
+# 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
* Thomas Bogendoerfer : Return ENODEV for dev_open, if there
* is no device open function.
* Andi Kleen : Fix error reporting for SIOCGIFCONF
+ * Régis Duchesne : Fix the argument check in dev_ioctl()
*
*/
return -EINVAL;
}
-
/*
* This function handles all "interface"-type I/O control requests. The actual
* 'doing' part of this is dev_ifsioc above.
return dev_ifname((struct ifreq *)arg);
}
+ /*
+ * Fetch the interface name from the info block.
+ */
+
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
return -EFAULT;
-
ifr.ifr_name[IFNAMSIZ-1] = 0;
-
#ifdef CONFIG_NET_ALIAS
colon = strchr(ifr.ifr_name, ':');
if (colon)
*colon = 0;
#endif
- /*
- * See which interface the caller is talking about.
- */
-
-#ifdef CONFIG_KERNELD
- dev_load(ifr.ifr_name);
-#endif
-
switch(cmd)
{
/*
case SIOCGIFMAP:
case SIOCGIFINDEX:
case SIOCGIFTXQLEN:
+#ifdef CONFIG_KERNELD
+ dev_load(ifr.ifr_name);
+#endif
ret = dev_ifsioc(&ifr, cmd);
if (!ret) {
#ifdef CONFIG_NET_ALIAS
case SIOCSIFTXQLEN:
if (!suser())
return -EPERM;
+#ifdef CONFIG_KERNELD
+ dev_load(ifr.ifr_name);
+#endif
rtnl_lock();
ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock();
default:
if (cmd >= SIOCDEVPRIVATE &&
cmd <= SIOCDEVPRIVATE + 15) {
+#ifdef CONFIG_KERNELD
+ dev_load(ifr.ifr_name);
+#endif
rtnl_lock();
ret = dev_ifsioc(&ifr, cmd);
rtnl_unlock();
if (IW_IS_SET(cmd)) {
if (!suser())
return -EPERM;
+#ifdef CONFIG_KERNELD
+ dev_load(ifr.ifr_name);
+#endif
rtnl_lock();
}
+#ifdef CONFIG_KERNELD
+ else
+ dev_load(ifr.ifr_name);
+#endif
ret = dev_ifsioc(&ifr, cmd);
if (IW_IS_SET(cmd))
rtnl_unlock();
#include <linux/major.h>
#include <linux/stat.h>
#include <linux/socket.h>
+#include <linux/file.h>
#include <linux/fcntl.h>
#include <linux/net.h>
#include <linux/interrupt.h>
static __inline__ int scm_check_creds(struct ucred *creds)
{
+ /* N.B. The test for suser should follow the credential check */
if (suser())
return 0;
if (creds->pid != current->pid ||
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 file **fpp;
- int *fdp = (int*)CMSG_DATA(cmsg);
- int i;
+ int i, num;
num = (cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)))/sizeof(int);
return -EINVAL;
/*
- * Verify the descriptors.
+ * Verify the descriptors and increment the usage count.
*/
for (i=0; i< num; i++)
{
- int fd;
-
- fd = fdp[i];
- if (fd < 0 || fd >= NR_OPEN)
- return -EBADF;
- if (current->files->fd[fd]==NULL)
+ int fd = fdp[i];
+ struct file *file;
+
+ if (fd < 0 || !(file = fget(fd)))
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;
}
void __scm_destroy(struct scm_cookie *scm)
{
- int i;
struct scm_fp_list *fpl = scm->fp;
+ int i;
- if (!fpl)
- return;
-
- for (i=fpl->count-1; i>=0; i--)
- close_fp(fpl->fp[i]);
-
- kfree(fpl);
+ if (fpl) {
+ scm->fp = NULL;
+ for (i=fpl->count-1; i>=0; i--)
+ close_fp(fpl->fp[i]);
+ kfree(fpl);
+ }
}
cmhdr.cmsg_level = level;
cmhdr.cmsg_type = type;
cmhdr.cmsg_len = cmlen;
- err = copy_to_user(cm, &cmhdr, sizeof cmhdr);
- if (!err)
- err = copy_to_user(CMSG_DATA(cm), data, cmlen - sizeof(struct cmsghdr));
- if (!err) {
- cmlen = CMSG_SPACE(len);
- msg->msg_control += cmlen;
- msg->msg_controllen -= cmlen;
- }
+
+ err = -EFAULT;
+ if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
+ goto out;
+ if (copy_to_user(CMSG_DATA(cm), data, cmlen - sizeof(struct cmsghdr)))
+ goto out;
+ cmlen = CMSG_SPACE(len);
+ msg->msg_control += cmlen;
+ msg->msg_controllen -= cmlen;
+ err = 0;
+out:
return err;
}
int fdmax = (msg->msg_controllen - sizeof(struct cmsghdr))/sizeof(int);
int fdnum = scm->fp->count;
- int *cmfptr;
- int err = 0;
- int i;
struct file **fp = scm->fp->fp;
+ int *cmfptr;
+ int err = 0, i;
if (fdnum < fdmax)
fdmax = fdnum;
for (i=0, cmfptr=(int*)CMSG_DATA(cm); i<fdmax; i++, cmfptr++)
{
- int new_fd = get_unused_fd();
- if (new_fd < 0)
+ int new_fd;
+ err = get_unused_fd();
+ if (err < 0)
break;
- current->files->fd[new_fd] = fp[i];
+ new_fd = err;
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)
msg->msg_controllen -= cmlen;
}
}
-
- if (err)
- i = 0;
+ if (i < fdnum)
+ msg->msg_flags |= MSG_CTRUNC;
/*
- * 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++) {
- msg->msg_flags |= MSG_CTRUNC;
- close_fp(fp[i]);
- }
-
- kfree (scm->fp);
- scm->fp = NULL;
+ __scm_destroy(scm);
}
struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
{
- int i;
struct scm_fp_list *new_fpl;
+ int i;
if (!fpl)
return NULL;
- new_fpl = kmalloc(fpl->count*sizeof(int) + sizeof(*fpl), GFP_KERNEL);
- if (!new_fpl)
- return NULL;
-
- memcpy(new_fpl, fpl, fpl->count*sizeof(int) + sizeof(*fpl));
-
- for (i=fpl->count-1; i>=0; i--)
- fpl->fp[i]->f_count++;
+ new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
+ if (new_fpl) {
+ memcpy(new_fpl, fpl, sizeof(*fpl));
+ for (i=fpl->count-1; i>=0; i--)
+ fpl->fp[i]->f_count++;
+ }
return new_fpl;
}
/*
* 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
u8 *c;
opt = ext;
ext += ext[1] + 2;
if (ext <= end)
- ic_do_bootp_ext(b, opt);
+ ic_do_bootp_ext(opt);
}
}
}
#! /usr/bin/perl
#
# checkconfig: find uses of CONFIG_* names without matching definitions.
+# Copyright abandoned, 1998, Michael Elizabeth Chastain <mailto:mec@shout.net>.
use integer;
+$| = 1;
+
foreach $file (@ARGV)
{
# Open this file.
# Pick up definitions.
if ( m/^#/o )
{
- $iLinuxConfig = $. if m/^#\s*include\s+<linux\/config\.h>/o;
- $configList{uc $1} = 1 if m/^#\s*include\s+<config\/(\S*)\.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{$1} = 1 if m/^#\s*define\s+CONFIG_(\w*)/o;
$configList{$1} = 1 if m/^#\s*undef\s+CONFIG_(\w*)/o;
}
# Look for usages.
next unless m/CONFIG_/o;
- WORD: while ( m/\bCONFIG_(\w*)/og )
+ WORD: while ( m/\bCONFIG_(\w+)/og )
{
$fUseConfig = 1;
last LINE if $iLinuxConfig;