S: USA
N: Patrick Mochel
-E: pat@osdl.org
+E: mochel@osdl.org
E: mochelp@infinity.powertie.org
D: PCI Power Management, ACPI work
S: 15275 SW Koll Parkway, Suite H
# Eric S. Raymond <mailto:esr@thyrsus.com>
# Steven Cole <mailto:elenstev@mesatop.com>
#
-# Merged version 2.49: Current with 2.4.15-pre1 and 2.4.13-ac8.
+# Merged version 2.61: current with 2.4.16/2.5.1-pre1.
#
# This version of the Linux kernel configuration help texts
-# corresponds to the kernel versions 2.4.x.
+# corresponds to kernel versions 2.4.x and 2.5.x.
#
# Translations of this file available on the WWW:
#
# - Russian, by <mailto:kaf@linux.nevod.perm.su>, at
# <http://nevod.perm.su/service/linux/doc/kernel/Configure.help>
# - French, by Pierre Tane <mailto:tanep@bigfoot.com>, at
-# <http://www.traduc.org/kernelfr>
+# <http://www.traduc.org/kernelfr/>
# - Polish, by Dominik Mierzejewski <mailto:dmierzej@elka.pw.edu.pl>, at
# <http://home.elka.pw.edu.pl/~dmierzej/linux/kernel/>
-# - German, by SuSE, at <http://www.suse.de/~ke/kernel>. This patch
+# - German, by SuSE, at <http://www.suse.de/~ke/kernel/>. This patch
# also includes infrastructure to support different languages.
+# - Catalan, by Antoni Bella <mailto:bella5@teleline.es>, at
+# <http://www.terra.es/personal7/bella5/traduccions.htm>
#
# To access a document on the WWW, you need to have a direct Internet
# connection and a browser program such as netscape or lynx. If you
See also the <file:Documentation/smp.tex>,
<file:Documentation/smp.txt>, <file:Documentation/i386/IO-APIC.txt>,
- <file:Documentation/nmi_watchdog.txt> and the SMP-FAQ on the WWW at
- <http://www.irisa.fr/prive/mentre/smp-faq/>.
+ <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+ <http://www.linuxdoc.org/docs.html#howto>.
If you don't know what to do here, say N.
To fine-tune ATA/IDE drive/interface parameters for improved
performance, look for the hdparm package at
- <http://www.ibiblio.org/pub/Linux/system/hardware>.
+ <ftp://ibiblio.org/pub/Linux/system/hardware/>.
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),
CD-ROM drive, you can say N to all other CD-ROM options, but be sure
to say Y or M to "ISO 9660 CD-ROM file system support".
- Read the CD-ROM-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto> and
- <file:Documentation/cdrom/ide-cd>. Note that older versions of lilo
- (the Linux boot loader) cannot properly deal with IDE/ATAPI CD-ROMs,
- so install lilo-16 or higher, available from
- <ftp://metalab.unc.edu/pub/Linux/system/boot/lilo>.
+ Note that older versions of LILO (LInux LOader) cannot properly deal
+ with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from
+ <ftp://brun.dyndns.org/pub/linux/lilo/>.
If you want to compile the driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
for these drives, but you can change that by saying Y to the
following question "Use DMA by default when available". You can get
the latest version of the hdparm utility from
- <ftp://metalab.unc.edu/pub/Linux/system/hardware/>.
+ <ftp://ibiblio.org/pub/Linux/system/hardware/>.
Read the comments at the beginning of <file:drivers/ide/ide-dma.c>
and the file <file:Documentation/ide.txt> for more information.
It is normally safe to answer Y; however, the default is N.
-ATA Work(s) In Progress (EXPERIMENTAL)\8b
+ATA Work(s) In Progress (EXPERIMENTAL)
CONFIG_IDEDMA_PCI_WIP
If you enable this you will be able to use and test highly
developmental projects. If you say N, the configurator will
Pacific Digital A-DMA support (EXPERIMENTAL)
CONFIG_BLK_DEV_PDC_ADMA
- Please read the comments at the top of <file:drivers/ide/pdcadma.c>.
+ Please read the comments at the top of <file:drivers/ide/ide-pci.c>.
3ware Hardware ATA-RAID support
CONFIG_BLK_DEV_3W_XXXX_RAID
Special UDMA Feature
CONFIG_PDC202XX_BURST
- For PDC20246, PDC20262, PDC20265 and PDC20267 Ultra DMA chipsets.
- Designed originally for PDC20246/Ultra33 that has BIOS setup
- failures when using 3 or more cards.
+ This option causes the pdc202xx driver to enable UDMA modes on the
+ PDC202xx even when the PDC202xx BIOS has not done so.
- Unknown for PDC20265/PDC20267 Ultra DMA 100.
+ It was originally designed for the PDC20246/Ultra33, whose BIOS will
+ only setup UDMA on the first two PDC20246 cards. It has also been
+ used succesfully on a PDC20265/Ultra100, allowing use of UDMA modes
+ when the PDC20265 BIOS has been disabled (for faster boot up).
Please read the comments at the top of
<file:drivers/ide/pdc202xx.c>.
<file:Documentation/ide.txt> and <file:drivers/ide/pdc4030.c> files
for more info.
-# This is for Linus's tree.
-QDI QD6580 support
-CONFIG_BLK_DEV_QD6580
- This driver is enabled at runtime using the "ide0=qd6580" kernel
- boot parameter. It permits faster I/O speeds to be set. See the
- <file:Documentation/ide.txt> and <file:drivers/ide/qd6580.c> for
- more info.
-
-# This is for Alan's tree. Note the name difference.
QDI QD65XX support
CONFIG_BLK_DEV_QD65XX
This driver is enabled at runtime using the "ide0=qd65xx" kernel
CONFIG_PARIDE_PG
This option enables a special high-level driver for generic ATAPI
devices connected through a parallel port. The driver allows user
- programs, such as cdrecord, to send ATAPI commands directly to a
+ programs, such as cdrtools, to send ATAPI commands directly to a
device.
If you chose to build PARIDE support into your kernel, you may
This driver implements an API loosely related to the generic SCSI
driver. See <file:include/linux/pg.h>. for details.
- You can obtain the most recent version of cdrecord from
+ You can obtain the most recent version of cdrtools from
<ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/>. Versions 1.6.1a3 and
later fully support this driver.
controller, you do not need to say Y here.
More information about Software RAID on Linux is contained in the
- Software-RAID mini-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>. There you will also
- learn where to get the supporting user space utilities raidtools.
+ Software RAID mini-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>. There you will also learn
+ where to get the supporting user space utilities raidtools.
If unsure, say N.
If unsure, say N.
-# AC tree only
Support for IDE Raid controllers
CONFIG_BLK_DEV_ATARAID
Say Y or M if you have an IDE Raid controller and want linux
has its own Raid drivers, which you should use if you need better
performance.
-# AC tree only
Support Promise software RAID (Fasttrak(tm))
CONFIG_BLK_DEV_ATARAID_PDC
Say Y or M if you have a Promise Fasttrak (tm) Raid controller
If you choose to compile this as a module, the module will be called
pdcraid.o.
-# AC tree only
Highpoint 370 software RAID
CONFIG_BLK_DEV_ATARAID_HPT
Say Y or M if you have a Highpoint HPT 370 Raid controller
This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
kernel that runs on these, say Y here. For details about Linux on
the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
- <http://oss.sgi.com/mips>.
+ <http://oss.sgi.com/mips/>.
Support for Algorithmics P4032 (EXPERIMENTAL)
CONFIG_ALGOR_P4032
This is an evaluation board of the British company Algorithmics.
The board uses the R4300 and a R5230 CPUs. For more information
- about this board see <http://www.algor.co.uk>.
+ about this board see <http://www.algor.co.uk/>.
Support for BAGET MIPS series
CONFIG_BAGET_MIPS
This enables support for the Baget, a Russian embedded system. For
more details about the Baget see the Linux/MIPS FAQ on
- <http://oss.sgi.com/mips>.
+ <http://oss.sgi.com/mips/>.
Baget AMD LANCE support
CONFIG_BAGETLANCE
Support for DECstations
CONFIG_DECSTATION
This enables support for DEC's MIPS based workstations. For details
- see the Linux/MIPS FAQ on <http://oss.sgi.com/mips> and the
- DECstation porting pages on <http://decstation.unix-ag.org>.
+ see the Linux/MIPS FAQ on <http://oss.sgi.com/mips/> and the
+ DECstation porting pages on <http://decstation.unix-ag.org/>.
If you have one of the following DECstation Models you definitely
want to choose R4xx0 for the CPU Type:
Support for the Momentum Computer Ocelot SBC
CONFIG_MOMENCO_OCELOT
The Ocelot is a MIPS-based Single Board Computer (SBC) made by
- Momentum Computer <http://www.momenco.com>.
+ Momentum Computer <http://www.momenco.com/>.
Support for NEC DDB Vrc-5074
CONFIG_DDB5074
evaluation board.
Features : kernel debugging, serial terminal, NFS root fs, on-board
- ether port (Need an additional patch at <http://linux.junsun.net>),
+ ether port (Need an additional patch at <http://linux.junsun.net/>),
USB, AC97, PCI, PCI VGA card & framebuffer console, IDE controller,
PS2 keyboard, PS2 mouse, etc.
evaluation board.
Features : kernel debugging, serial terminal, NFS root fs, on-board
- ether port (Need an additional patch at <http://linux.junsun.net>),
+ ether port (Need an additional patch at <http://linux.junsun.net/>),
USB, AC97, PCI, etc.
Support for MIPS Atlas board
This is a machine with a R4000 100 MHz CPU. To compile a Linux
kernel that runs on these, say Y here. For details about Linux on
the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
- <http://oss.sgi.com/mips>.
+ <http://oss.sgi.com/mips/>.
Enable Qtronix 990P Keyboard Support
CONFIG_QTRONIX_KEYBOARD
This is a machine with a R4000 100 MHz CPU. To compile a Linux
kernel that runs on these, say Y here. For details about Linux on
the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
- <http://oss.sgi.com/mips>.
+ <http://oss.sgi.com/mips/>.
Support for SNI RM200 PCI
CONFIG_SNI_RM200_PCI
CONFIG_PCMCIA_NINJA_SCSI
If you intend to attach this type of PCMCIA SCSI host adapter to
your computer, say Y here and read
- <file:Documentation/README.nsp_cs>.
+ <file:Documentation/README.nsp_cs.eng>.
This driver is also available as a module called nsp_cs.o ( =
code which can be inserted in and removed from the running kernel
of which are given in <file:Documentation/Changes>.
For a general introduction to Linux networking, it is highly
- recommended to read the NET-3-HOWTO, available from
+ recommended to read the NET-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>.
Socket filtering
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+Multiple port match support
+CONFIG_IP6_NF_MATCH_MULTIPORT
+ Multiport matching allows you to match TCP or UDP packets based on
+ a series of source or destination ports: normally a rule can only
+ match a single range of ports.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
+Owner match support
+CONFIG_IP6_NF_MATCH_OWNER
+ Packet owner matching allows you to match locally-generated packets
+ based on who created them: the user, group, process or session.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
Packet filtering
CONFIG_IP6_NF_FILTER
Packet filtering defines a table `filter', which has a series of
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
+LOG target support
+CONFIG_IP6_NF_TARGET_LOG
+ This option adds a `LOG' target, which allows you to create rules in
+ any iptables table which records the packet header to the syslog.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
SYN flood protection
CONFIG_SYN_COOKIES
Normal TCP/IP networking is open to an attack known as "SYN
To find out what type of Alpha system you have, you may want to
check out the Linux/Alpha FAQ, accessible on the WWW from
- <http://www.alphalinux.org>. In summary:
+ <http://www.alphalinux.org/>. In summary:
Alcor/Alpha-XLT AS 600
Alpha-XL XL-233, XL-266
which is command line driven, and ARC, which uses menus and arrow
keys. Details about the Linux/Alpha booting process are contained in
the Linux/Alpha FAQ, accessible on the WWW from
- <http://www.alphalinux.org>.
+ <http://www.alphalinux.org/>.
The usual way to load Linux on an Alpha machine is to use MILO
(a bootloader that lets you pass command line parameters to the
The user level application needed to use this driver can be found at
the IBM Linux Technology Center (LTC) web site:
- http://www.ibm.com/linux/ltc/
+ <http://www.ibm.com/linux/ltc/>.
If you own one of the above IBM Thinkpads which has the Mwave chipset
in it, say Y.
example, used on modern desktops as well as laptops, is USB.
Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
- software (at <http://linux-hotplug.sourceforge.net>) and install it.
+ software (at <http://linux-hotplug.sourceforge.net/>) and install it.
Then your kernel will automatically call out to a user mode "policy
agent" (/sbin/hotplug) to load modules and set up software needed
to use devices as you hotplug them.
If unsure, say Y.
+i82092 compatible bridge support
+CONFIG_I82092
+ This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device,
+ found in some older laptops and more commonly in evaluation boards for the
+ chip.
+
i82365 compatible host bridge support
CONFIG_I82365
Say Y here to include support for ISA-bus PCMCIA host bridges that
The program SVGATextMode can be used to utilize SVGA video cards to
their full potential in text mode. Download it from
- <ftp://metalab.unc.edu/pub/Linux/utils/console>.
+ <ftp://ibiblio.org/pub/Linux/utils/console/>.
Say Y.
module will be called aty128fb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
-# AC tree only
Maxine (Personal DECstation) onboard framebuffer support
CONFIG_FB_MAXINE
Say Y here to directly support the on-board framebuffer in the
Maxine (5000/20, /25, /33) version of the DECstation. There is a
page dedicated to Linux on DECstations at <http://decstation.unix-ag.org/>.
-# AC tree only
PMAG-BA TURBOchannel framebuffer support
CONFIG_FB_PMAG_BA
Say Y here to directly support the on-board PMAG-BA framebuffer in
the 5000/1xx versions of the DECstation. There is a page dedicated
to Linux on DECstations at <http://decstation.unix-ag.org/>.
-# AC tree only
PMAGB-B TURBOchannel framebuffer support
CONFIG_FB_PMAGB_B
Say Y here to directly support the on-board PMAGB-B framebuffer in
Say Y here if you intend to run this kernel on a FutureTV (nee Nexus
Electronics) StrongARM PCI card.
-P720T
-CONFIG_ARCH_P720T
- Say Y here if you intend to run this kernel on the ARM Prospector
- 720T.
+ANAKIN Vehicle Telematics Platform
+CONFIG_ARCH_ANAKIN
+ The Anakin is a StrongArm based SA110 - 2 DIN Vehicle Telematics Platform.
+ 64MB SDRAM - 4 Mb Flash - Compact Flash Interface - 1 MB VRAM
+
+ On board peripherals:
+ * Front display: 400x234 16 bit TFT touchscreen
+ * External independent second screen interface
+ * CAN controller SJA1000
+ * USB host controller
+ * 6 channel video codec with hardware overlay
+ * Smartcard reader
+ * IrDa
+
+ Modules interfaced over the Multi Media Extension slots:
+ * A communication card
+ Wavecom GPRS modem
+ uBlock GPS
+ Bosch DAB module
+ * An audio card ( 4 * 40W, AC97 Codec, I2S)
+
+Altera Excalibur XA10 Dev Board
+ARCH_CAMELOT
+ This enables support for Altera's Excalibur XA10 development board.
+ If you would like to build your kernel to run on one of these boards
+ then you must say 'Y' here. Otherwise say 'N'
Link-Up Systems LCD support
CONFIG_FB_L7200
a module, say M here and read <file:Documentation/modules.txt>.
You can pass several parameters to the driver at boot time or at
- module load time. The parameters look like "video=matrox:XXX", where
- the meaning of XXX can be found at the end of the main source file
- (<file:drivers/video/matroxfb.c>). Please see
- <file:Documentation/fb/matroxfb.txt>.
+ module load time. The parameters look like "video=matrox:XXX", and
+ are described in <file:Documentation/fb/matroxfb.txt>.
Matrox Millennium I/II support
CONFIG_FB_MATROX_MILLENIUM
The driver starts in monitor mode and you must use the matroxset
tool (available at
- <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest>) to switch it to
+ <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to switch it to
PAL or NTSC or to swap primary and secondary head outputs.
Secondary head driver also always start in 640x480 resolution, you
must use fbset to change it.
The driver starts in monitor mode and currently does not support
output in TV modes. You must use the matroxset tool (available
- at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest>) to swap
+ at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to swap
primary and secondary head outputs. Secondary head driver always
start in 640x480 resolution and you must use fbset to change it.
This is the frame buffer device driver for the SiS 630 and 640 Super
Socket 7 UMA cards. Specs available at <http://www.sis.com.tw/>.
-# AC tree only
SIS 630/540/730 support
CONFIG_FB_SIS_300
This is the frame buffer device driver for the SiS 630 and related
Super Socket 7 UMA cards. Specs available at
<http://www.sis.com.tw/>.
-# AC tree only
SIS 315H/315 support
CONFIG_FB_SIS_315
This is the frame buffer device driver for the SiS 315 graphics
is at
<http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
-# AC tree only
ATI Radeon display support
CONFIG_FB_RADEON
Choose this option if you want to use an ATI Radeon graphics card as
drive, PLIP link (Parallel Line Internet Protocol is mainly used to
create a mini network by connecting the parallel ports of two local
machines) etc., then you need to say Y here; please read
- <file:Documentation/parport.txt> and drivers/parport/BUGS-parport.
+ <file:Documentation/parport.txt> and
+ <file:drivers/parport/BUGS-parport>.
For extensive information about drivers for many devices attaching
to the parallel port see <http://www.torque.net/linux-pp.html> on
used for local networks of Windows machines. You need it if you
want to access Novell NetWare file or print servers using the Linux
Novell client ncpfs (available from
- <ftp://metalab.unc.edu/pub/Linux/system/filesystems/>) or from
+ <ftp://platan.vc.cvut.cz/pub/linux/ncpfs/>) or from
within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO,
available from <http://www.linuxdoc.org/docs.html#howto>). In order
to do the former, you'll also have to say Y to "NCP file system
To turn your Linux box into a fully featured NetWare file server and
IPX router, say Y here and fetch either lwared from
- <ftp://metalab.unc.edu/pub/Linux/system/network/daemons/> or
- mars_nwe from <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs>. For more
+ <ftp://ibiblio.org/pub/Linux/system/network/daemons/> or
+ mars_nwe from <ftp://www.compu-art.de/mars_nwe/>. For more
information, read the IPX-HOWTO available from
<http://www.linuxdoc.org/docs.html#howto>.
'special' sockets to sockets listening on the primary network is
disabled. This might break existing applications, especially RIP/SAP
daemons. A RIP/SAP daemon that works well with the full internal net
- can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs>.
+ can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/>.
If you don't know what you are doing, say N.
network link driver", "Routing messages" and "Network packet
filtering". The first two are required to allow configuration via
rtnetlink (currently you need Alexey Kuznetsov's iproute2 package
- from <ftp://ftp.inr.ac.ru>). The "Network packet filtering" option
+ from <ftp://ftp.inr.ac.ru/>). The "Network packet filtering" option
will be required for the forthcoming routing daemon to work.
See <file:Documentation/networking/decnet.txt> for more information.
Amateur Radio support
CONFIG_HAMRADIO
If you want to connect your Linux box to an amateur radio, answer Y
- here. You want to read <http://www.tapr.org/tapr/html/pkthome.html>
- and the HAM-HOWTO and the AX25-HOWTO, both available from
- <http://www.linuxdoc.org/docs.html#howto>.
+ here. You want to read <http://www.tapr.org/tapr/html/pkthome.html> and
+ the AX25-HOWTO, available from <http://www.linuxdoc.org/docs.html#howto>.
Note that the answer to this question won't directly affect the
kernel: saying N will just cause the configurator to skip all
connect to a parallel interface. The driver supports the picpar and
par96 designs. To configure the driver, use the sethdlc utility
available in the standard ax25 utilities package. For information on
- the modems, see <http://www.baycom.de> and the file
+ the modems, see <http://www.baycom.de/> and the file
<file:Documentation/networking/baycom.txt>.
If you want to compile this driver as a module ( = code which can be
connect to a parallel interface. The driver supports the EPP
designs. To configure the driver, use the sethdlc utility available
in the standard ax25 utilities package. For information on the
- modems, see <http://www.baycom.de> and the file
+ modems, see <http://www.baycom.de/> and the file
<file:Documentation/networking/baycom.txt>.
If you want to compile this driver as a module ( = code which can be
driver and still provided in case this driver does not work with
your serial interface chip. To configure the driver, use the sethdlc
utility available in the standard ax25 utilities package. For
- information on the modems, see <http://www.baycom.de> and
+ information on the modems, see <http://www.baycom.de/> and
<file:Documentation/networking/baycom.txt>.
If you want to compile this driver as a module ( = code which can be
the full-duplex driver. This driver is depreciated. To configure
the driver, use the sethdlc utility available in the standard ax25
utilities package. For information on the modems, see
- <http://www.baycom.de> and
+ <http://www.baycom.de/> and
<file:Documentation/networking/baycom.txt>.
If you want to compile this driver as a module ( = code which can be
- etc...
For more informations, please refer to:
- <http://www.freshmeat.net/projects/etherdivert>
+ <http://diverter.sourceforge.net/>
<http://perso.wanadoo.fr/magpie/EtherDivert.html>
If unsure, say N.
user processes. It does so by creating a new socket family,
PF_NETLINK. Over this socket, the kernel can send and receive
datagrams carrying information. It is documented on many systems in
- netlink(7), a HOWTO is provided as well, for example on
- <http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html>.
+ netlink(7).
So far, the kernel uses this feature to publish some network related
information if you say Y to "Routing messages", below. You also need
CONFIG_RTNETLINK
If you say Y here, user space programs can receive some network
related routing information over the netlink. 'rtmon', supplied
- with the iproute2 package (<ftp://ftp.inr.ac.ru>), can read and
+ with the iproute2 package (<ftp://ftp.inr.ac.ru/>), can read and
interpret this data. Information sent to the kernel over this link
is ignored.
control memory (128K-1KVC, 512K-4KVC), the size of the packet
memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3,
UTP155, UTP25, DS3 and E3). Go to:
- www.iphase.com/products/ClassSheet.cfm?ClassID=ATM
+ <http://www.iphase.com/products/ClassSheet.cfm?ClassID=ATM>
for more info about the cards. Say Y (or M to compile as a module
named iphase.o) here if you have one of these cards.
messages is controlled by a bitmap. This may be specified as a
module argument (kernel command line argument as well?), changed
dynamically using an ioctl (Get the debug utility, iadbg, from
- <ftp://ftp.iphase.com/pub/atm/pci>).
+ <ftp://ftp.iphase.com/pub/atm/pci/>).
See the file <file:drivers/atm/iphase.h> for the meanings of the
bits in the mask.
You also need to say Y here if you want support for the parallel
port version of the 100 MB IOMEGA ZIP drive.
- Please read the SCSI-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>. The
- SCSI-Programming-HOWTO contains information about how to add or
- remove an SCSI device from a running Linux machine without
- rebooting.
-
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 scsi_mod.o. If you want to compile it as
tape drives (ADR-x0) that supports the standard SCSI-2 commands for
tapes (QIC-157) and can be driven by the standard driver st.
For more information, you may have a look at the SCSI-HOWTO
- <ftp://metalab.unc.edu/pub/Linux/docs/HOWTO> and
+ <http://www.linuxdoc.org/docs.html#howto> and
<file:drivers/scsi/README.osst> in the kernel source.
More info on the OnStream driver may be found on
<http://linux1.onstream.nl/test/>
directly, so you need some additional software which knows how to
talk to these devices using the SCSI protocol:
- For scanners, look at SANE (<http://www.mostang.com/sane>). For CD
- writer software look at cdrecord
+ For scanners, look at SANE (<http://www.mostang.com/sane/>). For CD
+ writer software look at Cdrtools
(<http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/cdrecord.html>)
- and for burning a "disk at once": cdrdao
- (<http://www.ping.de/sites/daneb/cdrdao.html>). Cdparanoia is a high
- quality digital reader of audio CDs (<http://www.xiph.org/paranoia>).
+ and for burning a "disk at once": CDRDAO
+ (<http://cdrdao.sourceforge.net/>). Cdparanoia is a high
+ quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>).
For other devices, it's possible that you'll have to write the
driver software yourself. Please read the file
<file:Documentation/scsi-generic.txt> for more information.
This is support for BusLogic MultiMaster and FlashPoint SCSI Host
Adapters. Consult the SCSI-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>, and the files
- README.BusLogic and README.FlashPoint in drivers/scsi for more
- information. If this driver does not work correctly without
- modification, please contact the author, Leonard N. Zubkoff, by
- email to lnz@dandelion.com.
+ <file:drivers/scsi/README.BusLogic> and
+ <file:drivers/scsi/README.FlashPoint> for more information. If this
+ driver does not work correctly without modification, please contact
+ the author, Leonard N. Zubkoff, by email to lnz@dandelion.com.
You can also build this driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
If your system has problems using this new major version of the
SYM53C8XX driver, you may switch back to driver version 1.
- Please read drivers/scsi/sym53c8xx_2/Documentation.txt for more
+ Please read <file:drivers/scsi/sym53c8xx_2/Documentation.txt> for more
information.
PCI DMA addressing mode
NCR53c406a SCSI support
CONFIG_SCSI_NCR53C406A
This is support for the NCR53c406a SCSI host adapter. For user
- configurable parameters, check out <file:drivers/scsi/NCR53c406.c>
+ configurable parameters, check out <file:drivers/scsi/NCR53c406a.c>
in the kernel source. Also read the SCSI-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>.
This is a driver for RAID/SCSI Disk Array Controllers (EISA/ISA/PCI)
manufactured by Intel/ICP vortex (an Intel Company). It is documented
- in the kernel source in drivers/scsi/gdth.c and drivers/scsi/gdth.h.
+ in the kernel source in <file:drivers/scsi/gdth.c> and
+ <file:drivers/scsi/gdth.h.>
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
Normally, your access provider has to support SLIP in order for you
to be able to use it, but there is now a SLIP emulator called SLiRP
- around (available via FTP (user: anonymous) from
- <ftp://metalab.unc.edu/pub/Linux/system/network/serial/>) which
+ around (available from
+ <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
allows you to use SLIP over a regular dial up shell connection. If
you plan to use SLiRP, make sure to say Y to CSLIP, below. The
NET-3-HOWTO, available from
on both ends. Ask your access provider if you are not sure and
answer Y, just in case. You will still be able to use plain SLIP. If
you plan to use SLiRP, the SLIP emulator (available from
- <ftp://metalab.unc.edu/pub/Linux/system/network/serial/>) which
+ <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
allows you to use SLIP over a regular dial up shell connection, you
definitely want to say Y here. The NET-3-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>, explains how to configure
This driver requires a specially patched pppd daemon. The patch to
pppd, along with binaries of a patched pppd package can be found at:
- <http://www.shoshin.uwaterloo.ca/~mostrows>.
+ <http://www.shoshin.uwaterloo.ca/~mostrows/>.
Wireless LAN (non-hamradio)
CONFIG_NET_RADIO
Some user-level drivers for scarab devices which don't require
special kernel support are available from
- <ftp://shadow.cabi.net/pub/Linux>.
+ <ftp://shadow.cabi.net/pub/Linux/>.
STRIP (Metricom Starmode radio IP)
CONFIG_STRIP
configure your card and that /etc/pcmcia/wireless.opts works :
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
-Apple Airport support (built-in)
-CONFIG_APPLE_AIRPORT
- Enable support for the Apple Airport card (which is essentially a
- Lucent Orinoco card with a non-standard interface) built into some
- newer Apple Macintosh machines.
-
Hermes 802.11b in PLX9052 based PCI adaptor support
CONFIG_PLX_HERMES
Enable support for PCMCIA cards supported by the "Hermes" (aka
CONFIG_APPLE_AIRPORT
Say Y here to support the Airport 802.11b wireless Ethernet hardware
built into the Macintosh iBook and other recent PowerPC-based
- Macintosh machines.
+ Macintosh machines. This is essentially a Lucent Orinoco card with
+ a non-standard interface
Xircom Netwave AirSurfer wireless support
CONFIG_PCMCIA_NETWAVE
the price of an external router. If you have one of those cards and
wish to use your Linux box as a WAN router, say Y here and also to
the WAN driver for your card, below. You will then need the
- wan-tools package which is available from <ftp://ftp.sangoma.com>.
+ wan-tools package which is available from <ftp://ftp.sangoma.com/>.
Read <file:Documentation/networking/wan-router.txt> for more
information.
up. Look at the <http://www.fi.muni.cz/~kas/cosa/> for more
information about the cards (including the pointer to the user-space
utilities). You can also read the comment at the top of the
- <file:drivers/net/cosa.c> for details about the cards and the driver
+ <file:drivers/net/wan/cosa.c> for details about the cards and the driver
itself.
The driver will be compiled as a module ( = code which can be
CONFIG_DSCC4
This is a driver for Etinc PCISYNC boards based on the Infineon
(ex. Siemens) DSCC4 chipset. It is supposed to work with the four
- ports card. Take a look at <http://www.cogenit.fr/dscc4>
+ ports card. Take a look at <http://www.cogenit.fr/dscc4/>
for further informations about the driver and his configuration.
The driver will be compiled as a module ( = code which can be
additional external hardware.
To change setting such as syncPPP vs cisco HDLC or clock source you
- will need lmcctl. It is available at <ftp://ftp.lanmedia.com>.
+ will need lmcctl. It is available at <ftp://ftp.lanmedia.com/>.
This code is also available as a module called lmc.o ( = code
which can be inserted in and removed from the running kernel
module will be called sbni.o).
You can find more information and last versions of drivers and
- utilities at <http://www.granch.ru>. If you have any question you
+ utilities at <http://www.granch.ru/>. If you have any question you
can send email to sbni@granch.ru.
Say N if unsure.
Router".
You will need the wan-tools package which is available from
- <ftp://ftp.sangoma.com>. Read
+ <ftp://ftp.sangoma.com/>. Read
<file:Documentation/networking/wan-router.txt> for more information.
Note that the answer to this question won't directly affect the
Sangoma WANPIPE(tm) multiprotocol cards
CONFIG_VENDOR_SANGOMA
- WANPIPE from Sangoma Technologies Inc. (<http://www.sangoma.com>)
+ WANPIPE from Sangoma Technologies Inc. (<http://www.sangoma.com/>)
is a family of intelligent multiprotocol WAN adapters with data
transfer rates up to 4Mbps. They are also known as Synchronous
Data Link Adapters (SDLA) and are designated as S514-PCI or
Read <file:Documentation/networking/comx.txt> for help on
configuring and using COMX interfaces. Further info on these cards
- can be found at <http://www.itc.hu> or <info@itc.hu>.
+ can be found at <http://www.itc.hu/> or <info@itc.hu>.
You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
use this driver.
Cyclom 2X(tm) multiprotocol cards
CONFIG_CYCLADES_SYNC
- Cyclom 2X from Cyclades Corporation (<http://www.cyclades.com> and
- <http://www.cyclades.com.br)> is an intelligent multiprotocol WAN
+ Cyclom 2X from Cyclades Corporation (<http://www.cyclades.com/> and
+ <http://www.cyclades.com.br/>) is an intelligent multiprotocol WAN
adapter with data transfer rates up to 512 Kbps. These cards support
the X.25 and SNA related protocols. If you have one or more of these
cards, say Y to this option. The next questions will ask you about
While no documentation is available at this time please grab the
wanconfig tarball in
- <http://www.conectiva.com.br/~acme/cycsyn-devel> (with minor changes
+ <http://www.conectiva.com.br/~acme/cycsyn-devel/> (with minor changes
to make it compile with the current wanrouter include files; efforts
are being made to use the original package available at
- <ftp://ftp.sangoma.com>).
+ <ftp://ftp.sangoma.com/>).
Feel free to contact me or the cycsyn-devel mailing list at
acme@conectiva.com.br and cycsyn-devel@bazar.conectiva.com.br for
is a 10Mbit/sec Ethernet controller. Product overview and specs at
<http://www.national.com/pf/DP/DP83902A.html>.
-CompactFlash Connection Area
-CONFIG_CF_AREA5
- If your board has "Directly Connected" CompactFlash, You should
- select the area where your CF is connected to.
-
- - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
- - "Area6" if it is connected to Area 6 (0x18000000)
-
- "Area6" will work for most boards. For ADX, select "Area5".
+ If unsure, say N.
3COM cards
CONFIG_NET_VENDOR_3COM
module, say M here and read <file:Documentation/modules.txt> as well
as <file:Documentation/networking/net-modules.txt>.
-EtherExpressPro support/EtherExpress 10 (i82595) support
+EtherExpressPro and EtherExpress 10 (i82595) support
CONFIG_EEXPRESS_PRO
If you have a network (Ethernet) card of this type, say Y. This
driver supports intel i82595{FX,TX} based boards. Note however
driver and as a module ( = code which can be inserted in and removed
from the running kernel whenever you want). If you want to compile
it as a module, say M here and read <file:Documentation/modules.txt>
- as well as <file:Documentation/networking/net-modules.txt>.
- If you plan to use more than one network card under linux, read the
- Multiple-Ethernet-mini-HOWTO, available from
- <ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini>. The only
+ as well as <file:Documentation/networking/net-modules.txt>. The only
currently supported card is the IBM LAN Adapter/A for Ethernet. It
will both support 16K and 32K memory windows, however a 32K window
gives a better security against packet losses. Usage of multiple
CONFIG_FEALNX
Say Y here to support the Mysom MTD-800 family of PCI-based Ethernet
cards. Specifications and data at
- <http:www.myson.com.hk/mtd/datasheet>.
+ <http://www.myson.com.hk/mtd/datasheet/>.
ICL EtherTeam 16i/32 support
CONFIG_ETH16I
Davicom DM910x/DM980x support
CONFIG_DM9102
This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
- Davicom (<http://www.davicom.com.tw>). If you have such a network
+ Davicom (<http://www.davicom.com.tw/>). If you have such a network
(Ethernet) card, say Y. Some information is contained in the file
<file:Documentation/networking/dmfe.txt>.
Wake On Lan, and PCI 100/16/4 adapters.
If you have such an adapter, say Y and read the Token-Ring
- mini-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>.
+ mini-HOWTO, available from <http://www.linuxdoc.org/docs.html#howto>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
Also read <file:Documentation/networking/olympic.txt> or check the
Linux Token Ring Project site for the latest information at
- <http://www.linuxtr.net>.
+ <http://www.linuxtr.net/>.
IBM Lanstreamer chipset PCI adapter support
CONFIG_IBMLS
This is support for IBM Lanstreamer PCI Token Ring Cards.
If you have such an adapter, say Y and read the Token-Ring
- mini-HOWTO available via FTP (user:anonymous) from
- <ftp://metalab.unc/edu/pub/Linux/docs/HOWTO>.
+ mini-HOWTO, available from <http://www.linuxdoc.org/docs.html#howto>.
This driver is also available as a modules ( = code which can be
inserted in and removed from the running kernel whenever you want).
say Y to "QoS and/or fair queueing" above.
To set up and configure shaper devices, you need the shapecfg
- program, available from <ftp://shadow.cabi.net/pub/Linux> in the
+ program, available from <ftp://shadow.cabi.net/pub/Linux/> in the
shaper package.
This driver is also available as a module ( = code which can be
Say Y here only if you have two CD-ROM controller cards of this type
(usually only if you have more than four drives). You should enter
the parameters for the second, third and fourth interface card into
- <file:include/linux/sbpcd.h> before compiling the new kernel. Read
+ <file:drivers/cdrom/sbpcd.h> before compiling the new kernel. Read
the file <file:Documentation/cdrom/sbpcd>.
Matsushita/Panasonic, ... third CD-ROM controller support
NVRAM on the Momenco Ocelot board. If you have one of these boards
and would like access to either of these, say 'Y'.
+Support for absent chips in bus mapping
+CONFIG_MTD_ABSENT
+ This option enables support for a dummy probing driver used to
+ allocated placeholder MTD devices on systems that have socketed
+ or removable media. Use of this driver as a fallback chip probe
+ preserves the expected registration order of MTD device nodes on
+ the system regardless of media presence. Device nodes created
+ with this driver will return -ENODEV upon access.
+
+MTD Emulation using block device
+CONFIG_MTD_BLKMTD
+ This driver allows a block device to appear as an MTD. It would
+ generally be used in the following cases:
+
+ Using Compact Flash as an MTD, these usually present themselves to
+ the system as an ATA drive.
+ Testing MTD users (eg JFFS2) on large media and media that might
+ be removed during a write (using the floppy drive).
+
+Cirrus CDB89712 evaluation board mappings
+CONFIG_MTD_CDB89712
+ This enables access to the flash or ROM chips on the CDB89712 board.
+ If you have such a board, say 'Y'.
+
+Detect non-CFI AMD/JEDEC-compatible flash chips
+CONFIG_MTD_JEDECPROBE
+ This option enables JEDEC-style probing of flash chips which are not
+ compatible with the Common Flash Interface, but will use the common
+ CFI-targetted flash drivers for any chips which are identified which
+ are in fact compatible in all but the probe method. This actually
+ covers most AMD/Fujitsu-compatible chips, and will shortly cover also
+ non-CFI Intel chips (that code is in MTD CVS and should shortly be sent
+ for inclusion in Linus' tree)
+
+BIOS flash chip on Intel L440GX boards
+CONFIG_MTD_L440GX
+ Support for treating the BIOS flash chip on Intel L440GX motherboards
+ as an MTD device - with this you can reprogram your BIOS.
+
+ BE VERY CAREFUL.
+
+28F160xx flash driver for LART
+CONFIG_MTD_LART
+ This enables the flash driver for LART. Please note that you do
+ not need any mapping/chip driver for LART. This one does it all
+ for you, so go disable all of those if you enabled some of them (:
+
+Older (theoretically obsoleted now) drivers for non-CFI chips
+CONFIG_MTD_OBSOLETE_CHIPS
+ This option does not enable any code directly, but will allow you to
+ select some other chip drivers which are now considered obsolete,
+ because the generic CONFIG_JEDEC_PROBE code above should now detect
+ the chips which are supported by these drivers, and allow the generic
+ CFI-compatible drivers to drive the chips. Say 'N' here unless you have
+ already tried the CONFIG_JEDEC_PROBE method and reported its failure
+ to the MTD mailing list at <linux-mtd@lists.infradead.org>
+
+CFI Flash device mapped on Hitachi SolutionEngine
+CONFIG_MTD_SOLUTIONENGINE
+ This enables access to the flash chips on the Hitachi SolutionEngine and
+ similar boards. Say 'Y' if you are building a kernel for such a board.
+
+Flash chip mapping on TQM8xxL PPC board
+CONFIG_MTD_TQM8XXL
+ The TQM8xxL PowerPC board has up to two banks of CFI-compliant
+ chips, currently uses AMD one. This 'mapping' driver supports
+ that arrangement, allowing the CFI probe and command set driver
+ code to communicate with the chips on the TQM8xxL board. More at
+ <http://www.denx.de/embedded-ppc-en.html>.
+
+Darkness
+CONFIG_MEMORY_SET
+ This is an option about which you will never be asked a question.
+ Therefore, I conclude that you do not exist - go away.
+
+ There is a grue here.
+
+Physical memory size
+CONFIG_MEMORY_SIZE
+ This sets the default memory size assumed by your SH kernel. It can
+ be overridden as normal by the 'mem=' argument on the kernel command
+ line. If unsure, consult your board specifications or just leave it
+ as 0x00400000 which was the default value before this became
+ configurable.
+
+Cache and PCI noncoherent
+CONFIG_SH_PCIDMA_NONCOHERENT
+ Enable this option if your platform does not have a CPU cache which
+ remains coherent with PCI DMA. It is safest to say 'Y', although you
+ will see better performance if you can say 'N', because the PCI DMA
+ code will not have to flush the CPU's caches. If you have a PCI host
+ bridge integrated with your SH CPU, refer carefully to the chip specs
+ to see if you can say 'N' here. Otherwise, leave it as 'Y'.
+
USB (Universal Serial Bus) support
CONFIG_USB
Universal Serial Bus (USB) is a specification for a serial bus
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 aiptek.o. If you want to compile it as a
- module, say M here and read Documentation/modules.txt.
+ module, say M here and read <file:Documentation/modules.txt>.
Use input layer for ADB devices
CONFIG_INPUT_ADBHID
CONFIG_USB_SERIAL_VISOR
Say Y here if you want to connect to your HandSpring Visor, Palm
m500 or m505 through its USB docking station. See
- <http://usbvisor.sourceforge.net> for more information on using this
+ <http://usbvisor.sourceforge.net/> for more information on using this
driver.
This code is also available as a module ( = code which can be
The module will be called ir-usb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
+USB IR Dongle Serial Driver
+CONFIG_USB_SERIAL_IR
+ Say Y here if you want to enable simple serial support for USB IrDA
+ devices. This is useful if you do not want to use the full IrDA
+ stack.
+
+ This code 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 ir-usb.o. If you want to compile it as a
+ module, say M here and read <file:Documentation/modules.txt>.
+
USB Belkin and Paracom Single Port Serial Driver
CONFIG_USB_SERIAL_BELKIN
Say Y here if you want to use a Belkin USB Serial single port
converter device. The implementation I have is called the USC-1000.
This driver has also be tested with the 245 and 232 devices.
- See http://ftdi-usb-sio.sourceforge.net for more
+ See <http://ftdi-usb-sio.sourceforge.net/> for more
information on this driver and the device.
This code is also available as a module ( = code which can be
This driver supports devices conforming to the Communication Device
Class Ethernet Control Model. This is used in some cable modems.
For more details on the specification, get the Communication Device
- Class specification from <http://www.usb.org>.
+ Class specification from <http://www.usb.org/>.
This driver should work with the following devices:
* Ericsson PipeRider (all variants)
Say Y here if you want to connect this type of still camera to your
computer's USB port. See <file:Documentation/usb/dc2xx.txt> for
more information; some non-Kodak cameras may also work with this
- driver, given application support (such as <http://www.gPhoto.org>).
+ driver, given application support (such as <http://www.gphoto.org/>).
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_USB_MDC800
Say Y here if you want to connect this type of still camera to
your computer's USB port. This driver can be used with gphoto 0.4.3
- and higher (look at <http://www.gphoto.org>).
+ and higher (look at <http://www.gphoto.org/>).
To use it create a device node with "mknod /dev/mustek c 180 32" and
configure it in your software.
DABUSB driver
CONFIG_USB_DABUSB
A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
- brought to you by the DAB-Team (<http://dab.in.tum.de>). This
+ brought to you by the DAB-Team (<http://dab.in.tum.de/>). This
driver can be taken as an example for URB-based bulk, control, and
isochronous transactions. URB's are explained in
<file:Documentation/usb/URB.txt>.
running UML to exchange packets with its host over one of the
host's Ethertap devices, such as /dev/tap0. Additional running
UMLs can use additional Ethertap devices, one per running UML.
- While the UML believes its on a (multi-device, broadcast) virtual
+ While the UML believes it's on a (multi-device, broadcast) virtual
Ethernet network, it's in fact communicating over a point-to-point
link with the host.
CONFIG_USB_BLUETOOTH
Say Y here if you want to connect a USB Bluetooth device to your
computer's USB port. You will need the Bluetooth stack (available
- at <http://developer.axis.com/software/index.shtml)> to fully use
+ at <http://developer.axis.com/software/index.shtml>) to fully use
the device.
This code is also available as a module ( = code which can be
In general, ReiserFS is as fast as ext2, but is very efficient with
large directories and small files. Additional patches are needed
- for NFS and quotas, please see <http://www.reiserfs.org> for links.
+ for NFS and quotas, please see <http://www.reiserfs.org/> for links.
It is more easily extended to have features currently found in
database and keyword search systems than block allocation based file
plugins consistent with our motto ``It takes more than a license to
make source code open.''
- Read <http://www.reiserfs.org> to learn more about reiserfs.
+ Read <http://www.reiserfs.org/> to learn more about reiserfs.
Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com.
everyone but ReiserFS developers and people fine-tuning reiserfs or
tracing problems should say N.
-Publish some reiserfs-specific info under /proc/fs/reiserfs
-CONFIG_REISERFS_PROC_INFO
- Create under /proc/fs/reiserfs hierarchy of files, displaying
- various ReiserFS statistics and internal data on the expense of
- making your kernel or module slightly larger (+8K). This also increases
- amount of kernel memory required for each mount. Almost everyone
- but ReiserFS developers and people fine-tuning reiserfs or tracing
- problems should say NO.
-
Second extended fs support
CONFIG_EXT2_FS
This is the de facto standard Linux file system (method to organize
directories on ext2 file systems, use chattr ("man chattr").
Ext2fs partitions can be read from within DOS using the ext2tool
- command line tool package (available via FTP (user: anonymous) from
- <ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2>) and from
+ command line tool package (available from
+ <ftp://ibiblio.org/pub/Linux/system/filesystems/ext2/>) and from
within Windows NT using the ext2nt command line tool package from
- <ftp://metalab.unc.edu/pub/Linux/utils/dos>. Explore2fs is a
+ <ftp://ibiblio.org/pub/Linux/utils/dos/>. Explore2fs is a
graphical explorer for ext2fs partitions which runs on Windows 95
and Windows NT and includes experimental write support; it is
available from
which allows for long filenames in unicode format (unicode is the
new 16 bit character code, successor to ASCII, which encodes the
characters of almost all languages of the world; see
- <http://www.unicode.org> for more information). Say Y here if you
+ <http://www.unicode.org/> for more information). Say Y here if you
want to be able to read Joliet CD-ROMs under Linux.
Transparent decompression extension
Linux, you can either use the DOS emulator DOSEMU, described in the
DOSEMU-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>, or try dmsdosfs in
- <ftp://metalab.unc.edu/pub/Linux/system/filesystems/dosfs>. If you
+ <ftp://ibiblio.org/pub/Linux/system/filesystems/dosfs/>. If you
intend to use dosemu with a non-compressed MSDOS partition, say Y
here) and MSDOS floppies. This means that file access becomes
transparent, i.e. the MSDOS files look and behave just like all
level IP autoconfiguration" above and to "Root file system on NFS"
below. You cannot compile this driver as a module in this case.
There are two packages designed for booting diskless machines over
- the net: netboot and etherboot, both available via FTP from
- <ftp://metalab.unc.edu/pub/Linux/system/boot/Ethernet/>.
+ the net: netboot, available from
+ <http://ftp1.sourceforge.net/netboot/>, and Etherboot,
+ available from <http://ftp1.sourceforge.net/etherboot/>.
If you don't know what all this is about, say N.
a set of kernel modules that lets you run SCO, Xenix, Wyse,
UnixWare, Dell Unix and System V programs under Linux. It is
available via FTP (user: ftp) from
- <ftp://ftp.openlinux.org/pub/people/hch/linux-abi>).
+ <ftp://ftp.openlinux.org/pub/people/hch/linux-abi/>).
NOTE: that will work only for binaries from Intel-based systems;
PDP ones will have to wait until somebody ports Linux to -11 ;-)
automounter (amd), which is a pure user space daemon.
To use the automounter you need the user-space tools from
- <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4>; you also
+ <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4/>; you also
want to answer Y to "NFS file system support", below.
If you want to compile this as a module ( = code which can be
If reporting bugs, please try to have available a full dump of the
messages at debug level 1 while the misbehaviour was occurring.
+JFFS stats available in /proc filesystem
+CONFIG_JFFS_PROC_FS
+ Enabling this option will cause statistics from mounted JFFS file systems
+ to be made available to the user in the /proc/fs/jffs/ directory.
+
UFS file system support (read-only)
CONFIG_UFS_FS
BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
XP.
Technical documentation to accompany this driver is available from:
- <http://linux-ntfs.sf.net/ldm>.
+ <http://linux-ntfs.sf.net/ldm/>.
If unsure, say N.
Note that the experimental "/dev file system support"
(CONFIG_DEVFS_FS) is a more general facility.
-# This is for Linus's tree
FreeVxFS file system support (VERITAS VxFS(TM) compatible)
CONFIG_VXFS_FS
FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
module, say M here and read <file:Documentation/modules.txt>. If
unsure, say N.
-# This is for Alan's tree. Note the name difference.
-FreeVxFS file system support (VERITAS VxFS(TM) compatible)
-CONFIG_FREEVXFS_FS
- FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
- file system format. VERITAS VxFS(TM) is the standard file system
- of SCO UnixWare (and possibly others) and optionally available
- for Sunsoft Solaris, HP-UX and many other operating systems.
- Currently only readonly access is supported.
-
- NOTE: the file system type as used by mount(1), mount(2) and
- fstab(5) is 'vxfs' as it describes the filesystem format, not
- the actual driver.
-
- This file system is also available as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module is called freevxfs.o. If you want to compile it as a
- module, say M here and read <file:Documentation/modules.txt>. If
- unsure, say N.
-
UnixWare slices support
CONFIG_UNIXWARE_DISKLABEL
Like some systems, UnixWare uses its own slice table inside a
Note: if you just want your box to act as an SMB *server* and make
files and printing services available to Windows clients (which need
to have a TCP/IP stack), you don't need to say Y here; you can use
- the program samba (available via FTP (user: anonymous) in
- <ftp://metalab.unc.edu/pub/Linux/system/network/samba>) for that.
+ the program SAMBA (available from <ftp://ftp.samba.org/pub/samba/>)
+ for that.
General information about how to connect Linux, Windows machines and
Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
client and server. Servers are currently user level, i.e. they need
no kernel support. Please read
<file:Documentation/filesystems/coda.txt> and check out the Coda
- home page <http://www.coda.cs.cmu.edu>.
+ home page <http://www.coda.cs.cmu.edu/>.
If you want to compile the coda client support as a module ( = code
which can be inserted in and removed from the running kernel
If you say Y or M your kernel or module will provide InterMezzo
support. You will also need a file server daemon, which you can get
- from <http://www.inter-mezzo.org>.
+ from <http://www.inter-mezzo.org/>.
NCP file system support (to mount NetWare volumes)
CONFIG_NCP_FS
CONFIG_ADB_IOP
The I/O Processor (IOP) is an Apple custom IC designed to provide
intelligent support for I/O controllers. It is described at
- <http://www.angelfire.com/ca2/dev68k/iopdesc.html;> to enable direct
+ <http://www.angelfire.com/ca2/dev68k/iopdesc.html> to enable direct
support for it, say 'Y' here.
Mac II style Apple Desktop Bus support
Say Y here if your machine has a bus mouse as opposed to a serial
mouse. Most people have a regular serial MouseSystem or
Microsoft mouse (made by Logitech) that plugs into a COM port
- (rectangular with 9 or 25 pins). These people say N here. If you
- have something else, read the Busmouse-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>, and say Y here.
+ (rectangular with 9 or 25 pins). These people say N here.
If you have a laptop, you either have to check the documentation or
experiment a bit to find out whether the trackball is a serial mouse
When using a PS/2 mouse, you can get problems if you want to use the
mouse both on the Linux console and under X. Using the "-R" option
of the Linux mouse managing program gpm (available from
- <ftp://metalab.unc.edu/pub/Linux/system/mouse>) solves this
- problem, or you can get the "mconv2" utility from the same location.
+ <ftp://gnu.systemy.it/pub/gpm/>) solves this problem, or you can get
+ the "mconv2" utility from <ftp://ibiblio.org/pub/Linux/system/mouse/>.
C&T 82C710 mouse port support (as on TI Travelmate)
CONFIG_82C710_MOUSE
Note that the Ftape-HOWTO is out of date (sorry) and documents the
older version 2.08 of this software but still contains useful
information. There is a web page with more recent documentation at
- <http://www.math1.rwth-aachen.de/~heine/ftape/>. This page
+ <http://www.instmath.rwth-aachen.de/~heine/ftape/>. This page
always contains the latest release of the ftape driver and useful
information (backup software, ftape related patches and
documentation, FAQ). Note that the file system interface has
file <file:Documentation/ftape.txt> contains a short description of
the most important changes in the file system interface compared to
previous versions of ftape. The ftape home page
- <http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape/> contains
+ <http://www.instmath.rwth-aachen.de/~heine/ftape/> contains
further information.
IMPORTANT NOTE: zftape can read archives created by previous
introduced in XFree86 4.0. If you say Y here, you need to select
the module that's right for your graphics card from the list below.
These modules provide support for synchronization, security, and
- DMA transfers. Please see <http://dri.sourceforge.net> for more
+ DMA transfers. Please see <http://dri.sourceforge.net/> for more
details. You should also select and configure AGP
(/dev/agpgart) support.
in the kernel source.
The watchdog is usually used together with the watchdog daemon
- which is available via FTP (user: anonymous) from
- <ftp://tsx-11.mit.edu/pub/linux/sources/sbin/>. This daemon can also
- monitor NFS connections and can reboot the machine when the process
+ which is available from
+ <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can
+ also monitor NFS connections and can reboot the machine when the process
table is full.
If unsure, say N.
and if it does, it reboots your computer after a certain amount of
time. This driver is like the WDT501 driver but for different
hardware. Please read <file:Documentation/pcwd-watchdog.txt>. The PC
- watchdog cards can be ordered from <http://www.berkprod.com>.
+ watchdog cards can be ordered from <http://www.berkprod.com/>.
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 nvram.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
-# Linus tree only
Joystick support
CONFIG_JOYSTICK
If you have a joystick, 6dof controller, gamepad, steering wheel,
enable generic support for these controllers. You will also need to
say Y or M to at least one of the hardware specific drivers. This
will make the controllers available as /dev/input/jsX devices.
- Please read the file <file:Documentation/joystick.txt> which
+ Please read the file <file:Documentation/input/joystick.txt> which
contains more information and the location of the joystick package
that you'll need.
-# AC tree only
Game port support
CONFIG_INPUT_GAMEPORT
Gameport support is for the standard 15-pin PC gameport. If you
have a joystick, gamepad, gameport card, a soundcard with a gameport
or anything else that uses the gameport, say Y or M here and also to
at least one of the hardware specific drivers.
- Please read the file <file:Documentation/joystick.txt> which
+ Please read the file <file:Documentation/input/joystick.txt> which
contains more information and the location of the joystick package
that you'll need if you use the gameport with a joystick.
CONFIG_INPUT_NS558
Say Y here if you have an ISA or PnP gameport.
For more information on how to use the driver please read
- <file:Documentation/joystick.txt>.
+ <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_LIGHTNING
Say Y here if you have a PDPI Lightning 4 gamecard. For more
information on how to use the driver please read
- <file:Documentation/joystick.txt>.
+ <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_PCIGAME
Say Y here if you have a Trident 4DWave DX/NX or Aureal Vortex 1/2
card. For more information on how to use the driver please read
- <file:Documentation/joystick.txt>.
+ <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_EMU10K1
Say Y here if you have a SoundBlaster Live! card and want to use
its gameport. For more information on how to use the driver
- please read <file:Documentation/joystick.txt>.
+ please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
additional hats and buttons compatible with CH Flightstick Pro,
ThrustMaster FCS, 6 and 8 button gamepads, or Saitek Cyborg
joysticks. For more information on how to use the driver please
- read <file:Documentation/joystick.txt>.
+ read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_A3D
Say Y here if you have an FPGaming or MadCatz controller using the
A3D protocol over the PC gameport. For more information on how to
- use the driver please read <file:Documentation/joystick.txt>.
+ use the driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_ADI
Say Y here if you have a Logitech controller using the ADI
protocol over the PC gameport. For more information on how to use
- the driver please read <file:Documentation/joystick.txt>.
+ the driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_COBRA
Say Y here if you have a Creative Labs Blaster Cobra gamepad.
For more information on how to use the driver please read
- <file:Documentation/joystick.txt>.
+ <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_GF2K
Say Y here if you have a Genius Flight2000 or MaxFighter digitally
communicating joystick or gamepad. For more information on how to
- use the driver please read <file:Documentation/joystick.txt>.
+ use the driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_GRIP
Say Y here if you have a Gravis controller using the GrIP protocol
over the PC gameport. For more information on how to use the driver
- please read <file:Documentation/joystick.txt>.
+ please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_INTERACT
Say Y hereif you have an InterAct gameport or joystick
communicating digitally over the gameport. For more information on
- how to use the driver please read <file:Documentation/joystick.txt>.
+ how to use the driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
Say Y here if you have a ThrustMaster controller using the
DirectConnect (BSP) protocol over the PC gameport. For more
information on how to use the driver please read
- <file:Documentation/joystick.txt>.
+ <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_SIDEWINDER
Say Y here if you have a Microsoft controller using the Digital
Overdrive protocol over PC gameport. For more information on how to
- use the driver please read <file:Documentation/joystick.txt>.
+ use the driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
Say Y here and to the Serial port input line discipline option if
you plan to use a joystick that communicates over the serial (COM)
port. For more information on how to use the driver please read
- <file:Documentation/joystick.txt>.
+ <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_SERPORT
Say Y here if you plan to use a joystick that communicates over the
serial (COM) port. For more information on how to use the driver
- please read <file:Documentation/joystick.txt>.
+ please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_WARRIOR
Say Y here if you have a Logitech WingMan Warrior joystick connected
to your computer's serial port. For more information on how to use
- the driver please read <file:Documentation/joystick.txt>.
+ the driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_MAGELLAN
Say Y here if you have a Magellan or Space Mouse 6DOF controller
connected to your computer's serial port. For more information on
- how to use the driver please read <file:Documentation/joystick.txt>.
+ how to use the driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF
controller connected to your computer's serial port. For more
information on how to use the driver please read
- <file:Documentation/joystick.txt>.
+ <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_SPACEBALL
Say Y here if you have a SpaceTec SpaceBall 4000 FLX controller
connected to your computer's serial port. For more information on
- how to use the driver please read <file:Documentation/joystick.txt>.
+ how to use the driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_STINGER
Say Y here if you have a Gravis Stinger connected to one of your
serial ports. For more information on how to use the driver please
- read <file:Documentation/joystick.txt>.
+ read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_IFORCE_232
Say Y here if you have an I-Force joystick or steering wheel
connected to your serial (COM) port. For more information on how
- to use the driver please read <file:Documentation/joystick.txt>.
+ to use the driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_IFORCE_USB
Say Y here if you have an I-Force joystick or steering wheel
connected to your USB port. For more information on how to use the
- driver please read <file:Documentation/joystick.txt>.
+ driver please read <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
Commodore, Amstrad CPC joystick connected to your parallel port.
For more information on how to use the driver please read
- <file:Documentation/joystick.txt> and
- <file:Documentation/joystick-parport.txt>.
+ <file:Documentation/input/joystick.txt> and
+ <file:Documentation/input/joystick-parport.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
Sony PlayStation gamepad or a Multisystem -- Atari, Amiga,
Commodore, Amstrad CPC joystick connected to your parallel port.
For more information on how to use the driver please read
- <file:Documentation/joystick.txt> and
- <file:Documentation/joystick-parport.txt>.
+ <file:Documentation/input/joystick.txt> and
+ <file:Documentation/input/joystick-parport.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
and want to use it with Multisystem -- Atari, Amiga, Commodore,
Amstrad CPC joystick. For more information on how to use the driver
- please read <file:Documentation/joystick.txt> and
- <file:Documentation/joystick-parport.txt>.
+ please read <file:Documentation/input/joystick.txt> and
+ <file:Documentation/input/joystick-parport.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
CONFIG_INPUT_AMIJOY
Say Y here if you have an Amiga with a digital joystick connected
to it. For more information on how to use the driver please read
- <file:Documentation/joystick.txt>.
+ <file:Documentation/input/joystick.txt>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
questions.
Read the <file:Documentation/sound/README.OSS> file and the head of
- <file:drivers/sound/lowlevel/aedsp16.c> as well as
+ <file:drivers/sound/aedsp16.c> as well as
<file:Documentation/sound/AudioExcelDSP16> to get more information
about this driver and its configuration.
or the CMI8378 chipset. Data on these chips are available at
<http://www.cmedia.com.tw/>.
+ A userspace utility to control some internal registers of these
+ chips is available at
+ <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
+
Support CMI8738 based audio cards
CONFIG_SOUND_CMPCI_CM8738
Say Y or M if you have a PCI sound card using the CMI8338
or the CMI8378 chipset. Data on this chip is available at
<http://www.cmedia.com.tw/doc8738.htm>.
+ A userspace utility to control some internal registers of these
+ chips is available at
+ <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
+
Enable joystick
CONFIG_SOUND_CMPCI_JOYSTICK
Say here in order to enable the joystick port on a sound crd using
"The 8738 Audio SPDIF In/Out Technical Data" on the technical
support page at <http://www.cmedia.com.tw/>.
+ A userspace utility to control even more internal registers of these
+ chips is available at
+ <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
+ This package will among other things help you enable SPDIF
+ out/in/loop/monitor.
+
Creative SBLive! (EMU10K1) based PCI sound cards
CONFIG_SOUND_EMU10K1
Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
such as the Creative SBLive!, SB PCI512 or Emu-APS.
For more information on this driver and the degree of support for the
- different card models please check <http://opensource.creative.com>.
+ different card models please check <http://opensource.creative.com/>.
It is now possible to load dsp microcode patches into the EMU10K1
chip. These patches are used to implement real time sound
Support for ITE 8172G board
CONFIG_MIPS_ITE8172
- Ths is an evaluation board made by ITE (http://www.ite.com.tw/)
+ Ths is an evaluation board made by ITE <http://www.ite.com.tw/>
with ATX form factor that utilizes a MIPS R5000 to work with its
ITE8172G companion internet appliance chip. The MIPS core can be
either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build
can be inserted in and removed from the running kernel whenever you
want, details in <file:Documentation/modules.txt>); the module will
be called sc.o. See <file:Documentation/isdn/README.sc> and
- <http://www.spellcast.com> for more information.
+ <http://www.spellcast.com/> for more information.
Eicon active card support
CONFIG_ISDN_DRV_EICON
This enables support for the Auvertech TurboPAM ISDN-card.
For running this card, additional firmware is necessary, which has
to be downloaded into the card using a utility which is distributed
- separately from the Auvertech's web site: <http://www.auvertech.fr>.
+ separately from the Auvertech's web site: <http://www.auvertech.fr/>.
Please redirect all support questions to support@auvertech.fr.
It was designed as a replacement for cables and other short-range
technologies like IrDA. Bluetooth operates in personal area range
that typically extends up to 10 meters. More information about
- Bluetooth can be found at <http://www.bluetooth.com>.
+ Bluetooth can be found at <http://www.bluetooth.com/>.
Linux Bluetooth subsystem consist of several layers:
HCI Core (device and connection manager, scheduler)
To use Linux Bluetooth subsystem, you will need several user-space
utilities like hciconfig and hcid. These utilities and updates to
Bluetooth kernel modules are provided in the BlueZ package.
- For more information, see <http://bluez.sf.net>.
+ For more information, see <http://bluez.sourceforge.net/>.
If you want to compile HCI Core as module (hci.o) say M here.
# The following options are for Linux when running on the Hitachi
# SuperH family of RISC microprocessors.
-CPU Selection
-CONFIG_CPU_SUBTYPE_SH7707
- This is the type of your Hitachi SuperH processor. This information is
- used for optimizing and configuration purposes.
-
- - "SH7707" for SH7707
- - "SH7708" for SH7708, SH7708S, SH7708R
- - "SH7709" for SH7707, SH7709, SH7709A, and SH7729.
- - "SH7750" for SH7750, SH7750S
- - "SH7751" for SH7751
- - "ST40STB1" for ST40STB1
-
-Target machine selection
-CONFIG_SH_GENERIC
- This is machine type of your target.
-
- - "Generic" for Generic kernel which might support all of them
- - "SolutionEngine" for Hitachi SolutionEngine (7709A, 7750, 7750S)
- - "SolutionEngine7751" for Hitachi SolutionEngine (7751)
- - "STB1_Harp" for STMicroelectronics HARP
- - "STB1_Overdrive" for STMicroelectronics Overdrive
- - "HP620" for HP 'Jornada' 620
- - "HP680" for HP 'Jornada' 680
- - "HP690" for HP 'Jornada' 690
- - "CqREEK" for CQ Publishing CqREEK SH-4
- - "DMIDA" for DMIDA, industrial data assistant
- - "EC3104" for Compaq Aero 8000
- - "Dreamcast" for SEGA Dreamcast
- - "CAT68701" for CAT 68701 Evaluation Board (SH7708)
- - "BigSur" for Big Sur Evaluation Board
- - "SH2000" for SH2000 Evaluation Board (SH7709A)
- - "ADX" for A&D ADX
- - "BareCPU" for Bare CPU board such as CqREEK SH-3
-
- If unsure, select "BareCPU".
-
-Physical memory start address
-CONFIG_MEMORY_START
- Computers built with Hitachi SuperH processors always
- map the ROM starting at address zero. But the processor
- does not specify the range that RAM takes. RAM is usually
- mapped starting at 0c000000, but it may be elsewhere.
-
- You should set this value to the address of the lowest
- RAM location.
-
- A value of 0c000000 will work for most boards.
-
-Directly Connected Compact Flash support
-CONFIG_CF_ENABLER
- If your board has "Directly Connected" CompactFlash at area 5 or 6,
- you may want to enable this option. Then, you can use CF as
- primary IDE drive (only tested for SanDisk).
-
- If in doubt, press "n".
-
SuperH RTC support
CONFIG_SH_RTC
Selecting this option will allow the Linux kernel to emulate
If unsure, say N.
-SuperH SCI (serial) support
-CONFIG_SH_SCI
- Selecting this option will allow the Linux kernel to transfer
- data over SCI (Serial Communication Interface) and/or SCIF
- which are built into the Hitachi SuperH processor.
-
- If unsure, say N.
-
-Use LinuxSH standard BIOS
-CONFIG_SH_STANDARD_BIOS
- Say Y here if your target has the gdb-sh-stub package from
- www.m17n.org (or any conforming standard LinuxSH BIOS) in FLASH
- or EPROM. The kernel will use standard BIOS calls during boot
- for various housekeeping tasks. Note this does not work with
- WindowsCE machines. If unsure, say N.
-
-Early printk support
-CONFIG_SH_EARLY_PRINTK
- If you say Y here, the kernel printk routine will begin output to
- the console much earlier in the boot process, before the serial
- console is initialised, instead of buffering output. Standard
- LinuxSH BIOS calls are used for the output. This helps when
- debugging fatal problems early in the boot sequence. This is only
- useful for kernel hackers. If unsure, say N.
-
-National Semiconductor DP83902AV 'ST-NIC' support
-CONFIG_STNIC
- If you have a network adaptor with National Semiconductor DP83902AV,
- say Y or M (for module).
-
- If unsure, say N.
-
+# Choice: cf_area
CompactFlash Connection Area
CONFIG_CF_AREA5
If your board has "Directly Connected" CompactFlash, You should
<http://www.synergymicro.com/PressRel/97_10_15.html>.
Select APUS if configuring for a PowerUP Amiga. More information is
- available at: <http://linux-apus.sourceforge.net>.
+ available at: <http://linux-apus.sourceforge.net/>.
Synergy-Gemini
CONFIG_GEMINI
CONFIG_APUS
Select APUS if configuring for a PowerUP Amiga.
More information is available at:
- <http://linux-apus.sourceforge.net>.
-
-Embedded 8xx Board Type
-CONFIG_RPXLITE
- RPX-Lite:
- Embedded Planet RPX Lite
-
- RPX-Classic:
- Embedded Planet RPX Classic Low-fat.
-
- BSE-IP:
- Bright Star Engineering ip-Engine.
-
- TQM823L:
- TQM850L:
- TQM855L:
- TQM860L:
- MPC8xx based family of mini modules, half credit card size,
- up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
- 2 x CAN bus interface, ...
- Manufacturer: TQ Components, www.tq-group.de
- Date of Release: October (?) 1999
- End of Life: not yet :-)
- URL:
- - module: http://www.denx.de/PDF/TQM8xxLHWM201.pdf
- - starter kit: http://www.denx.de/PDF/STK8xxLHWM201.pdf
- - images: http://www.denx.de/embedded-ppc-en.html
-
- FPS850L:
- FingerPrint Sensor System (based on TQM850L)
- Manufacturer: IKENDI AG, http://www.ikendi.com/
- Date of Release: November 1999
- End of life: end 2000 ?
- URL: see TQM850L
-
- SPD823TS:
- MPC823 based board used in the "Tele Server" product
- Manufacturer: Speech Design, http://www.speech-design.de/
- Date of Release: Mid 2000 (?)
- End of life: -
- URL: http://www.speech-design.de/
- select "English", then "Teleteam Solutions", then "TeleServer"
-
- IVMS8:
- MPC860 based board used in the "Integrated Voice Mail System",
- Small Version (8 voice channels)
- Manufacturer: Speech Design, http://www.speech-design.de/
- Date of Release: December 2000 (?)
- End of life: -
- URL: http://www.speech-design.de/
-
- IVML24:
- MPC860 based board used in the "Integrated Voice Mail System",
- Large Version (24 voice channels)
- Manufacturer: Speech Design, http://www.speech-design.de/
- Date of Release: March 2001 (?)
- End of life: -
- URL: http://www.speech-design.de/
-
- SM850:
- Service Module (based on TQM850L)
- Manufacturer: Dependable Computer Systems, http://www.decomsys.com/
- Date of Release: end 2000 (?)
- End of life: mid 2001 (?)
- URL: http://www.tz-mikroelektronik.de/ServiceModule/index.html
-
- HERMES:
- Hermes-Pro ISDN/LAN router with integrated 8 x hub
- Manufacturer: Multidata Gesellschaft für Datentechnik und Informatik
- http://www.multidata.de/
- Date of Release: 2000 (?)
- End of life: -
- URL: http://www.multidata.de/english/products/hpro.htm
-
- IP860:
- VMEBus IP (Industry Pack) carrier board with MPC860
- Manufacturer: MicroSys GmbH, http://www.microsys.de/
- Date of Release: ?
- End of life: -
- URL: http://www.microsys.de/html/ip860.html
-
- PCU_E:
- PCU = Peripheral Controller Unit, Extended
- Manufacturer: Siemens AG, ICN (Information and Communication Networks)
- http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html
- Date of Release: April 2001
- End of life: August 2001
- URL: n. a.
-
-Embedded 82xx Board Type
-CONFIG_EST8260
- EST8260: Wind River System, Inc. EST SBC8260
-
- TQM8260:
- MPC8260 based module, little larger than credit card,
- up to 128 MB global + 64 MB local RAM, 32 MB Flash,
- 32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet,
- 2 x serial ports, ...
- Manufacturer: TQ Components, www.tq-group.de
- Date of Release: June 2001
- End of Life: not yet :-)
- URL: http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf
-
- PM826:
- Modular system with MPC8260 CPU
- Manufacturer: MicroSys GmbH, http://www.microsys.de/
- Date of Release: mid 2001
- End of life: -
- URL: http://www.microsys.de/html/pm826.html
-
- CU824:
- VMEBus Board with PCI extension with MPC8240 CPU
- Manufacturer: MicroSys GmbH, http://www.microsys.de/
- Date of Release: early 2001 (?)
- End of life: -
- URL: http://www.microsys.de/html/cu824.html
+ <http://linux-apus.sourceforge.net/>.
AltiVec Kernel Support
CONFIG_ALTIVEC
change the screen brightness.
# Choice: ppc8xxtype
-RPX-Lite
+Embedded 8xx Board Type
CONFIG_RPXLITE
Single-board computers based around the PowerPC MPC8xx chips and
intended for embedded applications. The following types are
supported:
- RPX-Lite -- PC104 form-factor SBC based on the MPC823
- RPX-Classic -- Credit-card-size SBC based on the MPC 860
- BSE-IP -- Bright Star Engineering BSE-IP SBC
- TQM823L -- TQM823L SBC from TQ Components
- TQM850L -- TQM850L SBC from TQ Components
- TQM855L -- TQM855L SBC from TQ Components
- TQM860L -- TQM860L SBC from TQ Components
- FPS850L -- FingerPrint Sensor from TQ Components
- TQM860 -- TQM860 SBC from IKENDI AG
- SPD823TS -- Speech Design TeleServer from Speech Design
- IVMS8 -- Integrated VoiceMail SBC from Speech Design
- SM850 -- Service Module 850 from Dependable Computer Systems
- MBX -- MBX821 and MBX860 SBCs
- Wincept -- Wincept SBCs for thin-client machines
+ RPX-Lite:
+ Embedded Planet RPX Lite. PC104 form-factor SBC based on the MPC823.
+
+ RPX-Classic:
+ Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on
+ the MPC 860
+
+ BSE-IP:
+ Bright Star Engineering ip-Engine.
+
+ TQM823L:
+ TQM850L:
+ TQM855L:
+ TQM860L:
+ MPC8xx based family of mini modules, half credit card size,
+ up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
+ 2 x CAN bus interface, ...
+ Manufacturer: TQ Components, www.tq-group.de
+ Date of Release: October (?) 1999
+ End of Life: not yet :-)
+ URL:
+ - module: <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>
+ - starter kit: <http://www.denx.de/PDF/STK8xxLHWM201.pdf>
+ - images: <http://www.denx.de/embedded-ppc-en.html>
+
+ FPS850L:
+ FingerPrint Sensor System (based on TQM850L)
+ Manufacturer: IKENDI AG, <http://www.ikendi.com/>
+ Date of Release: November 1999
+ End of life: end 2000 ?
+ URL: see TQM850L
+
+ SPD823TS:
+ MPC823 based board used in the "Tele Server" product
+ Manufacturer: Speech Design, <http://www.speech-design.de/>
+ Date of Release: Mid 2000 (?)
+ End of life: -
+ URL: <http://www.speech-design.de/>
+ select "English", then "Teleteam Solutions", then "TeleServer"
+
+ IVMS8:
+ MPC860 based board used in the "Integrated Voice Mail System",
+ Small Version (8 voice channels)
+ Manufacturer: Speech Design, <http://www.speech-design.de/>
+ Date of Release: December 2000 (?)
+ End of life: -
+ URL: <http://www.speech-design.de/>
+
+ IVML24:
+ MPC860 based board used in the "Integrated Voice Mail System",
+ Large Version (24 voice channels)
+ Manufacturer: Speech Design, <http://www.speech-design.de/>
+ Date of Release: March 2001 (?)
+ End of life: -
+ URL: <http://www.speech-design.de/>
+
+ SM850:
+ Service Module (based on TQM850L)
+ Manufacturer: Dependable Computer Systems, <http://www.decomsys.com/>
+ Date of Release: end 2000 (?)
+ End of life: mid 2001 (?)
+ URL: <http://www.tz-mikroelektronik.de/ServiceModule/index.html>
+
+ HERMES:
+ Hermes-Pro ISDN/LAN router with integrated 8 x hub
+ Manufacturer: Multidata Gesellschaft für Datentechnik und Informatik
+ <http://www.multidata.de/>
+ Date of Release: 2000 (?)
+ End of life: -
+ URL: <http://www.multidata.de/english/products/hpro.htm>
+
+ IP860:
+ VMEBus IP (Industry Pack) carrier board with MPC860
+ Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
+ Date of Release: ?
+ End of life: -
+ URL: <http://www.microsys.de/html/ip860.html>
+
+ PCU_E:
+ PCU = Peripheral Controller Unit, Extended
+ Manufacturer: Siemens AG, ICN (Information and Communication Networks)
+ <http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html>
+ Date of Release: April 2001
+ End of life: August 2001
+ URL: n. a.
RPX-Classic
CONFIG_RPXCLASSIC
# Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
# Date of Release: early 2001 (?)
# End of life: -
-# URL: <http://www.microsys.de/html/cu824.html
+# URL: <http://www.microsys.de/html/cu824.html>
#
# PM826:
# Modular system with MPC8260 CPU
# End of life: -
# URL: n. a.o
-Support for EST8260
+# Choice: ppc82xxtype
+Embedded 82xx Board Type
CONFIG_EST8260
- The EST8260 is a single-board computer manufactured by Wind River
- Systems, Inc. (formerly Embedded Support Tools Corp.) and based on
- the MPC8260. Wind River Systems has a website at
- <http://www.windriver.com/>, but the EST8260 cannot be found on it
- and has probably been discontinued or rebadged.
+ EST8260:
+ The EST8260 is a single-board computer manufactured by Wind River
+ Systems, Inc. (formerly Embedded Support Tools Corp.) and based on
+ the MPC8260. Wind River Systems has a website at
+ <http://www.windriver.com/>, but the EST8260 cannot be found on it
+ and has probably been discontinued or rebadged.
+
+ TQM8260:
+ MPC8260 based module, little larger than credit card,
+ up to 128 MB global + 64 MB local RAM, 32 MB Flash,
+ 32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet,
+ 2 x serial ports, ...
+ Manufacturer: TQ Components, www.tq-group.de
+ Date of Release: June 2001
+ End of Life: not yet :-)
+ URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf>
+
+ PM826:
+ Modular system with MPC8260 CPU
+ Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
+ Date of Release: mid 2001
+ End of life: -
+ URL: <http://www.microsys.de/html/pm826.html>
+
+ CU824:
+ VMEBus Board with PCI extension with MPC8240 CPU
+ Manufacturer: MicroSys GmbH, http://www.microsys.de/
+ Date of Release: early 2001 (?)
+ End of life: -
+ URL: <http://www.microsys.de/html/cu824.html>
ADB raw keycode support
CONFIG_MAC_ADBKEYCODES
If unsure, say Y here.
+I2C/SPI Microcode Patch
+UCODE_PATCH
+ Motorola releases microcode updates for their 8xx CPM modules. The
+ microcode update file has updates for IIC, SMC and USB. Currently only
+ the USB update is available by default, if the MPC8xx USB option is
+ enabled. If in doubt, say 'N' here.
+
Mouse button 2+3 emulation support
CONFIG_MAC_EMUMOUSEBTN
This provides generic support for emulating the 2nd and 3rd mouse
Support for audio/video capture and overlay devices and FM radio
cards. The exact capabilities of each device vary. User tools for
this are available from
- <ftp://ftp.uk.linux.org/pub/linux/video4linux>.
+ <ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
If you are interested in writing a driver for such an audio/video
device or user software interacting with such a driver, please read
Miro DC10 and DC30 video capture cards).
Include support for Iomega Buz
-CONFIG_VIDEO_BUZ
+CONFIG_VIDEO_ZORAN_BUZ
Say Y here to include support for the Iomega Buz video card. There
is a Buz/Linux homepage at <http://www.lysator.liu.se/~gz/buz/>.
otherwise say N.
This driver is also available as a module (w9966.o).
- Check out <file:Documentation/video4linux/w9966.txt> and
- <file:Documentation/video4linux/w9966.c> for more information.
+ Check out <file:Documentation/video4linux/w9966.txt> for more
+ information.
CPiA Video For Linux
CONFIG_VIDEO_CPIA
CONFIG_IPLABE.
Support for 3215 line mode terminal
-CONFIG_3215
- Include support for IBM 3215 line-mode terminals. Can't be used
- if 3270 console support is chosen.
+CONFIG_TN3215
+ Include support for IBM 3215 line-mode terminals.
Support for console on 3215 line mode terminal
-CONFIG_3215_CONSOLE
- Include support for using an IBM 3215 line-mode terminal as the
- Linux system console. Can't be used if 3270 console support is
- chosen.
+CONFIG_TN3215_CONSOLE
+ Include support for using an IBM 3215 line-mode terminal as a
+ Linux system console.
Support for 3270 line mode terminal
-CONFIG_3270
+CONFIG_TN3270
Include support for IBM 3270 line-mode terminals.
Support for console on 3270 line mode terminal
-CONFIG_3270_CONSOLE
- Include support for using an IBM 3270 line-mode terminal as the
- Linux system console. Excludes using 3215s. Available only if 3270
- support is compiled in statically.
+CONFIG_TN3270_CONSOLE
+ Include support for using an IBM 3270 line-mode terminal as a Linux
+ system console. Available only if 3270 support is compiled in
+ statically.
Support for HWC line mode terminal
CONFIG_HWC
There are no product plans beyond the current research
prototypes at this time. Information is available at:
- <http://crl.research.compaq.com/projects/personalserver>
+ <http://crl.research.compaq.com/projects/personalserver/>
If you have any questions or comments about the Compaq Personal
Server, send e-mail to skiff@crl.dec.com.
Say Y if configuring for an Intrinsyc CerfBoard.
Say N otherwise.
+FlexaNet
+CONFIG_SA1100_FLEXANET
+ Say Y here if you intend to run this kernel on the FlexaNet
+ handheld instruments. Information about this machine can be
+ found at: <http://www.flexanet.com/>.
+
nanoEngine
CONFIG_SA1100_NANOENGINE
The nanoEngine is a StrongARM 1110-based single board computer
this. If in doubt, say Y.
/proc/efi/vars support
-CONFIG_IA64_EFIVARS
+CONFIG_EFI_VARS
If you say Y here, you are able to get EFI (Extensible Firmware
Interface) variable information in /proc/efi/vars. You may read,
write, create, and destroy EFI variables through this interface.
each of the machines below is described by a machine vector.
Select SolutionEngine if configuring for a Hitachi SH7709
- or SH7750 evalutation board.
+ or SH7750/7750S evalutation board.
Select Overdrive if configuring for a ST407750 Overdrive board.
More information at
Select HP620 if configuring for a HP Jornada HP620.
More information (hardware only) at
- <http://www.hp.com/jornada>.
+ <http://www.hp.com/jornada/>.
Select HP680 if configuring for a HP Jornada HP680.
More information (hardware only) at
- <http://www.hp.com/jornada/products/680>.
+ <http://www.hp.com/jornada/products/680/>.
Select HP690 if configuring for a HP Jornada HP690.
More information (hardware only) at
- <http://www.hp.com/jornada/products/680>.
+ <http://www.hp.com/jornada/products/680/>.
Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
More information at
<http://sources.redhat.com/ecos/hardware.html#SuperH>.
Select DMIDA if configuring for a DataMyte 4000 Industrial
- Digital Assistant. More information at <http://www.dmida.com>.
+ Digital Assistant. More information at <http://www.dmida.com/>.
Select EC3104 if configuring for a system with an Eclipse
- International EC3104 chip, e.g. the Harris AD2000.
+ International EC3104 chip, e.g. the Harris AD2000 or Compaq Aero 8000.
Select Dreamcast if configuring for a SEGA Dreamcast.
More information at
- <http://www.m17n.org/linux-sh/dreamcast>. There is a
+ <http://www.m17n.org/linux-sh/dreamcast/>. There is a
Dreamcast project is at <http://linuxdc.sourceforge.net/>.
Select BareCPU if you know what this means, and it applies
to your system.
+# These may have to be merged in when we go to CML2:
+# - "SolutionEngine7751" for Hitachi SolutionEngine (7751)
+# - "STB1_Harp" for STMicroelectronics HARP
+# - "CqREEK" for CQ Publishing CqREEK SH-4
+# - "CAT68701" for CAT 68701 Evaluation Board (SH7708)
+# - "BigSur" for Big Sur Evaluation Board
+# - "SH2000" for SH2000 Evaluation Board (SH7709A)
+# - "ADX" for A&D ADX
+
SolutionEngine
CONFIG_SH_SOLUTION_ENGINE
Select SolutionEngine if configuring for a Hitachi SH7709
CONFIG_SH_HP620
Select HP620 if configuring for a HP jornada HP620.
More information (hardware only) at
- <http://www.hp.com/jornada>.
+ <http://www.hp.com/jornada/>.
HP680
CONFIG_SH_HP680
Select HP680 if configuring for a HP Jornada HP680.
More information (hardware only) at
- <http://www.hp.com/jornada/products/680>.
+ <http://www.hp.com/jornada/products/680/>.
HP690
CONFIG_SH_HP690
Select HP690 if configuring for a HP Jornada HP690.
More information (hardware only)
- at <http://www.hp.com/jornada/products/680>.
+ at <http://www.hp.com/jornada/products/680/>.
CqREEK
CONFIG_SH_CQREEK
DMIDA
CONFIG_SH_DMIDA
Select DMIDA if configuring for a DataMyte 4000 Industrial
- Digital Assistant. More information at <http://www.dmida.com>.
+ Digital Assistant. More information at <http://www.dmida.com/>.
EC3104
CONFIG_SH_EC3104
CONFIG_SH_DREAMCAST
Select Dreamcast if configuring for a SEGA Dreamcast.
More information at
- <http://www.m17n.org/linux-sh/dreamcast>. There is a
+ <http://www.m17n.org/linux-sh/dreamcast/>. There is a
Dreamcast project is at <http://linuxdc.sourceforge.net/>.
BareCPU
# Choice: superhtype
SH7707
CONFIG_CPU_SUBTYPE_SH7707
- Select the type of SuperH processor you have.
+ Select the type of SuperH processor you have. This information is
+ used for optimizing and configuration purposes.
Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU.
Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
+ Select SH7751 if you have a SH7751
+
+ Select ST40STB1 if you have a ST40STB1
+
SH7708
CONFIG_CPU_SUBTYPE_SH7708
Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or
Physical memory start address
CONFIG_MEMORY_START
- The physical memory start address will be automatically
+ Computers built with Hitachi SuperH processors always
+ map the ROM starting at address zero. But the processor
+ does not specify the range that RAM takes.
+
+ The physical memory (RAM) start address will be automatically
set to 08000000, unless you selected one of the following
processor types: SolutionEngine, Overdrive, HP620, HP680, HP690,
in which case the start address will be set to 0c000000.
The default setting of the HD64465 IO base address is 0xb0000000.
Do not change this unless you know what you are doing.
-
+
Early printk support
CONFIG_SH_EARLY_PRINTK
- Say Y here to redirect kernel messages to the serial port
+ Say Y here to redirect kernel printk messages to the serial port
used by the SH-IPL bootloader, starting very early in the boot
process and ending when the kernel's serial console is initialised.
This option is only useful porting the kernel to a new machine,
when the kernel may crash or hang before the serial console is
- initialised.
+ initialised. If unsure, say N.
SuperH SCI (serial) support
CONFIG_SH_SCI
#
# This is used by Emacs' spell checker ispell.el:
#
-# LocalWords: CONFIG coprocessor DX Pentium SX lilo loadlin HOWTO ftp metalab
+# LocalWords: CONFIG coprocessor DX Pentium SX lilo loadlin HOWTO ftp ibiblio
# LocalWords: unc edu docs emu README kB BLK DEV FD Thinkpad fd MFM RLL IDE gz
# LocalWords: cdrom diskless netboot nfs xzvf ATAPI MB ide pavia rubini pl pd
# LocalWords: HD CD-ROMs IDECD NEC MITSUMI filesystem XT XD PCI BIOS cezar ATEN
# LocalWords: bsd comp SPARCstation le SunOS ie Gracilis PackeTwin PT pt LU FX
# LocalWords: FX TEAC CR LCS mS ramdisk IDETAPE cmd fperllo encis tcfs unisa
# LocalWords: Vertos Genoa Funai hsfs NCP NetWare tgz APM apm ioctls UltraLite
-# LocalWords: TravelMate CDT LCD backlight VC RPC Mips AXP barlow cdrecord pg
+# LocalWords: TravelMate CDT LCD backlight VC RPC Mips AXP barlow cdrtools pg
# LocalWords: PMAX MILO Alphas Multia Tseng linuxelf endian mipsel mips drv HT
# LocalWords: kerneld callouts AdvanSys advansys Admin WDT DataStor EP verden
# LocalWords: wdt hdb hdc bugfix SiS vlb Acculogic CSA DTC dtc Holtek ht QDI
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 1
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/io.h>
}
int
-get_irq_list(char *buf)
+show_interrupts(struct seq_file *p, void *v)
{
#ifdef CONFIG_SMP
int j;
#endif
int i;
struct irqaction * action;
- char *p = buf;
#ifdef CONFIG_SMP
- p += sprintf(p, " ");
+ seq_puts(p, " ");
for (i = 0; i < smp_num_cpus; i++)
- p += sprintf(p, "CPU%d ", i);
+ seq_printf(p, "CPU%d ", i);
#ifdef DO_BROADCAST_INTS
for (i = 0; i < smp_num_cpus; i++)
- p += sprintf(p, "TRY%d ", i);
+ seq_printf(p, "TRY%d ", i);
#endif
- *p++ = '\n';
+ seq_putc(p, '\n');
#endif
for (i = 0; i < NR_IRQS; i++) {
action = irq_desc[i].action;
if (!action)
continue;
- p += sprintf(p, "%3d: ",i);
+ seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
- p += sprintf(p, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%10u ", kstat_irqs(i));
#else
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
+ seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
#ifdef DO_BROADCAST_INTS
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10lu ",
+ seq_printf(p, "%10lu ",
irq_attempt(cpu_logical_map(j), i));
#endif
#endif
- p += sprintf(p, " %14s", irq_desc[i].handler->typename);
- p += sprintf(p, " %c%s",
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %c%s",
(action->flags & SA_INTERRUPT)?'+':' ',
action->name);
for (action=action->next; action; action = action->next) {
- p += sprintf(p, ", %c%s",
+ seq_printf(p, ", %c%s",
(action->flags & SA_INTERRUPT)?'+':' ',
action->name);
}
- *p++ = '\n';
+ seq_putc(p, '\n');
}
#if CONFIG_SMP
- p += sprintf(p, "IPI: ");
+ seq_puts(p, "IPI: ");
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10lu ",
+ seq_printf(p, "%10lu ",
cpu_data[cpu_logical_map(j)].ipi_count);
- p += sprintf(p, "\n");
+ seq_putc(p, '\n');
#endif
- p += sprintf(p, "ERR: %10lu\n", irq_err_count);
- return p - buf;
+ seq_printf(p, "ERR: %10lu\n", irq_err_count);
+ return 0;
}
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/fiq.h>
#include <asm/io.h>
static struct fiq_handler *current_fiq = &default_owner;
-int get_fiq_list(char *buf)
+int show_fiq_list(struct seq_file *p, void *v)
{
- char *p = buf;
-
if (current_fiq != &default_owner)
- p += sprintf(p, "FIQ: %s\n",
- current_fiq->name);
+ seq_printf(p, "FIQ: %s\n", current_fiq->name);
- return p - buf;
+ return 0;
}
void set_fiq_handler(void *start, unsigned int length)
#include <linux/random.h>
#include <linux/smp.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/irq.h>
#include <asm/system.h>
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
int i;
struct irqaction * action;
- char *p = buf;
for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_desc[i].action;
if (!action)
continue;
- p += sprintf(p, "%3d: %10u ", i, kstat_irqs(i));
- p += sprintf(p, " %s", action->name);
+ seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
+ seq_printf(p, " %s", action->name);
for (action = action->next; action; action = action->next) {
- p += sprintf(p, ", %s", action->name);
+ seq_printf(p, ", %s", action->name);
}
- *p++ = '\n';
+ seq_putc(p, '\n');
}
#ifdef CONFIG_ARCH_ACORN
- p += get_fiq_list(p);
+ show_fiq_list(p);
#endif
- p += sprintf(p, "Err: %10lu\n", irq_err_count);
- return p - buf;
+ seq_printf(p, "Err: %10lu\n", irq_err_count);
+ return 0;
}
/*
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/io.h>
NULL, NULL, NULL, NULL
};
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
struct irqaction * action;
for (i = 0; i < NR_IRQS; i++) {
action = irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %10u %c %s",
+ seq_printf(p, "%2d: %10u %c %s",
i, kstat.irqs[0][i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action = action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, "\n");
+ seq_putc(p, '\n');
}
- return len;
+ return 0;
}
/* called by the assembler IRQ entry functions defined in irq.h
rp_read:
#ifdef __BIG_KERNEL__ # look in setup.S for bootsect_kludge
bootsect_kludge = 0x220 # 0x200 + 0x20 which is the size of the
- lcall bootsect_kludge # bootsector + bootsect_kludge offset
+ lcall *bootsect_kludge # bootsector + bootsect_kludge offset
#else
movw %es, %ax
subw $SYSSEG, %ax
cmpw $0, %cs:realmode_swtch
jz rmodeswtch_normal
- lcall %cs:realmode_swtch
+ lcall *%cs:realmode_swtch
jmp rmodeswtch_end
static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
static struct apm_user * user_list;
+static spinlock_t user_list_lock;
static char driver_version[] = "1.15"; /* no spaces */
__asm__ __volatile__(APM_DO_ZERO_SEGS
"pushl %%edi\n\t"
"pushl %%ebp\n\t"
- "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
+ "lcall *%%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
"setc %%al\n\t"
"popl %%ebp\n\t"
"popl %%edi\n\t"
__asm__ __volatile__(APM_DO_ZERO_SEGS
"pushl %%edi\n\t"
"pushl %%ebp\n\t"
- "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
+ "lcall *%%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
"setc %%bl\n\t"
"popl %%ebp\n\t"
"popl %%edi\n\t"
{
struct apm_user * as;
+ spin_lock( &user_list_lock );
if (user_list == NULL)
return;
for (as = user_list; as != NULL; as = as->next) {
break;
}
}
+ spin_unlock( &user_list_lock );
wake_up_interruptible(&apm_waitqueue);
}
send_event(APM_NORMAL_RESUME);
sti();
queue_event(APM_NORMAL_RESUME, NULL);
+ spin_lock( &user_list_lock );
for (as = user_list; as != NULL; as = as->next) {
as->suspend_wait = 0;
as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO);
}
+ spin_unlock( &user_list_lock );
ignore_normal_resume = 1;
wake_up_interruptible(&apm_suspend_waitqueue);
return err;
if (check_apm_user(as, "release"))
return 0;
filp->private_data = NULL;
- lock_kernel();
if (as->standbys_pending > 0) {
standbys_pending -= as->standbys_pending;
if (standbys_pending <= 0)
if (suspends_pending <= 0)
(void) suspend();
}
+ spin_lock( &user_list_lock );
if (user_list == as)
user_list = as->next;
else {
else
as1->next = as->next;
}
- unlock_kernel();
+ spin_unlock( &user_list_lock );
kfree(as);
return 0;
}
as->suser = capable(CAP_SYS_ADMIN);
as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+ spin_lock( &user_list_lock );
as->next = user_list;
user_list = as;
+ spin_unlock( &user_list_lock );
filp->private_data = as;
return 0;
}
#include <linux/kernel_stat.h>
#include <linux/irq.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/atomic.h>
#include <asm/io.h>
* Generic, controller-independent functions:
*/
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
struct irqaction * action;
- char *p = buf;
- p += sprintf(p, " ");
+ seq_printf(p, " ");
for (j=0; j<smp_num_cpus; j++)
- p += sprintf(p, "CPU%d ",j);
- *p++ = '\n';
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_desc[i].action;
if (!action)
continue;
- p += sprintf(p, "%3d: ",i);
+ seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
- p += sprintf(p, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%10u ", kstat_irqs(i));
#else
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
+ seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
#endif
- p += sprintf(p, " %14s", irq_desc[i].handler->typename);
- p += sprintf(p, " %s", action->name);
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
- p += sprintf(p, ", %s", action->name);
- *p++ = '\n';
+ seq_printf(p, ", %s", action->name);
+ seq_putc(p, '\n');
}
- p += sprintf(p, "NMI: ");
+ seq_printf(p, "NMI: ");
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
- nmi_count(cpu_logical_map(j)));
- p += sprintf(p, "\n");
+ seq_printf(p, "%10u ", nmi_count(cpu_logical_map(j)));
+ seq_putc(p, '\n');
#if CONFIG_X86_LOCAL_APIC
- p += sprintf(p, "LOC: ");
+ seq_printf(p, "LOC: ");
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
- apic_timer_irqs[cpu_logical_map(j)]);
- p += sprintf(p, "\n");
+ seq_printf(p, "%10u ", apic_timer_irqs[cpu_logical_map(j)]);
+ seq_putc(p, '\n');
#endif
- p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+ seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
#ifdef CONFIG_X86_IO_APIC
#ifdef APIC_MISMATCH_DEBUG
- p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+ seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
#endif
#endif
- return p - buf;
+ return 0;
}
-
/*
* Global interrupt locks for SMP. Allow interrupts to come in on any
* CPU, yet make cli/sti act globally to protect critical regions..
unsigned int *fcount = file->private_data;
if (fcount == NULL) return 0;
- lock_kernel();
max = get_num_var_ranges ();
for (i = 0; i < max; ++i)
{
--fcount[i];
}
}
- unlock_kernel();
kfree (fcount);
file->private_data = NULL;
return 0;
unsigned long flags;
__save_flags(flags); __cli();
- __asm__("lcall (%%edi); cld"
+ __asm__("lcall *(%%edi); cld"
: "=a" (return_code),
"=b" (address),
"=c" (length),
__save_flags(flags); __cli();
__asm__(
- "lcall (%%edi); cld\n\t"
+ "lcall *(%%edi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
unsigned short bx;
unsigned short ret;
- __asm__("lcall (%%edi); cld\n\t"
+ __asm__("lcall *(%%edi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
switch (len) {
case 1:
- __asm__("lcall (%%esi); cld\n\t"
+ __asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
"S" (&pci_indirect));
break;
case 2:
- __asm__("lcall (%%esi); cld\n\t"
+ __asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
"S" (&pci_indirect));
break;
case 4:
- __asm__("lcall (%%esi); cld\n\t"
+ __asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
switch (len) {
case 1:
- __asm__("lcall (%%esi); cld\n\t"
+ __asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
"S" (&pci_indirect));
break;
case 2:
- __asm__("lcall (%%esi); cld\n\t"
+ __asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
"S" (&pci_indirect));
break;
case 4:
- __asm__("lcall (%%esi); cld\n\t"
+ __asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
__asm__("push %%es\n\t"
"push %%ds\n\t"
"pop %%es\n\t"
- "lcall (%%esi); cld\n\t"
+ "lcall *(%%esi); cld\n\t"
"pop %%es\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
{
int ret;
- __asm__("lcall (%%esi); cld\n\t"
+ __asm__("lcall *(%%esi); cld\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
#include <linux/kernel_stat.h>
#include <linux/irq.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/atomic.h>
#include <asm/io.h>
* Generic, controller-independent functions:
*/
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
struct irqaction * action;
irq_desc_t *idesc;
- char *p = buf;
- p += sprintf(p, " ");
+ seq_puts(p, " ");
for (j=0; j<smp_num_cpus; j++)
- p += sprintf(p, "CPU%d ",j);
- *p++ = '\n';
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++) {
idesc = irq_desc(i);
action = idesc->action;
if (!action)
continue;
- p += sprintf(p, "%3d: ",i);
+ seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
- p += sprintf(p, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%10u ", kstat_irqs(i));
#else
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
+ seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
#endif
- p += sprintf(p, " %14s", idesc->handler->typename);
- p += sprintf(p, " %s", action->name);
+ seq_printf(p, " %14s", idesc->handler->typename);
+ seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
- p += sprintf(p, ", %s", action->name);
- *p++ = '\n';
+ seq_printf(p, ", %s", action->name);
+ seq_putc('\n');
}
- p += sprintf(p, "NMI: ");
+ seq_puts(p, "NMI: ");
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
+ seq_printf(p, "%10u ",
nmi_count(cpu_logical_map(j)));
- p += sprintf(p, "\n");
+ seq_putc(p, '\n');
#if defined(CONFIG_SMP) && defined(CONFIG_X86)
- p += sprintf(p, "LOC: ");
+ seq_puts(p, "LOC: ");
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
+ seq_printf(p, "%10u ",
apic_timer_irqs[cpu_logical_map(j)]);
- p += sprintf(p, "\n");
+ seq_putc(p, '\n');
#endif
- p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+ seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
- p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+ seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
#endif
- return p - buf;
+ return 0;
}
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/irq.h>
unsigned long flags, const char *devname, void *dev_id);
extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id);
extern void cia_init_IRQ(struct ciabase *base);
-extern int cia_get_irq_list(struct ciabase *base, char *buf);
+extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p);
/* irq node variables for amiga interrupt sources */
static irq_node_t *ami_irq_list[AMI_STD_IRQS];
ami_int4, ami_int5, ami_badint, ami_int7
};
-int amiga_get_irq_list(char *buf)
+int show_amiga_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
irq_node_t *node;
for (i = 0; i < AMI_STD_IRQS; i++) {
if (!(node = ami_irq_list[i]))
continue;
- len += sprintf(buf+len, "ami %2d: %10u ", i,
+ seq_printf(p, "ami %2d: %10u ", i,
kstat.irqs[0][SYS_IRQS + i]);
do {
if (node->flags & SA_INTERRUPT)
- len += sprintf(buf+len, "F ");
+ seq_puts(p, "F ");
else
- len += sprintf(buf+len, " ");
- len += sprintf(buf+len, "%s\n", node->devname);
+ seq_puts(p, " ");
+ seq_printf(p, "%s\n", node->devname);
if ((node = node->next))
- len += sprintf(buf+len, " ");
+ seq_puts(p, " ");
} while (node);
}
- len += cia_get_irq_list(&ciaa_base, buf+len);
- len += cia_get_irq_list(&ciab_base, buf+len);
- return len;
+ cia_get_irq_list(&ciaa_base, p);
+ cia_get_irq_list(&ciab_base, p);
+ return 0;
}
#include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
custom.intena = IF_SETCLR | base->int_mask;
}
-int cia_get_irq_list(struct ciabase *base, char *buf)
+int cia_get_irq_list(struct ciabase *base, struct seq_file *p)
{
- int i, j, len = 0;
+ int i, j;
j = base->cia_irq;
for (i = 0; i < CIA_IRQS; i++) {
- len += sprintf(buf+len, "cia %2d: %10d ", j + i,
+ seq_printf(p, "cia %2d: %10d ", j + i,
kstat.irqs[0][SYS_IRQS + j + i]);
- len += sprintf(buf+len, " ");
- len += sprintf(buf+len, "%s\n", base->irq_list[i].devname);
+ seq_puts(p, " ");
+ seq_printf(p, "%s\n", base->irq_list[i].devname);
}
- return len;
+ return 0;
}
extern void amiga_disable_irq (unsigned int);
static void amiga_get_model(char *model);
static int amiga_get_hardware_list(char *buffer);
-extern int amiga_get_irq_list (char *);
+extern int show_amiga_interrupts (struct seq_file *, void *);
/* amiga specific timer functions */
static unsigned long amiga_gettimeoffset (void);
static void a3000_gettod (int *, int *, int *, int *, int *, int *);
disable_irq = amiga_disable_irq;
mach_get_model = amiga_get_model;
mach_get_hardware_list = amiga_get_hardware_list;
- mach_get_irq_list = amiga_get_irq_list;
+ mach_get_irq_list = show_amiga_interrupts;
mach_gettimeoffset = amiga_gettimeoffset;
if (AMIGAHW_PRESENT(A3000_CLK)){
mach_gettod = a3000_gettod;
extern void dn_free_irq(unsigned int irq, void *dev_id);
extern void dn_enable_irq(unsigned int);
extern void dn_disable_irq(unsigned int);
-extern int dn_get_irq_list(char *);
+extern int show_dn_interrupts(struct seq_file *, void *);
extern unsigned long dn_gettimeoffset(void);
extern void dn_gettod(int *, int *, int *, int *, int *, int *);
extern int dn_dummy_hwclk(int, struct hwclk_time *);
mach_free_irq = dn_free_irq;
enable_irq = dn_enable_irq;
disable_irq = dn_disable_irq;
- mach_get_irq_list = dn_get_irq_list;
+ mach_get_irq_list = show_dn_interrupts;
mach_gettimeoffset = dn_gettimeoffset;
mach_gettod = dn_gettod; /* */
mach_max_dma_address = 0xffffffff;
}
-int dn_get_irq_list(char *buf) {
+int show_dn_interrupts(struct seq_file *p, void *v) {
printk("dn get irq list\n");
#include <linux/ptrace.h>
#include <linux/kernel_stat.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/traps.h>
}
-int atari_get_irq_list(char *buf)
+int show_atari_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
for (i = 0; i < NUM_INT_SOURCES; ++i) {
if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt)
continue;
if (i < STMFP_SOURCE_BASE)
- len += sprintf(buf+len, "auto %2d: %10u ",
+ seq_printf(p,, "auto %2d: %10u ",
i, kstat.irqs[0][i]);
else
- len += sprintf(buf+len, "vec $%02x: %10u ",
+ seq_printf(p,, "vec $%02x: %10u ",
IRQ_SOURCE_TO_VECTOR(i),
kstat.irqs[0][i]);
if (irq_handler[i].handler != atari_call_irq_list) {
- len += sprintf(buf+len, "%s\n", irq_param[i].devname);
+ seq_printf(p,, "%s\n", irq_param[i].devname);
}
else {
irq_node_t *p;
for( p = (irq_node_t *)irq_handler[i].dev_id; p; p = p->next ) {
- len += sprintf(buf+len, "%s\n", p->devname);
+ seq_printf(p,, "%s\n", p->devname);
if (p->next)
- len += sprintf( buf+len, " " );
+ seq_puts(p,, " " );
}
}
}
if (num_spurious)
- len += sprintf(buf+len, "spurio.: %10u\n", num_spurious);
+ seq_printf(p, "spurio.: %10u\n", num_spurious);
- return len;
+ return 0;
}
extern void atari_free_irq (unsigned int irq, void *dev_id);
extern void atari_enable_irq (unsigned int);
extern void atari_disable_irq (unsigned int);
-extern int atari_get_irq_list (char *buf);
+extern int show_atari_interrupts (struct seq_file *, void *);
extern void atari_mksound( unsigned int count, unsigned int ticks );
#ifdef CONFIG_HEARTBEAT
static void atari_heartbeat( int on );
disable_irq = atari_disable_irq;
mach_get_model = atari_get_model;
mach_get_hardware_list = atari_get_hardware_list;
- mach_get_irq_list = atari_get_irq_list;
+ mach_get_irq_list = show_atari_interrupts;
mach_gettimeoffset = atari_gettimeoffset;
mach_reset = atari_reset;
#ifdef CONFIG_ATARI_FLOPPY
{
int minor = DEVICE_NR(inode->i_rdev);
- lock_kernel();
joystick[minor].active = 0;
joystick[minor].ready = 0;
if ((joystick[0].active == 0) && (joystick[1].active == 0))
ikbd_joystick_disable();
- unlock_kernel();
return 0;
}
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/seq_file.h>
#include <asm/ptrace.h>
#include <asm/system.h>
}
}
-int bvme6000_get_irq_list (char *buf)
+int show_bvme6000_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
for (i = 0; i < 256; i++) {
if (irq_tab[i].count)
- len += sprintf (buf+len, "Vec 0x%02x: %8d %s\n",
+ seq_printf(p, "Vec 0x%02x: %8d %s\n",
i, irq_tab[i].count,
irq_tab[i].devname ? irq_tab[i].devname : "free");
}
- return len;
+ return 0;
}
extern void bvme6000_process_int (int level, struct pt_regs *regs);
extern void bvme6000_init_IRQ (void);
extern void bvme6000_free_irq (unsigned int, void *);
-extern int bvme6000_get_irq_list (char *);
+extern int show_bvme6000_interrupts(struct seq_file *, void *);
extern void bvme6000_enable_irq (unsigned int);
extern void bvme6000_disable_irq (unsigned int);
static void bvme6000_get_model(char *model);
mach_reset = bvme6000_reset;
mach_free_irq = bvme6000_free_irq;
mach_process_int = bvme6000_process_int;
- mach_get_irq_list = bvme6000_get_irq_list;
+ mach_get_irq_list = show_bvme6000_interrupts;
mach_request_irq = bvme6000_request_irq;
enable_irq = bvme6000_enable_irq;
disable_irq = bvme6000_disable_irq;
extern void hp300_reset(void);
extern void (*hp300_default_handler[])(int, void *, struct pt_regs *);
-extern int hp300_get_irq_list(char *buf);
+extern int show_hp300_interrupts(struct seq_file *, void *);
#ifdef CONFIG_VT
extern int hp300_keyb_init(void);
mach_request_irq = hp300_request_irq;
mach_free_irq = hp300_free_irq;
mach_get_model = hp300_get_model;
- mach_get_irq_list = hp300_get_irq_list;
+ mach_get_irq_list = show_hp300_interrupts;
mach_gettimeoffset = hp300_gettimeoffset;
mach_default_handler = &hp300_default_handler;
#if 0
spin_unlock_irqrestore(&irqlist_lock, flags);
}
-int hp300_get_irq_list(char *buf)
+int show_hp300_interrupts(struct seq_file *p, void *v)
{
return 0;
}
}
}
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
/* autovector interrupts */
if (mach_default_handler) {
for (i = 0; i < SYS_IRQS; i++) {
- len += sprintf(buf+len, "auto %2d: %10u ", i,
+ seq_printf(p, "auto %2d: %10u ", i,
i ? kstat.irqs[0][i] : num_spurious);
- len += sprintf(buf+len, " ");
- len += sprintf(buf+len, "%s\n", irq_list[i].devname);
+ seq_puts(p, " ");
+ seq_printf(p, "%s\n", irq_list[i].devname);
}
}
- len += mach_get_irq_list(buf+len);
- return len;
+ mach_get_irq_list(p, v);
+ return 0;
}
void init_irq_proc(void)
void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
void (*mach_get_model) (char *model) = NULL;
int (*mach_get_hardware_list) (char *buffer) = NULL;
-int (*mach_get_irq_list) (char *) = NULL;
+int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
void (*mach_process_int) (int, struct pt_regs *) = NULL;
/* machine dependent timer functions */
unsigned long (*mach_gettimeoffset) (void);
extern unsigned long mac_gettimeoffset (void);
extern int mac_hwclk (int, struct hwclk_time *);
extern int mac_set_clock_mmss (unsigned long);
-extern int mac_get_irq_list(char *);
+extern int show_mac_interrupts(struct seq_file *, void *);
extern void iop_preinit(void);
extern void iop_init(void);
extern void via_init(void);
disable_irq = mac_disable_irq;
mach_get_model = mac_get_model;
mach_default_handler = &mac_handlers;
- mach_get_irq_list = mac_get_irq_list;
+ mach_get_irq_list = show_mac_interrupts;
mach_gettimeoffset = mac_gettimeoffset;
mach_gettod = mac_gettod;
mach_hwclk = mac_hwclk;
#include <linux/kernel_stat.h>
#include <linux/interrupt.h> /* for intr_count */
#include <linux/delay.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/irq.h>
* displayed for us as autovector irq 0.
*/
-int mac_get_irq_list (char *buf)
+int show_mac_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
irq_node_t *node;
char *base;
case 8: base = "bbn";
break;
}
- len += sprintf(buf+len, "%4s %2d: %10u ",
- base, i, kstat.irqs[0][i]);
+ seq_printf(p, "%4s %2d: %10u ", base, i, kstat.irqs[0][i]);
do {
if (node->flags & IRQ_FLG_FAST) {
- len += sprintf(buf+len, "F ");
+ seq_puts(p, "F ");
} else if (node->flags & IRQ_FLG_SLOW) {
- len += sprintf(buf+len, "S ");
+ seq_puts(p, "S ");
} else {
- len += sprintf(buf+len, " ");
+ seq_puts(p, " ");
}
- len += sprintf(buf+len, "%s\n", node->devname);
+ seq_printf(p, "%s\n", node->devname);
if ((node = node->next)) {
- len += sprintf(buf+len, " ");
+ seq_puts(p, " ");
}
} while(node);
}
- return len;
+ return 0;
}
void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/seq_file.h>
#include <asm/ptrace.h>
#include <asm/system.h>
}
}
-int mvme147_get_irq_list (char *buf)
+int show_mvme147_interrupts (struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
for (i = 0; i < 256; i++) {
if (irq_tab[i].count)
- len += sprintf (buf+len, "Vec 0x%02x: %8d %s\n",
+ seq_printf(p, "Vec 0x%02x: %8d %s\n",
i, irq_tab[i].count,
irq_tab[i].devname ? irq_tab[i].devname : "free");
}
- return len;
+ return 0;
}
extern void mvme147_process_int (int level, struct pt_regs *regs);
extern void mvme147_init_IRQ (void);
extern void mvme147_free_irq (unsigned int, void *);
-extern int mvme147_get_irq_list (char *);
+extern int show_mvme147_interrupts (struct seq_file *, void *);
extern void mvme147_enable_irq (unsigned int);
extern void mvme147_disable_irq (unsigned int);
static void mvme147_get_model(char *model);
mach_reset = mvme147_reset;
mach_free_irq = mvme147_free_irq;
mach_process_int = mvme147_process_int;
- mach_get_irq_list = mvme147_get_irq_list;
+ mach_get_irq_list = show_mvme147_interrupts;
mach_request_irq = mvme147_request_irq;
enable_irq = mvme147_enable_irq;
disable_irq = mvme147_disable_irq;
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/ptrace.h>
}
}
-int mvme16x_get_irq_list (char *buf)
+int show_mvme16x_interrupts (struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
for (i = 0; i < 192; i++) {
if (irq_tab[i].count)
- len += sprintf (buf+len, "Vec 0x%02x: %8d %s\n",
+ seq_printf(p, "Vec 0x%02x: %8d %s\n",
i+64, irq_tab[i].count,
irq_tab[i].devname ? irq_tab[i].devname : "free");
}
- return len;
+ return 0;
}
extern void mvme16x_process_int (int level, struct pt_regs *regs);
extern void mvme16x_init_IRQ (void);
extern void mvme16x_free_irq (unsigned int, void *);
-extern int mvme16x_get_irq_list (char *);
+extern int show_mvme16x_interrupts (struct seq_file *, void *);
extern void mvme16x_enable_irq (unsigned int);
extern void mvme16x_disable_irq (unsigned int);
static void mvme16x_get_model(char *model);
mach_reset = mvme16x_reset;
mach_free_irq = mvme16x_free_irq;
mach_process_int = mvme16x_process_int;
- mach_get_irq_list = mvme16x_get_irq_list;
+ mach_get_irq_list = show_mvme16x_interrupts;
mach_request_irq = mvme16x_request_irq;
enable_irq = mvme16x_enable_irq;
disable_irq = mvme16x_disable_irq;
static unsigned char days_in_mo[] =
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static char rtc_status = 0;
+static atomic_t rtc_ready = ATOMIC_INIT(1);
static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
static int rtc_open(struct inode *inode, struct file *file)
{
- if(rtc_status)
+ if( !atomic_dec_and_test(&rtc_ready) )
+ {
+ atomic_inc( &rtc_ready );
return -EBUSY;
+ }
- rtc_status = 1;
return 0;
}
static int rtc_release(struct inode *inode, struct file *file)
{
- lock_kernel();
- rtc_status = 0;
- unlock_kernel();
+ atomic_inc( &rtc_ready );
return 0;
}
extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
extern void q40_init_IRQ (void);
extern void q40_free_irq (unsigned int, void *);
-extern int q40_get_irq_list (char *);
+extern int show_q40_interrupts (struct seq_file *, void *);
extern void q40_enable_irq (unsigned int);
extern void q40_disable_irq (unsigned int);
static void q40_get_model(char *model);
mach_reset = q40_reset;
mach_free_irq = q40_free_irq;
mach_process_int = q40_process_int;
- mach_get_irq_list = q40_get_irq_list;
+ mach_get_irq_list = show_q40_interrupts;
mach_request_irq = q40_request_irq;
enable_irq = q40_enable_irq;
disable_irq = q40_disable_irq;
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/sched.h>
+#include <linux/seq_file.h>
#include <asm/rtc.h>
#include <asm/ptrace.h>
}
}
-int q40_get_irq_list (char *buf)
+int show_q40_interrupts (struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
- for (i = 0; i <= Q40_IRQ_MAX; i++)
- {
+ for (i = 0; i <= Q40_IRQ_MAX; i++) {
if (irq_tab[i].count)
- len += sprintf (buf+len, "%sIRQ %02d: %8d %s%s\n",
+ seq_printf(p, "%sIRQ %02d: %8d %s%s\n",
(i<=15) ? "ISA-" : " " ,
i, irq_tab[i].count,
irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
irq_tab[i].handler == q40_defhand ?
" (now unassigned)" : "");
}
- return len;
+ return 0;
}
char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
extern unsigned long sun3_gettimeoffset(void);
-extern int sun3_get_irq_list (char *);
+extern int show_sun3_interrupts (char *);
extern void sun3_sched_init(void (*handler)(int, void *, struct pt_regs *));
extern void sun3_get_model (char* model);
extern void idprom_init (void);
enable_irq = sun3_enable_irq;
disable_irq = sun3_disable_irq;
mach_process_int = sun3_process_int;
- mach_get_irq_list = sun3_get_irq_list;
+ mach_get_irq_list = show_sun3_interrupts;
mach_gettod = sun3_gettod;
mach_reset = sun3_reboot;
mach_gettimeoffset = sun3_gettimeoffset;
#include <asm/intersil.h>
#include <asm/oplib.h>
#include <asm/sun3ints.h>
+#include <linux/seq_file.h>
extern void sun3_leds (unsigned char);
*sun3_intreg |= (1<<irq);
}
-int sun3_get_irq_list(char *buf)
+int show_sun3_interrupts(struct seq_file *p, void *v)
{
return 0;
}
sun3x_prom_init();
- mach_get_irq_list = sun3_get_irq_list;
+ mach_get_irq_list = show_sun3_interrupts;
mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
mach_keyb_init = sun3x_keyb_init;
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/delay.h>
+#include <linux/seq_file.h>
#include <asm/bitops.h>
#include <asm/bootinfo.h>
*/
static struct irqaction *irq_action[BAGET_IRQ_NR] = { NULL, };
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
struct irqaction * action;
for (i = 0 ; i < BAGET_IRQ_NR ; i++) {
action = irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s",
+ seq_printf(p, "%2d: %8d %c %s",
i, kstat.irqs[0][i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, "\n");
+ seq_putc(p, '\n');
}
- return len;
+ return 0;
}
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
+#include <linux/seq_file.h>
#include <asm/bitops.h>
#include <asm/bootinfo.h>
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
- struct irqaction *action;
-
- for (i = 0; i < 32; i++) {
- action = irq_action[i];
- if (!action)
- continue;
- len += sprintf(buf + len, "%2d: %8d %c %s",
- i, kstat.irqs[0][i],
- (action->flags & SA_INTERRUPT) ? '+' : ' ',
- action->name);
- for (action = action->next; action; action = action->next) {
- len += sprintf(buf + len, ",%s %s",
- (action->flags & SA_INTERRUPT) ? " +" : "",
- action->name);
+ int i;
+ struct irqaction *action;
+
+ for (i = 0; i < 32; i++) {
+ action = irq_action[i];
+ if (!action)
+ continue;
+ seq_printf(p, "%2d: %8d %c %s",
+ i, kstat.irqs[0][i],
+ (action->flags & SA_INTERRUPT) ? '+' : ' ',
+ action->name);
+ for (action = action->next; action; action = action->next) {
+ seq_printf(p, ",%s %s",
+ (action->flags & SA_INTERRUPT) ? " +" : "",
+ action->name);
+ }
+ seq_putc(p, '\n');
}
- len += sprintf(buf + len, "\n");
- }
- return len;
+ return 0;
}
/*
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/serial_reg.h>
+#include <linux/seq_file.h>
#include <asm/bitops.h>
#include <asm/bootinfo.h>
};
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0, j;
+ int i, j;
struct irqaction * action;
- len += sprintf(buf+len, " ");
+ seq_printf(p, " ");
for (j=0; j<smp_num_cpus; j++)
- len += sprintf(buf+len, "CPU%d ",j);
- *(char *)(buf+len++) = '\n';
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_desc[i].action;
if ( !action || !action->handler )
continue;
- len += sprintf(buf+len, "%3d: ", i);
- len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%3d: ", i);
+ seq_printf(p, "%10u ", kstat_irqs(i));
if ( irq_desc[i].handler )
- len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
+ seq_printf(p, " %s ", irq_desc[i].handler->typename );
else
- len += sprintf(buf+len, " None ");
- len += sprintf(buf+len, " %s",action->name);
+ seq_puts(p, " None ");
+ seq_printf(p, " %s",action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ", %s", action->name);
+ seq_printf(p, ", %s", action->name);
}
- len += sprintf(buf+len, "\n");
+ seq_putc(p, '\n');
}
- len += sprintf(buf+len, "BAD: %10lu\n", spurious_count);
- return len;
+ seq_printf(p, "BAD: %10lu\n", spurious_count);
+ return 0;
}
asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
#include <linux/mm.h>
#include <linux/random.h>
#include <linux/sched.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
* Generic, controller-independent functions:
*/
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
struct irqaction * action;
- char *p = buf;
int i;
- p += sprintf(p, " ");
+ seq_puts(p, " ");
for (i=0; i < 1 /*smp_num_cpus*/; i++)
- p += sprintf(p, "CPU%d ", i);
- *p++ = '\n';
+ seq_printf(p, "CPU%d ", i);
+ seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_desc[i].action;
if (!action)
continue;
- p += sprintf(p, "%3d: ",i);
- p += sprintf(p, "%10u ", kstat_irqs(i));
- p += sprintf(p, " %14s", irq_desc[i].handler->typename);
- p += sprintf(p, " %s", action->name);
+ seq_printf(p, "%3d: ",i);
+ seq_printf(p, "%10u ", kstat_irqs(i));
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
- p += sprintf(p, ", %s", action->name);
- *p++ = '\n';
+ seq_printf(p, ", %s", action->name);
+ seq_putc(p, '\n');
}
- p += sprintf(p, "ERR: %10lu\n", irq_err_count);
- return p - buf;
+ seq_printf(p, "ERR: %10lu\n", irq_err_count);
+ return 0;
}
/*
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
+#include <linux/seq_file.h>
#include <asm/bitops.h>
#include <asm/bootinfo.h>
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
struct irqaction * action;
for (i = 0 ; i < 32 ; i++) {
action = irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s",
+ seq_printf(p, "%2d: %8d %c %s",
i, kstat.irqs[0][i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, "\n");
+ seq_putc(p, '\n');
}
- return len;
+ return 0;
}
static inline void i8259_mask_and_ack_irq(int irq)
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
#include <asm/irq.h>
#include <asm/mips-boards/atlas.h>
NULL
};
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
int num = 0;
struct irqaction *action;
action = irq_desc[i].action;
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s",
+ seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, " [hw0]\n");
+ seq_printf(p, " [hw0]\n");
}
- return len;
+ return 0;
}
int request_irq(unsigned int irq,
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
+#include <linux/seq_file.h>
#include <asm/bitops.h>
#include <asm/bootinfo.h>
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
struct irqaction *action;
for (i = 0; i < NR_IRQS; i++) {
action = irq_action[i];
if (!action)
continue;
- len += sprintf(buf + len, "%2d: %8d %c %s",
+ seq_printf(p, "%2d: %8d %c %s",
i, kstat.irqs[0][i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action = action->next; action; action = action->next) {
- len += sprintf(buf + len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf + len, "\n");
+ seq_putc(p, '\n');
}
- return len;
+ return 0;
}
atomic_t __mips_bh_counter;
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
#include <asm/irq.h>
#include <asm/mips-boards/atlas.h>
NULL
};
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
int num = 0;
struct irqaction *action;
action = irq_desc[i].action;
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s",
+ seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, " [hw0]\n");
+ seq_puts(p, " [hw0]\n");
}
- return len;
+ return 0;
}
int request_irq(unsigned int irq,
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/random.h>
+#include <linux/seq_file.h>
#include <asm/irq.h>
#include <asm/io.h>
}
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
int num = 0;
struct irqaction *action;
action = irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s",
+ seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, " [on-chip]\n");
+ seq_puts(p, " [on-chip]\n");
}
for (i = 0; i < MALTAINT_END; i++, num++) {
action = hw0_irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s",
+ seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, " [hw0]\n");
+ seq_puts(p, " [hw0]\n");
}
- return len;
+ return 0;
}
int request_irq(unsigned int irq,
*/
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <linux/errno.h>
#include <linux/kernel_stat.h>
NULL, NULL, NULL, NULL
};
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
int num = 0;
struct irqaction * action;
action = irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s",
+ seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, " [on-chip]\n");
+ seq_puts(p, " [on-chip]\n");
}
for (i = 0 ; i < 24 ; i++, num++) {
action = local_irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s",
+ seq_printf(p, "%2d: %8d %c %s",
num, kstat.irqs[0][num],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, " [local]\n");
+ seq_puts(p, " [local]\n");
}
- return len;
+ return 0;
}
/*
#include <linux/kernel_stat.h>
#include <linux/delay.h>
#include <linux/irq.h>
+#include <linux/seq_file.h>
#include <asm/bitops.h>
#include <asm/bootinfo.h>
/* This is stupid for an Origin which can have thousands of IRQs ... */
static struct irqaction *irq_action[NR_IRQS];
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
struct irqaction * action;
for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_action[i];
if (!action)
continue;
- len += sprintf(buf+len, "%2d: %8d %c %s", i, kstat.irqs[0][i],
+ seq_printf(p, "%2d: %8d %c %s", i, kstat.irqs[0][i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT)
? " +" : "",
action->name);
}
- len += sprintf(buf+len, "\n");
+ seq_putc(p, '\n');
}
- return len;
+ return 0;
}
/*
static void get_rtc_time(struct rtc_time *rtc_tm);
-/*
- * Bits in rtc_status. (6 bits of room for future expansion)
- */
-
-#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
-#define RTC_TIMER_ON 0x02 /* missed irq timer active */
-
-static unsigned char rtc_status; /* bitmapped status byte. */
+static atomic_t rtc_ready = ATOMIC_INIT(1);
static unsigned long rtc_freq; /* Current periodic IRQ rate */
static struct m48t35_rtc *rtc;
static int rtc_open(struct inode *inode, struct file *file)
{
- if(rtc_status & RTC_IS_OPEN)
+ if( atomic_dec_and_test( &rtc_ready ) )
+ {
+ atomic_inc( &rtc_ready );
return -EBUSY;
-
- rtc_status |= RTC_IS_OPEN;
+ }
return 0;
}
static int rtc_release(struct inode *inode, struct file *file)
{
- /*
- * Turn off all interrupts once the device is no longer
- * in use, and clear the data.
- */
-
- lock_kernel();
- rtc_status &= ~RTC_IS_OPEN;
- unlock_kernel();
+ atomic_inc( &rtc_ready );
return 0;
}
#include <linux/random.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/seq_file.h>
#include <asm/cache.h>
BUG();
}
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
#ifdef CONFIG_PROC_FS
- char *p = buf;
int i, j;
int regnr, irq_no;
struct irq_region *region;
struct irqaction *action, *mainaction;
- p += sprintf(p, " ");
+ seq_puts(p, " ");
for (j=0; j<smp_num_cpus; j++)
- p += sprintf(p, "CPU%d ",j);
- *p++ = '\n';
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
for (regnr = 0; regnr < NR_IRQ_REGS; regnr++) {
region = irq_region[regnr];
irq_no = IRQ_FROM_REGION(regnr) + i;
- p += sprintf(p, "%3d: ", irq_no);
+ seq_printf(p, "%3d: ", irq_no);
#ifndef CONFIG_SMP
- p += sprintf(p, "%10u ", kstat_irqs(irq_no));
+ seq_printf(p, "%10u ", kstat_irqs(irq_no));
#else
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
+ seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][irq_no]);
#endif
- p += sprintf(p, " %14s",
+ seq_printf(p, " %14s",
region->data.name ? region->data.name : "N/A");
- p += sprintf(p, " %s", action->name);
+ seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
- p += sprintf(p, ", %s", action->name);
- *p++ = '\n';
+ seq_printf(p, ", %s", action->name);
+ seq_putc(p, '\n');
}
}
- p += sprintf(p, "\n");
+ seq_putc(p, '\n');
#if CONFIG_SMP
- p += sprintf(p, "LOC: ");
+ seq_puts(p, "LOC: ");
for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
+ seq_printf(p, "%10u ",
apic_timer_irqs[cpu_logical_map(j)]);
- p += sprintf(p, "\n");
+ seq_putc(p, '\n');
#endif
-
- return p - buf;
-
-#else /* CONFIG_PROC_FS */
-
- return 0;
-
#endif /* CONFIG_PROC_FS */
+ return 0;
}
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/irq.h>
unsigned long flags, const char *devname, void *dev_id);
extern void cia_free_irq(unsigned int irq, void *dev_id);
extern void cia_init_IRQ(struct ciabase *base);
-extern int cia_get_irq_list(struct ciabase *base, char *buf);
+extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p);
/* irq node variables for amiga interrupt sources */
static irq_node_t *ami_irq_list[AMI_STD_IRQS];
};
#endif
-int amiga_get_irq_list(char *buf)
+int show_amiga_intreeupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
irq_node_t *node;
for (i = 0; i < AMI_STD_IRQS; i++) {
if (!(node = ami_irq_list[i]))
continue;
- len += sprintf(buf+len, "ami %2d: %10u ", i,
+ seq_printf(p, "ami %2d: %10u ", i,
kstat.irqs[0][SYS_IRQS + i]);
do {
if (node->flags & SA_INTERRUPT)
- len += sprintf(buf+len, "F ");
+ seq_puts(p, "F ");
else
- len += sprintf(buf+len, " ");
- len += sprintf(buf+len, "%s\n", node->devname);
+ seq_puts(p, " ");
+ seq_printf(p, "%s\n", node->devname);
if ((node = node->next))
- len += sprintf(buf+len, " ");
+ seq_puts(p, " ");
} while (node);
}
- len += cia_get_irq_list(&ciaa_base, buf+len);
- len += cia_get_irq_list(&ciab_base, buf+len);
+ cia_get_irq_list(&ciaa_base, p);
+ cia_get_irq_list(&ciab_base, p);
return len;
}
#include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
custom.intena = IF_SETCLR | base->int_mask;
}
-int cia_get_irq_list(struct ciabase *base, char *buf)
+int cia_get_irq_list(struct ciabase *base, struct seq_file *p)
{
- int i, j, len = 0;
+ int i, j;
j = base->cia_irq;
for (i = 0; i < CIA_IRQS; i++) {
- len += sprintf(buf+len, "cia %2d: %10d ", j + i,
+ seq_printf(p, "cia %2d: %10d ", j + i,
kstat.irqs[0][SYS_IRQS + j + i]);
- len += sprintf(buf+len, " ");
- len += sprintf(buf+len, "%s\n", base->irq_list[i].devname);
+ seq_puts(p, " ");
+ seq_printf(p, "%s\n", base->irq_list[i].devname);
}
- return len;
+ return 0;
}
#ifdef CONFIG_ZORRO
#include <linux/zorro.h>
#endif
+#include <linux/seq_file.h>
#include <asm/bootinfo.h>
#include <asm/setup.h>
extern void amiga_disable_irq (unsigned int);
static void amiga_get_model(char *model);
static int amiga_get_hardware_list(char *buffer);
-extern int amiga_get_irq_list (char *);
+extern int show_amiga_interrupts (struct seq_file *, void *);
/* amiga specific timer functions */
static unsigned long amiga_gettimeoffset (void);
static void a3000_gettod (int *, int *, int *, int *, int *, int *);
#endif
mach_get_model = amiga_get_model;
mach_get_hardware_list = amiga_get_hardware_list;
- mach_get_irq_list = amiga_get_irq_list;
+ mach_get_irq_list = show_amiga_interrupts;
mach_gettimeoffset = amiga_gettimeoffset;
if (AMIGAHW_PRESENT(A3000_CLK)){
mach_gettod = a3000_gettod;
#include <linux/kernel_stat.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/setup.h>
#include <asm/system.h>
}
}
-int m68k_get_irq_list(char *buf)
+int m68k_get_irq_list(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
/* autovector interrupts */
if (mach_default_handler) {
for (i = 0; i < SYS_IRQS; i++) {
- len += sprintf(buf+len, "auto %2d: %10u ", i,
+ seq_printf(p, "auto %2d: %10u ", i,
i ? kstat.irqs[0][i] : num_spurious);
- len += sprintf(buf+len, " ");
- len += sprintf(buf+len, "%s\n", irq_list[i].devname);
+ seq_puts(p, " ");
+ seq_printf(p, "%s\n", irq_list[i].devname);
}
}
- len += mach_get_irq_list(buf+len);
- return len;
+ mach_get_irq_list(p, v);
+ return 0;
}
void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
void (*mach_get_model) (char *model) = NULL;
int (*mach_get_hardware_list) (char *buffer) = NULL;
-int (*mach_get_irq_list) (char *) = NULL;
+int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
void (*mach_process_int) (int, struct pt_regs *) = NULL;
/* machine dependent timer functions */
unsigned long (*mach_gettimeoffset) (void);
return irq;
}
-int apus_get_irq_list(char *buf)
+int show_apus_interrupts(struct seq_file *p, void *v)
{
#ifdef CONFIG_APUS
- extern int amiga_get_irq_list(char *buf);
+ extern int show_amiga_interrupts(struct seq_file *p, void *v)
- return amiga_get_irq_list (buf);
+ return show_amiga_interrupts(p, v);
#else
return 0;
#endif
#include <linux/irq.h>
#include <linux/proc_fs.h>
#include <linux/random.h>
+#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
spin_unlock_irqrestore(&desc->lock, flags);
}
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
#ifdef CONFIG_APUS
- return apus_get_irq_list (buf);
+ return show_apus_interrupts(p, v);
#else
- int i, len = 0, j;
+ int i, j;
struct irqaction * action;
- len += sprintf(buf+len, " ");
+ seq_puts(p, " ");
for (j=0; j<smp_num_cpus; j++)
- len += sprintf(buf+len, "CPU%d ",j);
- *(char *)(buf+len++) = '\n';
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_desc[i].action;
if ( !action || !action->handler )
continue;
- len += sprintf(buf+len, "%3d: ", i);
+ seq_printf(p, "%3d: ", i);
#ifdef CONFIG_SMP
for (j = 0; j < smp_num_cpus; j++)
- len += sprintf(buf+len, "%10u ",
+ seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
#else
- len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%10u ", kstat_irqs(i));
#endif /* CONFIG_SMP */
if ( irq_desc[i].handler )
- len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
+ seq_printf(p, " %s ", irq_desc[i].handler->typename );
else
- len += sprintf(buf+len, " None ");
- len += sprintf(buf+len, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge ");
- len += sprintf(buf+len, " %s",action->name);
+ seq_puts(p, " None ");
+ seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge ");
+ seq_printf(p, " %s",action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ", %s", action->name);
+ seq_printf(p, ", %s", action->name);
}
- len += sprintf(buf+len, "\n");
+ seq_putc(p, '\n');
}
#ifdef CONFIG_TAU_INT
if (tau_initialized){
- len += sprintf(buf+len, "TAU: ");
+ seq_puts(p, "TAU: ");
for (j = 0; j < smp_num_cpus; j++)
- len += sprintf(buf+len, "%10u ",
+ seq_printf(p, "%10u ",
tau_interrupts(j));
- len += sprintf(buf+len, " PowerPC Thermal Assist (cpu temp)\n");
+ seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n");
}
#endif
#ifdef CONFIG_SMP
/* should this be per processor send/receive? */
- len += sprintf(buf+len, "IPI (recv/sent): %10u/%u\n",
+ seq_printf(p, "IPI (recv/sent): %10u/%u\n",
atomic_read(&ipi_recv), atomic_read(&ipi_sent));
#endif
- len += sprintf(buf+len, "BAD: %10u\n", ppc_spurious_interrupts);
- return len;
+ seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
+ return 0;
#endif /* CONFIG_APUS */
}
#include <linux/threads.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/io.h>
BUILD_SMP_INTERRUPT(spurious_interrupt)
#endif
-#if 0
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
struct irqaction * action;
- char *p = buf;
- p += sprintf(p, " ");
+ seq_puts(p, " ");
for (j=0; j<smp_num_cpus; j++)
- p += sprintf(p, "CPU%d ",j);
+ seq_printf(p, "CPU%d ",j);
- *p++ = '\n';
+ seq_putc(p, '\n');
- for (i = 0 ; i < NR_IRQS ; i++)
- {
+ for (i = 0 ; i < NR_IRQS ; i++) {
if (ioinfo[i] == INVALID_STORAGE_AREA)
continue;
if (!action)
continue;
- p += sprintf(p, "%3d: ",i);
+ seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
- p += sprintf(p, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%10u ", kstat_irqs(i));
#else
for (j=0; j<smp_num_cpus; j++)
- p += sprintf( p, "%10u ",
+ seq_printf( p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
#endif
- p += sprintf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
- p += sprintf(p, " %s", action->name);
+ seq_printf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
+ seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
{
- p += sprintf(p, ", %s", action->name);
+ seq_printf(p, ", %s", action->name);
} /* endfor */
- *p++ = '\n';
+ seq_putc(p, '\n');
} /* endfor */
- p += sprintf(p, "NMI: %10u\n", nmi_counter);
+ seq_printf(p, "NMI: %10u\n", nmi_counter);
#ifdef CONFIG_SMP
- p += sprintf(p, "IPI: %10u\n", atomic_read(&ipi_count));
+ seq_printf(p, "IPI: %10u\n", atomic_read(&ipi_count));
#endif
-
- return p - buf;
+ return 0;
}
-#endif
/*
* Global interrupt locks for SMP. Allow interrupts to come in on any
#include <linux/threads.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/io.h>
BUILD_SMP_INTERRUPT(spurious_interrupt)
#endif
-#if 0
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
struct irqaction * action;
- char *p = buf;
- p += sprintf(p, " ");
+ seq_puts(p, " ");
for (j=0; j<smp_num_cpus; j++)
- p += sprintf(p, "CPU%d ",j);
+ seq_printf(p, "CPU%d ",j);
- *p++ = '\n';
+ seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++)
{
if (!action)
continue;
- p += sprintf(p, "%3d: ",i);
+ seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
- p += sprintf(p, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%10u ", kstat_irqs(i));
#else
for (j=0; j<smp_num_cpus; j++)
- p += sprintf( p, "%10u ",
+ seq_printf( p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
#endif
- p += sprintf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
- p += sprintf(p, " %s", action->name);
+ seq_printf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
+ seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
{
- p += sprintf(p, ", %s", action->name);
+ seq_printf(p, ", %s", action->name);
} /* endfor */
- *p++ = '\n';
+ seq_putc(p, '\n');
} /* endfor */
- p += sprintf(p, "NMI: %10u\n", nmi_counter);
+ seq_printf(p, "NMI: %10u\n", nmi_counter);
#ifdef CONFIG_SMP
- p += sprintf(p, "IPI: %10u\n", atomic_read(&ipi_count));
+ seq_printf(p, "IPI: %10u\n", atomic_read(&ipi_count));
#endif
- return p - buf;
+ return 0;
}
-#endif
/*
* Global interrupt locks for SMP. Allow interrupts to come in on any
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/system.h>
#include <asm/io.h>
*/
#if defined(CONFIG_PROC_FS)
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
struct irqaction * action;
- char *p = buf;
- p += sprintf(p, " ");
+ seq_puts(p, " ");
for (j=0; j<smp_num_cpus; j++)
- p += sprintf(p, "CPU%d ",j);
- *p++ = '\n';
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
action = irq_desc[i].action;
if (!action)
continue;
- p += sprintf(p, "%3d: ",i);
- p += sprintf(p, "%10u ", kstat_irqs(i));
- p += sprintf(p, " %14s", irq_desc[i].handler->typename);
- p += sprintf(p, " %s", action->name);
+ seq_printf(p, "%3d: ",i);
+ seq_printf(p, "%10u ", kstat_irqs(i));
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
- p += sprintf(p, ", %s", action->name);
- *p++ = '\n';
+ seq_printf(p, ", %s", action->name);
+ seq_putc(p, '\n');
}
- return p - buf;
+ return 0;
}
#endif
#include <linux/delay.h>
#include <linux/threads.h>
#include <linux/spinlock.h>
+#include <linux/seq_file.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
};
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
struct irqaction * action;
#ifdef CONFIG_SMP
int j;
#endif
if (sparc_cpu_model == sun4d) {
- extern int sun4d_get_irq_list(char *);
+ extern int show_sun4d_interrupts(struct seq_file *, void *);
- return sun4d_get_irq_list(buf);
+ return show_sun4d_interrupts(p, v);
}
for (i = 0 ; i < (NR_IRQS+1) ; i++) {
action = *(i + irq_action);
if (!action)
continue;
- len += sprintf(buf+len, "%3d: ", i);
+ seq_printf(p, "%3d: ", i);
#ifndef CONFIG_SMP
- len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%10u ", kstat_irqs(i));
#else
for (j = 0; j < smp_num_cpus; j++)
- len += sprintf(buf+len, "%10u ",
+ seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
#endif
- len += sprintf(buf+len, " %c %s",
+ seq_printf(p, " %c %s",
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
- len += sprintf(buf+len, "\n");
+ seq_putc(p, '\n');
}
- return len;
+ return 0;
}
void free_irq(unsigned int irq, void *dev_id)
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
+#include <linux/seq_file.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
spinlock_t sun4d_imsk_lock = SPIN_LOCK_UNLOCKED;
#endif
-int sun4d_get_irq_list(char *buf)
+int show_sun4d_interrupts(struct seq_file *p, void *v)
{
- int i, j = 0, k = 0, len = 0, sbusl;
+ int i, j = 0, k = 0, sbusl;
struct irqaction * action;
#ifdef CONFIG_SMP
int x;
}
continue;
}
-found_it: len += sprintf(buf+len, "%3d: ", i);
+found_it: seq_printf(p, "%3d: ", i);
#ifndef CONFIG_SMP
- len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%10u ", kstat_irqs(i));
#else
for (x = 0; x < smp_num_cpus; x++)
- len += sprintf(buf+len, "%10u ",
+ seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(x)][i]);
#endif
- len += sprintf(buf+len, "%c %s",
+ seq_printf(p, "%c %s",
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
action = action->next;
for (;;) {
for (; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
+ seq_printf(p, ",%s %s",
(action->flags & SA_INTERRUPT) ? " +" : "",
action->name);
}
action = sbus_actions [(j << 5) + (sbusl << 2)].action;
}
}
- len += sprintf(buf+len, "\n");
+ seq_putc(p, '\n');
}
- return len;
+ return 0;
}
void sun4d_free_irq(unsigned int irq, void *dev_id)
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
#define put_smpaff_in_irqaction(action, smpaff) (action)->mask = (smpaff)
#define get_smpaff_in_irqaction(action) ((action)->mask)
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, len = 0;
+ int i;
struct irqaction *action;
#ifdef CONFIG_SMP
int j;
for(i = 0; i < (NR_IRQS + 1); i++) {
if(!(action = *(i + irq_action)))
continue;
- len += sprintf(buf + len, "%3d: ", i);
+ seq_print(p, "%3d: ", i);
#ifndef CONFIG_SMP
- len += sprintf(buf + len, "%10u ", kstat_irqs(i));
+ seq_print(p, "%10u ", kstat_irqs(i));
#else
for (j = 0; j < smp_num_cpus; j++)
- len += sprintf(buf + len, "%10u ",
+ seq_print(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
#endif
- len += sprintf(buf + len, " %s:%lx", action->name, \
+ seq_print(p, " %s:%lx", action->name,
get_ino_in_irqaction(action));
for(action = action->next; action; action = action->next) {
- len += sprintf(buf+len, ", %s:%lx", action->name, \
+ seq_print(p, ", %s:%lx", action->name,
get_ino_in_irqaction(action));
}
- len += sprintf(buf + len, "\n");
+ seq_putc(p, '\n');
}
- return len;
+ return 0;
}
/* Now these are always passed a true fully specified sun4u INO. */
struct T_primsg *it;
/* XXX: check this */
- lock_kernel();
sock = (struct sol_socket_struct *)filp->private_data;
SOLDD(("sock release %016lx(%016lx)\n", sock, filp));
it = sock->pfirst;
filp->private_data = NULL;
SOLDD(("socksys_release %016lx\n", sock));
mykfree((char*)sock);
- unlock_kernel();
return 0;
}
eh_bus_reset_handler: fas216_eh_bus_reset, \
eh_device_reset_handler: fas216_eh_device_reset, \
eh_abort_handler: fas216_eh_abort, \
-use_new_eh_code: 1 \
}
#ifndef HOSTS_C
eh_bus_reset_handler: fas216_eh_bus_reset,
eh_device_reset_handler: fas216_eh_device_reset,
eh_abort_handler: fas216_eh_abort,
- use_new_eh_code: 1
};
static int __init cumanascsi2_init(void)
eh_bus_reset_handler: fas216_eh_bus_reset,
eh_device_reset_handler: fas216_eh_device_reset,
eh_abort_handler: fas216_eh_abort,
- use_new_eh_code: 1
};
static int __init eesox_init(void)
eh_bus_reset_handler: fas216_eh_bus_reset,
eh_device_reset_handler: fas216_eh_device_reset,
eh_abort_handler: fas216_eh_abort,
- use_new_eh_code: 1
};
static int __init powertecscsi_init(void)
Initialize the I/O Request Queue.
*/
RequestQueue = BLK_DEFAULT_QUEUE(MajorNumber);
- blk_init_queue(RequestQueue, DAC960_RequestFunction, "dac960");
+ blk_init_queue(RequestQueue, DAC960_RequestFunction);
blk_queue_headactive(RequestQueue, 0);
RequestQueue->queuedata = Controller;
RequestQueue->max_segments = Controller->DriverScatterGatherLimit;
static struct slm {
unsigned target; /* target number */
unsigned lun; /* LUN in target controller */
- unsigned wbusy : 1; /* output part busy */
- unsigned rbusy : 1; /* status part busy */
+ atomic_t wr_ok; /* set to 0 if output part busy */
+ atomic_t rd_ok; /* set to 0 if status part busy */
} slm_info[MAX_SLM];
int N_SLM_Printers = 0;
if (file->f_mode & 2) {
/* open for writing is exclusive */
- if (sip->wbusy)
+ if ( !atomic_dec_and_test(&sip->wr_ok) ) {
+ atomic_inc(&sip->wr_ok);
return( -EBUSY );
- sip->wbusy = 1;
+ }
}
if (file->f_mode & 1) {
- /* open for writing is exclusive */
- if (sip->rbusy)
- return( -EBUSY );
- sip->rbusy = 1;
+ /* open for reading is exclusive */
+ if ( !atomic_dec_and_test(&sip->rd_ok) ) {
+ atomic_inc(&sip->rd_ok);
+ return( -EBUSY );
+ }
}
return( 0 );
device = MINOR(inode->i_rdev);
sip = &slm_info[device];
- lock_kernel();
if (file->f_mode & 2)
- sip->wbusy = 0;
+ atomic_inc( &sip->wr_ok );
if (file->f_mode & 1)
- sip->rbusy = 0;
- unlock_kernel();
+ atomic_inc( &sip->rd_ok );
return( 0 );
}
slm_info[N_SLM_Printers].target = target;
slm_info[N_SLM_Printers].lun = lun;
- slm_info[N_SLM_Printers].wbusy = 0;
- slm_info[N_SLM_Printers].rbusy = 0;
+ atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 );
+ atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 );
printk( KERN_INFO " Printer: %s\n", SLMBuffer );
printk( KERN_INFO "Detected slm%d at id %d lun %d\n",
case BLKELVSET:
return -ENOTTY;
- case BLKHASHPROF:
- case BLKHASHCLEAR:
- return bio_ioctl(dev, cmd, arg);
-
case BLKBSZGET:
/* get the logical block size (cf. BLKSSZGET) */
intval = BLOCK_SIZE;
q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
q->queuedata = hba[i];
- blk_init_queue(q, do_cciss_request, hba[i]->devname);
+ blk_init_queue(q, do_cciss_request);
blk_queue_headactive(q, 0);
blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
q->max_segments = MAXSGENTRIES;
q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
q->queuedata = hba[i];
- blk_init_queue(q, do_ida_request, hba[i]->devname);
+ blk_init_queue(q, do_ida_request);
blk_queue_headactive(q, 0);
blk_queue_bounce_limit(q, hba[i]->pci_dev->dma_mask);
q->max_segments = SG_MAX;
*
* Jens:
* - Rework again to work with bio instead of buffer_heads
- * - added merge by hash-lookup
* - loose bi_dev comparisons, partition handling is right now
* - completely modularize elevator setup and teardown
*
return 0;
}
-/*
- * find a struct request that has a bio linked that we can merge with
- */
-inline struct request *bio_get_hash_rq(kdev_t dev, sector_t sector, int vc)
-{
- struct bio *bio = bio_hash_find(dev, sector, vc);
- struct request *rq = NULL;
-
- /*
- * bio is pinned until we bio_put it
- */
- if (bio) {
- rq = bio->bi_hash_desc;
-
- BUG_ON(!rq);
-
- bio_put(bio);
- }
-
- return rq;
-}
-
int elevator_linus_merge(request_queue_t *q, struct request **req,
struct list_head *head, struct bio *bio)
{
unsigned int count = bio_sectors(bio);
- struct elv_linus_data *edat = q->elevator.elevator_data;
- unsigned int vc = q->hash_valid_counter;
- struct list_head *entry;
+ struct list_head *entry = &q->queue_head;
+ int ret = ELEVATOR_NO_MERGE;
struct request *__rq;
- /*
- * first try a back merge, then front, then give up and scan. this
- * will of course fail for different size bios on the same queue,
- * however that isn't really an issue
- */
- if (likely(edat->flags & ELV_LINUS_BACK_MERGE)) {
- __rq = bio_get_hash_rq(bio->bi_dev, bio->bi_sector - count, vc);
- if (__rq) {
- if (!elv_rq_merge_ok(q, __rq, bio))
- goto front;
-
- /*
- * looks ok to merge
- */
- if (__rq->sector + __rq->nr_sectors == bio->bi_sector) {
- *req = __rq;
- return ELEVATOR_BACK_MERGE;
- }
- }
- }
-
-front:
- if (likely(edat->flags & ELV_LINUS_FRONT_MERGE)) {
- __rq = bio_get_hash_rq(bio->bi_dev, bio->bi_sector + count, vc);
- if (__rq) {
- if (!elv_rq_merge_ok(q, __rq, bio))
- goto scan;
-
- /*
- * looks ok to merge
- */
- if (__rq->sector - count == bio->bi_sector) {
- *req = __rq;
- return ELEVATOR_FRONT_MERGE;
- }
- }
- }
-
- /*
- * no merge possible, scan for insertion
- */
-scan:
entry = &q->queue_head;
while ((entry = entry->prev) != head) {
__rq = list_entry_rq(entry);
prefetch(list_entry_rq(entry->prev));
+ /*
+ * simply "aging" of requests in queue
+ */
+ if (__rq->elevator_sequence-- <= 0)
+ break;
+
if (unlikely(__rq->waiting || __rq->special))
continue;
if (unlikely(!__rq->inactive))
break;
if (!*req && bio_rq_in_between(bio, __rq, &q->queue_head))
*req = __rq;
+ if (!elv_rq_merge_ok(q, __rq, bio))
+ continue;
+
+ if (__rq->elevator_sequence < count)
+ break;
/*
- * simple "aging" of requests in queue
+ * we can merge and sequence is ok, check if it's possible
*/
- if (__rq->elevator_sequence-- <= 0)
+ if (__rq->sector + __rq->nr_sectors == bio->bi_sector) {
+ ret = ELEVATOR_BACK_MERGE;
+ *req = __rq;
break;
- else if (__rq->elevator_sequence < count)
+ } else if (__rq->sector - count == bio->bi_sector) {
+ ret = ELEVATOR_FRONT_MERGE;
+ __rq->elevator_sequence -= count;
+ *req = __rq;
break;
+ }
}
- return ELEVATOR_NO_MERGE;
+ return ret;
}
void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int count)
void elv_add_request_fn(request_queue_t *q, struct request *rq,
struct list_head *insert_here)
{
- /*
- * insert into queue pending list, merge hash, and possible latency
- * list
- */
list_add(&rq->queuelist, insert_here);
}
int elv_linus_init(request_queue_t *q, elevator_t *e)
{
- struct elv_linus_data *edata;
-
- edata = kmalloc(sizeof(struct elv_linus_data), GFP_ATOMIC);
- if (!edata)
- return -ENOMEM;
-
- /*
- * default to doing both front and back merges
- */
- edata->flags = ELV_LINUS_BACK_MERGE | ELV_LINUS_FRONT_MERGE;
- e->elevator_data = edata;
return 0;
}
void elv_linus_exit(request_queue_t *q, elevator_t *e)
{
- kfree(e->elevator_data);
}
/*
* See if we can find a request that this buffer can be coalesced with.
*/
int elevator_noop_merge(request_queue_t *q, struct request **req,
- struct list_head * head, struct bio *bio)
+ struct list_head *head, struct bio *bio)
{
+ unsigned int count = bio_sectors(bio);
+ struct list_head *entry = &q->queue_head;
struct request *__rq;
- int count, ret;
- unsigned int vc;
- count = bio_sectors(bio);
- ret = ELEVATOR_NO_MERGE;
- vc = q->hash_valid_counter;
+ entry = &q->queue_head;
+ while ((entry = entry->prev) != head) {
+ __rq = list_entry_rq(entry);
+
+ prefetch(list_entry_rq(entry->prev));
- __rq = bio_get_hash_rq(bio->bi_dev, bio->bi_sector - count, vc);
- if (__rq) {
+ if (unlikely(__rq->waiting || __rq->special))
+ continue;
+ if (unlikely(!__rq->inactive))
+ break;
if (!elv_rq_merge_ok(q, __rq, bio))
- goto front;
+ continue;
+ /*
+ * we can merge and sequence is ok, check if it's possible
+ */
if (__rq->sector + __rq->nr_sectors == bio->bi_sector) {
- ret = ELEVATOR_BACK_MERGE;
*req = __rq;
- goto out;
- }
- }
-
-front:
- __rq = bio_get_hash_rq(bio->bi_dev, bio->bi_sector + count, vc);
- if (__rq) {
- if (!elv_rq_merge_ok(q, __rq, bio))
- goto out;
-
- if (__rq->sector - count == bio->bi_sector) {
- ret = ELEVATOR_FRONT_MERGE;
+ return ELEVATOR_BACK_MERGE;
+ } else if (__rq->sector - count == bio->bi_sector) {
*req = __rq;
- goto out;
+ return ELEVATOR_FRONT_MERGE;
}
}
-out:
- return ret;
+ return ELEVATOR_NO_MERGE;
}
void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int count) {}
void elevator_noop_merge_req(struct request *req, struct request *next) {}
-int elevator_init(request_queue_t *q, elevator_t *e, elevator_t type,char *name)
+int elevator_init(request_queue_t *q, elevator_t *e, elevator_t type)
{
*e = type;
INIT_LIST_HEAD(&q->queue_head);
- strncpy(e->queue_name, name, 15);
if (e->elevator_init_fn)
return e->elevator_init_fn(q, e);
blk_size[MAJOR_NR] = floppy_sizes;
blksize_size[MAJOR_NR] = floppy_blocksizes;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST, "floppy");
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
config_types();
extern int fusion_init(void);
#endif
extern int net_dev_init(void);
-extern void console_map_init(void);
extern int soc_probe(void);
extern int atmdev_init(void);
extern int i2o_init(void);
#endif
#ifdef CONFIG_ATM
(void) atmdev_init();
-#endif
-#ifdef CONFIG_VT
- console_map_init();
#endif
return 0;
}
q->hardsect_size = size;
}
+/**
+ * blk_queue_segment_boundary - set boundary rules for segment merging
+ * @q: the request queue for the device
+ * @mask: the memory boundary mask
+ **/
+void blk_queue_segment_boundary(request_queue_t *q, unsigned long mask)
+{
+ q->seg_boundary_mask = mask;
+}
+
/*
* can we merge the two segments, or do we need to start a new one?
*/
return 0;
/*
- * bio and nxt are contigous, if they don't span a 4GB mem boundary
- * return ok
+ * bio and nxt are contigous in memory, check if the queue allows
+ * these two to be merged into one
*/
- if (BIO_PHYS_4G(bio, nxt))
+ if (BIO_SEG_BOUNDARY(q, bio, nxt))
return 1;
return 0;
unsigned long long lastend;
struct bio_vec *bvec;
struct bio *bio;
- int nsegs, i;
+ int nsegs, i, cluster;
nsegs = 0;
bio = rq->bio;
lastend = ~0ULL;
+ cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
/*
* for each bio in rq
bio_for_each_segment(bvec, bio, i) {
int nbytes = bvec->bv_len;
- BIO_BUG_ON(i > bio->bi_io_vec->bvl_cnt);
+ BIO_BUG_ON(i > bio->bi_vcnt);
+
+ if (!cluster)
+ goto new_segment;
if (bvec_to_phys(bvec) == lastend) {
- if (sg[nsegs - 1].length + nbytes > q->max_segment_size) {
- printk("blk_rq_map_sg: %d segment size exceeded\n", q->max_segment_size);
+ if (sg[nsegs - 1].length + nbytes > q->max_segment_size)
goto new_segment;
- }
/*
- * make sure to not map a 4GB boundary into
- * same sg entry
+ * make sure to not map a segment across a
+ * boundary that the queue doesn't want
*/
- if (!__BIO_PHYS_4G(lastend, lastend + nbytes)) {
- printk("blk_rq_map_sg: 4GB cross\n");
+ if (!__BIO_SEG_BOUNDARY(lastend, lastend + nbytes, q->seg_boundary_mask))
lastend = ~0ULL;
- } else
+ else
lastend += nbytes;
sg[nsegs - 1].length += nbytes;
* blk_init_queue() must be paired with a blk_cleanup_queue() call
* when the block device is deactivated (such as at module unload).
**/
-int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, char *name)
+int blk_init_queue(request_queue_t *q, request_fn_proc *rfn)
{
int ret;
if (blk_init_free_list(q))
return -ENOMEM;
- if ((ret = elevator_init(q, &q->elevator, ELEVATOR_LINUS, name))) {
+ if ((ret = elevator_init(q, &q->elevator, ELEVATOR_LINUS))) {
blk_cleanup_queue(q);
return ret;
}
q->plug_tq.sync = 0;
q->plug_tq.routine = &generic_unplug_device;
q->plug_tq.data = q;
- q->queue_flags = 0;
-
+ q->queue_flags = (1 << QUEUE_FLAG_CLUSTER);
+
/*
* by default assume old behaviour and bounce for any highmem page
*/
blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
+ blk_queue_segment_boundary(q, 0xffffffff);
+
blk_queue_make_request(q, __make_request);
blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
return 0;
req->rq_status = RQ_INACTIVE;
req->q = NULL;
- /*
- * should only happen on freereq logic in __make_request, in which
- * case we don't want to prune these entries from the hash
- */
-#if 1
- if (req->bio)
- bio_hash_remove(req->bio);
- if (req->biotail)
- bio_hash_remove(req->biotail);
-#endif
-
/*
* Request may not have originated from ll_rw_blk. if not,
* assume it has free buffers and check waiters
if (q->merge_requests_fn(q, req, next)) {
q->elevator.elevator_merge_req_fn(req, next);
- bio_hash_remove(req->biotail);
-
- /*
- * will handle dangling hash too
- */
blkdev_dequeue_request(next);
req->biotail->bi_next = next->bio;
next->bio = next->biotail = NULL;
- bio_hash_add_unique(req->biotail, req, q->hash_valid_counter);
-
req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
blkdev_release_request(next);
* the back of the queue and invalidate the entire existing merge hash
* for this device
*/
- if (barrier && !freereq) {
+ if (barrier && !freereq)
latency = 0;
- bio_hash_invalidate(q, bio->bi_dev);
- }
insert_here = head->prev;
if (blk_queue_empty(q) || barrier) {
break;
elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
- bio_hash_remove(req->biotail);
-
req->biotail->bi_next = bio;
req->biotail = bio;
req->nr_sectors = req->hard_nr_sectors += nr_sectors;
break;
elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
- bio_hash_remove(req->bio);
-
bio->bi_next = req->bio;
req->bio = bio;
/*
req->hard_sector = req->sector = sector;
req->hard_nr_sectors = req->nr_sectors = nr_sectors;
req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors;
- req->nr_segments = bio->bi_io_vec->bvl_cnt;
+ req->nr_segments = bio->bi_vcnt;
req->nr_hw_segments = req->nr_segments;
req->buffer = bio_data(bio); /* see ->buffer comment above */
req->waiting = NULL;
}
spin_unlock_irq(&q->queue_lock);
- bio_hash_add_unique(bio, req, q->hash_valid_counter);
return 0;
end_io:
*
* The caller of generic_make_request must make sure that bi_io_vec
* are set to describe the memory buffer, and that bi_dev and bi_sector are
- & set to describe the device address, and the
+ * set to describe the device address, and the
* bi_end_io and optionally bi_private are set to describe how
* completion notification should be signaled.
*
* generic_make_request and the drivers it calls may use bi_next if this
* bio happens to be merged with someone else, and may change bi_dev and
- * bi_rsector for remaps as it sees fit. So the values of these fields
+ * bi_sector for remaps as it sees fit. So the values of these fields
* should NOT be depended on after the call to generic_make_request.
*
* */
BIO_BUG_ON(nr_sectors != (bh->b_size >> 9));
- /*
- * I/O is complete -- remove from hash, end buffer_head, put bio
- */
- bio_hash_remove(bio);
-
bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags));
bio_put(bio);
bio->bi_private = bh;
bio->bi_end_io = end_bio_bh_io_sync;
- bio->bi_io_vec->bvl_vec[0].bv_page = bh->b_page;
- bio->bi_io_vec->bvl_vec[0].bv_len = bh->b_size;
- bio->bi_io_vec->bvl_vec[0].bv_offset = bh_offset(bh);
+ bio->bi_io_vec[0].bv_page = bh->b_page;
+ bio->bi_io_vec[0].bv_len = bh->b_size;
+ bio->bi_io_vec[0].bv_offset = bh_offset(bh);
- bio->bi_io_vec->bvl_cnt = 1;
- bio->bi_io_vec->bvl_idx = 0;
- bio->bi_io_vec->bvl_size = bh->b_size;
+ bio->bi_vcnt = 1;
+ bio->bi_idx = 0;
+ bio->bi_size = bh->b_size;
return submit_bio(rw, bio);
}
/**
* end_that_request_first - end I/O on one buffer.
- * &q: queue that finished request
* @req: the request being processed
* @uptodate: 0 for I/O error
+ * @nr_sectors: number of sectors to end I/O on
*
* Description:
* Ends I/O on the first buffer attached to @req, and sets it up
bio->bi_next = nxt;
if ((bio = req->bio) != NULL) {
- bio_hash_add_unique(bio,req,req->q->hash_valid_counter);
req->hard_sector += nsect;
req->hard_nr_sectors -= nsect;
req->sector = req->hard_sector;
* check bi_end_io, may just be a remapped bio
*/
if (bio && bio->bi_end_io == loop_end_io_transfer) {
- __free_page(bio_page(bio));
+ int i;
+ for (i = 0; i < bio->bi_vcnt; i++)
+ __free_page(bio->bi_io_vec[i].bv_page);
+
bio_put(bio);
}
}
static struct bio *loop_get_buffer(struct loop_device *lo, struct bio *rbh)
{
- struct page *page;
struct bio *bio;
/*
goto out_bh;
}
- bio = bio_alloc(GFP_NOIO, 1);
-
- /*
- * easy way out, although it does waste some memory for < PAGE_SIZE
- * blocks... if highmem bounce buffering can get away with it,
- * so can we :-)
- */
- do {
- page = alloc_page(GFP_NOIO);
- if (page)
- break;
-
- run_task_queue(&tq_disk);
- schedule_timeout(HZ);
- } while (1);
-
- bio->bi_io_vec->bvl_vec[0].bv_page = page;
- bio->bi_io_vec->bvl_vec[0].bv_len = bio_size(rbh);
- bio->bi_io_vec->bvl_vec[0].bv_offset = bio_offset(rbh);
-
- bio->bi_io_vec->bvl_cnt = 1;
- bio->bi_io_vec->bvl_idx = 1;
- bio->bi_io_vec->bvl_size = bio_size(rbh);
+ bio = bio_copy(rbh, GFP_NOIO, rbh->bi_rw & WRITE);
bio->bi_end_io = loop_end_io_transfer;
bio->bi_private = rbh;
#endif
blksize_size[MAJOR_NR] = nbd_blksizes;
blk_size[MAJOR_NR] = nbd_sizes;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request, "nbd");
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request);
blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
for (i = 0; i < MAX_NBD; i++) {
nbd_dev[i].refcnt = 0;
pg_drive_count = 0;
for (unit=0;unit<PG_UNITS;unit++) {
PG.pi = & PG.pia;
- PG.access = 0;
+ set_bit( 0, &PG.access );
PG.busy = 0;
PG.present = 0;
PG.bufptr = NULL;
if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV;
- PG.access++;
-
- if (PG.access > 1) {
- PG.access--;
+ if ( test_and_set_bit(0, &PG.access) ) {
return -EBUSY;
}
PG.bufptr = kmalloc(PG_MAX_DATA,GFP_KERNEL);
if (PG.bufptr == NULL) {
- PG.access--;
+ clear_bit( 0, &PG.access ) ;
printk("%s: buffer allocation failed\n",PG.name);
return -ENOMEM;
}
{
int unit = DEVICE_NR(inode->i_rdev);
- if ((unit >= PG_UNITS) || (PG.access <= 0))
+ if ( unit >= PG_UNITS || !test_bit(0,&PG.access) )
return -EINVAL;
- lock_kernel();
- PG.access--;
+ clear_bit( 0, &PG.access);
kfree(PG.bufptr);
PG.bufptr = NULL;
- unlock_kernel();
return 0;
int flags; /* various state flags */
int last_sense; /* result of last request sense */
int drive; /* drive */
- int access; /* count of active opens ... */
+ atomic_t available; /* 1 if access is available 0 otherwise */
int bs; /* block size */
int capacity; /* Size of tape in KB */
int present; /* device present ? */
pt_drive_count = 0;
for (unit=0;unit<PT_UNITS;unit++) {
PT.pi = & PT.pia;
- PT.access = 0;
+ atomic_set( &PT.available, 1 );
PT.flags = 0;
PT.last_sense = 0;
PT.present = 0;
if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV;
- PT.access++;
-
- if (PT.access > 1) {
- PT.access--;
+ if ( !atomic_dec_and_test(&PT.available) ) {
+ atomic_inc( &PT.available );
return -EBUSY;
}
pt_identify(unit);
if (!PT.flags & PT_MEDIA) {
- PT.access--;
+ atomic_inc( &PT.available );
return -ENODEV;
}
if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) {
- PT.access--;
+ atomic_inc( &PT.available );
return -EROFS;
}
PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL);
if (PT.bufptr == NULL) {
- PT.access--;
+ atomic_inc( &PT.available );
printk("%s: buffer allocation failed\n",PT.name);
return -ENOMEM;
}
{
int unit = DEVICE_NR(inode->i_rdev);
- if ((unit >= PT_UNITS) || (PT.access <= 0))
+ if ((unit >= PT_UNITS) || (atomic_read(&PT.available) > 1))
return -EINVAL;
- lock_kernel();
if (PT.flags & PT_WRITING) pt_write_fm(unit);
if (PT.flags & PT_REWIND) pt_rewind(unit);
- PT.access--;
-
kfree(PT.bufptr);
PT.bufptr = NULL;
- unlock_kernel();
+ atomic_inc( &PT.available );
+
return 0;
}
#ifdef CONFIG_BLK_DEV_INITRD
static int initrd_users;
+static spinlock_t initrd_users_lock = SPIN_LOCK_UNLOCKED;
#endif
#endif
{
extern void free_initrd_mem(unsigned long, unsigned long);
- lock_kernel();
+ spin_lock( &initrd_users_lock );
if (!--initrd_users) {
+ spin_unlock( &initrd_users_lock );
free_initrd_mem(initrd_start, initrd_end);
initrd_start = 0;
+ } else {
+ spin_unlock( &initrd_users_lock );
}
- unlock_kernel();
+
blkdev_put(inode->i_bdev, BDEV_FILE);
return 0;
}
#ifdef CONFIG_BLK_DEV_INITRD
if (unit == INITRD_MINOR) {
- if (!initrd_start) return -ENODEV;
+ spin_lock( &initrd_users_lock );
initrd_users++;
+ if (!initrd_start) return -ENODEV;
+ spin_unlock( &initrd_users_lock );
filp->f_op = &initrd_fops;
return 0;
}
static int acq_close(struct inode *inode, struct file *file)
{
- lock_kernel();
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
spin_lock(&acq_lock);
acq_is_open=0;
spin_unlock(&acq_lock);
}
- unlock_kernel();
return 0;
}
static int
advwdt_close(struct inode *inode, struct file *file)
{
- lock_kernel();
if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
spin_lock(&advwdt_lock);
#ifndef CONFIG_WATCHDOG_NOWAYOUT
advwdt_is_open = 0;
spin_unlock(&advwdt_lock);
}
- unlock_kernel();
return 0;
}
#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5)
#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3)
+#define INTEL_I830_ERRSTS 0x92
+
/* intel i820 registers */
#define INTEL_I820_RDCR 0x51
#define INTEL_I820_ERRSTS 0xc8
return 0;
}
+static int intel_830mp_configure(void)
+{
+ u32 temp;
+ u16 temp2;
+ aper_size_info_8 *current_size;
+
+ current_size = A_SIZE_8(agp_bridge.current_size);
+
+ /* aperture size */
+ pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
+ current_size->size_value);
+
+ /* address to map to */
+ pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp);
+ agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+ /* attbase - aperture base */
+ pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE,
+ agp_bridge.gatt_bus_addr);
+
+ /* agpctrl */
+ pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000);
+
+ /* gmch */
+ pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp2);
+ pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG,
+ temp2 | (1 << 9));
+ /* clear any possible AGP-related error conditions */
+ pci_write_config_word(agp_bridge.dev, INTEL_I830_ERRSTS, 0x1c);
+ return 0;
+}
+
static unsigned long intel_mask_memory(unsigned long addr, int type)
{
/* Memory type is ignored */
{4, 1024, 0, 63}
};
+static aper_size_info_8 intel_830mp_sizes[4] =
+{
+ {256, 65536, 6, 0},
+ {128, 32768, 5, 32},
+ {64, 16384, 4, 48},
+ {32, 8192, 3, 56}
+};
+
static int __init intel_generic_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
(void) pdev; /* unused */
}
+static int __init intel_830mp_setup (struct pci_dev *pdev)
+{
+ agp_bridge.masks = intel_generic_masks;
+ agp_bridge.num_of_masks = 1;
+ agp_bridge.aperture_sizes = (void *) intel_830mp_sizes;
+ agp_bridge.size_type = U8_APER_SIZE;
+ agp_bridge.num_aperture_sizes = 4;
+ agp_bridge.dev_private_data = NULL;
+ agp_bridge.needs_scratch_page = FALSE;
+ agp_bridge.configure = intel_830mp_configure;
+ agp_bridge.fetch_size = intel_8xx_fetch_size;
+ agp_bridge.cleanup = intel_8xx_cleanup;
+ agp_bridge.tlb_flush = intel_8xx_tlbflush;
+ agp_bridge.mask_memory = intel_mask_memory;
+ agp_bridge.agp_enable = agp_generic_agp_enable;
+ agp_bridge.cache_flush = global_cache_flush;
+ agp_bridge.create_gatt_table = agp_generic_create_gatt_table;
+ agp_bridge.free_gatt_table = agp_generic_free_gatt_table;
+ agp_bridge.insert_memory = agp_generic_insert_memory;
+ agp_bridge.remove_memory = agp_generic_remove_memory;
+ agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
+ agp_bridge.free_by_type = agp_generic_free_by_type;
+ agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+ agp_bridge.agp_destroy_page = agp_generic_destroy_page;
+
+ return 0;
+
+ (void) pdev; /* unused */
+}
static int __init intel_840_setup (struct pci_dev *pdev)
{
INTEL_I830_M,
"Intel",
"i830M",
- intel_generic_setup },
+ intel_830mp_setup },
{ PCI_DEVICE_ID_INTEL_840_0,
PCI_VENDOR_ID_INTEL,
INTEL_I840,
i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_830_M_1,
NULL);
- if(PCI_FUNC(i810_dev->devfn) != 0) {
+ if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) {
i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_830_M_1,
i810_dev);
}
if (i810_dev == NULL) {
- printk(KERN_ERR PFX "Detected an "
- "Intel 830M, but could not find the"
- " secondary device.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return -ENODEV;
+ /* Intel 830MP with external graphic card */
+ /* It will be initialized later */
+ agp_bridge.type = INTEL_I830_M;
+ break;
}
printk(KERN_INFO PFX "Detected an Intel "
"830M Chipset.\n");
agp_file_private *priv = (agp_file_private *) file->private_data;
agp_kern_info kerninfo;
- lock_kernel();
AGP_LOCK();
if (agp_fe.backend_acquired != TRUE) {
AGP_UNLOCK();
- unlock_kernel();
return -EPERM;
}
if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags))) {
AGP_UNLOCK();
- unlock_kernel();
return -EPERM;
}
agp_copy_info(&kerninfo);
if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
if ((size + offset) > current_size) {
AGP_UNLOCK();
- unlock_kernel();
return -EINVAL;
}
client = agp_find_client_by_pid(current->pid);
if (client == NULL) {
AGP_UNLOCK();
- unlock_kernel();
return -EPERM;
}
if (!agp_find_seg_in_client(client, offset,
size, vma->vm_page_prot)) {
AGP_UNLOCK();
- unlock_kernel();
return -EINVAL;
}
if (remap_page_range(vma->vm_start,
(kerninfo.aper_base + offset),
size, vma->vm_page_prot)) {
AGP_UNLOCK();
- unlock_kernel();
return -EAGAIN;
}
AGP_UNLOCK();
- unlock_kernel();
return 0;
}
if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
if (size != current_size) {
AGP_UNLOCK();
- unlock_kernel();
return -EINVAL;
}
if (remap_page_range(vma->vm_start, kerninfo.aper_base,
size, vma->vm_page_prot)) {
AGP_UNLOCK();
- unlock_kernel();
return -EAGAIN;
}
AGP_UNLOCK();
- unlock_kernel();
return 0;
}
AGP_UNLOCK();
- unlock_kernel();
return -EPERM;
}
{
agp_file_private *priv = (agp_file_private *) file->private_data;
- lock_kernel();
AGP_LOCK();
if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
agp_remove_file_private(priv);
kfree(priv);
AGP_UNLOCK();
- unlock_kernel();
return 0;
}
lock_kernel();
busmouse_fasync(-1, file, 0);
+ down(&mouse_sem); /* to protect mse->active */
if (--mse->active == 0) {
if (mse->ops->release)
ret = mse->ops->release(inode, file);
mse->ready = 0;
}
unlock_kernel();
-
+ up( &mouse_sem);
+
return ret;
}
break;
}
TRACE_RET;
-
- lock_kernel();
+
del_timer(&dtlk_timer);
- unlock_kernel();
return 0;
}
/* Local vars.
*/
-static int busy_flag = 0;
+static int busy_flag;
+
static sigset_t orig_sigmask;
/* the interface to the kernel vfs layer
TRACE_FUN(ft_t_flow);
TRACE(ft_t_flow, "called for minor %d", MINOR(ino->i_rdev));
- if (busy_flag) {
+ if ( test_and_set_bit(0,&busy_flag) )) {
TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");
}
- busy_flag = 1;
if ((MINOR(ino->i_rdev) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))
>
FTAPE_SEL_D) {
- busy_flag = 0;
+ clear_bit(0,&busy_flag);
TRACE_ABORT(-ENXIO, ft_t_err, "failed: illegal unit nr");
}
orig_sigmask = current->blocked;
result = _zft_open(MINOR(ino->i_rdev), filep->f_flags & O_ACCMODE);
if (result < 0) {
current->blocked = orig_sigmask; /* restore mask */
- busy_flag = 0;
+ clear_bit(0,&busy_flag);
TRACE_ABORT(result, ft_t_err, "_ftape_open failed");
} else {
/* Mask signals that will disturb proper operation of the
int result;
TRACE_FUN(ft_t_flow);
- lock_kernel();
- if (!busy_flag || MINOR(ino->i_rdev) != zft_unit) {
+ if ( !test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit) {
TRACE(ft_t_err, "failed: not busy or wrong unit");
- unlock_kernel();
TRACE_EXIT 0;
}
sigfillset(¤t->blocked);
TRACE(ft_t_err, "_zft_close failed");
}
current->blocked = orig_sigmask; /* restore before open state */
- busy_flag = 0;
- unlock_kernel();
+ clear_bit(0,&busy_flag);
TRACE_EXIT 0;
}
sigset_t old_sigmask;
TRACE_FUN(ft_t_flow);
- if (!busy_flag || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
+ if ( !test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
TRACE_ABORT(-EIO, ft_t_err,
"failed: not busy, failure or wrong unit");
}
sigset_t old_sigmask;
TRACE_FUN(ft_t_flow);
- if (!busy_flag ||
+ if ( !test_bit(0,&busy_flag) ||
MINOR(filep->f_dentry->d_inode->i_rdev) != zft_unit ||
ft_failure)
{
}
old_sigmask = current->blocked; /* save mask */
sigfillset(¤t->blocked);
- lock_kernel();
if ((result = ftape_mmap(vma)) >= 0) {
#ifndef MSYNC_BUG_WAS_FIXED
static struct vm_operations_struct dummy = { NULL, };
vma->vm_ops = &dummy;
#endif
}
- unlock_kernel();
current->blocked = old_sigmask; /* restore mask */
TRACE_EXIT result;
}
TRACE_FUN(ft_t_flow);
TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);
- if (!busy_flag || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
+ if (!test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
TRACE_ABORT(-EIO, ft_t_err,
"failed: not busy, failure or wrong unit");
}
TRACE_FUN(ft_t_flow);
TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);
- if (!busy_flag || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
+ if (!test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
TRACE_ABORT(-EIO, ft_t_err,
"failed: not busy, failure or wrong unit");
}
*/
static int can_unload(void)
{
- return (GET_USE_COUNT(THIS_MODULE)||zft_dirty()||busy_flag)?-EBUSY:0;
+ return (GET_USE_COUNT(THIS_MODULE)||zft_dirty()||test_bit(0,&busy_flag))?-EBUSY:0;
}
/* Called by modules package when installing the driver
*/
parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT);
lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
lp_release_parport (&lp_table[minor]);
- lock_kernel();
kfree(lp_table[minor].lp_buffer);
lp_table[minor].lp_buffer = NULL;
LP_F(minor) &= ~LP_BUSY;
- unlock_kernel();
return 0;
}
static int mixcomwd_release(struct inode *inode, struct file *file)
{
- lock_kernel();
#ifndef CONFIG_WATCHDOG_NOWAYOUT
if(mixcomwd_timer_alive) {
printk(KERN_ERR "mixcomwd: release called while internal timer alive");
- unlock_kernel();
return -EBUSY;
}
init_timer(&mixcomwd_timer);
#endif
clear_bit(0,&mixcomwd_opened);
- unlock_kernel();
return 0;
}
#include <asm/system.h>
static int nvram_open_cnt; /* #times opened */
-static int nvram_open_mode; /* special open modes */
+static int nvram_open_mode; /* special open modes */
+static spinlock_t nvram_open_lock = SPIN_LOCK_UNLOCKED;
+ /* guards nvram_open_cnt and
+ nvram_open_mode */
#define NVRAM_WRITE 1 /* opened for writing (exclusive) */
#define NVRAM_EXCL 2 /* opened with O_EXCL */
static int nvram_open( struct inode *inode, struct file *file )
{
+ spin_lock( &nvram_open_lock );
if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
(nvram_open_mode & NVRAM_EXCL) ||
((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE)))
+ {
+ spin_unlock( &nvram_open_lock );
return( -EBUSY );
+ }
if (file->f_flags & O_EXCL)
nvram_open_mode |= NVRAM_EXCL;
if (file->f_mode & 2)
nvram_open_mode |= NVRAM_WRITE;
nvram_open_cnt++;
+ spin_unlock( &nvram_open_lock );
return( 0 );
}
static int nvram_release( struct inode *inode, struct file *file )
{
- lock_kernel();
+ spin_lock( &nvram_open_lock );
nvram_open_cnt--;
if (file->f_flags & O_EXCL)
nvram_open_mode &= ~NVRAM_EXCL;
if (file->f_mode & 2)
nvram_open_mode &= ~NVRAM_WRITE;
- unlock_kernel();
-
+ spin_unlock( &nvram_open_lock );
return( 0 );
}
/* driver/filesystem interface management */
static wait_queue_head_t queue;
static struct fasync_struct *asyncptr;
-static int active; /* number of concurrent open()s */
+static active_count = 0; /* number of concurrent open()s */
+static spinlock_t active_lock = SPIN_LOCK_UNLOCKED;
+/* this lock should be held when referencing active_count */
static struct semaphore reader_lock;
/**
static int close_pad(struct inode * inode, struct file * file)
{
- lock_kernel();
fasync_pad(-1, file, 0);
- if (!--active)
+ spin_lock( &active_lock );
+ if (!--active_count)
outb(0x30, current_params.io+2); /* switch off digitiser */
- unlock_kernel();
+ spin_unlock( &active_lock );
return 0;
}
{
unsigned long flags;
- if (active++)
+ spin_lock( &active_lock );
+ if (active_count++)
+ {
+ spin_unlock( &active_lock );
return 0;
+ }
+ spin_unlock( &active_lock );
save_flags(flags);
cli();
static struct aux_queue *queue; /* Mouse data buffer. */
static int aux_count;
+static spinlock_t aux_count_lock = SPIN_LOCK_UNLOCKED;
/* used when we send commands to the mouse that expect an ACK. */
static unsigned char mouse_reply_expected;
if (rqst == PM_RESUME) {
if (queue) { /* Aux port detected */
- if (aux_count == 0) { /* Mouse not in use */
- spin_lock_irqsave(&kbd_controller_lock, flags);
+ spin_lock_irqsave( &aux_count_lock, flags);
+ if ( aux_count == 0) { /* Mouse not in use */
+ spin_lock(&kbd_controller_lock);
/*
* Dell Lat. C600 A06 enables mouse after resume.
* When user touches the pad, it posts IRQ 12
kbd_write_command(KBD_CCMD_WRITE_MODE);
kb_wait();
kbd_write_output(AUX_INTS_OFF);
- spin_unlock_irqrestore(&kbd_controller_lock, flags);
+ spin_unlock(&kbd_controller_lock, flags);
}
+ spin_unlock_irqrestore( &aux_count_lock,flags );
}
}
#endif
static inline void handle_mouse_event(unsigned char scancode)
{
#ifdef CONFIG_PSMOUSE
+ int flags;
static unsigned char prev_code;
if (mouse_reply_expected) {
if (scancode == AUX_ACK) {
prev_code = scancode;
add_mouse_randomness(scancode);
- if (aux_count) {
+ spin_lock_irqsave( &aux_count_lock, flags);
+ if ( aux_count ) {
int head = queue->head;
queue->buf[head] = scancode;
wake_up_interruptible(&queue->proc_list);
}
}
+ spin_unlock_irqrestore( &aux_count_lock, flags);
#endif
}
static int release_aux(struct inode * inode, struct file * file)
{
- lock_kernel();
+ int flags;
fasync_aux(-1, file, 0);
- if (--aux_count) {
- unlock_kernel();
+ spin_lock_irqsave( &aux_count, flags );
+ if ( --aux_count ) {
+ spin_unlock_irqrestore( &aux_count_lock );
return 0;
}
+ spin_unlock_irqrestore( &aux_count_lock, flags );
kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */
kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
aux_free_irq(AUX_DEV);
- unlock_kernel();
return 0;
}
static int open_aux(struct inode * inode, struct file * file)
{
- if (aux_count++) {
+ int flags;
+ spin_lock_irqsave( &aux_count_lock, flags );
+ if ( aux_count++ ) {
+ spin_unlock_irqrestore( &aux_count_lock );
return 0;
}
queue->head = queue->tail = 0; /* Flush input queue */
if (aux_request_irq(keyboard_interrupt, AUX_DEV)) {
aux_count--;
+ spin_unlock_irqrestore( &aux_count_lock, flags );
return -EBUSY;
}
kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable the
mdelay(2); /* Ensure we follow the kbc access delay rules.. */
send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */
-
+ spin_unlock_irqrestore( &aux_count_lock, flags );
return 0;
}
#define WD_SRLY2 0x80 /* Software external relay triggered */
static int current_readport, revision, temp_panic;
-static int is_open, initial_status, supports_temp, mode_debug;
+static atomic_t open_allowed = ATOMIC_INIT(1);
+static int initial_status, supports_temp, mode_debug;
static spinlock_t io_lock;
/*
switch (MINOR(ino->i_rdev))
{
case WATCHDOG_MINOR:
- if (is_open)
+ if ( !atomic_dec_and_test(&open_allowed) )
+ {
+ atomic_inc( &open_allowed );
return -EBUSY;
- MOD_INC_USE_COUNT;
+ }
+ MOD_INC_USE_COUNT;
/* Enable the port */
if (revision == PCWD_REVISION_C)
{
outb_p(0x00, current_readport + 3);
spin_unlock(&io_lock);
}
- is_open = 1;
return(0);
case TEMP_MINOR:
return(0);
{
if (MINOR(ino->i_rdev)==WATCHDOG_MINOR)
{
- lock_kernel();
- is_open = 0;
#ifndef CONFIG_WATCHDOG_NOWAYOUT
/* Disable the board */
if (revision == PCWD_REVISION_C) {
outb_p(0xA5, current_readport + 3);
spin_unlock(&io_lock);
}
+ atomic_inc( &open_allowed );
#endif
- unlock_kernel();
}
return 0;
}
printk("pcwd: v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER);
/* Initial variables */
- is_open = 0;
+ set_bit( 0, &open_allowed );
supports_temp = 0;
mode_debug = 0;
temp_panic = 0;
struct pp_struct *pp = file->private_data;
int compat_negot;
- lock_kernel();
compat_negot = 0;
if (!(pp->flags & PP_CLAIMED) && pp->pdev &&
(pp->state.mode != IEEE1284_MODE_COMPAT)) {
printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n",
minor);
}
- unlock_kernel();
kfree (pp);
static int qp_present;
static int qp_count;
+static spinlock_t qp_count_lock = SPIN_LOCK_UNLOCKED;
static int qp_data = QP_DATA;
static int qp_status = QP_STATUS;
{
unsigned char status;
- lock_kernel();
fasync_qp(-1, file, 0);
+ spin_lock( &qp_count_lock );
if (!--qp_count) {
if (!poll_qp_status())
printk(KERN_WARNING "Warning: Mouse device busy in release_qp()\n");
printk(KERN_WARNING "Warning: Mouse device busy in release_qp()\n");
free_irq(QP_IRQ, NULL);
}
- unlock_kernel();
+ spin_unlock( &qp_count_lock );
return 0;
}
if (!qp_present)
return -EINVAL;
+ spin_lock( &qp_count_lock );
if (qp_count++)
+ {
+ spin_unlock( &qp_count_lock );
return 0;
+ }
+ spin_unlock( &qp_count_lock );
if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse", NULL)) {
qp_count--;
static int release_aux(struct inode * inode, struct file * file)
{
- lock_kernel();
fasync_aux(-1, file, 0);
aux_count--;
- unlock_kernel();
return 0;
}
static int fop_close(struct inode * inode, struct file * file)
{
- lock_kernel();
if(MINOR(inode->i_rdev) == WATCHDOG_MINOR)
{
if(wdt_expect_close)
}
}
wdt_is_open = 0;
- unlock_kernel();
return 0;
}
* Shut off the timer.
* Lock it in if it's a module and we defined ...NOWAYOUT
*/
- lock_kernel();
#ifndef CONFIG_WATCHDOG_NOWAYOUT
del_timer(&watchdog_ticktock);
#endif
timer_alive=0;
- unlock_kernel();
return 0;
}
{
kdev_t dev = inode->i_rdev;
- lock_kernel();
if (TP_DIAGS(dev)) {
printk("qic02_tape_release: dev=%s\n", kdevname(dev));
}
(void) do_qic_cmd(QCMD_REWIND, TIM_R);
}
}
- unlock_kernel();
return 0;
} /* qic02_tape_release */
if (tty_register_driver(&dev_console_driver))
panic("Couldn't register /dev/tty0 driver\n");
+ vcs_init();
kbd_init();
+ console_map_init();
#endif
#ifdef CONFIG_ESPSERIAL /* init ESP before rs, so rs doesn't see the port */
#ifdef CONFIG_MOXA_INTELLIO
moxa_init();
#endif
-#ifdef CONFIG_VT
- vcs_init();
-#endif
#ifdef CONFIG_TN3270
tub3270_init();
#endif
static int fop_close(struct inode * inode, struct file * file)
{
- lock_kernel();
if(MINOR(inode->i_rdev) == WATCHDOG_MINOR)
{
if(wdt_expect_close)
}
}
wdt_is_open = 0;
- unlock_kernel();
return 0;
}
static int wdt_release(struct inode *inode, struct file *file)
{
- lock_kernel();
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
#ifndef CONFIG_WATCHDOG_NOWAYOUT
#endif
wdt_is_open=0;
}
- unlock_kernel();
return 0;
}
static int watchdog_release(struct inode *inode, struct file *file)
{
#ifdef ONLY_TESTING
- lock_kernel();
free_irq(IRQ_TIMER4, NULL);
timer_alive = 0;
- unlock_kernel();
#else
/*
* It's irreversible!
* Lock it in if it's a module and we defined ...NOWAYOUT
*/
#ifndef CONFIG_WATCHDOG_NOWAYOUT
- lock_kernel();
// unlock the SuperIO chip
outb(0x87,0x370);
outb(0xAA,0x370);
timer_alive=0;
- unlock_kernel();
printk(KERN_INFO "Watchdog: shutdown.\n");
#endif
switch(MINOR(inode->i_rdev))
{
case WATCHDOG_MINOR:
- if(wdt_is_open)
+ if( test_and_set_bit(0,&wdt_is_open) )
+ {
return -EBUSY;
+ }
#ifdef CONFIG_WATCHDOG_NOWAYOUT
MOD_INC_USE_COUNT;
#endif
/*
* Activate
*/
-
- wdt_is_open=1;
inb_p(WDT_DC); /* Disable */
{
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
{
- lock_kernel();
#ifndef CONFIG_WATCHDOG_NOWAYOUT
inb_p(WDT_DC); /* Disable counters */
wdtpci_ctr_load(2,0); /* 0 length reset pulses now */
#endif
- wdt_is_open=0;
- unlock_kernel();
+ clear_bit(0, &wdt_is_open );
}
return 0;
}
#endif
#if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0)
MOD_DEC_USE_COUNT;
-#else /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
- lock_kernel();
#endif /* LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0) */
if (i2cdev_adaps[minor]->dec_use)
i2cdev_adaps[minor]->dec_use(i2cdev_adaps[minor]);
-#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
- unlock_kernel();
-#endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
return 0;
}
int max_sectors;
q->queuedata = HWGROUP(drive);
- blk_init_queue(q, do_ide_request, drive->name);
+ blk_init_queue(q, do_ide_request);
+ blk_queue_segment_boundary(q, 0xffff);
/* IDE can do up to 128K per request, pdc4030 needs smaller limit */
#ifdef CONFIG_BLK_DEV_PDC4030
idetape_pc_t pc;
unsigned int minor=MINOR (inode->i_rdev);
- lock_kernel();
tape = drive->driver_data;
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 3)
MOD_DEC_USE_COUNT;
}
clear_bit (IDETAPE_BUSY, &tape->flags);
- unlock_kernel();
return 0;
}
};
MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
+MODULE_LICENSE("GPL");
static void __exit idetape_exit (void)
{
case BLKELVSET:
case BLKBSZGET:
case BLKBSZSET:
- case BLKHASHPROF:
- case BLKHASHCLEAR:
return blk_ioctl(inode->i_rdev, cmd, arg);
case HDIO_GET_BUSSTATE:
struct pending_request *req;
int done = 0, i;
- lock_kernel();
for (i = 0; i < 64; i++) {
if (fi->listen_channels & (1ULL << i)) {
hpsb_unlisten_channel(hl_handle, fi->host, i);
kfree(fi);
V22_COMPAT_MOD_DEC_USE_COUNT;
- unlock_kernel();
return 0;
}
struct evdev_list *list = file->private_data;
struct evdev_list **listptr;
- lock_kernel();
listptr = &list->evdev->list;
evdev_fasync(-1, file, 0);
}
kfree(list);
- unlock_kernel();
return 0;
}
old_fops = file->f_op;
file->f_op = new_fops;
- lock_kernel();
err = new_fops->open(inode, file);
- unlock_kernel();
if (err) {
fops_put(file->f_op);
{
struct joydev_list *list = file->private_data;
struct joydev_list **listptr;
-
- lock_kernel();
+
listptr = &list->joydev->list;
joydev_fasync(-1, file, 0);
}
kfree(list);
- unlock_kernel();
return 0;
}
{
struct mousedev_list *list = file->private_data;
struct mousedev_list **listptr;
-
- lock_kernel();
+
listptr = &list->mousedev->list;
mousedev_fasync(-1, file, 0);
}
kfree(list);
- unlock_kernel();
return 0;
}
{
struct capidev *cdev = (struct capidev *)file->private_data;
- lock_kernel();
capincci_free(cdev, 0xffffffff);
capidev_free(cdev);
file->private_data = NULL;
#ifdef _DEBUG_REFCOUNT
printk(KERN_DEBUG "capi_release %d\n", GET_USE_COUNT(THIS_MODULE));
#endif
- unlock_kernel();
return 0;
}
struct capiminor *mp = (struct capiminor *)file->private_data;
if (mp) {
- lock_kernel();
mp->file = 0;
if (mp->nccip == 0) {
capiminor_free(mp);
file->private_data = NULL;
}
- unlock_kernel();
}
#ifdef _DEBUG_REFCOUNT
ulong if_used = 0; /* number of interface users */
static struct divert_info *divert_info_head = NULL; /* head of queue */
static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */
+static spinlock_t divert_info_lock = SPIN_LOCK_UNLOCKED;/* lock for queue */
static wait_queue_head_t rd_queue;
/*********************************/
return; /* no memory */
strcpy(ib->info_start, cp); /* set output string */
ib->next = NULL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave( &divert_info_lock, flags );
ib->usage_cnt = if_used;
if (!divert_info_head)
divert_info_head = ib; /* new head */
} else
break;
} /* divert_info_head->next */
+ spin_lock_irqrestore( &divert_info_lock, flags );
wake_up_interruptible(&(rd_queue));
} /* put_info_buffer */
{
unsigned long flags;
- lock_kernel();
- save_flags(flags);
- cli();
- if_used++;
+ spin_lock_irqsave( &divert_info_lock, flags );
+ if_used++;
if (divert_info_head)
(struct divert_info **) filep->private_data = &(divert_info_tail->next);
else
(struct divert_info **) filep->private_data = &divert_info_head;
- restore_flags(flags);
+ spin_unlock_irqrestore( &divert_info_lock, flags );
/* start_divert(); */
- unlock_kernel();
return (0);
} /* isdn_divert_open */
struct divert_info *inf;
unsigned long flags;
- lock_kernel();
- save_flags(flags);
- cli();
+ spin_lock_irqsave( &divert_info_lock, flags );
if_used--;
inf = *((struct divert_info **) filep->private_data);
while (inf) {
divert_info_head = divert_info_head->next;
kfree(inf);
}
- unlock_kernel();
+ spin_unlock_irq( &divert_info_lock, flags );
return (0);
} /* isdn_divert_close */
struct adbdev_state *state = file->private_data;
unsigned long flags;
- lock_kernel();
if (state) {
file->private_data = NULL;
spin_lock_irqsave(&state->lock, flags);
spin_unlock_irqrestore(&state->lock, flags);
}
}
- unlock_kernel();
return 0;
}
struct pmu_private *pp = file->private_data;
unsigned long flags;
- lock_kernel();
if (pp != 0) {
file->private_data = 0;
spin_lock_irqsave(&all_pvt_lock, flags);
spin_unlock_irqrestore(&all_pvt_lock, flags);
kfree(pp);
}
- unlock_kernel();
return 0;
}
cmd_per_lun: MPT_SCSI_CMD_PER_LUN, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1 \
}
#else
* unlocked.
*/
- while (end_that_request_first(req, !req->errors))
+ while (end_that_request_first(req, !req->errors, req->hard_cur_sectors))
;
/*
u8 unit = (m[2]>>8)&0xF0; /* low 4 bits are partition */
struct i2ob_device *dev = &i2ob_dev[(unit&0xF0)];
- /*
- * Pull the lock over ready
- */
-
- spin_lock_prefetch(&io_request_lock);
-
/*
* FAILed message
*/
*/
static int i2ob_init_iop(unsigned int unit)
{
- char name[16];
int i;
i2ob_queues[unit] = (struct i2ob_iop_queue*)
i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0];
atomic_set(&i2ob_queues[unit]->queue_depth, 0);
- sprintf(name, "i2o%d", unit);
- blk_init_queue(&i2ob_queues[unit]->req_queue, i2ob_request, name);
+ blk_init_queue(&i2ob_queues[unit]->req_queue, i2ob_request);
blk_queue_headactive(&i2ob_queues[unit]->req_queue, 0);
i2ob_queues[unit]->req_queue.queuedata = &i2ob_queues[unit];
blk_size[MAJOR_NR] = i2ob_sizes;
blk_dev[MAJOR_NR].queue = i2ob_get_queue;
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), i2ob_request, "i2o");
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), i2ob_request);
blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
for (i = 0; i < MAX_I2OB << 4; i++) {
struct i2o_cfg_info *p1, *p2;
unsigned long flags;
- lock_kernel();
p1 = p2 = NULL;
spin_lock_irqsave(&i2o_config_lock, flags);
p1 = p1->next;
}
spin_unlock_irqrestore(&i2o_config_lock, flags);
- unlock_kernel();
return 0;
}
static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
{
Scsi_Cmnd *current_command;
+ spinlock_t *lock;
u32 *m = (u32 *)msg;
u8 as,ds,st;
- spin_lock_prefetch(&io_request_lock);
-
if(m[0] & (1<<13))
{
printk("IOP fail.\n");
{
/* Create a scsi error for this */
current_command = (Scsi_Cmnd *)m[3];
+ lock = ¤t_command->host->host_lock;
printk("Aborted %ld\n", current_command->serial_number);
- spin_lock_irq(&io_request_lock);
+ spin_lock_irq(lock);
current_command->result = DID_ERROR << 16;
current_command->scsi_done(current_command);
- spin_unlock_irq(&io_request_lock);
+ spin_unlock_irq(lock);
/* Now flush the message by making it a NOP */
m[0]&=0x00FFFFFF;
* It worked maybe ?
*/
current_command->result = DID_OK << 16 | ds;
- spin_lock(&io_request_lock);
+ lock = ¤t_command->host->host_lock;
+ spin_lock(lock);
current_command->scsi_done(current_command);
- spin_unlock(&io_request_lock);
+ spin_unlock(lock);
return;
}
fi->host = host;
//host->max_id = MAX_SCSI_TARGETS;
host->max_id = 5;
- host->hostt->use_new_eh_code = 1;
host->this_id = tmpt->this_id;
pci_maddr = pci_resource_start(pdev, 0);
{
struct ppp_file *pf = (struct ppp_file *) file->private_data;
- lock_kernel();
if (pf != 0) {
file->private_data = 0;
if (atomic_dec_and_test(&pf->refcnt)) {
}
}
}
- unlock_kernel();
return 0;
}
struct cosa_data *cosa;
unsigned long flags;
- lock_kernel();
cosa = channel->cosa;
spin_lock_irqsave(&cosa->lock, flags);
cosa->usage--;
channel->usage--;
spin_unlock_irqrestore(&cosa->lock, flags);
- unlock_kernel();
return 0;
}
DEBUG(0, "ds_release(socket %d)\n", i);
if ((i >= sockets) || (sockets == 0))
return 0;
- lock_kernel();
s = &socket_table[i];
user = file->private_data;
if (CHECK_USER(user))
user->user_magic = 0;
kfree(user);
out:
- unlock_kernel();
return 0;
} /* ds_release */
kfree(buffer);
return -ENOMEM;
}
- lock_kernel();
buffer->curr = buffer->buffer;
file->private_data = buffer;
if (mode == O_RDONLY)
isapnp_info_read(buffer);
- unlock_kernel();
return 0;
}
if ((buffer = (isapnp_info_buffer_t *) file->private_data) == NULL)
return -EINVAL;
mode = file->f_flags & O_ACCMODE;
- lock_kernel();
if (mode == O_WRONLY)
isapnp_info_write(buffer);
vfree(buffer->buffer);
kfree(buffer);
- unlock_kernel();
return 0;
}
present : 0, \
unchecked_isa_dma : 0, \
use_clustering : ENABLE_CLUSTERING, \
- use_new_eh_code : 1, \
emulated : 1 \
}
#endif /* _3W_XXXX_H */
tpnt->sg_tablesize = NCR_700_SG_SEGMENTS;
tpnt->cmd_per_lun = NCR_700_MAX_TAGS;
tpnt->use_clustering = DISABLE_CLUSTERING;
- tpnt->use_new_eh_code = 1;
tpnt->proc_info = NCR_700_proc_directory_info;
if(tpnt->name == NULL)
obj-$(CONFIG_CHR_DEV_SG) += sg.o
list-multi := scsi_mod.o sd_mod.o sr_mod.o initio.o a100u2w.o cpqfc.o
-scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o \
- scsicam.o scsi_proc.o scsi_error.o \
- scsi_obsolete.o scsi_queue.o scsi_lib.o \
- scsi_merge.o scsi_dma.o scsi_scan.o \
- scsi_syms.o
+scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o scsicam.o \
+ scsi_proc.o scsi_error.o scsi_queue.o scsi_lib.o \
+ scsi_merge.o scsi_dma.o scsi_scan.o scsi_syms.o
sd_mod-objs := sd.o
sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o
initio-objs := ini9100u.o i91uscsi.o
release: advansys_release, \
info: advansys_info, \
queuecommand: advansys_queuecommand, \
- use_new_eh_code: 1, \
eh_bus_reset_handler: advansys_reset, \
bios_param: advansys_biosparam, \
/* \
present: 0, \
unchecked_isa_dma: 0, \
use_clustering: DISABLE_CLUSTERING, \
- use_new_eh_code: 1 }
#endif
sg_tablesize: AHA1542_SCATTER, \
cmd_per_lun: AHA1542_CMDLUN, \
unchecked_isa_dma: 1, \
- use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1}
-
+ use_clustering: ENABLE_CLUSTERING \
+}
#endif
present: 0, /* number of 7xxx's present */\
unchecked_isa_dma: 0, /* no memory DMA restrictions */\
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1, \
highmem_io: 1 \
}
present: 0, /* number of 7xxx's present */\
unchecked_isa_dma: 0, /* no memory DMA restrictions */\
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 0 \
}
extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
present: 0, /* number of 7xxx's present */\
unchecked_isa_dma: 0, /* no memory DMA restrictions */\
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 0 \
}
#endif
present: 0, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1 \
}
#endif /* CPQFCTS_H */
this_id: 7, \
sg_tablesize: SG_ALL, \
cmd_per_lun: 16, \
- NEW_EH \
unchecked_isa_dma: 0, \
use_clustering: DISABLE_CLUSTERING \
}
adpt_hba* pHba;
adpt_init();
- sht->use_new_eh_code = 1;
PINFO("Detecting Adaptec I2O RAID controllers...\n");
sg_tablesize: 0, /* max scatter-gather cmds */\
cmd_per_lun: 256, /* cmds per lun (linked cmds) */\
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1, \
proc_name: "dpt_i2o" /* this is the name of our proc node*/ \
}
#endif
this_id: 7, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1 /* Enable new error code */ \
}
#endif
sg_tablesize: SG_ALL, \
cmd_per_lun: 1, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 0 \
}
/* For our interrupt engine. */
sg_tablesize: 1, \
cmd_per_lun: 1, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: FCP_SCSI_USE_NEW_EH_CODE, \
abort: fcp_old_abort, \
eh_abort_handler: fcp_scsi_abort, \
eh_device_reset_handler:fcp_scsi_dev_reset, \
present: 0, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1 /* use new error code */ }
#elif LINUX_VERSION_CODE >= 0x02015F
int gdth_bios_param(Disk *,kdev_t,int *);
present: 0, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1 /* use new error code */ }
#elif LINUX_VERSION_CODE >= 0x010300
int gdth_bios_param(Disk *,kdev_t,int *);
*/
unsigned use_clustering:1;
- /*
- * True if this driver uses the new error handling code. This flag is
- * really only temporary until all of the other drivers get converted
- * to use the new error handling code.
- */
- unsigned use_new_eh_code:1;
-
/*
* True for emulated SCSI host adapters (e.g. ATAPI)
*/
if ((first_bh = bhp = bh = bio_alloc(GFP_ATOMIC, 1)) == NULL)
goto abort;
- memset (bh, 0, sizeof (struct bio));
+ bio_init(bh);
while (--count) {
if ((bh = bio_alloc(GFP_ATOMIC, 1)) == NULL)
goto abort;
- memset (bh, 0, sizeof (struct bio));
+ bio_init(bh);
+ bh->bi_vcnt = 1;
bhp->bi_next = bh;
bhp = bh;
bh->bi_next = NULL;
printk ("ide-scsi: %s: building DMA table, %d segments, %dkB total\n", drive->name, segments, pc->request_transfer >> 10);
#endif /* IDESCSI_DEBUG_LOG */
while (segments--) {
- bh->bi_io_vec.bv_page = sg->page;
- bh->bi_io_vec.bv_len = sg->length;
- bh->bi_io_vec.bv_offset = sg->offset;
+ bh->bi_io_vec[0].bv_page = sg->page;
+ bh->bi_io_vec[0].bv_len = sg->length;
+ bh->bi_io_vec[0].bv_offset = sg->offset;
+ bh->bi_size = sg->length;
bh = bh->bi_next;
+ /*
+ * just until scsi_merge is fixed up...
+ */
+ BUG_ON(PageHighMem(sg->page));
+ sg->address = page_address(sg->page) + sg->offset;
sg++;
}
} else {
#if IDESCSI_DEBUG_LOG
printk ("ide-scsi: %s: building DMA table for a single buffer (%dkB)\n", drive->name, pc->request_transfer >> 10);
#endif /* IDESCSI_DEBUG_LOG */
- bh->bi_io_vec.bv_page = virt_to_page(pc->scsi_cmd->request_buffer);
- bh->bi_io_vec.bv_len = pc->request_transfer;
- bh->bi_io_vec.bv_offset = (unsigned long) pc->scsi_cmd->request_buffer & ~PAGE_MASK;
+ bh->bi_io_vec[0].bv_page = virt_to_page(pc->scsi_cmd->request_buffer);
+ bh->bi_io_vec[0].bv_len = pc->request_transfer;
+ bh->bi_io_vec[0].bv_offset = (unsigned long) pc->scsi_cmd->request_buffer & ~PAGE_MASK;
+ bh->bi_size = pc->request_transfer;
}
return first_bh;
}
eh_device_reset_handler: NULL, \
eh_bus_reset_handler: imm_reset, \
eh_host_reset_handler: imm_reset, \
- use_new_eh_code: 1, \
bios_param: imm_biosparam, \
this_id: 7, \
sg_tablesize: SG_ALL, \
sg_tablesize: IN2000_SG, /* scatter-gather table size */ \
cmd_per_lun: IN2000_CPL, /* commands per lun */ \
use_clustering: DISABLE_CLUSTERING, /* ENABLE_CLUSTERING may speed things up */ \
- use_new_eh_code: 0 /* new error code - not using it yet */ \
}
#endif /* IN2000_H */
present: 0, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 0 \
}
#define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i))
present: 0, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 0 \
}
#define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i))
present : 0, \
unchecked_isa_dma : 0, \
use_clustering : ENABLE_CLUSTERING, \
- use_new_eh_code : 1 \
}
#endif
sg_tablesize: SG_ALL, \
cmd_per_lun: 1, \
use_clustering: DISABLE_CLUSTERING, \
- use_new_eh_code: 1, \
}
/*
sg_tablesize: SG_ALL, \
cmd_per_lun: 1, \
use_clustering: DISABLE_CLUSTERING, \
- use_new_eh_code: 0 }
#endif /* MAC_ESP_H */
sg_tablesize: SG_ALL, \
cmd_per_lun: 2, \
use_clustering: DISABLE_CLUSTERING, \
- use_new_eh_code: 1, \
}
/*
present: 0, \
unchecked_isa_dma:0, \
use_clustering: DISABLE_CLUSTERING, \
- use_new_eh_code:0 \
}
#endif
present: 0, \
unchecked_isa_dma: 0, \
use_clustering: DISABLE_CLUSTERING, \
- use_new_eh_code: 0 \
}
#endif
/* present: 0,*/
/* unchecked_isa_dma: 0,*/
use_clustering: DISABLE_CLUSTERING,
- use_new_eh_code: 0,
/* emulated: 0,*/
};
sg_tablesize: 1, \
cmd_per_lun: 1, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: FCP_SCSI_USE_NEW_EH_CODE, \
abort: fcp_old_abort, \
eh_abort_handler: fcp_scsi_abort, \
eh_device_reset_handler:fcp_scsi_dev_reset, \
eh_device_reset_handler: NULL, \
eh_bus_reset_handler: ppa_reset, \
eh_host_reset_handler: ppa_reset, \
- use_new_eh_code: 1, \
bios_param: ppa_biosparam, \
this_id: -1, \
sg_tablesize: SG_ALL, \
present: 0, /* number of 7xxx's present */\
unchecked_isa_dma: 0, /* no memory DMA restrictions */\
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 0, \
emulated: 0 \
}
#endif
scsi_set_pci_device(host, pdev);
host->max_id = QLOGICFC_MAX_ID + 1;
host->max_lun = QLOGICFC_MAX_LUN;
- host->hostt->use_new_eh_code = 1;
hostdata = (struct isp2x00_hostdata *) host->hostdata;
memset(hostdata, 0, sizeof(struct isp2x00_hostdata));
sg_tablesize: QLOGICPTI_MAX_SG(QLOGICPTI_REQ_QUEUE_LEN), \
cmd_per_lun: 1, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 0 \
}
/* For our interrupt engine. */
extern void scsi_times_out(Scsi_Cmnd * SCpnt);
void scsi_build_commandblocks(Scsi_Device * SDpnt);
-/*
- * These are the interface to the old error handling code. It should go away
- * someday soon.
- */
-extern void scsi_old_done(Scsi_Cmnd * SCpnt);
-extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
-
-
/*
* Function: scsi_initialize_queue()
*
*/
void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt)
{
- char name[16];
-
request_queue_t *q = &SDpnt->request_queue;
- sprintf(name, "scsi%d%d%d", SDpnt->id, SDpnt->lun, SDpnt->channel);
- blk_init_queue(q, scsi_request_fn, name);
+ blk_init_queue(q, scsi_request_fn);
blk_queue_headactive(q, 0);
q->queuedata = (void *) SDpnt;
#ifdef DMA_CHUNK_SIZE
blk_queue_max_segments(q, SHpnt->sg_tablesize);
#endif
blk_queue_max_sectors(q, SHpnt->max_sectors);
+
+ if (!SHpnt->use_clustering)
+ clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
}
#ifdef MODULE
mdelay(1 + 999 / HZ);
host->resetting = 0;
}
- if (host->hostt->use_new_eh_code) {
- scsi_add_timer(SCpnt, SCpnt->timeout_per_command, scsi_times_out);
- } else {
- scsi_add_timer(SCpnt, SCpnt->timeout_per_command,
- scsi_old_times_out);
- }
+
+ scsi_add_timer(SCpnt, SCpnt->timeout_per_command, scsi_times_out);
/*
* We will use a queued command if possible, otherwise we will emulate the
SCSI_LOG_MLQUEUE(3, printk("queuecommand : routine at %p\n",
host->hostt->queuecommand));
/*
- * Use the old error handling code if we haven't converted the driver
- * to use the new one yet. Note - only the new queuecommand variant
- * passes a meaningful return value.
+ * Before we queue this command, check if the command
+ * length exceeds what the host adapter can handle.
*/
- if (host->hostt->use_new_eh_code) {
- /*
- * Before we queue this command, check if the command
- * length exceeds what the host adapter can handle.
- */
- if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
- spin_lock_irqsave(&host->host_lock, flags);
- rtn = host->hostt->queuecommand(SCpnt, scsi_done);
- spin_unlock_irqrestore(&host->host_lock, flags);
- if (rtn != 0) {
- scsi_delete_timer(SCpnt);
- scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY);
- SCSI_LOG_MLQUEUE(3, printk("queuecommand : request rejected\n"));
- }
- } else {
- SCSI_LOG_MLQUEUE(3, printk("queuecommand : command too long.\n"));
- SCpnt->result = (DID_ABORT << 16);
- spin_lock_irqsave(&host->host_lock, flags);
- scsi_done(SCpnt);
- spin_unlock_irqrestore(&host->host_lock, flags);
- rtn = 1;
-
+ if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
+ spin_lock_irqsave(&host->host_lock, flags);
+ rtn = host->hostt->queuecommand(SCpnt, scsi_done);
+ spin_unlock_irqrestore(&host->host_lock, flags);
+ if (rtn != 0) {
+ scsi_delete_timer(SCpnt);
+ scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY);
+ SCSI_LOG_MLQUEUE(3,
+ printk("queuecommand : request rejected\n"));
}
} else {
- /*
- * Before we queue this command, check if the command
- * length exceeds what the host adapter can handle.
- */
- if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
- spin_lock_irqsave(&host->host_lock, flags);
- host->hostt->queuecommand(SCpnt, scsi_old_done);
- spin_unlock_irqrestore(&host->host_lock, flags);
- } else {
- SCSI_LOG_MLQUEUE(3, printk("queuecommand : command too long.\n"));
- SCpnt->result = (DID_ABORT << 16);
- spin_lock_irqsave(&host->host_lock, flags);
- scsi_old_done(SCpnt);
- spin_unlock_irqrestore(&host->host_lock, flags);
- rtn = 1;
- }
+ SCSI_LOG_MLQUEUE(3,
+ printk("queuecommand : command too long.\n"));
+ SCpnt->result = (DID_ABORT << 16);
+ spin_lock_irqsave(&host->host_lock, flags);
+ scsi_done(SCpnt);
+ spin_unlock_irqrestore(&host->host_lock, flags);
+ rtn = 1;
}
} else {
int temp;
host->host_no, temp, host->hostt->command);
spin_lock_irqsave(&host->host_lock, flags);
#endif
- if (host->hostt->use_new_eh_code) {
- scsi_done(SCpnt);
- } else {
- scsi_old_done(SCpnt);
- }
+ scsi_done(SCpnt);
spin_unlock_irqrestore(&host->host_lock, flags);
}
SCSI_LOG_MLQUEUE(3, printk("leaving scsi_dispatch_cmnd()\n"));
/* The detect routine must carefully spinunlock/spinlock if
it enables interrupts, since all interrupt handlers do
- spinlock as well.
- All lame drivers are going to fail due to the following
- spinlock. For the time beeing let's use it only for drivers
- using the new scsi code. NOTE: the detect routine could
- redefine the value tpnt->use_new_eh_code. (DB, 13 May 1998) */
+ spinlock as well. */
/*
* detect should do its own locking
*/
- if (tpnt->use_new_eh_code) {
- tpnt->present = tpnt->detect(tpnt);
- } else
- tpnt->present = tpnt->detect(tpnt);
+ tpnt->present = tpnt->detect(tpnt);
if (tpnt->present) {
if (pcount == next_scsi_host) {
* handle error correction.
*/
for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt == tpnt && shpnt->hostt->use_new_eh_code) {
+ if (shpnt->hostt == tpnt) {
DECLARE_MUTEX_LOCKED(sem);
shpnt->eh_notify = &sem;
*/
for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
if (shpnt->hostt == tpnt
- && shpnt->hostt->use_new_eh_code
&& shpnt->ehandler != NULL) {
DECLARE_MUTEX_LOCKED(sem);
cmd_per_lun: 3, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1, \
}
#endif
panic("DMA pool exhausted");
}
-/*
- * FIXME(eric) - the original disk code disabled clustering for MOD
- * devices. I have no idea why we thought this was a good idea - my
- * guess is that it was an attempt to limit the size of requests to MOD
- * devices.
- */
-#define CLUSTERABLE_DEVICE(SH,SD) (SH->use_clustering && \
- SD->type != TYPE_MOD)
-
/*
* This entire source file deals with the new queueing code.
*/
*
* Arguments: q - Queue for which we are merging request.
* req - request into which we wish to merge.
- * use_clustering - 1 if this host wishes to use clustering
* dma_host - 1 if this host has ISA DMA issues (bus doesn't
* expose all of the address lines, so that DMA cannot
* be done from an arbitrary address).
* Notes: This is only used for diagnostic purposes.
*/
__inline static int __count_segments(struct request *req,
- int use_clustering,
int dma_host,
int * remainder)
{
int ret = 1;
int reqsize = 0;
- struct bio *bio, *bionext;
+ int i;
+ struct bio *bio;
+ struct bio_vec *bvec;
if (remainder)
reqsize = *remainder;
ret++;
#endif
- for (bio = req->bio, bionext = bio->bi_next;
- bionext != NULL;
- bio = bionext, bionext = bio->bi_next) {
- if (use_clustering) {
- /*
- * See if we can do this without creating another
- * scatter-gather segment. In the event that this is a
- * DMA capable host, make sure that a segment doesn't span
- * the DMA threshold boundary.
- */
- if (dma_host && bio_to_phys(bionext) - 1 == ISA_DMA_THRESHOLD) {
- ret++;
- reqsize = bio_size(bionext);
- } else if (BIO_CONTIG(bio, bionext)) {
- /*
- * This one is OK. Let it go.
- */
-#ifdef DMA_SEGMENT_SIZE_LIMITED
- /* Note scsi_malloc is only able to hand out
- * chunks of memory in sizes of PAGE_SIZE or
- * less. Thus we need to keep track of
- * the size of the piece that we have
- * seen so far, and if we have hit
- * the limit of PAGE_SIZE, then we are
- * kind of screwed and we need to start
- * another segment.
- */
- if(dma_host && bio_to_phys(bionext) - 1 >= ISA_DMA_THRESHOLD
- && reqsize + bio_size(bionext) > PAGE_SIZE )
- {
- ret++;
- reqsize = bio_size(bionext);
- continue;
- }
-#endif
- reqsize += bio_size(bionext);
- continue;
- }
- ret++;
- reqsize = bio_size(bionext);
- } else {
+ rq_for_each_bio(bio, req) {
+ bio_for_each_segment(bvec, bio, i)
ret++;
- reqsize = bio_size(bionext);
- }
+
+ reqsize += bio_size(bio);
}
- if( remainder != NULL ) {
+
+ if (remainder)
*remainder = reqsize;
- }
+
return ret;
}
SHpnt = SCpnt->host;
SDpnt = SCpnt->device;
- req->nr_segments = __count_segments(req,
- CLUSTERABLE_DEVICE(SHpnt, SDpnt),
- SHpnt->unchecked_isa_dma, NULL);
+ req->nr_segments = __count_segments(req, SHpnt->unchecked_isa_dma,NULL);
}
#define MERGEABLE_BUFFERS(X,Y) \
* Arguments: q - Queue for which we are merging request.
* req - request into which we wish to merge.
* bio - Block which we may wish to merge into request
- * use_clustering - 1 if this host wishes to use clustering
* dma_host - 1 if this host has ISA DMA issues (bus doesn't
* expose all of the address lines, so that DMA cannot
* be done from an arbitrary address).
*
* This function is not designed to be directly called. Instead
* it should be referenced from other functions where the
- * use_clustering and dma_host parameters should be integer
- * constants. The compiler should thus be able to properly
- * optimize the code, eliminating stuff that is irrelevant.
+ * dma_host parameter should be an integer constant. The
+ * compiler should thus be able to properly optimize the code,
+ * eliminating stuff that is irrelevant.
* It is more maintainable to do this way with a single function
* than to have 4 separate functions all doing roughly the
* same thing.
__inline static int __scsi_back_merge_fn(request_queue_t * q,
struct request *req,
struct bio *bio,
- int use_clustering,
int dma_host)
{
- unsigned int count;
- unsigned int segment_size = 0;
Scsi_Device *SDpnt = q->queuedata;
if (req->nr_sectors + bio_sectors(bio) > q->max_sectors)
return 0;
- else if (!BIO_PHYS_4G(req->biotail, bio))
+ else if (!BIO_SEG_BOUNDARY(q, req->biotail, bio))
return 0;
- if (use_clustering) {
- /*
- * See if we can do this without creating another
- * scatter-gather segment. In the event that this is a
- * DMA capable host, make sure that a segment doesn't span
- * the DMA threshold boundary.
- */
- if (dma_host && bio_to_phys(req->biotail) - 1 == ISA_DMA_THRESHOLD) {
- goto new_end_segment;
- }
- if (BIO_CONTIG(req->biotail, bio)) {
-#ifdef DMA_SEGMENT_SIZE_LIMITED
- if( dma_host && bio_to_phys(bio) - 1 >= ISA_DMA_THRESHOLD ) {
- segment_size = 0;
- count = __count_segments(req, use_clustering, dma_host, &segment_size);
- if( segment_size + bio_size(bio) > PAGE_SIZE ) {
- goto new_end_segment;
- }
- }
-#endif
- /*
- * This one is OK. Let it go.
- */
- return 1;
- }
- }
- new_end_segment:
#ifdef DMA_CHUNK_SIZE
if (MERGEABLE_BUFFERS(req->biotail, bio))
return scsi_new_mergeable(q, req, SDpnt->host);
__inline static int __scsi_front_merge_fn(request_queue_t * q,
struct request *req,
struct bio *bio,
- int use_clustering,
int dma_host)
{
- unsigned int count;
- unsigned int segment_size = 0;
Scsi_Device *SDpnt = q->queuedata;
if (req->nr_sectors + bio_sectors(bio) > q->max_sectors)
return 0;
- else if (!BIO_PHYS_4G(bio, req->bio))
+ else if (!BIO_SEG_BOUNDARY(q, bio, req->bio))
return 0;
- if (use_clustering) {
- /*
- * See if we can do this without creating another
- * scatter-gather segment. In the event that this is a
- * DMA capable host, make sure that a segment doesn't span
- * the DMA threshold boundary.
- */
- if (dma_host && bio_to_phys(bio) - 1 == ISA_DMA_THRESHOLD) {
- goto new_start_segment;
- }
- if (BIO_CONTIG(bio, req->bio)) {
-#ifdef DMA_SEGMENT_SIZE_LIMITED
- if( dma_host && bio_to_phys(bio) - 1 >= ISA_DMA_THRESHOLD ) {
- segment_size = bio_size(bio);
- count = __count_segments(req, use_clustering, dma_host, &segment_size);
- if( count != req->nr_segments ) {
- goto new_start_segment;
- }
- }
-#endif
- /*
- * This one is OK. Let it go.
- */
- return 1;
- }
- }
- new_start_segment:
#ifdef DMA_CHUNK_SIZE
if (MERGEABLE_BUFFERS(bio, req->bio))
return scsi_new_mergeable(q, req, SDpnt->host);
* Notes: Optimized for different cases depending upon whether
* ISA DMA is in use and whether clustering should be used.
*/
-#define MERGEFCT(_FUNCTION, _BACK_FRONT, _CLUSTER, _DMA) \
+#define MERGEFCT(_FUNCTION, _BACK_FRONT, _DMA) \
static int _FUNCTION(request_queue_t * q, \
struct request * req, \
struct bio *bio) \
ret = __scsi_ ## _BACK_FRONT ## _merge_fn(q, \
req, \
bio, \
- _CLUSTER, \
_DMA); \
return ret; \
}
-/* Version with use_clustering 0 and dma_host 1 is not necessary,
- * since the only use of dma_host above is protected by use_clustering.
- */
-MERGEFCT(scsi_back_merge_fn_, back, 0, 0)
-MERGEFCT(scsi_back_merge_fn_c, back, 1, 0)
-MERGEFCT(scsi_back_merge_fn_dc, back, 1, 1)
+MERGEFCT(scsi_back_merge_fn_, back, 0)
+MERGEFCT(scsi_back_merge_fn_d, back, 1)
-MERGEFCT(scsi_front_merge_fn_, front, 0, 0)
-MERGEFCT(scsi_front_merge_fn_c, front, 1, 0)
-MERGEFCT(scsi_front_merge_fn_dc, front, 1, 1)
+MERGEFCT(scsi_front_merge_fn_, front, 0)
+MERGEFCT(scsi_front_merge_fn_d, front, 1)
/*
* Function: __scsi_merge_requests_fn()
* Arguments: q - Queue for which we are merging request.
* req - request into which we wish to merge.
* next - 2nd request that we might want to combine with req
- * use_clustering - 1 if this host wishes to use clustering
* dma_host - 1 if this host has ISA DMA issues (bus doesn't
* expose all of the address lines, so that DMA cannot
* be done from an arbitrary address).
* function is called from ll_rw_blk before it attempts to merge
* a new block into a request to make sure that the request will
* not become too large.
- *
- * This function is not designed to be directly called. Instead
- * it should be referenced from other functions where the
- * use_clustering and dma_host parameters should be integer
- * constants. The compiler should thus be able to properly
- * optimize the code, eliminating stuff that is irrelevant.
- * It is more maintainable to do this way with a single function
- * than to have 4 separate functions all doing roughly the
- * same thing.
*/
__inline static int __scsi_merge_requests_fn(request_queue_t * q,
struct request *req,
struct request *next,
- int use_clustering,
int dma_host)
{
Scsi_Device *SDpnt;
*/
if (req->special || next->special)
return 0;
- else if (!BIO_PHYS_4G(req->biotail, next->bio))
+ else if (!BIO_SEG_BOUNDARY(q, req->biotail, next->bio))
return 0;
SDpnt = (Scsi_Device *) q->queuedata;
if ((req->nr_sectors + next->nr_sectors) > SHpnt->max_sectors)
return 0;
- /*
- * The main question is whether the two segments at the boundaries
- * would be considered one or two.
- */
- if (use_clustering) {
- /*
- * See if we can do this without creating another
- * scatter-gather segment. In the event that this is a
- * DMA capable host, make sure that a segment doesn't span
- * the DMA threshold boundary.
- */
- if (dma_host && bio_to_phys(req->biotail) - 1 == ISA_DMA_THRESHOLD) {
- goto dont_combine;
- }
-#ifdef DMA_SEGMENT_SIZE_LIMITED
- /*
- * We currently can only allocate scatter-gather bounce
- * buffers in chunks of PAGE_SIZE or less.
- */
- if (dma_host
- && BIO_CONTIG(req->biotail, next->bio)
- && bio_to_phys(req->biotail) - 1 >= ISA_DMA_THRESHOLD )
- {
- int segment_size = 0;
- int count = 0;
-
- count = __count_segments(req, use_clustering, dma_host, &segment_size);
- count += __count_segments(next, use_clustering, dma_host, &segment_size);
- if( count != req->nr_segments + next->nr_segments ) {
- goto dont_combine;
- }
- }
-#endif
- if (BIO_CONTIG(req->biotail, next->bio)) {
- /*
- * This one is OK. Let it go.
- */
- req->nr_segments += next->nr_segments - 1;
-#ifdef DMA_CHUNK_SIZE
- req->nr_hw_segments += next->nr_hw_segments - 1;
-#endif
- return 1;
- }
- }
- dont_combine:
#ifdef DMA_CHUNK_SIZE
if (req->nr_segments + next->nr_segments > q->max_segments)
return 0;
* Notes: Optimized for different cases depending upon whether
* ISA DMA is in use and whether clustering should be used.
*/
-#define MERGEREQFCT(_FUNCTION, _CLUSTER, _DMA) \
+#define MERGEREQFCT(_FUNCTION, _DMA) \
static int _FUNCTION(request_queue_t * q, \
struct request * req, \
struct request * next) \
{ \
int ret; \
- ret = __scsi_merge_requests_fn(q, req, next, _CLUSTER, _DMA); \
+ ret = __scsi_merge_requests_fn(q, req, next, _DMA); \
return ret; \
}
-/* Version with use_clustering 0 and dma_host 1 is not necessary,
- * since the only use of dma_host above is protected by use_clustering.
- */
-MERGEREQFCT(scsi_merge_requests_fn_, 0, 0)
-MERGEREQFCT(scsi_merge_requests_fn_c, 1, 0)
-MERGEREQFCT(scsi_merge_requests_fn_dc, 1, 1)
+MERGEREQFCT(scsi_merge_requests_fn_, 0)
+MERGEREQFCT(scsi_merge_requests_fn_d, 1)
/*
* Function: __init_io()
*
*
* Arguments: SCpnt - Command descriptor we wish to initialize
* sg_count_valid - 1 if the sg count in the req is valid.
- * use_clustering - 1 if this host wishes to use clustering
* dma_host - 1 if this host has ISA DMA issues (bus doesn't
* expose all of the address lines, so that DMA cannot
* be done from an arbitrary address).
*/
__inline static int __init_io(Scsi_Cmnd * SCpnt,
int sg_count_valid,
- int use_clustering,
int dma_host)
{
struct bio * bio;
int this_count;
void ** bbpnt;
- /*
- * now working right now
- */
- BUG_ON(dma_host);
-
req = &SCpnt->request;
/*
* First we need to know how many scatter gather segments are needed.
*/
if (!sg_count_valid) {
- count = __count_segments(req, use_clustering, dma_host, NULL);
+ count = __count_segments(req, dma_host, NULL);
} else {
count = req->nr_segments;
}
return 1;
}
-#define INITIO(_FUNCTION, _VALID, _CLUSTER, _DMA) \
-static int _FUNCTION(Scsi_Cmnd * SCpnt) \
-{ \
- return __init_io(SCpnt, _VALID, _CLUSTER, _DMA); \
+#define INITIO(_FUNCTION, _VALID, _DMA) \
+static int _FUNCTION(Scsi_Cmnd * SCpnt) \
+{ \
+ return __init_io(SCpnt, _VALID, _DMA); \
}
/*
* We always force "_VALID" to 1. Eventually clean this up
* and get rid of the extra argument.
*/
-INITIO(scsi_init_io_v, 1, 0, 0)
-INITIO(scsi_init_io_vd, 1, 0, 1)
-INITIO(scsi_init_io_vc, 1, 1, 0)
-INITIO(scsi_init_io_vdc, 1, 1, 1)
+INITIO(scsi_init_io_v, 1, 0)
+INITIO(scsi_init_io_vd, 1, 1)
/*
* Function: initialize_merge_fn()
* is simply easier to do it ourselves with our own functions
* rather than rely upon the default behavior of ll_rw_blk.
*/
- if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
+ if (SHpnt->unchecked_isa_dma == 0) {
q->back_merge_fn = scsi_back_merge_fn_;
q->front_merge_fn = scsi_front_merge_fn_;
q->merge_requests_fn = scsi_merge_requests_fn_;
SDpnt->scsi_init_io_fn = scsi_init_io_v;
- } else if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) {
- q->back_merge_fn = scsi_back_merge_fn_;
- q->front_merge_fn = scsi_front_merge_fn_;
- q->merge_requests_fn = scsi_merge_requests_fn_;
+ } else {
+ q->back_merge_fn = scsi_back_merge_fn_d;
+ q->front_merge_fn = scsi_front_merge_fn_d;
+ q->merge_requests_fn = scsi_merge_requests_fn_d;
SDpnt->scsi_init_io_fn = scsi_init_io_vd;
- } else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
- q->back_merge_fn = scsi_back_merge_fn_c;
- q->front_merge_fn = scsi_front_merge_fn_c;
- q->merge_requests_fn = scsi_merge_requests_fn_c;
- SDpnt->scsi_init_io_fn = scsi_init_io_vc;
- } else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) {
- q->back_merge_fn = scsi_back_merge_fn_dc;
- q->front_merge_fn = scsi_front_merge_fn_dc;
- q->merge_requests_fn = scsi_merge_requests_fn_dc;
- SDpnt->scsi_init_io_fn = scsi_init_io_vdc;
}
/*
+++ /dev/null
-/*
- * scsi_obsolete.c Copyright (C) 1992 Drew Eckhardt
- * Copyright (C) 1993, 1994, 1995 Eric Youngdale
- *
- * generic mid-level SCSI driver
- * Initial versions: Drew Eckhardt
- * Subsequent revisions: Eric Youngdale
- *
- * <drew@colorado.edu>
- *
- * Bug correction thanks go to :
- * Rik Faith <faith@cs.unc.edu>
- * Tommy Thorn <tthorn>
- * Thomas Wuensche <tw@fgb1.fgb.mw.tu-muenchen.de>
- *
- * Modified by Eric Youngdale eric@andante.org to
- * add scatter-gather, multiple outstanding request, and other
- * enhancements.
- *
- * Native multichannel, wide scsi, /proc/scsi and hot plugging
- * support added by Michael Neuffer <mike@i-connect.net>
- *
- * Major improvements to the timeout, abort, and reset processing,
- * as well as performance modifications for large queue depths by
- * Leonard N. Zubkoff <lnz@dandelion.com>
- *
- * Improved compatibility with 2.0 behaviour by Manfred Spraul
- * <masp0008@stud.uni-sb.de>
- */
-
-/*
- *#########################################################################
- *#########################################################################
- *#########################################################################
- *#########################################################################
- * NOTE - NOTE - NOTE - NOTE - NOTE - NOTE - NOTE
- *
- *#########################################################################
- *#########################################################################
- *#########################################################################
- *#########################################################################
- *
- * This file contains the 'old' scsi error handling. It is only present
- * while the new error handling code is being debugged, and while the low
- * level drivers are being converted to use the new code. Once the last
- * driver uses the new code this *ENTIRE* file will be nuked.
- */
-
-#define __NO_VERSION__
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/stat.h>
-#include <linux/blk.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-
-#include "scsi.h"
-#include "hosts.h"
-#include "constants.h"
-
-#undef USE_STATIC_SCSI_MEMORY
-
-/*
- static const char RCSid[] = "$Header: /mnt/ide/home/eric/CVSROOT/linux/drivers/scsi/scsi_obsolete.c,v 1.1 1997/05/18 23:27:21 eric Exp $";
- */
-
-
-#define INTERNAL_ERROR (panic ("Internal error in file %s, line %d.\n", __FILE__, __LINE__))
-
-
-static int scsi_abort(Scsi_Cmnd *, int code);
-static int scsi_reset(Scsi_Cmnd *, unsigned int);
-
-extern void scsi_old_done(Scsi_Cmnd * SCpnt);
-int update_timeout(Scsi_Cmnd *, int);
-extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
-
-extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt);
-
-#define SCSI_BLOCK(HOST) (HOST->can_queue && HOST->host_busy >= HOST->can_queue)
-
-static unsigned char generic_sense[6] =
-{REQUEST_SENSE, 0, 0, 0, 255, 0};
-
-/*
- * This is the number of clock ticks we should wait before we time out
- * and abort the command. This is for where the scsi.c module generates
- * the command, not where it originates from a higher level, in which
- * case the timeout is specified there.
- *
- * ABORT_TIMEOUT and RESET_TIMEOUT are the timeouts for RESET and ABORT
- * respectively.
- */
-
-#ifdef DEBUG_TIMEOUT
-static void scsi_dump_status(void);
-#endif
-
-
-#ifdef DEBUG
-#define SCSI_TIMEOUT (5*HZ)
-#else
-#define SCSI_TIMEOUT (2*HZ)
-#endif
-
-#ifdef DEBUG
-#define SENSE_TIMEOUT SCSI_TIMEOUT
-#define ABORT_TIMEOUT SCSI_TIMEOUT
-#define RESET_TIMEOUT SCSI_TIMEOUT
-#else
-#define SENSE_TIMEOUT (5*HZ/10)
-#define RESET_TIMEOUT (5*HZ/10)
-#define ABORT_TIMEOUT (5*HZ/10)
-#endif
-
-
-/* Do not call reset on error if we just did a reset within 15 sec. */
-#define MIN_RESET_PERIOD (15*HZ)
-
-
-
-/*
- * Flag bits for the internal_timeout array
- */
-#define IN_ABORT 1
-#define IN_RESET 2
-#define IN_RESET2 4
-#define IN_RESET3 8
-
-/*
- * This is our time out function, called when the timer expires for a
- * given host adapter. It will attempt to abort the currently executing
- * command, that failing perform a kernel panic.
- */
-
-void scsi_old_times_out(Scsi_Cmnd * SCpnt)
-{
- struct Scsi_Host *host = SCpnt->host;
- unsigned long flags;
-
- spin_lock_irqsave(&host->host_lock, flags);
-
- /* Set the serial_number_at_timeout to the current serial_number */
- SCpnt->serial_number_at_timeout = SCpnt->serial_number;
-
- switch (SCpnt->internal_timeout & (IN_ABORT | IN_RESET | IN_RESET2 | IN_RESET3)) {
- case NORMAL_TIMEOUT:
- {
-#ifdef DEBUG_TIMEOUT
- scsi_dump_status();
-#endif
- }
-
- if (!scsi_abort(SCpnt, DID_TIME_OUT))
- break;
- case IN_ABORT:
- printk("SCSI host %d abort (pid %ld) timed out - resetting\n",
- host->host_no, SCpnt->pid);
- if (!scsi_reset(SCpnt, SCSI_RESET_ASYNCHRONOUS))
- break;
- case IN_RESET:
- case (IN_ABORT | IN_RESET):
- /* This might be controversial, but if there is a bus hang,
- * you might conceivably want the machine up and running
- * esp if you have an ide disk.
- */
- printk("SCSI host %d channel %d reset (pid %ld) timed out - "
- "trying harder\n",
- host->host_no, SCpnt->channel, SCpnt->pid);
- SCpnt->internal_timeout &= ~IN_RESET;
- SCpnt->internal_timeout |= IN_RESET2;
- scsi_reset(SCpnt,
- SCSI_RESET_ASYNCHRONOUS | SCSI_RESET_SUGGEST_BUS_RESET);
- break;
- case IN_RESET2:
- case (IN_ABORT | IN_RESET2):
- /* Obviously the bus reset didn't work.
- * Let's try even harder and call for an HBA reset.
- * Maybe the HBA itself crashed and this will shake it loose.
- */
- printk("SCSI host %d reset (pid %ld) timed out - trying to shake it loose\n",
- host->host_no, SCpnt->pid);
- SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2);
- SCpnt->internal_timeout |= IN_RESET3;
- scsi_reset(SCpnt,
- SCSI_RESET_ASYNCHRONOUS | SCSI_RESET_SUGGEST_HOST_RESET);
- break;
-
- default:
- printk("SCSI host %d reset (pid %ld) timed out again -\n",
- host->host_no, SCpnt->pid);
- printk("probably an unrecoverable SCSI bus or device hang.\n");
- break;
-
- }
- spin_unlock_irqrestore(&host->host_lock, flags);
-
-}
-
-/*
- * From what I can find in scsi_obsolete.c, this function is only called
- * by scsi_old_done and scsi_reset. Both of these functions run with the
- * host_lock already held, so we need do nothing here about grabbing
- * any locks.
- */
-static void scsi_request_sense(Scsi_Cmnd * SCpnt)
-{
- SCpnt->flags |= WAS_SENSE | ASKED_FOR_SENSE;
- update_timeout(SCpnt, SENSE_TIMEOUT);
-
- memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
- sizeof(generic_sense));
- memset((void *) SCpnt->sense_buffer, 0,
- sizeof(SCpnt->sense_buffer));
-
- if (SCpnt->device->scsi_level <= SCSI_2)
- SCpnt->cmnd[1] = SCpnt->lun << 5;
- SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer);
-
- SCpnt->request_buffer = &SCpnt->sense_buffer;
- SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer);
- SCpnt->use_sg = 0;
- SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
- SCpnt->result = 0;
- SCpnt->sc_data_direction = SCSI_DATA_READ;
-
- /*
- * Ugly, ugly. The newer interfaces all assume that the lock
- * isn't held. Mustn't disappoint, or we deadlock the system.
- */
- spin_unlock_irq(&SCpnt->host->host_lock);
- scsi_dispatch_cmd(SCpnt);
- spin_lock_irq(&SCpnt->host->host_lock);
-}
-
-
-
-
-static int check_sense(Scsi_Cmnd * SCpnt)
-{
- /* If there is no sense information, request it. If we have already
- * requested it, there is no point in asking again - the firmware must
- * be confused.
- */
- if (((SCpnt->sense_buffer[0] & 0x70) >> 4) != 7) {
- if (!(SCpnt->flags & ASKED_FOR_SENSE))
- return SUGGEST_SENSE;
- else
- return SUGGEST_RETRY;
- }
- SCpnt->flags &= ~ASKED_FOR_SENSE;
-
-#ifdef DEBUG_INIT
- printk("scsi%d, channel%d : ", SCpnt->host->host_no, SCpnt->channel);
- print_sense("", SCpnt);
- printk("\n");
-#endif
- if (SCpnt->sense_buffer[2] & 0xe0)
- return SUGGEST_ABORT;
-
- switch (SCpnt->sense_buffer[2] & 0xf) {
- case NO_SENSE:
- return 0;
- case RECOVERED_ERROR:
- return SUGGEST_IS_OK;
-
- case ABORTED_COMMAND:
- return SUGGEST_RETRY;
- case NOT_READY:
- case UNIT_ATTENTION:
- /*
- * If we are expecting a CC/UA because of a bus reset that we
- * performed, treat this just as a retry. Otherwise this is
- * information that we should pass up to the upper-level driver
- * so that we can deal with it there.
- */
- if (SCpnt->device->expecting_cc_ua) {
- SCpnt->device->expecting_cc_ua = 0;
- return SUGGEST_RETRY;
- }
- return SUGGEST_ABORT;
-
- /* these three are not supported */
- case COPY_ABORTED:
- case VOLUME_OVERFLOW:
- case MISCOMPARE:
-
- case MEDIUM_ERROR:
- return SUGGEST_REMAP;
- case BLANK_CHECK:
- case DATA_PROTECT:
- case HARDWARE_ERROR:
- case ILLEGAL_REQUEST:
- default:
- return SUGGEST_ABORT;
- }
-}
-
-/* This function is the mid-level interrupt routine, which decides how
- * to handle error conditions. Each invocation of this function must
- * do one and *only* one of the following:
- *
- * (1) Call last_cmnd[host].done. This is done for fatal errors and
- * normal completion, and indicates that the handling for this
- * request is complete.
- * (2) Call internal_cmnd to requeue the command. This will result in
- * scsi_done being called again when the retry is complete.
- * (3) Call scsi_request_sense. This asks the host adapter/drive for
- * more information about the error condition. When the information
- * is available, scsi_done will be called again.
- * (4) Call reset(). This is sort of a last resort, and the idea is that
- * this may kick things loose and get the drive working again. reset()
- * automatically calls scsi_request_sense, and thus scsi_done will be
- * called again once the reset is complete.
- *
- * If none of the above actions are taken, the drive in question
- * will hang. If more than one of the above actions are taken by
- * scsi_done, then unpredictable behavior will result.
- */
-void scsi_old_done(Scsi_Cmnd * SCpnt)
-{
- int status = 0;
- int exit = 0;
- int checked;
- int oldto;
- struct Scsi_Host *host = SCpnt->host;
- Scsi_Device * device = SCpnt->device;
- int result = SCpnt->result;
- SCpnt->serial_number = 0;
- SCpnt->serial_number_at_timeout = 0;
- oldto = update_timeout(SCpnt, 0);
-
-#ifdef DEBUG_TIMEOUT
- if (result)
- printk("Non-zero result in scsi_done %x %d:%d\n",
- result, SCpnt->target, SCpnt->lun);
-#endif
-
- /* If we requested an abort, (and we got it) then fix up the return
- * status to say why
- */
- if (host_byte(result) == DID_ABORT && SCpnt->abort_reason)
- SCpnt->result = result = (result & 0xff00ffff) |
- (SCpnt->abort_reason << 16);
-
-
-#define CMD_FINISHED 0
-#define MAYREDO 1
-#define REDO 3
-#define PENDING 4
-
-#ifdef DEBUG
- printk("In scsi_done(host = %d, result = %06x)\n", host->host_no, result);
-#endif
-
- if (SCpnt->flags & SYNC_RESET) {
- /*
- * The behaviou of scsi_reset(SYNC) was changed in 2.1.? .
- * The scsi mid-layer does a REDO after every sync reset, the driver
- * must not do that any more. In order to prevent old drivers from
- * crashing, all scsi_done() calls during sync resets are ignored.
- */
- printk("scsi%d: device driver called scsi_done() "
- "for a synchronous reset.\n", SCpnt->host->host_no);
- return;
- }
- if (SCpnt->flags & WAS_SENSE) {
- SCpnt->use_sg = SCpnt->old_use_sg;
- SCpnt->cmd_len = SCpnt->old_cmd_len;
- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
- SCpnt->underflow = SCpnt->old_underflow;
- }
- switch (host_byte(result)) {
- case DID_OK:
- if (status_byte(result) && (SCpnt->flags & WAS_SENSE))
- /* Failed to obtain sense information */
- {
- SCpnt->flags &= ~WAS_SENSE;
-#if 0 /* This cannot possibly be correct. */
- SCpnt->internal_timeout &= ~SENSE_TIMEOUT;
-#endif
-
- if (!(SCpnt->flags & WAS_RESET)) {
- printk("scsi%d : channel %d target %d lun %d request sense"
- " failed, performing reset.\n",
- SCpnt->host->host_no, SCpnt->channel, SCpnt->target,
- SCpnt->lun);
- scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
- status = REDO;
- break;
- } else {
- exit = (DRIVER_HARD | SUGGEST_ABORT);
- status = CMD_FINISHED;
- }
- } else
- switch (msg_byte(result)) {
- case COMMAND_COMPLETE:
- switch (status_byte(result)) {
- case GOOD:
- if (SCpnt->flags & WAS_SENSE) {
-#ifdef DEBUG
- printk("In scsi_done, GOOD status, COMMAND COMPLETE, "
- "parsing sense information.\n");
-#endif
- SCpnt->flags &= ~WAS_SENSE;
-#if 0 /* This cannot possibly be correct. */
- SCpnt->internal_timeout &= ~SENSE_TIMEOUT;
-#endif
-
- switch (checked = check_sense(SCpnt)) {
- case SUGGEST_SENSE:
- case 0:
-#ifdef DEBUG
- printk("NO SENSE. status = REDO\n");
-#endif
- update_timeout(SCpnt, oldto);
- status = REDO;
- break;
- case SUGGEST_IS_OK:
- break;
- case SUGGEST_REMAP:
-#ifdef DEBUG
- printk("SENSE SUGGEST REMAP - status = CMD_FINISHED\n");
-#endif
- status = CMD_FINISHED;
- exit = DRIVER_SENSE | SUGGEST_ABORT;
- break;
- case SUGGEST_RETRY:
-#ifdef DEBUG
- printk("SENSE SUGGEST RETRY - status = MAYREDO\n");
-#endif
- status = MAYREDO;
- exit = DRIVER_SENSE | SUGGEST_RETRY;
- break;
- case SUGGEST_ABORT:
-#ifdef DEBUG
- printk("SENSE SUGGEST ABORT - status = CMD_FINISHED");
-#endif
- status = CMD_FINISHED;
- exit = DRIVER_SENSE | SUGGEST_ABORT;
- break;
- default:
- printk("Internal error %s %d \n", __FILE__,
- __LINE__);
- }
- }
- /* end WAS_SENSE */
- else {
-#ifdef DEBUG
- printk("COMMAND COMPLETE message returned, "
- "status = CMD_FINISHED. \n");
-#endif
- exit = DRIVER_OK;
- status = CMD_FINISHED;
- }
- break;
-
- case CHECK_CONDITION:
- case COMMAND_TERMINATED:
- switch (check_sense(SCpnt)) {
- case 0:
- update_timeout(SCpnt, oldto);
- status = REDO;
- break;
- case SUGGEST_REMAP:
- status = CMD_FINISHED;
- exit = DRIVER_SENSE | SUGGEST_ABORT;
- break;
- case SUGGEST_RETRY:
- status = MAYREDO;
- exit = DRIVER_SENSE | SUGGEST_RETRY;
- break;
- case SUGGEST_ABORT:
- status = CMD_FINISHED;
- exit = DRIVER_SENSE | SUGGEST_ABORT;
- break;
- case SUGGEST_SENSE:
- scsi_request_sense(SCpnt);
- status = PENDING;
- break;
- }
- break;
-
- case CONDITION_GOOD:
- case INTERMEDIATE_GOOD:
- case INTERMEDIATE_C_GOOD:
- break;
-
- case BUSY:
- case QUEUE_FULL:
- update_timeout(SCpnt, oldto);
- status = REDO;
- break;
-
- case RESERVATION_CONFLICT:
- printk("scsi%d, channel %d : RESERVATION CONFLICT performing"
- " reset.\n", SCpnt->host->host_no, SCpnt->channel);
- scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
- status = REDO;
- break;
- default:
- printk("Internal error %s %d \n"
- "status byte = %d \n", __FILE__,
- __LINE__, status_byte(result));
-
- }
- break;
- default:
- panic("scsi: unsupported message byte %d received\n",
- msg_byte(result));
- }
- break;
- case DID_TIME_OUT:
-#ifdef DEBUG
- printk("Host returned DID_TIME_OUT - ");
-#endif
-
- if (SCpnt->flags & WAS_TIMEDOUT) {
-#ifdef DEBUG
- printk("Aborting\n");
-#endif
- /*
- Allow TEST_UNIT_READY and INQUIRY commands to timeout early
- without causing resets. All other commands should be retried.
- */
- if (SCpnt->cmnd[0] != TEST_UNIT_READY &&
- SCpnt->cmnd[0] != INQUIRY)
- status = MAYREDO;
- exit = (DRIVER_TIMEOUT | SUGGEST_ABORT);
- } else {
-#ifdef DEBUG
- printk("Retrying.\n");
-#endif
- SCpnt->flags |= WAS_TIMEDOUT;
- SCpnt->internal_timeout &= ~IN_ABORT;
- status = REDO;
- }
- break;
- case DID_BUS_BUSY:
- case DID_PARITY:
- status = REDO;
- break;
- case DID_NO_CONNECT:
-#ifdef DEBUG
- printk("Couldn't connect.\n");
-#endif
- exit = (DRIVER_HARD | SUGGEST_ABORT);
- break;
- case DID_ERROR:
- status = MAYREDO;
- exit = (DRIVER_HARD | SUGGEST_ABORT);
- break;
- case DID_BAD_TARGET:
- case DID_ABORT:
- exit = (DRIVER_INVALID | SUGGEST_ABORT);
- break;
- case DID_RESET:
- if (SCpnt->flags & IS_RESETTING) {
- SCpnt->flags &= ~IS_RESETTING;
- status = REDO;
- break;
- }
- if (msg_byte(result) == GOOD &&
- status_byte(result) == CHECK_CONDITION) {
- switch (check_sense(SCpnt)) {
- case 0:
- update_timeout(SCpnt, oldto);
- status = REDO;
- break;
- case SUGGEST_REMAP:
- case SUGGEST_RETRY:
- status = MAYREDO;
- exit = DRIVER_SENSE | SUGGEST_RETRY;
- break;
- case SUGGEST_ABORT:
- status = CMD_FINISHED;
- exit = DRIVER_SENSE | SUGGEST_ABORT;
- break;
- case SUGGEST_SENSE:
- scsi_request_sense(SCpnt);
- status = PENDING;
- break;
- }
- } else {
- status = REDO;
- exit = SUGGEST_RETRY;
- }
- break;
- default:
- exit = (DRIVER_ERROR | SUGGEST_DIE);
- }
-
- switch (status) {
- case CMD_FINISHED:
- case PENDING:
- break;
- case MAYREDO:
-#ifdef DEBUG
- printk("In MAYREDO, allowing %d retries, have %d\n",
- SCpnt->allowed, SCpnt->retries);
-#endif
- if ((++SCpnt->retries) < SCpnt->allowed) {
- if ((SCpnt->retries >= (SCpnt->allowed >> 1))
- && !(SCpnt->host->resetting && time_before(jiffies, SCpnt->host->last_reset + MIN_RESET_PERIOD))
- && !(SCpnt->flags & WAS_RESET)) {
- printk("scsi%d channel %d : resetting for second half of retries.\n",
- SCpnt->host->host_no, SCpnt->channel);
- scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
- /* fall through to REDO */
- }
- } else {
- status = CMD_FINISHED;
- break;
- }
- /* fall through to REDO */
-
- case REDO:
-
- if (SCpnt->flags & WAS_SENSE)
- scsi_request_sense(SCpnt);
- else {
- memcpy((void *) SCpnt->cmnd,
- (void *) SCpnt->data_cmnd,
- sizeof(SCpnt->data_cmnd));
- memset((void *) SCpnt->sense_buffer, 0,
- sizeof(SCpnt->sense_buffer));
- SCpnt->request_buffer = SCpnt->buffer;
- SCpnt->request_bufflen = SCpnt->bufflen;
- SCpnt->use_sg = SCpnt->old_use_sg;
- SCpnt->cmd_len = SCpnt->old_cmd_len;
- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
- SCpnt->underflow = SCpnt->old_underflow;
- SCpnt->result = 0;
- /*
- * Ugly, ugly. The newer interfaces all
- * assume that the lock isn't held. Mustn't
- * disappoint, or we deadlock the system.
- */
- spin_unlock_irq(&host->host_lock);
- scsi_dispatch_cmd(SCpnt);
- spin_lock_irq(&host->host_lock);
- }
- break;
- default:
- INTERNAL_ERROR;
- }
-
- if (status == CMD_FINISHED) {
- Scsi_Request *SRpnt;
-#ifdef DEBUG
- printk("Calling done function - at address %p\n", SCpnt->done);
-#endif
- host->host_busy--; /* Indicate that we are free */
- device->device_busy--; /* Decrement device usage counter. */
-
- SCpnt->result = result | ((exit & 0xff) << 24);
- SCpnt->use_sg = SCpnt->old_use_sg;
- SCpnt->cmd_len = SCpnt->old_cmd_len;
- SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
- SCpnt->underflow = SCpnt->old_underflow;
- /*
- * The upper layers assume the lock isn't held. We mustn't
- * disappoint them. When the new error handling code is in
- * use, the upper code is run from a bottom half handler, so
- * it isn't an issue.
- */
- spin_unlock_irq(&host->host_lock);
- SRpnt = SCpnt->sc_request;
- if( SRpnt != NULL ) {
- SRpnt->sr_result = SRpnt->sr_command->result;
- if( SRpnt->sr_result != 0 ) {
- memcpy(SRpnt->sr_sense_buffer,
- SRpnt->sr_command->sense_buffer,
- sizeof(SRpnt->sr_sense_buffer));
- }
- }
-
- SCpnt->done(SCpnt);
- spin_lock_irq(&host->host_lock);
- }
-#undef CMD_FINISHED
-#undef REDO
-#undef MAYREDO
-#undef PENDING
-}
-
-/*
- * The scsi_abort function interfaces with the abort() function of the host
- * we are aborting, and causes the current command to not complete. The
- * caller should deal with any error messages or status returned on the
- * next call.
- *
- * This will not be called reentrantly for a given host.
- */
-
-/*
- * Since we're nice guys and specified that abort() and reset()
- * can be non-reentrant. The internal_timeout flags are used for
- * this.
- */
-
-
-static int scsi_abort(Scsi_Cmnd * SCpnt, int why)
-{
- int oldto;
- struct Scsi_Host *host = SCpnt->host;
-
- while (1) {
-
- /*
- * Protect against races here. If the command is done, or we are
- * on a different command forget it.
- */
- if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) {
- return 0;
- }
- if (SCpnt->internal_timeout & IN_ABORT) {
- spin_unlock_irq(&host->host_lock);
- while (SCpnt->internal_timeout & IN_ABORT)
- barrier();
- spin_lock_irq(&host->host_lock);
- } else {
- SCpnt->internal_timeout |= IN_ABORT;
- oldto = update_timeout(SCpnt, ABORT_TIMEOUT);
-
- if ((SCpnt->flags & IS_RESETTING) && SCpnt->device->soft_reset) {
- /* OK, this command must have died when we did the
- * reset. The device itself must have lied.
- */
- printk("Stale command on %d %d:%d appears to have died when"
- " the bus was reset\n",
- SCpnt->channel, SCpnt->target, SCpnt->lun);
- }
- if (!host->host_busy) {
- SCpnt->internal_timeout &= ~IN_ABORT;
- update_timeout(SCpnt, oldto);
- return 0;
- }
- printk("scsi : aborting command due to timeout : pid %lu, scsi%d,"
- " channel %d, id %d, lun %d ",
- SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->channel,
- (int) SCpnt->target, (int) SCpnt->lun);
- print_command(SCpnt->cmnd);
- if (SCpnt->serial_number != SCpnt->serial_number_at_timeout)
- return 0;
- SCpnt->abort_reason = why;
- switch (host->hostt->abort(SCpnt)) {
- /* We do not know how to abort. Try waiting another
- * time increment and see if this helps. Set the
- * WAS_TIMEDOUT flag set so we do not try this twice
- */
- case SCSI_ABORT_BUSY: /* Tough call - returning 1 from
- * this is too severe
- */
- case SCSI_ABORT_SNOOZE:
- if (why == DID_TIME_OUT) {
- SCpnt->internal_timeout &= ~IN_ABORT;
- if (SCpnt->flags & WAS_TIMEDOUT) {
- return 1; /* Indicate we cannot handle this.
- * We drop down into the reset handler
- * and try again
- */
- } else {
- SCpnt->flags |= WAS_TIMEDOUT;
- oldto = SCpnt->timeout_per_command;
- update_timeout(SCpnt, oldto);
- }
- }
- return 0;
- case SCSI_ABORT_PENDING:
- if (why != DID_TIME_OUT) {
- update_timeout(SCpnt, oldto);
- }
- return 0;
- case SCSI_ABORT_SUCCESS:
- /* We should have already aborted this one. No
- * need to adjust timeout
- */
- SCpnt->internal_timeout &= ~IN_ABORT;
- return 0;
- case SCSI_ABORT_NOT_RUNNING:
- SCpnt->internal_timeout &= ~IN_ABORT;
- update_timeout(SCpnt, 0);
- return 0;
- case SCSI_ABORT_ERROR:
- default:
- SCpnt->internal_timeout &= ~IN_ABORT;
- return 1;
- }
- }
- }
-}
-
-
-/* Mark a single SCSI Device as having been reset. */
-
-static inline void scsi_mark_device_reset(Scsi_Device * Device)
-{
- Device->was_reset = 1;
- Device->expecting_cc_ua = 1;
-}
-
-
-/* Mark all SCSI Devices on a specific Host as having been reset. */
-
-void scsi_mark_host_reset(struct Scsi_Host *Host)
-{
- Scsi_Cmnd *SCpnt;
- Scsi_Device *SDpnt;
-
- for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next) {
- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)
- scsi_mark_device_reset(SCpnt->device);
- }
-}
-
-
-/* Mark all SCSI Devices on a specific Host Bus as having been reset. */
-
-static void scsi_mark_bus_reset(struct Scsi_Host *Host, int channel)
-{
- Scsi_Cmnd *SCpnt;
- Scsi_Device *SDpnt;
-
- for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next) {
- for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)
- if (SCpnt->channel == channel)
- scsi_mark_device_reset(SCpnt->device);
- }
-}
-
-
-static int scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
-{
- int temp;
- Scsi_Cmnd *SCpnt1;
- Scsi_Device *SDpnt;
- struct Scsi_Host *host = SCpnt->host;
-
- printk("SCSI bus is being reset for host %d channel %d.\n",
- host->host_no, SCpnt->channel);
-
-#if 0
- /*
- * First of all, we need to make a recommendation to the low-level
- * driver as to whether a BUS_DEVICE_RESET should be performed,
- * or whether we should do a full BUS_RESET. There is no simple
- * algorithm here - we basically use a series of heuristics
- * to determine what we should do.
- */
- SCpnt->host->suggest_bus_reset = FALSE;
-
- /*
- * First see if all of the active devices on the bus have
- * been jammed up so that we are attempting resets. If so,
- * then suggest a bus reset. Forcing a bus reset could
- * result in some race conditions, but no more than
- * you would usually get with timeouts. We will cross
- * that bridge when we come to it.
- *
- * This is actually a pretty bad idea, since a sequence of
- * commands will often timeout together and this will cause a
- * Bus Device Reset followed immediately by a SCSI Bus Reset.
- * If all of the active devices really are jammed up, the
- * Bus Device Reset will quickly timeout and scsi_times_out
- * will follow up with a SCSI Bus Reset anyway.
- */
- SCpnt1 = host->host_queue;
- while (SCpnt1) {
- if (SCpnt1->request.rq_status != RQ_INACTIVE
- && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0)
- break;
- SCpnt1 = SCpnt1->next;
- }
- if (SCpnt1 == NULL) {
- reset_flags |= SCSI_RESET_SUGGEST_BUS_RESET;
- }
- /*
- * If the code that called us is suggesting a hard reset, then
- * definitely request it. This usually occurs because a
- * BUS_DEVICE_RESET times out.
- *
- * Passing reset_flags along takes care of this automatically.
- */
- if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) {
- SCpnt->host->suggest_bus_reset = TRUE;
- }
-#endif
-
- while (1) {
-
- /*
- * Protect against races here. If the command is done, or we are
- * on a different command forget it.
- */
- if (reset_flags & SCSI_RESET_ASYNCHRONOUS)
- if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) {
- return 0;
- }
- if (SCpnt->internal_timeout & IN_RESET) {
- spin_unlock_irq(&host->host_lock);
- while (SCpnt->internal_timeout & IN_RESET)
- barrier();
- spin_lock_irq(&host->host_lock);
- } else {
- SCpnt->internal_timeout |= IN_RESET;
- update_timeout(SCpnt, RESET_TIMEOUT);
-
- if (reset_flags & SCSI_RESET_SYNCHRONOUS)
- SCpnt->flags |= SYNC_RESET;
- if (host->host_busy) {
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
- SCpnt1 = SDpnt->device_queue;
- while (SCpnt1) {
- if (SCpnt1->request.rq_status != RQ_INACTIVE) {
-#if 0
- if (!(SCpnt1->flags & IS_RESETTING) &&
- !(SCpnt1->internal_timeout & IN_ABORT))
- scsi_abort(SCpnt1, DID_RESET);
-#endif
- SCpnt1->flags |= (WAS_RESET | IS_RESETTING);
- }
- SCpnt1 = SCpnt1->next;
- }
- }
-
- host->last_reset = jiffies;
- host->resetting = 1;
- /*
- * I suppose that the host reset callback will not play
- * with the resetting field. We have just set the resetting
- * flag here. -arca
- */
- temp = host->hostt->reset(SCpnt, reset_flags);
- /*
- This test allows the driver to introduce an additional bus
- settle time delay by setting last_reset up to 20 seconds in
- the future. In the normal case where the driver does not
- modify last_reset, it must be assumed that the actual bus
- reset occurred immediately prior to the return to this code,
- and so last_reset must be updated to the current time, so
- that the delay in internal_cmnd will guarantee at least a
- MIN_RESET_DELAY bus settle time.
- */
- if (host->last_reset - jiffies > 20UL * HZ)
- host->last_reset = jiffies;
- } else {
- host->host_busy++;
- host->last_reset = jiffies;
- host->resetting = 1;
- SCpnt->flags |= (WAS_RESET | IS_RESETTING);
- /*
- * I suppose that the host reset callback will not play
- * with the resetting field. We have just set the resetting
- * flag here. -arca
- */
- temp = host->hostt->reset(SCpnt, reset_flags);
- if (time_before(host->last_reset, jiffies) ||
- (time_after(host->last_reset, jiffies + 20 * HZ)))
- host->last_reset = jiffies;
- host->host_busy--;
- }
- if (reset_flags & SCSI_RESET_SYNCHRONOUS)
- SCpnt->flags &= ~SYNC_RESET;
-
-#ifdef DEBUG
- printk("scsi reset function returned %d\n", temp);
-#endif
-
- /*
- * Now figure out what we need to do, based upon
- * what the low level driver said that it did.
- * If the result is SCSI_RESET_SUCCESS, SCSI_RESET_PENDING,
- * or SCSI_RESET_WAKEUP, then the low level driver did a
- * bus device reset or bus reset, so we should go through
- * and mark one or all of the devices on that bus
- * as having been reset.
- */
- switch (temp & SCSI_RESET_ACTION) {
- case SCSI_RESET_SUCCESS:
- if (temp & SCSI_RESET_HOST_RESET)
- scsi_mark_host_reset(host);
- else if (temp & SCSI_RESET_BUS_RESET)
- scsi_mark_bus_reset(host, SCpnt->channel);
- else
- scsi_mark_device_reset(SCpnt->device);
- SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3);
- return 0;
- case SCSI_RESET_PENDING:
- if (temp & SCSI_RESET_HOST_RESET)
- scsi_mark_host_reset(host);
- else if (temp & SCSI_RESET_BUS_RESET)
- scsi_mark_bus_reset(host, SCpnt->channel);
- else
- scsi_mark_device_reset(SCpnt->device);
- case SCSI_RESET_NOT_RUNNING:
- return 0;
- case SCSI_RESET_PUNT:
- SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3);
- scsi_request_sense(SCpnt);
- return 0;
- case SCSI_RESET_WAKEUP:
- if (temp & SCSI_RESET_HOST_RESET)
- scsi_mark_host_reset(host);
- else if (temp & SCSI_RESET_BUS_RESET)
- scsi_mark_bus_reset(host, SCpnt->channel);
- else
- scsi_mark_device_reset(SCpnt->device);
- SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3);
- scsi_request_sense(SCpnt);
- /*
- * If a bus reset was performed, we
- * need to wake up each and every command
- * that was active on the bus or if it was a HBA
- * reset all active commands on all channels
- */
- if (temp & SCSI_RESET_HOST_RESET) {
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
- SCpnt1 = SDpnt->device_queue;
- while (SCpnt1) {
- if (SCpnt1->request.rq_status != RQ_INACTIVE
- && SCpnt1 != SCpnt)
- scsi_request_sense(SCpnt1);
- SCpnt1 = SCpnt1->next;
- }
- }
- } else if (temp & SCSI_RESET_BUS_RESET) {
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
- SCpnt1 = SDpnt->device_queue;
- while (SCpnt1) {
- if (SCpnt1->request.rq_status != RQ_INACTIVE
- && SCpnt1 != SCpnt
- && SCpnt1->channel == SCpnt->channel)
- scsi_request_sense(SCpnt);
- SCpnt1 = SCpnt1->next;
- }
- }
- }
- return 0;
- case SCSI_RESET_SNOOZE:
- /* In this case, we set the timeout field to 0
- * so that this command does not time out any more,
- * and we return 1 so that we get a message on the
- * screen.
- */
- SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3);
- update_timeout(SCpnt, 0);
- /* If you snooze, you lose... */
- case SCSI_RESET_ERROR:
- default:
- return 1;
- }
-
- return temp;
- }
- }
-}
-
-/*
- * The strategy is to cause the timer code to call scsi_times_out()
- * when the soonest timeout is pending.
- * The arguments are used when we are queueing a new command, because
- * we do not want to subtract the time used from this time, but when we
- * set the timer, we want to take this value into account.
- */
-
-int update_timeout(Scsi_Cmnd * SCset, int timeout)
-{
- int rtn;
-
- /*
- * We are using the new error handling code to actually register/deregister
- * timers for timeout.
- */
-
- if (!timer_pending(&SCset->eh_timeout)) {
- rtn = 0;
- } else {
- rtn = SCset->eh_timeout.expires - jiffies;
- }
-
- if (timeout == 0) {
- scsi_delete_timer(SCset);
- } else {
- scsi_add_timer(SCset, timeout, scsi_old_times_out);
- }
-
- return rtn;
-}
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
EXPORT_SYMBOL(scsi_release_command);
EXPORT_SYMBOL(print_Scsi_Cmnd);
EXPORT_SYMBOL(scsi_block_when_processing_errors);
-EXPORT_SYMBOL(scsi_mark_host_reset);
EXPORT_SYMBOL(scsi_ioctl_send_command);
#if defined(CONFIG_SCSI_LOGGING) /* { */
EXPORT_SYMBOL(scsi_logging_level);
case BLKELVSET:
case BLKBSZGET:
case BLKBSZSET:
- case BLKHASHPROF:
- case BLKHASHCLEAR:
return blk_ioctl(inode->i_rdev, cmd, arg);
case BLKRRPART: /* Re-read partition tables */
Sg_device * sdp;
Sg_fd * sfp;
- lock_kernel();
if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) {
- unlock_kernel();
return -ENXIO;
}
SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", MINOR(sdp->i_rdev)));
sdp->exclude = 0;
wake_up_interruptible(&sdp->o_excl_wait);
}
- unlock_kernel();
return 0;
}
sg_tablesize: 128, \
cmd_per_lun: 1, \
use_clustering: DISABLE_CLUSTERING, \
- use_new_eh_code: 1}
#ifndef HOSTS_C
}
if (old_sg) {
memcpy(sg + i, old_sg, SCpnt->use_sg * sizeof(struct scatterlist));
- memcpy(bbpnt + i, old_bbpnt, SCpnt->use_sg * sizeof(void *));
+ if (old_bbpnt)
+ memcpy(bbpnt + i, old_bbpnt, SCpnt->use_sg * sizeof(void *));
scsi_free(old_sg, (((SCpnt->use_sg * sizeof(struct scatterlist)) +
(SCpnt->use_sg * sizeof(void *))) + 511) & ~511);
} else {
- sg[i].address = SCpnt->request_buffer;
+ sg[i].address = NULL;
+ sg[i].page = virt_to_page(SCpnt->request_buffer);
+ sg[i].offset = (unsigned long) SCpnt->request_buffer&~PAGE_MASK;
sg[i].length = SCpnt->request_bufflen;
}
SCpnt->use_sg += i;
if (bsize) {
- sg[SCpnt->use_sg].address = back;
+ sg[SCpnt->use_sg].address = NULL;
+ sg[SCpnt->use_sg].page = virt_to_page(back);
+ sg[SCpnt->use_sg].offset = (unsigned long) back & ~PAGE_MASK;
bbpnt[SCpnt->use_sg] = back;
sg[SCpnt->use_sg].length = bsize;
SCpnt->use_sg++;
release: sym53c8xx_release, \
info: sym53c8xx_info, \
queuecommand: sym53c8xx_queue_command, \
- use_new_eh_code: 1, \
eh_abort_handler: sym53c8xx_eh_abort_handler, \
eh_device_reset_handler:sym53c8xx_eh_device_reset_handler, \
eh_bus_reset_handler: sym53c8xx_eh_bus_reset_handler, \
this_id: 7, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 1 /* Enable new error code */ \
}
#endif
cmd_per_lun: 1, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
- use_new_eh_code: 0 \
}
#endif
int board = GRAPHICS_CARD (inode->i_rdev);
/* Tell the rendering manager that one client is going away */
- lock_kernel();
rrm_close (inode, file);
/* Was this file handle from the board owner?, clear it */
(*cards [board].g_reset_console)();
enable_gconsole ();
}
- unlock_kernel();
return 0;
}
/* /dev/qcntlN attached memory regions, location and size of the event queue */
static struct {
- int opened; /* if this device has been opened */
- void *shmiq_vaddr; /* mapping in kernel-land */
- int tail; /* our copy of the shmiq->tail */
- int events;
- int mapped;
+ int opened;
+ void *shmiq_vaddr; /* mapping in kernel-land */
+ spinlock_t shmiq_lock:SPIN_LOCK_UNLOCKED;
+ /* protects vaddr and opened */
+ int tail; /* our copy of the shmiq->tail */
+ int events;
+ int mapped;
wait_queue_head_t proc_list;
struct fasync_struct *fasync;
size = vma->vm_end - vma->vm_start;
start = vma->vm_start;
- lock_kernel();
+ spin_lock( &shmiqs [minor].shmiq_lock );
mem = (unsigned long) shmiqs [minor].shmiq_vaddr = vmalloc_uncached (size);
if (!mem) {
- unlock_kernel();
+ spin_unlock( &shmiqs [minor].shmiq_lock );
return -EINVAL;
}
shmiqs [minor].tail = 0;
/* Init the shared memory input queue */
memset (shmiqs [minor].shmiq_vaddr, 0, size);
- unlock_kernel();
-
+ spin_unlock( &shmiqs [minor].shmiq_lock );
return error;
}
minor--;
if (minor > MAX_SHMI_QUEUES)
return -EINVAL;
+ spin_lock( &shmiqs [minor].shmiq_lock );
if (shmiqs [minor].opened)
+ {
+ spin_unlock( &shmiqs [minor].shmiq_lock );
return -EBUSY;
+ }
- lock_kernel ();
shmiqs [minor].opened = 1;
shmiqs [minor].shmiq_vaddr = 0;
- unlock_kernel ();
+ spin_unlock( &shmiqs [minor].shmiq_lock );
return 0;
}
if (minor > MAX_SHMI_QUEUES)
return -EINVAL;
+
+ spin_lock( &shmiqs [minor].shmiq_lock );
if (shmiqs [minor].opened == 0)
return -EINVAL;
- lock_kernel ();
shmiq_qcntl_fasync (-1, filp, 0);
- shmiqs [minor].opened = 0;
+ shmiqs [minor].opened = 0;
shmiqs [minor].mapped = 0;
shmiqs [minor].events = 0;
shmiqs [minor].fasync = 0;
vfree (shmiqs [minor].shmiq_vaddr);
shmiqs [minor].shmiq_vaddr = 0;
- unlock_kernel ();
+ spin_unlock( &shmiqs [minor].shmiq_lock );
return 0;
}
static int
sgi_mouse_close (struct inode *inode, struct file *filp)
{
- lock_kernel();
mouse_opened = 0;
- unlock_kernel();
return 0;
}
* Aki Laukkanen : added power management support
* Arnaldo C. de Melo : added missing restore_flags in ad1848_resume
* Miguel Freitas : added ISA PnP support
+ * Alan Cox : Added CS4236->4239 identification
+ * Daniel T. Cobra : Alernate config/mixer for later chips
+ * Alan Cox : Merged chip idents and config code
+ *
+ * TODO
+ * APM save restore assist code on IBM thinkpad
*
* Status:
* Tested. Believed fully functional.
int dual_dma; /* 1, when two DMA channels allocated */
int subtype;
unsigned char MCE_bit;
- unsigned char saved_regs[32];
+ unsigned char saved_regs[64]; /* Includes extended register space */
int debug_flag;
int audio_flags;
#define MD_IWAVE 7
#define MD_4235 8 /* Crystal Audio CS4235 */
#define MD_1845_SSCAPE 9 /* Ensoniq Soundscape PNP*/
+#define MD_4236 10 /* 4236 and higher */
+#define MD_42xB 11 /* CS 42xB */
+#define MD_4239 12 /* CS4239 */
/* Mixer parameters */
int recmask;
save_flags(flags);
cli();
- outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
- x = inb(io_Indexed_Data(devc));
-/* printk("(%02x<-%02x) ", reg|devc->MCE_bit, x); */
+
+ if(reg < 32)
+ {
+ outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+ x = inb(io_Indexed_Data(devc));
+ }
+ else
+ {
+ int xreg, xra;
+
+ xreg = (reg & 0xff) - 32;
+ xra = (((xreg & 0x0f) << 4) & 0xf0) | 0x08 | ((xreg & 0x10) >> 2);
+ outb(((unsigned char) (23 & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+ outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
+ x = inb(io_Indexed_Data(devc));
+ }
restore_flags(flags);
return x;
save_flags(flags);
cli();
- outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
- outb(((unsigned char) (data & 0xff)), io_Indexed_Data(devc));
- /* printk("(%02x->%02x) ", reg|devc->MCE_bit, data); */
+
+ if(reg < 32)
+ {
+ outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+ outb(((unsigned char) (data & 0xff)), io_Indexed_Data(devc));
+ }
+ else
+ {
+ int xreg, xra;
+
+ xreg = (reg & 0xff) - 32;
+ xra = (((xreg & 0x0f) << 4) & 0xf0) | 0x08 | ((xreg & 0x10) >> 2);
+ outb(((unsigned char) (23 & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+ outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
+ outb((unsigned char) (data & 0xff), io_Indexed_Data(devc));
+ }
restore_flags(flags);
}
devc->mix_devices = &(iwave_mix_devices[0]);
break;
+ case MD_42xB:
+ case MD_4239:
+ devc->mix_devices = &(cs42xb_mix_devices[0]);
+ devc->supported_devices = MODE3_MIXER_DEVICES;
+ break;
case MD_4232:
+ case MD_4236:
devc->supported_devices = MODE3_MIXER_DEVICES;
break;
}
old_fs = ad_read(devc, 8);
- if (devc->model == MD_4232)
+ if (devc->model == MD_4232 || devc->model >= MD_4236)
{
tmp = ad_read(devc, 16);
ad_write(devc, 16, tmp | 0x30);
while (timeout < 10000 && inb(devc->base) == 0x80)
timeout++;
- if (devc->model == MD_4232)
+ if (devc->model >= MD_4232)
ad_write(devc, 16, tmp & ~0x30);
ad_leave_MCE(devc); /*
static void ad1848_init_hw(ad1848_info * devc)
{
int i;
+ int *init_values;
/*
* Initial values for the indirect registers of CS4248/AD1848.
*/
- static int init_values[] =
+ static int init_values_a[] =
{
0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x0c, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+ static int init_values_b[] =
+ {
+ /*
+ Values for the newer chips
+ Some of the register initialization values were changed. In
+ order to get rid of the click that preceded PCM playback,
+ calibration was disabled on the 10th byte. On that same byte,
+ dual DMA was enabled; on the 11th byte, ADC dithering was
+ enabled, since that is theoretically desirable; on the 13th
+ byte, Mode 3 was selected, to enable access to extended
+ registers.
+ */
+ 0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0xe0, 0x01, 0x00, 0x00,
+ 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ /*
+ * Select initialisation data
+ */
+
+ init_values = init_values_a;
+ if(devc->model >= MD_4236)
+ init_values = init_values_b;
for (i = 0; i < 16; i++)
ad_write(devc, i, init_values[i]);
else
{
switch (id & 0x1f) {
- case 3: /* CS4236/CS4235 */
+ case 3: /* CS4236/CS4235/CS42xB/CS4239 */
{
int xid;
ad_write(devc, 12, ad_read(devc, 12) | 0x60); /* switch to mode 3 */
ad_write(devc, 23, 0x9c); /* select extended register 25 */
xid = inb(io_Indexed_Data(devc));
ad_write(devc, 12, ad_read(devc, 12) & ~0x60); /* back to mode 0 */
- if ((xid & 0x1f) == 0x1d) {
- devc->chip_name = "CS4235";
- devc->model = MD_4235;
- } else {
- devc->chip_name = "CS4236";
- devc->model = MD_4232;
+ switch (xid & 0x1f)
+ {
+ case 0x00:
+ devc->chip_name = "CS4237B(B)";
+ devc->model = MD_42xB;
+ break;
+ case 0x08:
+ /* Seems to be a 4238 ?? */
+ devc->chip_name = "CS4238";
+ devc->model = MD_42xB;
+ break;
+ case 0x09:
+ devc->chip_name = "CS4238B";
+ devc->model = MD_42xB;
+ break;
+ case 0x0b:
+ devc->chip_name = "CS4236B";
+ devc->model = MD_4236;
+ break;
+ case 0x10:
+ devc->chip_name = "CS4237B";
+ devc->model = MD_42xB;
+ break;
+ case 0x1d:
+ devc->chip_name = "CS4235";
+ devc->model = MD_4235;
+ break;
+ case 0x1e:
+ devc->chip_name = "CS4239";
+ devc->model = MD_4239;
+ break;
+ default:
+ printk("Chip ident is %X.\n", xid&0x1F);
+ devc->chip_name = "CS42xx";
+ devc->model = MD_4232;
+ break;
}
}
break;
save_flags(flags);
cli();
+
+ /* Thinkpad is a bit more of PITA than normal. The BIOS tends to
+ restore it in a different config to the one we use. Need to
+ fix this somehow */
/* store old mixer levels */
memcpy(mixer_levels, devc->levels, sizeof (mixer_levels));
SOUND_MASK_OGAIN)
struct mixer_def {
- unsigned int regno:5; /* register number for volume */
+ unsigned int regno:6; /* register number for volume */
unsigned int polarity:1; /* volume polarity: 0=normal, 1=reversed */
unsigned int bitpos:3; /* position of bits in register for volume */
unsigned int nbits:3; /* number of bits in register for volume */
- unsigned int mutereg:5; /* register number for mute bit */
+ unsigned int mutereg:6; /* register number for mute bit */
unsigned int mutepol:1; /* mute polarity: 0=normal, 1=reversed */
unsigned int mutepos:4; /* position of mute bit in register */
- unsigned int recreg:5; /* register number for recording bit */
+ unsigned int recreg:6; /* register number for recording bit */
unsigned int recpol:1; /* recording polarity: 0=normal, 1=reversed */
unsigned int recpos:4; /* position of recording bit in register */
};
rec_reg_r, rec_pola_r, rec_pos_r}}
static mixer_ents ad1848_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 8),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
-MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
-MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
+ MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
+ MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
+ MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
};
static mixer_ents iwave_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 25, 1, 0, 5, 27, 1, 0, 5, 8),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
-MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
-MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_IMIX, 16, 1, 0, 5, 17, 1, 0, 5, 8),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
+ MIX_ENT(SOUND_MIXER_VOLUME, 25, 1, 0, 5, 27, 1, 0, 5, 8),
+ MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
+ MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8),
+ MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_IMIX, 16, 1, 0, 5, 17, 1, 0, 5, 8),
+ MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7)
+};
+
+static mixer_ents cs42xb_mix_devices[32] = {
+ /* Digital master volume actually has seven bits, but we only use
+ six to avoid the discontinuity when the analog gain kicks in. */
+ MIX_ENT(SOUND_MIXER_VOLUME, 46, 1, 0, 6, 47, 1, 0, 6, 7),
+ MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7),
+ MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_MIC, 34, 1, 0, 5, 35, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ /* For the IMIX entry, it was not possible to use the MIX_ENT macro
+ because the mute bit is in different positions for the two
+ channels and requires reverse polarity. */
+ [SOUND_MIXER_IMIX] = {{13, 1, 2, 6, 13, 1, 0, 0, 0, 8},
+ {42, 1, 0, 6, 42, 1, 7, 0, 0, 8}},
+ MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE3, 38, 1, 0, 6, 39, 1, 0, 6, 7)
};
/* OPTi 82C930 has somewhat different port addresses.
* MIC is level of mic monitoring direct to output. Same for CD, LINE, etc.
*/
static mixer_ents c930_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5, 7),
-MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 5, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 5, 7, 1, 0, 5, 7),
-MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 1, 5, 23, 1, 1, 5, 7),
-MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_MIC, 20, 1, 1, 4, 21, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
-MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4, 7),
-MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4, 7)
+ MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5, 7),
+ MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 5, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 5, 7, 1, 0, 5, 7),
+ MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 1, 5, 23, 1, 1, 5, 7),
+ MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_MIC, 20, 1, 1, 4, 21, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8),
+ MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4, 7),
+ MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4, 7)
};
static mixer_ents spro_mix_devices[32] = {
-MIX_ENT (SOUND_MIXER_VOLUME, 19, 0, 4, 4, 19, 0, 0, 4, 8),
-MIX_ENT (SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT2(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 23, 0, 3, 0, 0, 8,
- 5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_PCM, 6, 1, 1, 4, 7, 1, 1, 4, 8),
-MIX_ENT (SOUND_MIXER_SPEAKER, 18, 0, 3, 2, 0, 0, 0, 0, 8),
-MIX_ENT2(SOUND_MIXER_LINE, 20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
- 20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
-MIX_ENT2(SOUND_MIXER_MIC, 18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
-MIX_ENT2(SOUND_MIXER_CD, 21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
- 21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
-MIX_ENT (SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_IGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_OGAIN, 17, 1, 6, 1, 0, 0, 0, 0, 8),
-/* This is external wavetable */
-MIX_ENT2(SOUND_MIXER_LINE1, 22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
- 22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
+ MIX_ENT (SOUND_MIXER_VOLUME, 19, 0, 4, 4, 19, 0, 0, 4, 8),
+ MIX_ENT (SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT2(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 23, 0, 3, 0, 0, 8,
+ 5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_PCM, 6, 1, 1, 4, 7, 1, 1, 4, 8),
+ MIX_ENT (SOUND_MIXER_SPEAKER, 18, 0, 3, 2, 0, 0, 0, 0, 8),
+ MIX_ENT2(SOUND_MIXER_LINE, 20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
+ 20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
+ MIX_ENT2(SOUND_MIXER_MIC, 18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ MIX_ENT2(SOUND_MIXER_CD, 21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
+ 21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
+ MIX_ENT (SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_IGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+ MIX_ENT (SOUND_MIXER_OGAIN, 17, 1, 6, 1, 0, 0, 0, 0, 8),
+ /* This is external wavetable */
+ MIX_ENT2(SOUND_MIXER_LINE1, 22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
+ 22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
};
static int default_mixer_levels[32] =
{
- 0x3232, /* Master Volume */
- 0x3232, /* Bass */
- 0x3232, /* Treble */
- 0x4b4b, /* FM */
- 0x3232, /* PCM */
- 0x1515, /* PC Speaker */
- 0x2020, /* Ext Line */
- 0x1010, /* Mic */
- 0x4b4b, /* CD */
- 0x0000, /* Recording monitor */
- 0x4b4b, /* Second PCM */
- 0x4b4b, /* Recording level */
- 0x4b4b, /* Input gain */
- 0x4b4b, /* Output gain */
- 0x2020, /* Line1 */
- 0x2020, /* Line2 */
- 0x1515 /* Line3 (usually line in)*/
+ 0x3232, /* Master Volume */
+ 0x3232, /* Bass */
+ 0x3232, /* Treble */
+ 0x4b4b, /* FM */
+ 0x3232, /* PCM */
+ 0x1515, /* PC Speaker */
+ 0x2020, /* Ext Line */
+ 0x1010, /* Mic */
+ 0x4b4b, /* CD */
+ 0x0000, /* Recording monitor */
+ 0x4b4b, /* Second PCM */
+ 0x4b4b, /* Recording level */
+ 0x4b4b, /* Input gain */
+ 0x4b4b, /* Output gain */
+ 0x2020, /* Line1 */
+ 0x2020, /* Line2 */
+ 0x1515 /* Line3 (usually line in)*/
};
#define LEFT_CHN 0
dbg("dabusb_release");
- lock_kernel();
down (&s->mutex);
dabusb_stop (s);
dabusb_free_buffers (s);
wake_up (&s->remove_ok);
s->opened = 0;
- unlock_kernel();
return 0;
}
struct hiddev_list *list = file->private_data;
struct hiddev_list **listptr;
- lock_kernel();
listptr = &list->hiddev->list;
hiddev_fasync(-1, file, 0);
}
kfree(list);
- unlock_kernel();
return 0;
}
present: 0,
unchecked_isa_dma: FALSE,
use_clustering: TRUE,
- use_new_eh_code: TRUE,
emulated: TRUE
};
present: 0,
unchecked_isa_dma: FALSE,
use_clustering: TRUE,
- use_new_eh_code: TRUE,
emulated: TRUE
};
present: 0,
unchecked_isa_dma: FALSE,
use_clustering: TRUE,
- use_new_eh_code: TRUE,
emulated: TRUE
};
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/fb.h>
-#include <linux/console_struct.h>
#include <linux/sched.h>
+#include <video/fbcon.h>
#undef DEBUG
}
}
-static int PROC_CONSOLE(const struct fb_info *info)
-{
- int fgc;
-
- if (info->display_fg != NULL)
- fgc = info->display_fg->vc_num;
- else
- return -1;
-
- if (!current->tty)
- return fgc;
-
- if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
- /* XXX Should report error here? */
- return fgc;
-
- if (MINOR(current->tty->device) < 1)
- return fgc;
-
- return MINOR(current->tty->device) - 1;
-}
-
-
/**
* __fb_try_mode - test a video mode
* @var: frame buffer user defined part of display
{
struct autofs_info *inf;
- lock_kernel();
-
DPRINTK(("autofs4_dentry_release: releasing %p\n", de));
inf = autofs4_dentry_ino(de);
autofs4_free_ino(inf);
}
-
- unlock_kernel();
}
/* For dentries of directories in the root dir */
static DECLARE_WAIT_QUEUE_HEAD(bio_pool_wait);
static DECLARE_WAIT_QUEUE_HEAD(biovec_pool_wait);
-struct bio_hash_bucket *bio_hash_table;
-unsigned int bio_hash_bits, bio_hash_mask;
-
static unsigned int bio_pool_free;
#define BIOVEC_NR_POOLS 6
#define BIO_MAX_PAGES (bvec_pool_sizes[BIOVEC_NR_POOLS - 1])
-#ifdef BIO_HASH_PROFILING
-static struct bio_hash_stats bio_stats;
-#endif
-
-/*
- * optimized for 2^BIO_HASH_SCALE kB block size
- */
-#define BIO_HASH_SCALE 3
-#define BIO_HASH_BLOCK(sector) ((sector) >> BIO_HASH_SCALE)
-
-/*
- * pending further testing, grabbed from fs/buffer.c hash so far...
- */
-#define __bio_hash(dev,block) \
- (((((dev)<<(bio_hash_bits - 6)) ^ ((dev)<<(bio_hash_bits - 9))) ^ \
- (((block)<<(bio_hash_bits - 6)) ^ ((block) >> 13) ^ \
- ((block) << (bio_hash_bits - 12)))) & bio_hash_mask)
-
-#define bio_hash(dev, sector) &((bio_hash_table + __bio_hash(dev, BIO_HASH_BLOCK((sector))))->hash)
-
-#define bio_hash_bucket(dev, sector) (bio_hash_table + __bio_hash(dev, BIO_HASH_BLOCK((sector))))
-
-#define __BIO_HASH_RWLOCK(dev, sector) \
- &((bio_hash_table + __bio_hash((dev), BIO_HASH_BLOCK((sector))))->lock)
-#define BIO_HASH_RWLOCK(bio) \
- __BIO_HASH_RWLOCK((bio)->bi_dev, (bio)->bi_sector)
-
/*
* TODO: change this to use slab reservation scheme once that infrastructure
* is in place...
*/
#define BIO_POOL_SIZE (256)
-void __init bio_hash_init(unsigned long mempages)
-{
- unsigned long htable_size, order;
- int i;
-
- /*
- * need to experiment on size of hash
- */
- mempages >>= 2;
-
- htable_size = mempages * sizeof(struct bio_hash_bucket *);
- for (order = 0; (PAGE_SIZE << order) < htable_size; order++)
- ;
-
- do {
- unsigned long tmp = (PAGE_SIZE << order) / sizeof(struct bio_hash_bucket);
-
- bio_hash_bits = 0;
- while ((tmp >>= 1UL) != 0UL)
- bio_hash_bits++;
-
- bio_hash_table = (struct bio_hash_bucket *) __get_free_pages(GFP_ATOMIC, order);
- } while (bio_hash_table == NULL && --order > 0);
-
- if (!bio_hash_table)
- panic("Failed to allocate page hash table\n");
-
- printk("Bio-cache hash table entries: %ld (order: %ld, %ld bytes)\n",
- BIO_HASH_SIZE, order, (PAGE_SIZE << order));
-
- for (i = 0; i < BIO_HASH_SIZE; i++) {
- struct bio_hash_bucket *hb = &bio_hash_table[i];
-
- rwlock_init(&hb->lock);
- hb->hash = NULL;
- }
-
- bio_hash_mask = BIO_HASH_SIZE - 1;
-}
-
-inline void __bio_hash_remove(struct bio *bio)
-{
- bio_hash_t *entry = &bio->bi_hash;
- bio_hash_t **pprev = entry->pprev_hash;
-
- if (pprev) {
- bio_hash_t *nxt = entry->next_hash;
-
- if (nxt)
- nxt->pprev_hash = pprev;
-
- *pprev = nxt;
-#if 1
- entry->next_hash = NULL;
-#endif
- entry->pprev_hash = NULL;
- entry->valid_counter = 0;
- bio->bi_hash_desc = NULL;
-#ifdef BIO_HASH_PROFILING
- atomic_dec(&bio_stats.nr_entries);
-#endif
- }
-}
-
-inline void bio_hash_remove(struct bio *bio)
-{
- rwlock_t *hash_lock = BIO_HASH_RWLOCK(bio);
- unsigned long flags;
-
- write_lock_irqsave(hash_lock, flags);
- __bio_hash_remove(bio);
- write_unlock_irqrestore(hash_lock, flags);
-}
-
-inline void __bio_hash_add(struct bio *bio, bio_hash_t **hash,
- void *hash_desc, unsigned int vc)
-{
- bio_hash_t *entry = &bio->bi_hash;
- bio_hash_t *nxt = *hash;
-
- BUG_ON(entry->pprev_hash);
-
- *hash = entry;
- entry->next_hash = nxt;
- entry->pprev_hash = hash;
- entry->valid_counter = vc;
-
- if (nxt)
- nxt->pprev_hash = &entry->next_hash;
-
- bio->bi_hash_desc = hash_desc;
-
-#ifdef BIO_HASH_PROFILING
- atomic_inc(&bio_stats.nr_inserts);
- atomic_inc(&bio_stats.nr_entries);
- {
- int entries = atomic_read(&bio_stats.nr_entries);
- if (entries > atomic_read(&bio_stats.max_entries))
- atomic_set(&bio_stats.max_entries, entries);
- }
-#endif
-}
-
-inline void bio_hash_add(struct bio *bio, void *hash_desc, unsigned int vc)
-{
- struct bio_hash_bucket *hb =bio_hash_bucket(bio->bi_dev,bio->bi_sector);
- unsigned long flags;
-
- write_lock_irqsave(&hb->lock, flags);
- __bio_hash_add(bio, &hb->hash, hash_desc, vc);
- write_unlock_irqrestore(&hb->lock, flags);
-}
-
-inline struct bio *__bio_hash_find(kdev_t dev, sector_t sector,
- bio_hash_t **hash, unsigned int vc)
-{
- bio_hash_t *next = *hash, *entry;
- struct bio *bio;
- int nr = 0;
-
-#ifdef BIO_HASH_PROFILING
- atomic_inc(&bio_stats.nr_lookups);
-#endif
- while ((entry = next)) {
- next = entry->next_hash;
- prefetch(next);
- bio = bio_hash_entry(entry);
-
- if (entry->valid_counter == vc) {
- if (bio->bi_sector == sector && bio->bi_dev == dev) {
-#ifdef BIO_HASH_PROFILING
- if (nr > atomic_read(&bio_stats.max_bucket_size))
- atomic_set(&bio_stats.max_bucket_size, nr);
- if (nr <= MAX_PROFILE_BUCKETS)
- atomic_inc(&bio_stats.bucket_size[nr]);
- atomic_inc(&bio_stats.nr_hits);
-#endif
- bio_get(bio);
- return bio;
- }
- }
- nr++;
- }
-
- return NULL;
-}
-
-inline struct bio *bio_hash_find(kdev_t dev, sector_t sector, unsigned int vc)
-{
- struct bio_hash_bucket *hb = bio_hash_bucket(dev, sector);
- unsigned long flags;
- struct bio *bio;
-
- read_lock_irqsave(&hb->lock, flags);
- bio = __bio_hash_find(dev, sector, &hb->hash, vc);
- read_unlock_irqrestore(&hb->lock, flags);
-
- return bio;
-}
-
-inline int __bio_hash_add_unique(struct bio *bio, bio_hash_t **hash,
- void *hash_desc, unsigned int vc)
-{
- struct bio *alias = __bio_hash_find(bio->bi_dev, bio->bi_sector, hash, vc);
-
- if (!alias) {
- __bio_hash_add(bio, hash, hash_desc, vc);
- return 0;
- }
-
- /*
- * release reference to alias
- */
- bio_put(alias);
- return 1;
-}
-
-inline int bio_hash_add_unique(struct bio *bio, void *hash_desc, unsigned int vc)
-{
- struct bio_hash_bucket *hb =bio_hash_bucket(bio->bi_dev,bio->bi_sector);
- unsigned long flags;
- int ret = 1;
-
- if (!bio->bi_hash.pprev_hash) {
- write_lock_irqsave(&hb->lock, flags);
- ret = __bio_hash_add_unique(bio, &hb->hash, hash_desc, vc);
- write_unlock_irqrestore(&hb->lock, flags);
- }
-
- return ret;
-}
-
-/*
- * increment validity counter on barrier inserts. if it wraps, we must
- * prune all existing entries for this device to be completely safe
- *
- * q->queue_lock must be held by caller
- */
-void bio_hash_invalidate(request_queue_t *q, kdev_t dev)
-{
- bio_hash_t *hash;
- struct bio *bio;
- int i;
-
- if (++q->hash_valid_counter)
- return;
-
- /*
- * it wrapped...
- */
- for (i = 0; i < (1 << bio_hash_bits); i++) {
- struct bio_hash_bucket *hb = &bio_hash_table[i];
- unsigned long flags;
-
- write_lock_irqsave(&hb->lock, flags);
- while ((hash = hb->hash) != NULL) {
- bio = bio_hash_entry(hash);
- if (bio->bi_dev != dev)
- __bio_hash_remove(bio);
- }
- write_unlock_irqrestore(&hb->lock, flags);
- }
-
- /*
- * entries pruned, reset validity counter
- */
- q->hash_valid_counter = 1;
-}
-
-
/*
* if need be, add bio_pool_get_irq() to match...
*/
#define BIO_CAN_WAIT(gfp_mask) \
(((gfp_mask) & (__GFP_WAIT | __GFP_IO)) == (__GFP_WAIT | __GFP_IO))
-static inline struct bio_vec_list *bvec_alloc(int gfp_mask, int nr)
+static inline struct bio_vec *bvec_alloc(int gfp_mask, int nr, int *idx)
{
- struct bio_vec_list *bvl = NULL;
+ struct bio_vec *bvl = NULL;
struct biovec_pool *bp;
- int idx;
/*
* see comment near bvec_pool_sizes define!
*/
switch (nr) {
case 1:
- idx = 0;
+ *idx = 0;
break;
case 2 ... 4:
- idx = 1;
+ *idx = 1;
break;
case 5 ... 16:
- idx = 2;
+ *idx = 2;
break;
case 17 ... 64:
- idx = 3;
+ *idx = 3;
break;
case 65 ... 128:
- idx = 4;
+ *idx = 4;
break;
case 129 ... 256:
- idx = 5;
+ *idx = 5;
break;
default:
return NULL;
}
- bp = &bvec_list[idx];
+ bp = &bvec_list[*idx];
/*
* ok, so idx now points to the slab we want to allocate from
__set_current_state(TASK_RUNNING);
}
- /*
- * we use bvl_max as index into bvec_pool_sizes, non-slab originated
- * bvecs may use it for something else if they use their own
- * destructor
- */
if (bvl) {
out_gotit:
memset(bvl, 0, bp->bp_size);
- bvl->bvl_max = idx;
}
return bvl;
*/
void bio_destructor(struct bio *bio)
{
- struct biovec_pool *bp = &bvec_list[bio->bi_io_vec->bvl_max];
+ struct biovec_pool *bp = &bvec_list[bio->bi_max];
- BUG_ON(bio->bi_io_vec->bvl_max >= BIOVEC_NR_POOLS);
+ BUG_ON(bio->bi_max >= BIOVEC_NR_POOLS);
/*
* cloned bio doesn't own the veclist
bio_pool_put(bio);
}
+inline void bio_init(struct bio *bio)
+{
+ bio->bi_next = NULL;
+ atomic_set(&bio->bi_cnt, 1);
+ bio->bi_flags = 0;
+ bio->bi_rw = 0;
+ bio->bi_end_io = NULL;
+}
+
static inline struct bio *__bio_alloc(int gfp_mask, bio_destructor_t *dest)
{
struct bio *bio;
if (bio) {
gotit:
- bio->bi_next = NULL;
- bio->bi_hash.pprev_hash = NULL;
- atomic_set(&bio->bi_cnt, 1);
+ bio_init(bio);
bio->bi_io_vec = NULL;
- bio->bi_flags = 0;
- bio->bi_rw = 0;
- bio->bi_end_io = NULL;
- bio->bi_hash_desc = NULL;
bio->bi_destructor = dest;
}
struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
{
struct bio *bio = __bio_alloc(gfp_mask, bio_destructor);
- struct bio_vec_list *bvl = NULL;
+ struct bio_vec *bvl = NULL;
if (unlikely(!bio))
return NULL;
- if (!nr_iovecs || (bvl = bvec_alloc(gfp_mask, nr_iovecs))) {
+ if (!nr_iovecs || (bvl = bvec_alloc(gfp_mask,nr_iovecs,&bio->bi_max))) {
bio->bi_io_vec = bvl;
return bio;
}
*/
static inline void bio_free(struct bio *bio)
{
- BUG_ON(bio_is_hashed(bio));
-
bio->bi_destructor(bio);
}
b->bi_dev = bio->bi_dev;
b->bi_flags |= 1 << BIO_CLONED;
b->bi_rw = bio->bi_rw;
+
+ b->bi_vcnt = bio->bi_vcnt;
+ b->bi_idx = bio->bi_idx;
+ b->bi_size = bio->bi_size;
+ b->bi_max = bio->bi_max;
}
return b;
* bio_copy - create copy of a bio
* @bio: bio to copy
* @gfp_mask: allocation priority
+ * @copy: copy data to allocated bio
*
* Create a copy of a &bio. Caller will own the returned bio and
* the actual data it points to. Reference count of returned
* bio will be one.
*/
-struct bio *bio_copy(struct bio *bio, int gfp_mask)
+struct bio *bio_copy(struct bio *bio, int gfp_mask, int copy)
{
- struct bio *b = bio_alloc(gfp_mask, bio->bi_io_vec->bvl_cnt);
+ struct bio *b = bio_alloc(gfp_mask, bio->bi_vcnt);
unsigned long flags = 0; /* gcc silly */
int i;
* iterate iovec list and alloc pages + copy data
*/
bio_for_each_segment(bv, bio, i) {
- struct bio_vec *bbv = &b->bi_io_vec->bvl_vec[i];
+ struct bio_vec *bbv = &b->bi_io_vec[i];
char *vfrom, *vto;
bbv->bv_page = alloc_page(gfp_mask);
if (bbv->bv_page == NULL)
goto oom;
+ if (!copy)
+ goto fill_in;
+
if (gfp_mask & __GFP_WAIT) {
vfrom = kmap(bv->bv_page);
- vto = kmap(bv->bv_page);
+ vto = kmap(bbv->bv_page);
} else {
__save_flags(flags);
__cli();
vfrom = kmap_atomic(bv->bv_page, KM_BIO_IRQ);
- vto = kmap_atomic(bv->bv_page, KM_BIO_IRQ);
+ vto = kmap_atomic(bbv->bv_page, KM_BIO_IRQ);
}
- memcpy(vto + bv->bv_offset, vfrom + bv->bv_offset, bv->bv_len);
+ memcpy(vto + bbv->bv_offset, vfrom + bv->bv_offset, bv->bv_len);
if (gfp_mask & __GFP_WAIT) {
- kunmap(vto);
- kunmap(vfrom);
+ kunmap(bbv->bv_page);
+ kunmap(bv->bv_page);
} else {
kunmap_atomic(vto, KM_BIO_IRQ);
kunmap_atomic(vfrom, KM_BIO_IRQ);
__restore_flags(flags);
}
+fill_in:
bbv->bv_len = bv->bv_len;
bbv->bv_offset = bv->bv_offset;
}
b->bi_dev = bio->bi_dev;
b->bi_rw = bio->bi_rw;
- b->bi_io_vec->bvl_cnt = bio->bi_io_vec->bvl_cnt;
- b->bi_io_vec->bvl_size = bio->bi_io_vec->bvl_size;
+ b->bi_vcnt = bio->bi_vcnt;
+ b->bi_size = bio->bi_size;
}
return b;
oom:
while (i >= 0) {
- __free_page(b->bi_io_vec->bvl_vec[i].bv_page);
+ __free_page(b->bi_io_vec[i].bv_page);
i--;
}
static int bio_end_io_kio(struct bio *bio, int nr_sectors)
{
struct kiobuf *kio = (struct kiobuf *) bio->bi_private;
- struct bio_vec_list *bv = bio->bi_io_vec;
int uptodate, done;
- BUG_ON(!bv);
-
done = 0;
uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
do {
- int sectors = bv->bvl_vec[bv->bvl_idx].bv_len >> 9;
+ int sectors = bio->bi_io_vec[bio->bi_idx].bv_len >> 9;
nr_sectors -= sectors;
- bv->bvl_idx++;
+ bio->bi_idx++;
done = !end_kio_request(kio, uptodate);
- if (bv->bvl_idx == bv->bvl_cnt)
+ if (bio->bi_idx == bio->bi_vcnt)
done = 1;
} while (!done && nr_sectors > 0);
* all done
*/
if (done) {
- bio_hash_remove(bio);
bio_put(bio);
return 0;
}
bio->bi_sector = sector;
bio->bi_dev = dev;
- bio->bi_io_vec->bvl_idx = 0;
+ bio->bi_idx = 0;
bio->bi_flags |= 1 << BIO_PREBUILT;
bio->bi_end_io = bio_end_io_kio;
bio->bi_private = kio;
- bvec = &bio->bi_io_vec->bvl_vec[0];
+ bvec = bio->bi_io_vec;
for (i = 0; i < nr_pages; i++, bvec++, map_i++) {
int nbytes = PAGE_SIZE - offset;
BUG_ON(kio->maplist[map_i] == NULL);
- if (bio->bi_io_vec->bvl_size + nbytes > max_bytes)
+ if (bio->bi_size + nbytes > max_bytes)
goto queue_io;
- bio->bi_io_vec->bvl_cnt++;
- bio->bi_io_vec->bvl_size += nbytes;
+ bio->bi_vcnt++;
+ bio->bi_size += nbytes;
bvec->bv_page = kio->maplist[map_i];
bvec->bv_len = nbytes;
struct biovec_pool *bp = &bvec_list[i];
size = bvec_pool_sizes[i] * sizeof(struct bio_vec);
- size += sizeof(struct bio_vec_list);
printk("biovec: init pool %d, %d entries, %d bytes\n", i,
bvec_pool_sizes[i], size);
biovec_init_pool();
-#ifdef BIO_HASH_PROFILING
- memset(&bio_stats, 0, sizeof(bio_stats));
-#endif
-
- return 0;
-}
-
-int bio_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
-{
-#ifdef BIO_HASH_PROFILING
- switch (cmd) {
- case BLKHASHPROF:
- if (copy_to_user((struct bio_hash_stats *) arg, &bio_stats, sizeof(bio_stats)))
- return -EFAULT;
- break;
- case BLKHASHCLEAR:
- memset(&bio_stats, 0, sizeof(bio_stats));
- break;
- default:
- return -ENOTTY;
- }
-
-#endif
return 0;
}
EXPORT_SYMBOL(bio_alloc);
EXPORT_SYMBOL(bio_put);
EXPORT_SYMBOL(ll_rw_kio);
-EXPORT_SYMBOL(bio_hash_remove);
-EXPORT_SYMBOL(bio_hash_add);
-EXPORT_SYMBOL(bio_hash_add_unique);
EXPORT_SYMBOL(bio_endio);
+EXPORT_SYMBOL(bio_init);
+EXPORT_SYMBOL(bio_copy);
+EXPORT_SYMBOL(bio_clone);
flush_failed:
spin_lock_irq(¤t->sigmask_lock);
if (current->sig != oldsig) {
- kfree(current->sig);
+ kmem_cache_free(sigact_cachep, current->sig);
current->sig = oldsig;
}
spin_unlock_irq(¤t->sigmask_lock);
return 0;
}
-static int minix_get_block(struct inode *inode, long block,
+static int minix_get_block(struct inode *inode, sector_t block,
struct buffer_head *bh_result, int create)
{
if (INODE_VERSION(inode) == MINIX_V1)
extern int get_partition_list(char *, char **, off_t, int);
extern int get_filesystem_list(char *);
extern int get_exec_domain_list(char *);
-extern int get_irq_list(char *);
extern int get_dma_list(char *);
extern int get_locks_status (char *, char **, off_t, int);
extern int get_swaparea_info (char *);
* display in kilobytes.
*/
#define K(x) ((x) << (PAGE_SHIFT - 10))
-#define B(x) ((unsigned long long)(x) << PAGE_SHIFT)
si_meminfo(&i);
si_swapinfo(&i);
pg_size = atomic_read(&page_cache_size) - i.bufferram ;
- len = sprintf(page, " total: used: free: shared: buffers: cached:\n"
- "Mem: %8Lu %8Lu %8Lu %8Lu %8Lu %8Lu\n"
- "Swap: %8Lu %8Lu %8Lu\n",
- B(i.totalram), B(i.totalram-i.freeram), B(i.freeram),
- B(i.sharedram), B(i.bufferram),
- B(pg_size), B(i.totalswap),
- B(i.totalswap-i.freeswap), B(i.freeswap));
/*
* Tagged format, for easy grepping and expansion.
- * The above will go away eventually, once the tools
- * have been updated.
*/
- len += sprintf(page+len,
+ len = sprintf(page,
"MemTotal: %8lu kB\n"
"MemFree: %8lu kB\n"
"MemShared: %8lu kB\n"
K(i.freeswap));
return proc_calc_metrics(page, start, off, count, eof, len);
-#undef B
#undef K
}
return len;
}
-#if !defined(CONFIG_ARCH_S390)
-static int interrupts_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static void *single_start(struct seq_file *p, loff_t *pos)
{
- int len = get_irq_list(page);
- return proc_calc_metrics(page, start, off, count, eof, len);
+ return (void *)(*pos == 0);
}
-#endif
+static void *single_next(struct seq_file *p, void *v, loff_t *pos)
+{
+ ++*pos;
+ return NULL;
+}
+static void single_stop(struct seq_file *p, void *v)
+{
+}
+extern int show_interrupts(struct seq_file *p, void *v);
+static struct seq_operations proc_interrupts_op = {
+ start: single_start,
+ next: single_next,
+ stop: single_stop,
+ show: show_interrupts,
+};
+static int interrupts_open(struct inode *inode, struct file *file)
+{
+ unsigned size = PAGE_SIZE;
+ /*
+ * probably should depend on NR_CPUS, but that's only rough estimate;
+ * if we'll need more it will be given,
+ */
+ char *buf = kmalloc(size, GFP_KERNEL);
+ struct seq_file *m;
+ int res;
+
+ if (!buf)
+ return -ENOMEM;
+ res = seq_open(file, &proc_interrupts_op);
+ if (!res) {
+ m = file->private_data;
+ m->buf = buf;
+ m->size = size;
+ } else
+ kfree(buf);
+ return res;
+}
+static struct file_operations proc_interrupts_operations = {
+ open: interrupts_open,
+ read: seq_read,
+ llseek: seq_lseek,
+ release: seq_release,
+};
static int filesystems_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{"stat", kstat_read_proc},
{"devices", devices_read_proc},
{"partitions", partitions_read_proc},
-#if !defined(CONFIG_ARCH_S390)
- {"interrupts", interrupts_read_proc},
-#endif
{"filesystems", filesystems_read_proc},
{"dma", dma_read_proc},
{"ioports", ioports_read_proc},
entry->proc_fops = &proc_kmsg_operations;
create_seq_entry("mounts", 0, &proc_mounts_operations);
create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
+#if defined(CONFIG_ARCH_S390) || defined(CONFIG_X86) || defined(CONFIG_ARCH_MIPS)
+ create_seq_entry("interrupts", 0, &proc_interrupts_operations);
+#endif
#ifdef CONFIG_MODULES
create_seq_entry("ksyms", 0, &proc_ksyms_operations);
#endif
return fs;
}
+/**
+ * alloc_super - create new superblock
+ *
+ * Allocates and initializes a new &struct super_block. alloc_super()
+ * returns a pointer new superblock or %NULL if allocation had failed.
+ */
+static struct super_block *alloc_super(void)
+{
+ struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER);
+ if (s) {
+ memset(s, 0, sizeof(struct super_block));
+ INIT_LIST_HEAD(&s->s_dirty);
+ INIT_LIST_HEAD(&s->s_locked_inodes);
+ INIT_LIST_HEAD(&s->s_files);
+ INIT_LIST_HEAD(&s->s_instances);
+ init_rwsem(&s->s_umount);
+ sema_init(&s->s_lock, 1);
+ down_write(&s->s_umount);
+ s->s_count = S_BIAS;
+ atomic_set(&s->s_active, 1);
+ sema_init(&s->s_vfs_rename_sem,1);
+ sema_init(&s->s_nfsd_free_path_sem,1);
+ sema_init(&s->s_dquot.dqio_sem, 1);
+ sema_init(&s->s_dquot.dqoff_sem, 1);
+ s->s_maxbytes = MAX_NON_LFS;
+ }
+ return s;
+}
+
+/**
+ * destroy_super - frees a superblock
+ * @s: superblock to free
+ *
+ * Frees a superblock.
+ */
+static inline void destroy_super(struct super_block *s)
+{
+ kfree(s);
+}
+
+/* Superblock refcounting */
+
+/**
+ * deactivate_super - turn an active reference into temporary
+ * @s: superblock to deactivate
+ *
+ * Turns an active reference into temporary one. Returns 0 if there are
+ * other active references, 1 if we had deactivated the last one.
+ */
+static inline int deactivate_super(struct super_block *s)
+{
+ if (!atomic_dec_and_lock(&s->s_active, &sb_lock))
+ return 0;
+ s->s_count -= S_BIAS-1;
+ spin_unlock(&sb_lock);
+ return 1;
+}
+
+/**
+ * put_super - drop a temporary reference to superblock
+ * @s: superblock in question
+ *
+ * Drops a temporary reference, frees superblock if there's no
+ * references left.
+ */
+static inline void put_super(struct super_block *s)
+{
+ spin_lock(&sb_lock);
+ if (!--s->s_count)
+ destroy_super(s);
+ spin_unlock(&sb_lock);
+}
+
+/**
+ * grab_super - acquire an active reference
+ * @s - reference we are trying to make active
+ *
+ * Tries to acquire an active reference. grab_super() is used when we
+ * had just found a superblock in super_blocks or fs_type->fs_supers
+ * and want to turn it into a full-blown active reference. grab_super()
+ * is called with sb_lock held and drops it. Returns 1 in case of
+ * success, 0 if we had failed (superblock contents was already dead or
+ * dying when grab_super() had been called).
+ */
+static int grab_super(struct super_block *s)
+{
+ s->s_count++;
+ spin_unlock(&sb_lock);
+ down_write(&s->s_umount);
+ if (s->s_root) {
+ spin_lock(&sb_lock);
+ if (s->s_count > S_BIAS) {
+ atomic_inc(&s->s_active);
+ s->s_count--;
+ spin_unlock(&sb_lock);
+ return 1;
+ }
+ spin_unlock(&sb_lock);
+ }
+ up_write(&s->s_umount);
+ put_super(s);
+ return 0;
+}
+
struct vfsmount *alloc_vfsmnt(void);
void free_vfsmnt(struct vfsmount *mnt);
void set_devname(struct vfsmount *mnt, const char *name);
extern struct vfsmount *root_vfsmnt;
extern int graft_tree(struct vfsmount *mnt, struct nameidata *nd);
-static inline void __put_super(struct super_block *sb)
-{
- spin_lock(&sb_lock);
- if (!--sb->s_count)
- kfree(sb);
- spin_unlock(&sb_lock);
-}
-
static inline struct super_block * find_super(kdev_t dev)
{
struct list_head *p;
void drop_super(struct super_block *sb)
{
up_read(&sb->s_umount);
- __put_super(sb);
-}
-
-static void put_super(struct super_block *sb)
-{
- atomic_dec(&sb->s_active);
- up_write(&sb->s_umount);
- __put_super(sb);
+ put_super(sb);
}
static inline void write_super(struct super_block *sb)
sb->s_op->write_super(sb);
unlock_super(sb);
}
-
+
/*
* Note: check the dirty flag before waiting, so we don't
* hold up the sync while mounting a device. (The newly
if (!dev)
return NULL;
-restart:
- spin_lock(&sb_lock);
- s = find_super(dev);
- if (s) {
+
+ while (1) {
+ spin_lock(&sb_lock);
+ s = find_super(dev);
spin_unlock(&sb_lock);
+ if (!s)
+ break;
down_read(&s->s_umount);
if (s->s_root)
- return s;
+ break;
drop_super(s);
- goto restart;
}
- spin_unlock(&sb_lock);
- return NULL;
+ return s;
}
asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf)
return err;
}
-/**
- * get_empty_super - find empty superblocks
- *
- * Find a superblock with no device assigned. A free superblock is
- * found and returned. If neccessary new superblocks are allocated.
- * %NULL is returned if there are insufficient resources to complete
- * the request.
- */
-
-static struct super_block *alloc_super(void)
-{
- struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER);
- if (s) {
- memset(s, 0, sizeof(struct super_block));
- INIT_LIST_HEAD(&s->s_dirty);
- INIT_LIST_HEAD(&s->s_locked_inodes);
- INIT_LIST_HEAD(&s->s_files);
- INIT_LIST_HEAD(&s->s_instances);
- init_rwsem(&s->s_umount);
- sema_init(&s->s_lock, 1);
- s->s_count = 1;
- atomic_set(&s->s_active, 1);
- sema_init(&s->s_vfs_rename_sem,1);
- sema_init(&s->s_nfsd_free_path_sem,1);
- sema_init(&s->s_dquot.dqio_sem, 1);
- sema_init(&s->s_dquot.dqoff_sem, 1);
- s->s_maxbytes = MAX_NON_LFS;
- }
- return s;
-}
-
static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
struct file_system_type *type, int flags,
void *data)
spin_lock(&sb_lock);
list_add (&s->s_list, super_blocks.prev);
list_add (&s->s_instances, &type->fs_supers);
- s->s_count += S_BIAS;
spin_unlock(&sb_lock);
- down_write(&s->s_umount);
lock_super(s);
if (!type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
goto out_fail;
s->s_bdev = 0;
s->s_type = NULL;
unlock_super(s);
+ deactivate_super(s);
spin_lock(&sb_lock);
list_del(&s->s_list);
list_del(&s->s_instances);
- s->s_count -= S_BIAS;
spin_unlock(&sb_lock);
+ up_write(&s->s_umount);
put_super(s);
return NULL;
}
kdevname(dev));
}
-static int grab_super(struct super_block *sb)
-{
- sb->s_count++;
- atomic_inc(&sb->s_active);
- spin_unlock(&sb_lock);
- down_write(&sb->s_umount);
- if (sb->s_root) {
- spin_lock(&sb_lock);
- if (sb->s_count > S_BIAS) {
- sb->s_count--;
- spin_unlock(&sb_lock);
- return 1;
- }
- spin_unlock(&sb_lock);
- }
- put_super(sb);
- return 0;
-}
-
static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
char *dev_name, int flags, void * data)
{
s = alloc_super();
if (!s)
goto out1;
- down_write(&s->s_umount);
error = -EBUSY;
restart:
if (old->s_type != fs_type ||
((flags ^ old->s_flags) & MS_RDONLY)) {
spin_unlock(&sb_lock);
- put_super(s);
+ destroy_super(s);
goto out1;
}
if (!grab_super(old))
goto restart;
- put_super(s);
+ destroy_super(s);
blkdev_put(bdev, BDEV_FS);
path_release(&nd);
return old;
s->s_type = fs_type;
list_add (&s->s_list, super_blocks.prev);
list_add (&s->s_instances, &fs_type->fs_supers);
- s->s_count += S_BIAS;
-
spin_unlock(&sb_lock);
error = -EINVAL;
s->s_bdev = 0;
s->s_type = NULL;
unlock_super(s);
+ deactivate_super(s);
spin_lock(&sb_lock);
list_del(&s->s_list);
list_del(&s->s_instances);
- s->s_count -= S_BIAS;
spin_unlock(&sb_lock);
+ up_write(&s->s_umount);
put_super(s);
out1:
blkdev_put(bdev, BDEV_FS);
struct super_block * s = alloc_super();
if (!s)
return ERR_PTR(-ENOMEM);
- down_write(&s->s_umount);
/*
* Get the superblock of kernel-wide instance, but
* keep the reference to fs_type.
s_instances);
if (!grab_super(old))
goto retry;
- put_super(s);
+ destroy_super(s);
do_remount_sb(old, flags, data);
return old;
} else {
kdev_t dev = get_unnamed_dev();
if (!dev) {
spin_unlock(&sb_lock);
- put_super(s);
+ destroy_super(s);
return ERR_PTR(-EMFILE);
}
s->s_dev = dev;
s->s_type = fs_type;
list_add (&s->s_list, super_blocks.prev);
list_add (&s->s_instances, &fs_type->fs_supers);
- s->s_count += S_BIAS;
spin_unlock(&sb_lock);
lock_super(s);
if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
s->s_bdev = 0;
s->s_type = NULL;
unlock_super(s);
+ deactivate_super(s);
spin_lock(&sb_lock);
list_del(&s->s_list);
list_del(&s->s_instances);
- s->s_count -= S_BIAS;
spin_unlock(&sb_lock);
+ up_write(&s->s_umount);
put_super(s);
put_unnamed_dev(dev);
return ERR_PTR(-EINVAL);
struct file_system_type *fs = sb->s_type;
struct super_operations *sop = sb->s_op;
- if (!atomic_dec_and_lock(&sb->s_active, &sb_lock))
+ if (!deactivate_super(sb))
return;
- sb->s_count -= S_BIAS;
- spin_unlock(&sb_lock);
-
down_write(&sb->s_umount);
lock_kernel();
sb->s_root = NULL;
list_del(&sb->s_list);
list_del(&sb->s_instances);
spin_unlock(&sb_lock);
- atomic_inc(&sb->s_active);
+ up_write(&sb->s_umount);
put_super(sb);
}
extern void (*init_arch_irq)(void);
extern int setup_arm_irq(int, struct irqaction *);
-extern int get_fiq_list(char *);
+extern int show_fiq_list(struct seq_file *, void *);
extern void init_FIQ(void);
#endif
/*
* Note: when you get a NULL pointer exception here this means someone
- * passed in an incorrect kernel address to one of these functions.
- *
- * If you use these functions directly please don't forget the
+ * passed in an incorrect kernel address to one of these functions.
+ *
+ * If you use these functions directly please don't forget the
* verify_area().
*/
static __inline__
* Arnt Gulbrandsen.
*/
static inline unsigned short ip_fast_csum(unsigned char * iph,
- unsigned int ihl) {
+ unsigned int ihl)
+{
unsigned int sum;
__asm__ __volatile__(
);
return (~sum) >> 16;
}
-
+
static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ unsigned int sum)
{
__asm__(
"addl %1, %0 ;\n"
unsigned long daddr,
unsigned short len,
unsigned short proto,
- unsigned int sum)
+ unsigned int sum)
{
return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
}
* in icmp.c
*/
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
return csum_fold (csum_partial(buff, len, 0));
}
struct in6_addr *daddr,
__u32 len,
unsigned short proto,
- unsigned int sum)
+ unsigned int sum)
{
__asm__(
- "addl 0(%1), %0"
- "adcl 4(%1), %0"
- "adcl 8(%1), %0"
- "adcl 12(%1), %0"
- "adcl 0(%2), %0"
- "adcl 4(%2), %0"
- "adcl 8(%2), %0"
- "adcl 12(%2), %0"
- "adcl %3, %0"
- "adcl %4, %0"
- "adcl $0, %0"
+ "addl 0(%1), %0 ;\n"
+ "adcl 4(%1), %0 ;\n"
+ "adcl 8(%1), %0 ;\n"
+ "adcl 12(%1), %0 ;\n"
+ "adcl 0(%2), %0 ;\n"
+ "adcl 4(%2), %0 ;\n"
+ "adcl 8(%2), %0 ;\n"
+ "adcl 12(%2), %0 ;\n"
+ "adcl %3, %0 ;\n"
+ "adcl %4, %0 ;\n"
+ "adcl $0, %0 ;\n"
: "=&r" (sum)
- : "r" (saddr), "r" (daddr),
+ : "r" (saddr), "r" (daddr),
"r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
return csum_fold(sum);
}
-/*
+/*
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
+static __inline__ unsigned int csum_and_copy_to_user(const char *src, char *dst,
int len, int sum, int *err_ptr)
{
if (access_ok(VERIFY_WRITE, dst, len))
#ifndef _M68K_MACHDEP_H
#define _M68K_MACHDEP_H
+#include <linux/seq_file.h>
+
struct pt_regs;
struct kbd_repeat;
struct mktime;
extern void (*mach_free_irq) (unsigned int irq, void *dev_id);
extern void (*mach_get_model) (char *model);
extern int (*mach_get_hardware_list) (char *buffer);
-extern int (*mach_get_irq_list) (char *buf);
+extern int (*mach_get_irq_list) (struct seq_file *p, void *v);
extern void (*mach_process_int) (int irq, struct pt_regs *fp);
/* machine dependent timer functions */
extern unsigned long (*mach_gettimeoffset)(void);
#ifndef __ASM_MACINTOSH_H
#define __ASM_MACINTOSH_H
+#include <linux/seq_file.h>
+
/*
* Apple Macintoshisms
*/
extern void mac_enable_irq(unsigned int);
extern void mac_disable_irq(unsigned int);
extern int mac_irq_pending(unsigned int);
-extern int mac_get_irq_list(char *);
+extern int show_mac_interrupts(struct seq_file *, void *);
#if 0
extern void mac_default_handler(int irq);
#endif
#include <linux/sched.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
+#include <linux/seq_file.h>
#include <asm/segment.h>
#include <asm/intersil.h>
#include <asm/oplib.h>
extern void sun3_free_irq (unsigned int irq, void *dev_id);
extern void sun3_enable_interrupts (void);
extern void sun3_disable_interrupts (void);
-extern int sun3_get_irq_list(char *buf);
+extern int show_sun3_interrupts(struct seq_file *, void *);
extern void sun3_process_int(int, struct pt_regs *);
extern volatile unsigned char* sun3_intreg;
#define BIO_BUG_ON
#endif
-/*
- * hash profiling stuff..
- */
-#define BIO_HASH_PROFILING
-
-#define BLKHASHPROF _IOR(0x12,108,sizeof(struct bio_hash_stats))
-#define BLKHASHCLEAR _IO(0x12,109)
-
-#define MAX_PROFILE_BUCKETS 64
-
-struct bio_hash_stats {
- atomic_t nr_lookups;
- atomic_t nr_hits;
- atomic_t nr_inserts;
- atomic_t nr_entries;
- atomic_t max_entries;
- atomic_t max_bucket_size;
- atomic_t bucket_size[MAX_PROFILE_BUCKETS + 1];
-};
-
/*
* was unsigned short, but we might as well be ready for > 64kB I/O pages
*/
unsigned int bv_offset;
};
-struct bio_vec_list {
- unsigned int bvl_cnt; /* how may bio_vec's */
- unsigned int bvl_idx; /* current index into bvl_vec */
- unsigned int bvl_size; /* total size in bytes */
- unsigned int bvl_max; /* max bvl_vecs we can hold, used
- as index into pool */
- struct bio_vec bvl_vec[0]; /* the iovec array */
-};
-
-typedef struct bio_hash_s {
- struct bio_hash_s *next_hash;
- struct bio_hash_s **pprev_hash;
- unsigned long valid_counter;
-} bio_hash_t;
-
-struct bio_hash_bucket {
- rwlock_t lock;
- bio_hash_t *hash;
-} __attribute__((__aligned__(16)));
-
-#define BIO_HASH_BITS (bio_hash_bits)
-#define BIO_HASH_SIZE (1UL << BIO_HASH_BITS)
-
-/*
- * shamelessly stolen from the list.h implementation
- */
-#define hash_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
-#define bio_hash_entry(ptr) \
- hash_entry((ptr), struct bio, bi_hash)
-
/*
* main unit of I/O for the block layer and lower layers (ie drivers and
* stacking drivers)
struct bio {
sector_t bi_sector;
struct bio *bi_next; /* request queue link */
- bio_hash_t bi_hash;
atomic_t bi_cnt; /* pin count */
kdev_t bi_dev; /* will be block device */
- struct bio_vec_list *bi_io_vec;
unsigned long bi_flags; /* status, command, etc */
unsigned long bi_rw; /* bottom bits READ/WRITE,
* top bits priority
*/
+
+ unsigned int bi_vcnt; /* how may bio_vec's */
+ unsigned int bi_idx; /* current index into bvl_vec */
+ unsigned int bi_size; /* total size in bytes */
+ unsigned int bi_max; /* max bvl_vecs we can hold,
+ used as index into pool */
+
+ struct bio_vec *bi_io_vec; /* the actual vec list */
+
int (*bi_end_io)(struct bio *bio, int nr_sectors);
void *bi_private;
- void *bi_hash_desc; /* cookie for hash */
-
void (*bi_destructor)(struct bio *); /* destructor */
};
-#define BIO_SECTOR_BITS 9
-#define BIO_OFFSET_MASK ((1UL << (PAGE_CACHE_SHIFT - BIO_SECTOR_BITS)) - 1)
-#define BIO_PAGE_MASK (PAGE_CACHE_SIZE - 1)
-
/*
* bio flags
*/
#define BIO_PREBUILT 3 /* not merged big */
#define BIO_CLONED 4 /* doesn't own data */
-#define bio_is_hashed(bio) ((bio)->bi_hash.pprev_hash)
-
/*
* bio bi_rw flags
*
* various member access, note that bio_data should of course not be used
* on highmem page vectors
*/
-#define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec->bvl_vec[(idx)]))
-#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_io_vec->bvl_idx)
+#define bio_iovec_idx(bio, idx) (&((bio)->bi_io_vec[(bio)->bi_idx]))
+#define bio_iovec(bio) bio_iovec_idx((bio), (bio)->bi_idx)
#define bio_page(bio) bio_iovec((bio))->bv_page
-#define bio_size(bio) ((bio)->bi_io_vec->bvl_size)
+#define bio_size(bio) ((bio)->bi_size)
+#define __bio_offset(bio, idx) bio_iovec_idx((bio), (idx))->bv_offset
#define bio_offset(bio) bio_iovec((bio))->bv_offset
-#define bio_sectors(bio) (bio_size((bio)) >> BIO_SECTOR_BITS)
+#define bio_sectors(bio) (bio_size((bio)) >> 9)
#define bio_data(bio) (page_address(bio_page((bio))) + bio_offset((bio)))
#define bio_barrier(bio) ((bio)->bi_rw & (1 << BIO_BARRIER))
* permanent PIO fall back, user is probably better off disabling highmem
* I/O completely on that queue (see ide-dma for example)
*/
-#define bio_kmap(bio) kmap(bio_page((bio))) + bio_offset((bio))
-#define bio_kunmap(bio) kunmap(bio_page((bio)))
+#define __bio_kmap(bio, idx) (kmap(bio_iovec_idx((bio), (idx))->bv_page) + bio_iovec_idx((bio), (idx))->bv_offset)
+#define bio_kmap(bio) __bio_kmap((bio), (bio)->bi_idx)
+#define __bio_kunmap(bio, idx) kunmap(bio_iovec_idx((bio), (idx))->bv_page)
+#define bio_kunmap(bio) __bio_kunmap((bio), (bio)->bi_idx)
#define BIO_CONTIG(bio, nxt) \
(bio_to_phys((bio)) + bio_size((bio)) == bio_to_phys((nxt)))
-#define __BIO_PHYS_4G(addr1, addr2) \
- (((addr1) | 0xffffffff) == (((addr2) -1 ) | 0xffffffff))
-#define BIO_PHYS_4G(b1, b2) \
- __BIO_PHYS_4G(bio_to_phys((b1)), bio_to_phys((b2)) + bio_size((b2)))
+#define __BIO_SEG_BOUNDARY(addr1, addr2, mask) \
+ (((addr1) | (mask)) == (((addr2) - 1) | (mask)))
+#define BIO_SEG_BOUNDARY(q, b1, b2) \
+ __BIO_SEG_BOUNDARY(bvec_to_phys(bio_iovec_idx((b1), (b1)->bi_cnt - 1)), bio_to_phys((b2)) + bio_size((b2)), (q)->seg_boundary_mask)
typedef int (bio_end_io_t) (struct bio *, int);
typedef void (bio_destructor_t) (struct bio *);
#define bio_io_error(bio) bio_endio((bio), 0, bio_sectors((bio)))
#define bio_for_each_segment(bvl, bio, i) \
- for (bvl = bio_iovec((bio)), i = (bio)->bi_io_vec->bvl_idx; \
- i < (bio)->bi_io_vec->bvl_cnt; \
+ for (bvl = bio_iovec((bio)), i = (bio)->bi_idx; \
+ i < (bio)->bi_vcnt; \
bvl++, i++)
/*
extern struct bio *bio_alloc(int, int);
extern void bio_put(struct bio *);
-/*
- * the hash stuff is pretty closely tied to the request queue (needed for
- * locking etc anyway, and it's in no way an attempt at a generic hash)
- */
-struct request_queue;
-
-extern inline void bio_hash_remove(struct bio *);
-extern inline void bio_hash_add(struct bio *, void *, unsigned int);
-extern inline struct bio *bio_hash_find(kdev_t, sector_t, unsigned int);
-extern inline int bio_hash_add_unique(struct bio *, void *, unsigned int);
-extern void bio_hash_invalidate(struct request_queue *, kdev_t);
extern int bio_endio(struct bio *, int, int);
extern struct bio *bio_clone(struct bio *, int);
-extern struct bio *bio_copy(struct bio *, int);
+extern struct bio *bio_copy(struct bio *, int, int);
+
+extern inline void bio_init(struct bio *);
extern int bio_ioctl(kdev_t, unsigned int, unsigned long);
static inline void blkdev_dequeue_request(struct request *req)
{
- if (req->bio)
- bio_hash_remove(req->bio);
- if (req->biotail)
- bio_hash_remove(req->biotail);
-
list_del(&req->queuelist);
}
unsigned short hardsect_size;
unsigned int max_segment_size;
- wait_queue_head_t queue_wait;
+ unsigned long seg_boundary_mask;
- unsigned int hash_valid_counter;
+ wait_queue_head_t queue_wait;
};
#define RQ_INACTIVE (-1)
#define QUEUE_FLAG_PLUGGED 0 /* queue is plugged */
#define QUEUE_FLAG_NOSPLIT 1 /* can process bio over several goes */
+#define QUEUE_FLAG_CLUSTER 2 /* cluster several segments into 1 */
#define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
if (rq) {
rq->inactive = 0;
wmb();
-
- if (rq->bio)
- bio_hash_remove(rq->bio);
- if (rq->biotail)
- bio_hash_remove(rq->biotail);
}
return rq;
{
struct page *page = bio_page(*bio);
- if (page - page->zone->zone_mem_map > q->bounce_pfn)
+ if ((page - page->zone->zone_mem_map) + (page->zone->zone_start_paddr >> PAGE_SHIFT) < q->bounce_pfn)
create_bounce(bio, q->bounce_gfp);
}
/*
* Access functions for manipulating queue properties
*/
-extern int blk_init_queue(request_queue_t *, request_fn_proc *, char *);
+extern int blk_init_queue(request_queue_t *, request_fn_proc *);
extern void blk_cleanup_queue(request_queue_t *);
extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
extern void blk_queue_bounce_limit(request_queue_t *, unsigned long long);
extern void blk_queue_max_segments(request_queue_t *q, unsigned short);
extern void blk_queue_max_segment_size(request_queue_t *q, unsigned int);
extern void blk_queue_hardsect_size(request_queue_t *q, unsigned short);
+extern void blk_queue_segment_boundary(request_queue_t *q, unsigned long);
extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
extern void generic_unplug_device(void *);
elevator_init_fn *elevator_init_fn;
elevator_exit_fn *elevator_exit_fn;
-
- /*
- * per-elevator private data
- */
- void *elevator_data;
-
- char queue_name[16];
};
int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct bio *);
#define BLKELVGET _IOR(0x12,106,sizeof(blkelv_ioctl_arg_t))
#define BLKELVSET _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t))
-extern int elevator_init(request_queue_t *, elevator_t *, elevator_t, char *);
+extern int elevator_init(request_queue_t *, elevator_t *, elevator_t);
extern void elevator_exit(request_queue_t *, elevator_t *);
/*
extern void update_atime (struct inode *);
#define UPDATE_ATIME(inode) update_atime (inode)
-extern void bio_hash_init(unsigned long);
extern void buffer_init(unsigned long);
extern void inode_init(unsigned long);
extern void mnt_init(unsigned long);
+++ /dev/null
-#ifndef I2C_H
-#define I2C_H
-
-/*
- * linux i2c interface. Works a little bit like the scsi subsystem.
- * There are:
- *
- * i2c the basic control module (like scsi_mod)
- * bus driver a driver with a i2c bus (hostadapter driver)
- * chip driver a driver for a chip connected
- * to a i2c bus (cdrom/hd driver)
- *
- * A device will be attached to one bus and one chip driver. Every chip
- * driver gets a unique ID.
- *
- * A chip driver can provide a ioctl-like callback for the
- * communication with other parts of the kernel (not every i2c chip is
- * useful without other devices, a TV card tuner for example).
- *
- * "i2c internal" parts of the structs: only the i2c module is allowed to
- * write to them, for others they are read-only.
- *
- */
-
-#include <linux/version.h>
-
-#define I2C_BUS_MAX 4 /* max # of bus drivers */
-#define I2C_DRIVER_MAX 8 /* max # of chip drivers */
-#define I2C_DEVICE_MAX 8 /* max # if devices per bus/driver */
-
-struct i2c_bus;
-struct i2c_driver;
-struct i2c_device;
-
-#define I2C_DRIVERID_MSP3400 1
-#define I2C_DRIVERID_TUNER 2
-#define I2C_DRIVERID_VIDEOTEXT 3
-#define I2C_DRIVERID_VIDEODECODER 4
-#define I2C_DRIVERID_VIDEOENCODER 5
-
-#define I2C_BUSID_BT848 1 /* I2C bus on a BT848 */
-#define I2C_BUSID_PARPORT 2 /* Bit banging on a parallel port */
-#define I2C_BUSID_BUZ 3
-#define I2C_BUSID_ZORAN 4
-#define I2C_BUSID_CYBER2000 5
-
-/*
- * struct for a driver for a i2c chip (tuner, soundprocessor,
- * videotext, ... ).
- *
- * a driver will register within the i2c module. The i2c module will
- * callback the driver (i2c_attach) for every device it finds on a i2c
- * bus at the specified address. If the driver decides to "accept"
- * the, device, it must return a struct i2c_device, and NULL
- * otherwise.
- *
- * i2c_detach = i2c_attach ** -1
- *
- * i2c_command will be used to pass commands to the driver in a
- * ioctl-line manner.
- *
- */
-
-struct i2c_driver
-{
- char name[32]; /* some useful label */
- int id; /* device type ID */
- unsigned char addr_l, addr_h; /* address range of the chip */
-
- int (*attach)(struct i2c_device *device);
- int (*detach)(struct i2c_device *device);
- int (*command)(struct i2c_device *device,unsigned int cmd, void *arg);
-
- /* i2c internal */
- struct i2c_device *devices[I2C_DEVICE_MAX];
- int devcount;
-};
-
-
-/*
- * this holds the informations about a i2c bus available in the system.
- *
- * a chip with a i2c bus interface (like bt848) registers the bus within
- * the i2c module. This struct provides functions to access the i2c bus.
- *
- * One must hold the spinlock to access the i2c bus (XXX: is the irqsave
- * required? Maybe better use a semaphore?).
- * [-AC-] having a spinlock_irqsave is only needed if we have drivers wishing
- * to bang their i2c bus from an interrupt.
- *
- * attach/detach_inform is a callback to inform the bus driver about
- * attached chip drivers.
- *
- */
-
-/* needed: unsigned long flags */
-
-#if LINUX_VERSION_CODE >= 0x020100
-# if 0
-# define LOCK_FLAGS unsigned long flags;
-# define LOCK_I2C_BUS(bus) spin_lock_irqsave(&(bus->bus_lock),flags);
-# define UNLOCK_I2C_BUS(bus) spin_unlock_irqrestore(&(bus->bus_lock),flags);
-# else
-# define LOCK_FLAGS
-# define LOCK_I2C_BUS(bus) spin_lock(&(bus->bus_lock));
-# define UNLOCK_I2C_BUS(bus) spin_unlock(&(bus->bus_lock));
-# endif
-#else
-# define LOCK_FLAGS unsigned long flags;
-# define LOCK_I2C_BUS(bus) { save_flags(flags); cli(); }
-# define UNLOCK_I2C_BUS(bus) { restore_flags(flags); }
-#endif
-
-struct i2c_bus
-{
- char name[32]; /* some useful label */
- int id;
- void *data; /* free for use by the bus driver */
-
-#if LINUX_VERSION_CODE >= 0x020100
- spinlock_t bus_lock;
-#endif
-
- /* attach/detach inform callbacks */
- void (*attach_inform)(struct i2c_bus *bus, int id);
- void (*detach_inform)(struct i2c_bus *bus, int id);
-
- /* Software I2C */
- void (*i2c_setlines)(struct i2c_bus *bus, int ctrl, int data);
- int (*i2c_getdataline)(struct i2c_bus *bus);
-
- /* Hardware I2C */
- int (*i2c_read)(struct i2c_bus *bus, unsigned char addr);
- int (*i2c_write)(struct i2c_bus *bus, unsigned char addr,
- unsigned char b1, unsigned char b2, int both);
-
- /* internal data for i2c module */
- struct i2c_device *devices[I2C_DEVICE_MAX];
- int devcount;
-};
-
-
-/*
- * This holds per-device data for a i2c device
- */
-
-struct i2c_device
-{
- char name[32]; /* some useful label */
- void *data; /* free for use by the chip driver */
- unsigned char addr; /* chip addr */
-
- /* i2c internal */
- struct i2c_bus *bus;
- struct i2c_driver *driver;
-};
-
-
-/* ------------------------------------------------------------------- */
-/* i2c module functions */
-
-/* register/unregister a i2c bus */
-int i2c_register_bus(struct i2c_bus *bus);
-int i2c_unregister_bus(struct i2c_bus *bus);
-
-/* register/unregister a chip driver */
-int i2c_register_driver(struct i2c_driver *driver);
-int i2c_unregister_driver(struct i2c_driver *driver);
-
-/* send a command to a chip using the ioctl-like callback interface */
-int i2c_control_device(struct i2c_bus *bus, int id,
- unsigned int cmd, void *arg);
-
-/* i2c bus access functions */
-void i2c_start(struct i2c_bus *bus);
-void i2c_stop(struct i2c_bus *bus);
-void i2c_one(struct i2c_bus *bus);
-void i2c_zero(struct i2c_bus *bus);
-int i2c_ack(struct i2c_bus *bus);
-
-int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack);
-unsigned char i2c_readbyte(struct i2c_bus *bus,int last);
-
-/* i2c (maybe) hardware functions */
-int i2c_read(struct i2c_bus *bus, unsigned char addr);
-int i2c_write(struct i2c_bus *bus, unsigned char addr,
- unsigned char b1, unsigned char b2, int both);
-
-int i2c_init(void);
-#endif /* I2C_H */
+++ /dev/null
-#ifndef _LINUX_MALLOC_H
-#define _LINUX_MALLOC_H
-
-#warning linux/malloc.h is deprecated, use linux/slab.h instead.
-
-#include <linux/slab.h>
-#endif /* _LINUX_MALLOC_H */
#include <asm/mmu.h>
#include <linux/smp.h>
-#include <linux/tty.h>
#include <linux/sem.h>
#include <linux/signal.h>
#include <linux/securebits.h>
#define _LINUX_SEQ_FILE_H
#ifdef __KERNEL__
+#include <linux/types.h>
+
struct seq_operations;
+struct file;
+struct inode;
struct seq_file {
char *buf;
loff_t index;
struct semaphore sem;
struct seq_operations *op;
+ void *private;
};
struct seq_operations {
vfs_caches_init(mempages);
buffer_init(mempages);
page_cache_init(mempages);
- bio_hash_init(mempages);
#if defined(CONFIG_ARCH_S390)
ccwcache_init();
#endif
__initcall(init_emergency_pool);
-static inline void bounce_end_io (struct bio *bio, int nr_sectors)
+static inline int bounce_end_io (struct bio *bio, int nr_sectors)
{
struct bio *bio_orig = bio->bi_private;
struct page *page = bio_page(bio);
unsigned long flags;
+ int ret;
if (test_bit(BIO_UPTODATE, &bio->bi_flags))
- set_bit(BIO_UPTODATE, bio_orig->bi_flags);
+ set_bit(BIO_UPTODATE, &bio_orig->bi_flags);
- bio_orig->bi_end_io(bio_orig, nr_sectors);
+ ret = bio_orig->bi_end_io(bio_orig, nr_sectors);
spin_lock_irqsave(&emergency_lock, flags);
if (nr_emergency_pages >= POOL_SIZE) {
spin_unlock_irqrestore(&emergency_lock, flags);
}
- bio_hash_remove(bio);
bio_put(bio);
+ return ret;
}
-static void bounce_end_io_write (struct bio *bio, int nr_sectors)
+static int bounce_end_io_write(struct bio *bio, int nr_sectors)
{
- bounce_end_io(bio, nr_sectors);
+ return bounce_end_io(bio, nr_sectors);
}
-static void bounce_end_io_read (struct bio *bio, int nr_sectors)
+static int bounce_end_io_read (struct bio *bio, int nr_sectors)
{
struct bio *bio_orig = bio->bi_private;
if (test_bit(BIO_UPTODATE, &bio->bi_flags))
copy_to_high_bio_irq(bio_orig, bio);
- bounce_end_io(bio, nr_sectors);
+ return bounce_end_io(bio, nr_sectors);
}
struct page *alloc_bounce_page(int gfp_mask)
{
struct page *page;
struct bio *bio;
+ int i, rw = bio_data_dir(*bio_orig);
- bio = bio_alloc(GFP_NOHIGHIO, 1);
+ BUG_ON((*bio_orig)->bi_idx);
- /*
- * wasteful for 1kB fs, but machines with lots of ram are less likely
- * to have 1kB fs for anything that needs to go fast. so all things
- * considered, it should be ok.
- */
- page = alloc_bounce_page(gfp_mask);
+ bio = bio_alloc(GFP_NOHIGHIO, (*bio_orig)->bi_vcnt);
bio->bi_dev = (*bio_orig)->bi_dev;
bio->bi_sector = (*bio_orig)->bi_sector;
bio->bi_rw = (*bio_orig)->bi_rw;
- bio->bi_io_vec->bvl_vec[0].bv_page = page;
- bio->bi_io_vec->bvl_vec[0].bv_len = bio_size(*bio_orig);
- bio->bi_io_vec->bvl_vec[0].bv_offset = 0;
-
- bio->bi_private = *bio_orig;
+ bio->bi_vcnt = (*bio_orig)->bi_vcnt;
+ bio->bi_idx = 0;
+ bio->bi_size = (*bio_orig)->bi_size;
- if (bio_rw(bio) == WRITE) {
+ if (rw & WRITE)
bio->bi_end_io = bounce_end_io_write;
- copy_from_high_bio(bio, *bio_orig);
- } else
+ else
bio->bi_end_io = bounce_end_io_read;
+ for (i = 0; i < bio->bi_vcnt; i++) {
+ char *vto, *vfrom;
+
+ page = alloc_bounce_page(gfp_mask);
+
+ bio->bi_io_vec[i].bv_page = page;
+ bio->bi_io_vec[i].bv_len = (*bio_orig)->bi_io_vec[i].bv_len;
+ bio->bi_io_vec[i].bv_offset = 0;
+
+ if (rw & WRITE) {
+ vto = page_address(page);
+ vfrom = __bio_kmap(*bio_orig, i);
+ memcpy(vto, vfrom + __bio_offset(*bio_orig, i), bio->bi_io_vec[i].bv_len);
+ __bio_kunmap(bio, i);
+ }
+ }
+
+ bio->bi_private = *bio_orig;
*bio_orig = bio;
}