$(TOPDIR)/scripts/docgen $(TOPDIR)/arch/i386/kernel/mca.c \
<mcabook.tmpl >mcabook.sgml
-videobook.sgml: videobook.tmpl $(TOPDIR)/drivers/char/videodev.c
- $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/char/videodev.c \
+videobook.sgml: videobook.tmpl $(TOPDIR)/drivers/media/video/videodev.c
+ $(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/media/video/videodev.c \
<videobook.tmpl >videobook.sgml
-APISOURCES := $(TOPDIR)/drivers/char/videodev.c \
+APISOURCES := $(TOPDIR)/drivers/media/video/videodev.c \
$(TOPDIR)/arch/i386/kernel/mca.c \
$(TOPDIR)/arch/i386/kernel/mtrr.c \
$(TOPDIR)/drivers/char/misc.c \
<chapter id="viddev">
<title>Video4Linux</title>
-!Edrivers/char/videodev.c
+!Edrivers/media/video/videodev.c
</chapter>
<chapter id="snddev">
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
-!Edrivers/char/videodev.c
+!Edrivers/media/video/videodev.c
</chapter>
</book>
--- /dev/null
+
+The Second Extended Filesystem
+==============================
+
+ext2 was originally released in January 1993. Written by R\'emy Card,
+Theodore Ts'o and Stephen Tweedie, it was a major rewrite of the
+Extended Filesystem. It is currently (February 1999) the predominant
+filesystem in use by Linux. There are also implementations available
+for NetBSD, FreeBSD, the GNU HURD, Windows 95/98/NT, OS/2 and RISC OS.
+
+Options
+=======
+
+When mounting an ext2 filesystem, the following options are accepted.
+Defaults are marked with (*).
+
+bsddf (*) Makes `df' act like BSD.
+minixdf Makes `df' act like Minix.
+
+check=none, nocheck Perform no checks upon the filesystem.
+check=normal (*) Perform normal checks on the filesystem.
+check=strict Perform extra checks on the filesystem.
+
+debug For developers only.
+
+errors=continue (*) Keep going on a filesystem error.
+errors=remount-ro Remount the filesystem read-only on an error.
+errors=panic Panic and halt the machine if an error occurs.
+
+grpid, bsdgroups Give objects the same group ID as their parent.
+nogrpid, sysvgroups (*) New objects have the group ID of their creator.
+
+resuid=n The user which may use the reserved blocks.
+resgid=n The group which may use the reserved blocks.
+
+sb=n Use alternate superblock at this location.
+
+grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2.
+
+
+Specification
+=============
+
+ext2 shares many properties with traditional Unix filesystems. It has
+the concepts of blocks, inodes and directories. It has space in the
+specification for Access Control Lists (ACLs), fragments, undeletion and
+compression though these are not yet implemented (some are available as
+separate patches). There is also a versioning mechanism to allow new
+features (such as journalling) to be added in a maximally compatible
+manner.
+
+Blocks
+------
+
+The space in the device or file is split up into blocks. These are
+a fixed size, of 1024, 2048 or 4096 bytes, which is decided when the
+filesystem is created. Smaller blocks mean less wasted space per file,
+but require slightly more accounting overhead.
+
+Blocks are clustered into block groups in order to reduce fragmentation
+and minimise the amount of head seeking when reading a large amount of
+consecutive data. Each block group has a descriptor and the array of
+descriptors is stored immediately after the superblock. Two blocks at
+the start of each group are reserved for the block usage bitmap and
+the inode usage bitmap which show which blocks and inodes are used.
+Since each bitmap fits in a block, this means that the maximum size of
+a block group is 8 times the size of a block.
+
+The first (non-reserved) blocks in the block group are designated as
+the inode table for the block and the remainder are the data blocks.
+The block allocation algorithm attempts to allocate data blocks in the
+same block group as the inode which contains them.
+
+The Superblock
+--------------
+
+The superblock contains all the information about the configuration of
+the filing system. It is stored in block 1 of the filesystem (numbering
+from 0) and it is essential to mounting it. Since it is so important,
+backup copies of the superblock are stored in block groups throughout
+the filesystem. The first revision of ext2 stores a copy at the start
+of every block group. Later revisions can store a copy in only some
+block groups to reduce the amount of redundancy on large filesystems.
+The groups chosen are 0, 1 and powers of 3, 5 and 7.
+
+The information in the superblock contains fields such as how many
+inodes and blocks are in the filesystem and how many are unused, how
+many inodes and blocks are in a block group, when the filesystem was
+mounted, when it was modified, what version of the filesystem it is
+(see the Revisions section below) and which OS created it.
+
+If the revision of the filesystem is recent enough then there are extra
+fields, such as a volume name, a unique identifier, the inode size,
+support for compression, block preallocation and creating fewer backup
+superblocks.
+
+All fields in the superblock (as in all other ext2 structures) are stored
+on the disc in little endian format, so a filesystem is portable between
+machines without having to know what machine it was created on.
+
+Inodes
+------
+
+The inode (index node) is the fundamental concept in the ext2 filesystem.
+Each object in the filesystem is represented by an inode. The inode
+structure contains pointers to the filesystem blocks which contain the
+data held in the object and all of the metadata about an object except
+its name. The metadata about an object includes the permissions, owner,
+group, flags, size, number of blocks used, access time, change time,
+modification time, deletion time, number of links, fragments, version
+(for NFS) and ACLs.
+
+There are several reserved fields which are currently unused in the inode
+structure and several which are overloaded. One field is used for the
+directory ACL if the inode is a directory and for the top 32 bits of
+the file size if the inode is a regular file. The translator field is
+unused under Linux, but is used by the HURD to reference the inode of
+a program which will be used to interpret this object. The HURD also
+has larger permissions, owner and group fields, so it uses some of the
+other unused by Linux fields to store the extra bits.
+
+There are pointers to the first 12 blocks which contain the file's data
+in the inode. There is a pointer to an indirect block (which contains
+pointers to the next set of blocks), a pointer to a doubly-indirect
+block (which contains pointers to indirect blocks) and a pointer to a
+trebly-indirect block (which contains pointers to doubly-indirect blocks).
+
+The flags field contains some ext2-specific flags which aren't catered
+for by the standard chmod flags. These flags can be listed with
+lsattr and changed with the chattr command. There are flags for secure
+deletion, undeletable, compression, synchronous updates, immutability,
+append-only, dumpable, no-atime, and btree directories. Not all of
+these are supported yet.
+
+Directories
+-----------
+
+A directory is a filesystem object and has an inode just like a file.
+It is a specially formatted file containing records which associate
+each name with an inode number. Later revisions of the filesystem also
+encode the type of the object (file, directory, symlink, device, fifo,
+socket) in the directory entry for speed. The current implementation
+of ext2 uses a linked list in directories; a planned enhancement will
+use btrees instead. The current implementation also never shrinks
+directories once they have grown to accommodate more files.
+
+Special files
+-------------
+
+Symbolic links are also filesystem objects with inodes. They deserve
+special mention because the data for them is stored within the inode
+itself if the symlink is less than 60 bytes long. It uses the fields
+which would normally be used to store the pointers to blocks to store
+the data. This is a worthwhile optimisation to make as it does not then
+take up a block, and most symlinks are less than 60 characters long.
+
+Character and block special devices never have data blocks assigned to
+them. Instead, their device number is stored in the inode, again reusing
+the fields which would be used to point to the blocks.
+
+Revisions
+---------
+
+The revisioning mechanism used in ext2 is sophisticated. The revisioning
+mechanism is not supported by version 0 (EXT2_GOOD_OLD_REV) of ext2 but
+was introduced in version 1. There are three 32-bit fields, one for
+compatible features, one for read-only compatible features and one for
+incompatible features.
+
+Reserved Space
+--------------
+
+In ext2, there is a mechanism for reserving a certain number of blocks
+for a particular user (normally the super-user). This is intended to
+allow for the system to continue functioning even if a user fills up
+all the available space. It also keeps the filesystem from filling up
+entirely which helps combat fragmentation.
+
+Filesystem check
+----------------
+
+At boot time, most systems run a consistency check (e2fsck) on their
+filesystems. The superblock of the ext2 filesystem contains several
+fields which indicate whether fsck should actually run (since checking
+the filesystem at boot can take a long time if it is large). fsck will
+run if the filesystem was not unmounted without errors, if the maximum
+mount count has been exceeded or if the maximum time between checks has
+been exceeded.
+
+Metadata
+--------
+
+It is frequently claimed that the ext2 implementation of writing
+asynchronous metadata is faster than the ffs synchronous metadata
+scheme but less reliable. Both methods are equally resolvable by their
+respective fsck programs.
+
+If you're exceptionally paranoid, there are 3 ways of making metadata
+writes synchronous:
+
+per-file if you have the source: use the O_SYNC argument to open()
+per-file if you don't have the source: use chattr +S
+per-filesystem: mount -o sync
+
+the first and last are not ext2 specific but do force the metadata to
+be written synchronously.
+
+References
+==========
+
+The kernel source file:/usr/src/linux/fs/ext2/
+Design & Implementation http://khg.redhat.com/HyperNews/get/fs/ext2intro.html
+Compression http://debs.fuller.edu/e2compr/
+ACL support ftp://tsx-11.mit.edu/pub/linux/ALPHA/ext2fs
+updated ACL work http://aerobee.informatik.uni-bremen.de/acl_eng.html
+e2fsprogs ftp://tsx-11.mit.edu/pub/linux/packages/ext2fs
+
+Implementations for:
+OS/2 http://perso.wanadoo.fr/matthieu.willm/ext2-os2/
+Windows 95 http://www.yipton.demon.co.uk/
+Windows NT http://www.cyco.nl/~andreys/ext2fsnt/
+ http://uranus.it.swin.edu.au/~jn/linux/Explore2fs.htm
+DOS client ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2/
+RISC OS client ftp://ftp.barnet.ac.uk/pub/acorn/armlinux/iscafs/
But until that happens, the subdirectory Makefile needs to define
these rules explicitly.
+ subdir-y subdir-m subdir-n subdir-
+
+ These variables replace $(ALL_SUB_DIRS), $(SUB_DIRS) and
+ $(MOD_SUB_DIRS).
+
+ Example:
+
+ # drivers/Makefile
+ subdir-$(CONFIG_PCI) += pci
+ subdir-$(CONFIG_PCMCIA) += pcmcia
+ subdir-$(CONFIG_MTD) += mtd
+ subdir-$(CONFIG_SBUS) += sbus
+
+ These variables work similar to obj-*, but are used for
+ subdirectories instead of object files.
+
+ After executing all of the assignments, the subdirectory
+ Makefile has built up four lists: $(subdir-y), $(subdir-m),
+ $(subdir-n), and $(subdir-).
+
+ $(subdir-y) is a list of directories that should be entered
+ for making vmlinux.
+ $(subdir-m) is a list of directories that should be entered
+ for making modules.
+ $(subdir-n) and $(subdir-) are only used for collecting a list
+ of all subdirectories of this directory.
+
+ Each list besides subdir-y may contain duplicates items; duplicates
+ are automatically removed later.
+
+ mod-subdirs
+
+ $(mod-subdirs) is a list of all the the subdirectories that should
+ be added to $(subdir-m), too if they appear in $(subdir-y)
+
+ Example:
+
+ # fs/Makefile
+ mod-subdirs := nls
+
+ This means nls should be added to (subdir-y) and $(subdir-m) if
+ CONFIG_NFS = y.
=== 9 Compatibility with Linux Kernel 2.2
Documentation for the AD1816(A) sound driver
============================================
-NOTE: This driver is still EXPERIMENTAL, so don't use it on production
-systems!
-
-
Installation:
-------------
-To get your AD1816(A) based sound card work, you'll have to enable
-module support ("Enable loadable module support") and support for
-experimental code ("Prompt for development and/or incomplete
-code/drivers") during kernel configuration. Enable "Sound card
-support", "OSS modules support" and "Support for AD1816(A) based cards
-(EXPERIMENTAL)" in the sound configuration menu, too. Be sure, that
-you build "Support for AD1816(A) based cards (EXPERIMENTAL)" as a MODULE,
-otherwise you may run into problems later.
-Now build, install and reboot the new kernel as usual.
-
-Since the AD1816(A) is a P'n'P sound chip you'll usually have to
-configure it using the isapnptools. See isapnptools documentation for
-details on configuring P'n'P cards.
-
-After you have successfully configured the card using isapnp, you may
-load the AD1816 driver using modprobe. A typical modprobe call should
-look like this:
-
- modprobe ad1816 io=0x530 irq=5 dma=1 dma2=3 ad1816_clockfreq=33000
-
-if your isapnp.conf file looks like this (relevant lines only):
-
- (INT 0 (IRQ 5 (MODE +E)))
- (DMA 0 (CHANNEL 1))
- (DMA 1 (CHANNEL 3))
- (IO 0 (BASE 0x0220))
- (IO 1 (BASE 0x0388))
- (IO 2 (BASE 0x0530))
-
-NOTE: Be sure, that you use the address IO 2 (in our example 0x530) when
-loading the module!
-
-If your setup was correct, you should see the following messages in
-/var/log/messages (numbers may be different):
-
-Nov 6 17:07:26 tek01 kernel: ad1816_detect(530)
-Nov 6 17:07:26 tek01 kernel: ad1816_detect() - Detected OK
-Nov 6 17:07:26 tek01 kernel: AD1816 Version: 3
-
+To get your AD1816(A) based sound card work, you'll have to enable support for
+experimental code ("Prompt for development and/or incomplete code/drivers")
+and isapnp ("Plug and Play support", "ISA Plug and Play support"). Enable
+"Sound card support", "OSS modules support" and "Support for AD1816(A) based
+cards (EXPERIMENTAL)" in the sound configuration menu, too. Now build, install
+and reboot the new kernel as usual.
Features:
---------
----------------
First of all you should check, if the driver has been loaded
-properly. If you get the following message in your /var/log/messages:
-
-Nov 6 17:06:31 tek01 kernel: ad1816_detect(530)
-Nov 6 17:06:31 tek01 kernel: Chip is not an AD1816 or chip is not active
-
-you either used the wrong address for loading the driver, your chip is
-not an AD1816 or you forgot to initialize the card with isapnp.
+properly.
If loading of the driver succeeds, but playback/capture fails, check
if you used the correct values for irq, dma and dma2 when loading the module.
Bugreports, bugfixes and related questions should be sent via E-Mail to:
tek@rbg.informatik.tu-darmstadt.de
-
Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
- Last modified: 1999/05/02
+Christoph Hellwig <hch@caldera.de>
+ Last modified: 2000/09/20
Documentation for the ESS AudioDrive chips
-In 2.2 kernels the SoundBlaster driver not only tries to detect an ESS chip, it
+In 2.4 kernels the SoundBlaster driver not only tries to detect an ESS chip, it
tries to detect the type of ESS chip too. The correct detection of the chip
-doesn't always succeed however, so the default behaviour is 2.0 behaviour
-which means: only detect ES688 and ES1688.
+doesn't always succeed however, so unless you use the kernel isapnp facilities
+(and you chip is pnp capable) the default behaviour is 2.0 behaviour which
+means: only detect ES688 and ES1688.
All ESS chips now have a recording level setting. This is a need-to-have for
people who want to use their ESS for recording sound.
The ESS1868 sound card is a PnP ESS1688-compatible 16-bit sound card.
-Notes about configuring the sound card:
+It should be automatically detected by the Linux Kernel isapnp support when you
+load the sb.o module. Otherwise you should take care of:
* The ESS1868 does not allow use of a 16-bit DMA, thus DMA 0, 1, 2, and 3
may only be used.
* isapnptools version 1.14 does work with ESS1868. Earlier versions might
not.
-
+
* Sound support MUST be compiled as MODULES, not statically linked
into the kernel.
-
+
+
+NOTE: this is only needed when not using the kernel isapnp support!
+
For configuring the sound card's I/O addresses, IRQ and DMA, here is a
sample copy of the isapnp.conf directives regarding the ESS1868:
/sbin/insmod opl3 io=0x388
/sbin/insmod v_midi
-opl3 is the FM synthesizer--I have not tried the SoftOSS wavetable
-synthesizer yet, but I assume it would work as well. Also, doing:
-/sbin/insmod opl3
-/sbin/insmod adlib_card io=0x388
-works, but I believe the sound quality is a bit distorted when playing MIDI
-files.
-
-When using the above setup, my /proc/sound gives the following:
-
-OSS/Free:3.8s2++-971130
-Load type: Driver loaded as a module
-Kernel: Linux scitus.dyn.ml.org 2.1.104 #1 SMP Sun May 24 11:04:27 EDT 1998 i486
-Config options: 0
-
-Installed drivers:
-
-Card config:
-
-Audio devices:
-0: ESS ES1688 AudioDrive (rev 11) (3.1)
-
-Synth devices:
-0: Yamaha OPL-3
-
-Midi devices:
-0: Loopback MIDI Port 1
-1: Loopback MIDI Port 2
-
-Timers:
-0: System clock
-
-Mixers:
-0: Sound Blaster
-
-
+opl3 is the FM synthesizer
+/sbin/insmod opl3 io=0x388
If you're using PnP cards, the initialization of PnP is required
before loading this driver. You have now three options:
1. Use isapnptools.
- 2. Install PnP kernel driver patch.
+ 2. Use in-kernel isapnp support.
3. Initialize PnP on DOS/Windows, then boot linux by loadlin.
In this document, only the case 1 case is treated.
-For the case 2, please refer to the instruction in PnP driver project.
-The home page of PnP driver project is the following URL:
- http://www-jcr.lmh.ox.ac.uk/~pnp/
----------------------------------------------------------------
* Installation on Red Hat 5.0 Sound Driver
added info on OSS and ALSA.
1.1.1 19991031 Added notes on sound-slot- and sound-service.
(Alan Cox)
+1.1.2 20000920 Modified for Kernel 2.4 (Christoph Hellwig)
+
Modular Sound Drivers:
======================
forums for bug reporting.
The modular sound drivers may be loaded via insmod or modprobe.
-To support all the various sound modules, there are three general
+To support all the various sound modules, there are two general
support modules that must be loaded first:
soundcore.o: Top level handler for the sound system, provides
a set of functions for registration of devices
by type.
- soundlow.o: Low-level sound drivers which are not part of
- OSS/Lite (Open Sound System), including SB32/AWE
- synthesizer, etc.
-
sound.o: Common sound functions required by all modules.
For the specific sound modules (e.g., sb.o for the Soundblaster),
Since this was originally release, I have received a couple of
mails from people who have accomplished this!
+NOTE: In Linux 2.4 the Sound Blaster driver (and only this one yet)
+supports multiple cards with one module by default.
+Read the file 'Soundblaster' in this directory for details.
Sound Problems:
===============
and /proc/dma. Are you trying to use an address,
IRQ or DMA port that another device is using?
- C) Check (cat) /proc/sys/pnp (if this exists, you
- may need a kernel patch to get this device).
+ C) Check (cat) /proc/isapnp
D) Inspect your /var/log/messages file. Often that will
indicate what IRQ or IO port could not be obtained.
There are several ways of configuring your sound:
-1) Hardcoded in the kernel at compile time (not applicable when
- using sound modules). This was the OLD way!
+1) On the kernel command line (when using the sound driver(s)
+ compiled in the kernel). Check the driver source and
+ documentation for details.
2) On the command line when using insmod or in a bash script
using command line calls to load sound.
5) Via the OSS soundconf program (with the commercial version
of the OSS driver.
+6) By just loading the module and let isapnp do everything relevant
+ for you. This works only with a few drivers yet and - of course -
+ only with isapnp hardware.
+
And I am sure, several other ways.
Anyone want to write a linuxconf module for configuring sound?
--- /dev/null
+Linux 2.4 Sound Changes
+2000-September-25
+Christoph Hellwig, <hch@caldera.de>
+
+
+
+=== isapnp support
+
+The Linux 2.4 Kernel does have reliable in-kernel isapnp support.
+Some drivers (sb.o, ad1816.o awe_wave.o) do now support automatically
+detecting and configuring isapnp devices.
+If you have a not yet supported isapnp soundcard, mail me the content
+of '/proc/isapnp' on your system and some information about your card
+and its driver(s) so I can try to get isapnp working for it.
+
+
+
+=== soundcard resources on kernel commandline
+
+Before Linux 2.4 you had to specify the resources for sounddrivers
+statically linked into the kernel at compile time
+(in make config/menuconfig/xconfig). In Linux 2.4 the ressources are
+now specified at the boot-time kernel commandline (e.g. the lilo
+'append=' line or everything that's after the kernel name in grub).
+Read the Configure.help entry for your card for the parameters.
+
+
+=== softoss is gone
+
+In Linux 2.4 the softoss in-kernel software synthesizer is no more aviable.
+Use a user space software synthesizer like timidity instead.
+
+
+
+=== /dev/sndstat and /proc/sound are gone
+
+In older Linux versions those files exported some information about the
+OSS/Free configuration to userspace. In Linux 2.3 they were removed because
+they did not support the growing number of pci soundcards and there were
+some general problems with this interface.
+
+
Greg Kroah-Hartman <greg@kroah.com>
Pavel Machek <pavel@suse.cz>
Paul Mackerras <paulus@cs.anu.edu.au>
+ Petko Manlolov <petkan@dce.bg>
David E. Nelson <dnelson@jump.net>
Vojtech Pavlik <vojtech@suse.cz>
Bill Ryder <bryder@sgi.com>
serial converter, and the documentation for the device to
allow a driver to be written.
+ - Thanks to ADMtek for providing Pegasus and Pegasus II
+ evaluation boards, specs and valuable advices during
+ the driver development.
+
And thanks go to (hey! in no particular order :)
- Oren Tirosh <orenti@hishome.net>, for standing so patiently
W: http://mosquitonet.Stanford.EDU/strip.html
S: Unsupported ?
+STRADIS MPEG-2 DECODER DRIVER
+P: Nathan Laredo
+M: laredo@gnu.org
+W: http://mpeg.openprojects.net/
+W: http://www.stradis.com/
+S: Maintained
+
SUPERH
P: Niibe Yutaka
M: gniibe@chroot.org
* [ if a single-CPU system runs an SMP kernel then we call the local
* interrupt as well. Thus we cannot inline the local irq ... ]
*/
-unsigned int apic_timer_irqs [NR_CPUS] = { 0, };
+unsigned int apic_timer_irqs [NR_CPUS];
void smp_apic_timer_interrupt(struct pt_regs * regs)
{
/*
* # of IO-APICs and # of IRQ routing registers
*/
-int nr_ioapics = 0;
+int nr_ioapics;
int nr_ioapic_registers[MAX_IO_APICS];
/* I/O APIC entries */
struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* MP IRQ source entries */
-int mp_irq_entries = 0;
+int mp_irq_entries;
#if CONFIG_SMP
# define TARGET_CPUS cpu_online_map
#define MAX_PIRQS 8
int pirq_entries [MAX_PIRQS];
-int pirqs_enabled = 0;
-int skip_ioapic_setup = 0;
+int pirqs_enabled;
+int skip_ioapic_setup;
static int __init ioapic_setup(char *str)
{
#include <asm/pgalloc.h>
/* Have we found an MP table */
-int smp_found_config = 0;
+int smp_found_config;
/*
* Various Linux-internal data structures created from the
int apic_version [MAX_APICS];
int mp_bus_id_to_type [MAX_MP_BUSSES];
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
-int mp_current_pci_id = 0;
+int mp_current_pci_id;
int pic_mode;
-unsigned long mp_lapic_addr = 0;
+unsigned long mp_lapic_addr;
/* Processor that is doing the boot up */
unsigned int boot_cpu_id = -1U;
/* Internal processor count */
-static unsigned int num_processors = 0;
+static unsigned int num_processors;
/* Bitmask of physically existing CPUs */
-unsigned long phys_cpu_present_map = 0;
+unsigned long phys_cpu_present_map;
/*
* Intel MP BIOS table parsing routines:
#endif
#ifdef USERSPACE_INTERFACE
-static char *ascii_buffer = NULL;
-static unsigned int ascii_buf_bytes = 0;
+static char *ascii_buffer;
+static unsigned int ascii_buf_bytes;
#endif
-static unsigned int *usage_table = NULL;
+static unsigned int *usage_table;
static DECLARE_MUTEX(main_lock);
/* Private functions */
/*break;*/
case X86_VENDOR_CYRIX:
/* Cyrix have 8 ARRs */
+ return 8;
case X86_VENDOR_CENTAUR:
/* and Centaur has 8 MCR's */
if(boot_cpu_data.x86==5)
} /* End Function centaur_get_mcr */
static void (*get_mtrr) (unsigned int reg, unsigned long *base,
- unsigned long *size, mtrr_type *type) = NULL;
+ unsigned long *size, mtrr_type *type);
static void intel_set_mtrr_up (unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type, int do_safe)
static void (*set_mtrr_up) (unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type,
- int do_safe) = NULL;
+ int do_safe);
#ifdef CONFIG_SMP
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
-int hlt_counter=0;
+int hlt_counter;
/*
* Powermanagement idle function, if any..
*/
-void (*pm_idle)(void) = NULL;
+void (*pm_idle)(void);
/*
* Power off function, if any
*/
-void (*pm_power_off)(void) = NULL;
+void (*pm_power_off)(void);
void disable_hlt(void)
{
__setup("idle=", idle_setup);
-static long no_idt[2] = {0, 0};
-static int reboot_mode = 0;
-static int reboot_thru_bios = 0;
+static long no_idt[2];
+static int reboot_mode;
+static int reboot_thru_bios;
static int __init reboot_setup(char *str)
{
* Machine setup..
*/
-char ignore_irq13 = 0; /* set if exception 16 works */
+char ignore_irq13; /* set if exception 16 works */
struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
-unsigned long mmu_cr4_features = 0;
+unsigned long mmu_cr4_features;
/*
* Bus types ..
*/
-int EISA_bus = 0;
-int MCA_bus = 0;
+int EISA_bus;
+int MCA_bus;
/* for MCA, but anyone else can use it if they want */
-unsigned int machine_id = 0;
-unsigned int machine_submodel_id = 0;
-unsigned int BIOS_revision = 0;
-unsigned int mca_pentium_flag = 0;
+unsigned int machine_id;
+unsigned int machine_submodel_id;
+unsigned int BIOS_revision;
+unsigned int mca_pentium_flag;
/*
* Setup options
unsigned char table[0];
};
-struct e820map e820 = { 0 };
+struct e820map e820;
unsigned char aux_device_present;
#endif
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+static char command_line[COMMAND_LINE_SIZE];
char saved_command_line[COMMAND_LINE_SIZE];
struct resource standard_io_resources[] = {
*/
{
struct call_data_struct data;
- int ret, cpus = smp_num_cpus-1;
+ int cpus = smp_num_cpus-1;
if (!cpus)
return 0;
while (atomic_read(&data.started) != cpus)
barrier();
- ret = 0;
if (wait)
while (atomic_read(&data.finished) != cpus)
barrier();
#include <asm/pgalloc.h>
/* Set if we find a B stepping CPU */
-static int smp_b_stepping = 0;
+static int smp_b_stepping;
/* Setup configured maximum number of CPUs to activate */
static int max_cpus = -1;
int smp_num_cpus = 1;
/* Bitmask of currently online CPUs */
-unsigned long cpu_online_map = 0;
+unsigned long cpu_online_map;
/* which CPU (physical APIC ID) maps to which logical CPU number */
volatile int x86_apicid_to_cpu[NR_CPUS];
/* which logical CPU number maps to which CPU (physical APIC ID) */
volatile int x86_cpu_to_apicid[NR_CPUS];
-static volatile unsigned long cpu_callin_map = 0;
-static volatile unsigned long cpu_callout_map = 0;
+static volatile unsigned long cpu_callin_map;
+static volatile unsigned long cpu_callout_map;
/* Per CPU bogomips and other parameters */
struct cpuinfo_x86 cpu_data[NR_CPUS];
/* Set when the idlers are all forked */
-int smp_threads_ready = 0;
+int smp_threads_ready;
/*
* Setup routine for controlling SMP activation
static atomic_t tsc_start_flag = ATOMIC_INIT(0);
static atomic_t tsc_count_start = ATOMIC_INIT(0);
static atomic_t tsc_count_stop = ATOMIC_INIT(0);
-static unsigned long long tsc_values[NR_CPUS] = { 0, };
+static unsigned long long tsc_values[NR_CPUS];
#define NR_LOOPS 5
synchronize_tsc_ap();
}
-int cpucount = 0;
+int cpucount;
extern int cpu_idle(void);
static struct vm86_irqs {
struct task_struct *tsk;
int sig;
-} vm86_irqs[16] = {{0},};
-static int irqbits=0;
+} vm86_irqs[16];
+static int irqbits;
#define ALLOWED_SIGS ( 1 /* 0 = don't send a signal */ \
| (1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGIO) | (1 << SIGURG) \
t_addr = __va(phys_addr);
t_end = t_addr + (size - 1);
- for(page = virt_to_page(t_addr); page < virt_to_page(t_end); page++)
+ for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
if(!PageReserved(page))
return NULL;
}
* device more directly.
*/
-static int initialized = 0;
+static int initialized;
static int rs_debug_init(struct async_struct *info)
{
static char input_buffer[BUFMAX];
static char output_buffer[BUFMAX];
-static int initialized = 0; /* !0 means we've been initialized */
+static int initialized; /* !0 means we've been initialized */
static const char hexchars[]="0123456789abcdef";
static char remcomInBuffer[BUFMAX];
static char remcomOutBuffer[BUFMAX];
-static int initialized = 0;
-static int kgdb_active = 0;
-static int kgdb_started = 0;
+static int initialized;
+static int kgdb_active;
+static int kgdb_started;
static u_int fault_jmp_buf[100];
static int kdebug;
*/
#define BUFMAX 2048
-static int initialized = 0; /* !0 means we've been initialized */
+static int initialized; /* !0 means we've been initialized */
static const char hexchars[]="0123456789abcdef";
#
# Makefile for the Linux kernel device drivers.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (not a .c file).
+# 15 Sep 2000, Christoph Hellwig <hch@caldera.de>
+# Rewritten to use lists instead of if-statements.
#
-# Note 2! The CFLAGS definitions are now in the main makefile.
-SUB_DIRS := block char net parport sound misc media
-MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) pci sgi ide scsi sbus cdrom isdn pnp i2o \
- ieee1394 macintosh video dio zorro fc4 \
- usb nubus tc atm pcmcia i2c telephony \
- acpi mtd input md
-ifdef CONFIG_DIO
-SUB_DIRS += dio
-MOD_SUB_DIRS += dio
-endif
-
-ifdef CONFIG_PCI
-SUB_DIRS += pci
-endif
-
-ifeq ($(CONFIG_PCMCIA),y)
-SUB_DIRS += pcmcia
-else
- ifeq ($(CONFIG_PCMCIA),m)
- MOD_SUB_DIRS += pcmcia
- endif
-endif
-
-ifdef CONFIG_MTD
-SUB_DIRS += mtd
-MOD_SUB_DIRS += mtd
-endif
-
-ifdef CONFIG_SBUS
-SUB_DIRS += sbus
-MOD_SUB_DIRS += sbus
-endif
-
-ifdef CONFIG_ZORRO
-SUB_DIRS += zorro
-endif
-
-ifdef CONFIG_NUBUS
-SUB_DIRS += nubus
-endif
-
-ifdef CONFIG_TC
-SUB_DIRS += tc
-endif
-
-ifdef CONFIG_VT
-SUB_DIRS += video
-MOD_SUB_DIRS += video
-endif
-
-ifdef CONFIG_MAC
-SUB_DIRS += macintosh
-MOD_SUB_DIRS += macintosh
-endif
-
-ifdef CONFIG_ALL_PPC
-SUB_DIRS += macintosh
-MOD_SUB_DIRS += macintosh
-endif
-
-ifeq ($(CONFIG_USB),y)
-SUB_DIRS += usb
-MOD_SUB_DIRS += usb
-else
- ifeq ($(CONFIG_USB),m)
- MOD_SUB_DIRS += usb
- endif
-endif
-
-ifeq ($(CONFIG_INPUT),y)
-SUB_DIRS += input
-MOD_SUB_DIRS += input
-else
- ifeq ($(CONFIG_INPUT),m)
- MOD_SUB_DIRS += input
- endif
-endif
-
-ifeq ($(CONFIG_PHONE),y)
-SUB_DIRS += telephony
-MOD_SUB_DIRS += telephony
-else
- ifeq ($(CONFIG_PHONE),m)
- MOD_SUB_DIRS += telephony
- endif
-endif
-
-ifdef CONFIG_SGI
-SUB_DIRS += sgi
-MOD_SUB_DIRS += sgi
-endif
-
-ifeq ($(CONFIG_I2O),y)
-SUB_DIRS += i2o
-MOD_SUB_DIRS += i2o
-else
- ifeq ($(CONFIG_I2O),m)
- MOD_SUB_DIRS += i2o
- endif
-endif
-
-# If CONFIG_IDE is set, the core of ATA support will be added to the kernel,
-# but some of the low-level things may also be modules.
-ifeq ($(CONFIG_IDE),y)
-SUB_DIRS += ide
-MOD_SUB_DIRS += ide
-else
- ifeq ($(CONFIG_IDE),m)
- MOD_SUB_DIRS += ide
- endif
-endif
-
-# If CONFIG_SCSI is set, the core of SCSI support will be added to the kernel,
-# but some of the low-level things may also be modules.
-ifeq ($(CONFIG_SCSI),y)
-SUB_DIRS += scsi
-MOD_SUB_DIRS += scsi
-else
- ifeq ($(CONFIG_SCSI),m)
- MOD_SUB_DIRS += scsi
- endif
-endif
-
-ifeq ($(CONFIG_BLK_DEV_MD),y)
-SUB_DIRS += md
-MOD_SUB_DIRS += md
-else
- ifeq ($(CONFIG_BLK_DEV_MD),m)
- MOD_SUB_DIRS += md
- endif
-endif
-
-ifeq ($(CONFIG_IEEE1394),y)
-SUB_DIRS += ieee1394
-MOD_SUB_DIRS += ieee1394
-else
- ifeq ($(CONFIG_IEEE1394),m)
- MOD_SUB_DIRS += ieee1394
- endif
-endif
-
-ifeq ($(CONFIG_PNP),y)
-SUB_DIRS += pnp
-MOD_SUB_DIRS += pnp
-else
- ifeq ($(CONFIG_PNP),m)
- MOD_SUB_DIRS += pnp
- endif
-endif
-
-ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),)
-SUB_DIRS += cdrom
-MOD_SUB_DIRS += cdrom
-endif
-
-ifeq ($(CONFIG_ISDN),y)
-SUB_DIRS += isdn
-MOD_SUB_DIRS += isdn
-else
- ifeq ($(CONFIG_ISDN),m)
- MOD_SUB_DIRS += isdn
- endif
-endif
-
-ifdef CONFIG_ATM
-SUB_DIRS += atm
-MOD_SUB_DIRS += atm
-endif
-
-ifeq ($(CONFIG_FC4),y)
-SUB_DIRS += fc4
-MOD_SUB_DIRS += fc4
-else
- ifeq ($(CONFIG_FC4),m)
- MOD_SUB_DIRS += fc4
- endif
-endif
-
-# When MOD_LIST_NAME is set, make will try to add $(MOD_SUB_DIRS).o to
-# modules/MOD_LIST_NAME. We don't have hamradio.o and Linus
-# sort of insisted on making hamradio/ a subdirectory of drivers/net/.
-# #FIXME# MOD_LIST_NAME doesn't exist any more -- does this comment
-# #FIXME# still mean anything?
-
-ifeq ($(CONFIG_HAMRADIO),y)
- SUB_DIRS += net/hamradio
- MOD_SUB_DIRS += net/hamradio
-endif
-
-ifeq ($(CONFIG_I2C),y)
-SUB_DIRS += i2c
-MOD_SUB_DIRS += i2c
-else
- ifeq ($(CONFIG_I2C),m)
- MOD_SUB_DIRS += i2c
- endif
-endif
-
-ifeq ($(CONFIG_ACPI),y)
-SUB_DIRS += acpi
-MOD_SUB_DIRS += acpi
-endif
+mod-subdirs := dio mtd sbus video macintosh usb input telephony sgi i2o ide \
+ scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi
+
+subdir-y := block char net parport sound misc media cdrom
+subdir-m := $(subdir-y)
+
+
+subdir-$(CONFIG_DIO) += dio
+subdir-$(CONFIG_PCI) += pci
+subdir-$(CONFIG_PCMCIA) += pcmcia
+subdir-$(CONFIG_MTD) += mtd
+subdir-$(CONFIG_SBUS) += sbus
+subdir-$(CONFIG_ZORRO) += zorro
+subdir-$(CONFIG_NUBUS) += nubus
+subdir-$(CONFIG_TC) += tc
+subdir-$(CONFIG_VT) += video
+subdir-$(CONFIG_MAC) += macintosh
+subdir-$(CONFIG_ALL_PPC) += macintosh
+subdir-$(CONFIG_USB) += usb
+subdir-$(CONFIG_INPUT) += input
+subdir-$(CONFIG_PHONE) += telephony
+subdir-$(CONFIG_SGI) += sgi
+subdir-$(CONFIG_I2O) += i2o
+subdir-$(CONFIG_IDE) += ide
+subdir-$(CONFIG_SCSI) += scsi
+subdir-$(CONFIG_MD) += md
+subdir-$(CONFIG_IEEE1394) += ieee1394
+subdir-$(CONFIG_PNP) += pnp
+subdir-$(CONFIG_ISDN) += isdn
+subdir-$(CONFIG_ATM) += atm
+subdir-$(CONFIG_FC4) += fc4
+
+# CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set -- ch
+subdir-$(CONFIG_HAMRADIO) += net/hamradio
+subdir-$(CONFIG_I2C) += i2c
+subdir-$(CONFIG_ACPI) += acpi
+
+
+# Subdirectories that should be entered when MAKING_MODULES=1, even if set to 'y'.
+both-m := $(filter $(mod-subdirs), $(subdir-y))
+
+# Translate to Rules.make lists.
+SUB_DIRS := $(subdir-y)
+MOD_SUB_DIRS := $(sort $(subdir-m) $(both-m))
+ALL_SUB_DIRS := $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-))
+
+# net/hamradio is already in ALL_SUB_DIRS of drivers/net/Makefile
+ALL_SUB_DIRS := $(filter-out net/hamradio, $(ALL_SUB_DIRS))
include $(TOPDIR)/Rules.make
+
#define MAX_DISK_SIZE 720
static int floppy_sizes[256];
-static int floppy_blocksizes[256] = {0,};
+static int floppy_blocksizes[256];
/* current info on each unit */
static struct archy_floppy_struct {
/* defaults for 3 1/2" HD-Disks */
static int floppy_sizes[256]={880,880,880,880,720,720,720,720,};
-static int floppy_blocksizes[256]={0,};
+static int floppy_blocksizes[256];
/* hardsector size assumed to be 512 */
static int amiga_read(int), dos_read(int);
};
/* current info on each unit */
-static struct amiga_floppy_struct unit[FD_MAX_UNITS] = {{ 0,}};
+static struct amiga_floppy_struct unit[FD_MAX_UNITS];
static struct timer_list flush_track_timer[FD_MAX_UNITS];
static struct timer_list post_write_timer;
/* Synchronization of FDC access */
/* request loop (trackbuffer) */
static volatile int fdc_busy = -1;
-static volatile int fdc_nested = 0;
+static volatile int fdc_nested;
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
static DECLARE_WAIT_QUEUE_HEAD(motor_wait);
static volatile int selected = -1; /* currently selected drive */
-static int writepending = 0;
-static int writefromint = 0;
+static int writepending;
+static int writefromint;
static char *raw_buf;
#define RAW_BUF_SIZE 30000 /* size of raw disk data */
* information to interrupts. They are the data used for the current
* request.
*/
-static volatile char block_flag = 0;
+static volatile char block_flag;
static DECLARE_WAIT_QUEUE_HEAD(wait_fd_block);
/* MS-Dos MFM Coding tables (should go quick and easy) */
pciinfo.bus = hba[ctlr]->pci_bus;
pciinfo.dev_fn = hba[ctlr]->pci_dev_fn;
pciinfo.board_id = hba[ctlr]->board_id;
- if (copy_to_user((void *) arg, &pciinfo, sizeof( cciss_pci_info_struct ))
+ if (copy_to_user((void *) arg, &pciinfo, sizeof( cciss_pci_info_struct )))
return -EFAULT;
return(0);
}
if (!arg) return -EINVAL;
intinfo.delay = readl(&c->cfgtable->HostWrite.CoalIntDelay);
intinfo.count = readl(&c->cfgtable->HostWrite.CoalIntCount);
- if (copy_to_user((void *) arg, &intinfo, sizeof( cciss_coalint_struct ))
+ if (copy_to_user((void *) arg, &intinfo, sizeof( cciss_coalint_struct )))
return -EFAULT;
return(0);
}
if (!arg) return -EINVAL;
if (!capable(CAP_SYS_ADMIN)) return -EPERM;
- if (copy_from_user(&intinfo, (void *) arg, sizeof( cciss_coalint_struct))
+ if (copy_from_user(&intinfo, (void *) arg, sizeof( cciss_coalint_struct)))
return -EFAULT;
if ( (intinfo.delay == 0 ) && (intinfo.count == 0))
if (!arg) return -EINVAL;
for(i=0;i<16;i++)
NodeName[i] = readb(&c->cfgtable->ServerName[i]);
- if (copy_to_user((void *) arg, NodeName, sizeof( NodeName_type))
+ if (copy_to_user((void *) arg, NodeName, sizeof( NodeName_type)))
return -EFAULT;
return(0);
}
if (!arg) return -EINVAL;
if (!capable(CAP_SYS_ADMIN)) return -EPERM;
- if (copy_from_user(NodeName, (void *) arg, sizeof( NodeName_type))
+ if (copy_from_user(NodeName, (void *) arg, sizeof( NodeName_type)))
return -EFAULT;
spin_lock_irqsave(&io_request_lock, flags);
if (!arg) return -EINVAL;
heartbeat = readl(&c->cfgtable->HeartBeat);
- if (copy_to_user((void *) arg, &heartbeat, sizeof( Heartbeat_type))
+ if (copy_to_user((void *) arg, &heartbeat, sizeof( Heartbeat_type)))
return -EFAULT;
return(0);
}
if (!arg) return -EINVAL;
BusTypes = readl(&c->cfgtable->BusTypes);
- if (copy_to_user((void *) arg, &BusTypes, sizeof( BusTypes_type) )
+ if (copy_to_user((void *) arg, &BusTypes, sizeof( BusTypes_type) ))
return -EFAULT;
return(0);
}
if (!arg) return -EINVAL;
memcpy(firmware, hba[ctlr]->firm_ver, 4);
- if (copy_to_user((void *) arg, firmware, sizeof( FirmwareVer_type))
+ if (copy_to_user((void *) arg, firmware, sizeof( FirmwareVer_type)))
return -EFAULT;
return(0);
}
if (!arg) return -EINVAL;
- if (copy_to_user((void *) arg, &DriverVer, sizeof( DriverVer_type) )
+ if (copy_to_user((void *) arg, &DriverVer, sizeof( DriverVer_type) ))
return -EFAULT;
return(0);
}
if (!capable(CAP_SYS_RAWIO)) return -EPERM;
- if (copy_from_user(&iocommand, (void *) arg, sizeof( IOCTL_Command_struct) )
+ if (copy_from_user(&iocommand, (void *) arg, sizeof( IOCTL_Command_struct) ))
return -EFAULT;
if((iocommand.buf_size < 1) &&
(iocommand.Request.Type.Direction != XFER_NONE))
* It's been recommended that take about 1/4 of the default speed
* in some more extreme cases.
*/
-static int slow_floppy = 0;
+static int slow_floppy;
#include <asm/dma.h>
#include <asm/irq.h>
void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs);
static int set_dor(int fdc, char mask, char data);
static void register_devfs_entries (int drive) __init;
-static devfs_handle_t devfs_handle = NULL;
+static devfs_handle_t devfs_handle;
#define K_64 0x10000 /* 64KB */
#include <asm/floppy.h>
-static int irqdma_allocated = 0;
+static int irqdma_allocated;
#define MAJOR_NR FLOPPY_MAJOR
/* End dma memory related stuff */
-static unsigned long fake_change = 0;
+static unsigned long fake_change;
static int initialising=1;
static inline int TYPE(kdev_t x) {
#define SECTSIZE (_FD_SECTSIZE(*floppy))
/* Auto-detection: Disk type used until the next media change occurs. */
-static struct floppy_struct *current_type[N_DRIVE] = {
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
-};
+static struct floppy_struct *current_type[N_DRIVE];
/*
* User-provided type information. current_type points to
static struct floppy_struct user_params[N_DRIVE];
static int floppy_sizes[256];
-static int floppy_blocksizes[256] = { 0, };
+static int floppy_blocksizes[256];
/*
* The driver is trying to determine the correct media format
* while probing is set. rw_interrupt() clears it after a
* successful access.
*/
-static int probing = 0;
+static int probing;
/* Synchronization of FDC access. */
#define FD_COMMAND_NONE -1
#define FD_COMMAND_OKAY 3
static volatile int command_status = FD_COMMAND_NONE;
-static unsigned long fdc_busy = 0;
+static unsigned long fdc_busy;
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
static DECLARE_WAIT_QUEUE_HEAD(command_done);
#define NEED_1_RECAL -2
#define NEED_2_RECAL -3
-/* */
-static int usage_count = 0;
-
+static int usage_count;
/* buffer related variables */
static int buffer_track = -1;
static int fdc; /* current fdc */
static struct floppy_struct *_floppy = floppy_type;
-static unsigned char current_drive = 0;
-static long current_count_sectors = 0;
+static unsigned char current_drive;
+static long current_count_sectors;
static unsigned char sector_t; /* sector in track */
static unsigned char in_sector_offset; /* offset within physical sector,
* expressed in units of 512 bytes */
#define OLOGSIZE 20
-static void (*lasthandler)(void) = NULL;
+static void (*lasthandler)(void);
static unsigned long interruptjiffies;
static unsigned long resultjiffies;
static int resultsize;
{
}
-static struct tq_struct floppy_tq =
-{ 0, 0, 0, 0 };
+static struct tq_struct floppy_tq;
static void schedule_bh( void (*handler)(void*) )
{
} /* perpendicular_mode */
static int fifo_depth = 0xa;
-static int no_fifo = 0;
+static int no_fifo;
static int fdc_configure(void)
{
return;
cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
+#ifdef CONFIG_PROC_FS
cdrom_root_table->child->de->owner = THIS_MODULE;
-
+#endif /* CONFIG_PROC_FS */
/* set the defaults */
cdrom_sysctl_settings.autoclose = autoclose;
cdrom_sysctl_settings.autoeject = autoeject;
static unsigned short read_status_reg;
static unsigned short data_reg;
-static int initialized = 0; /* Has the drive been initialized? */
+static int initialized; /* Has the drive been initialized? */
static int sony_disc_changed = 1; /* Has the disk been changed
since the last check? */
-static int sony_toc_read = 0; /* Has the table of contents been
+static int sony_toc_read; /* Has the table of contents been
read? */
static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead
buffer. */
static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of
the read-ahead buffer. */
-static unsigned int sony_usage = 0; /* How many processes have the
+static unsigned int sony_usage; /* How many processes have the
drive open. */
static int sony_first_block = -1; /* First OS block (512 byte) in
static Byte **sony_buffer; /* Points to the pointers
to the sector buffers */
-static int sony_inuse = 0; /* is the drive in use? Only one
+static int sony_inuse; /* is the drive in use? Only one
open at a time allowed */
/*
* I just kept the CDU-31A driver behavior rather than using the PAUSE
* command on the CDU-535.
*/
-static Byte cur_pos_msf[3] = {0, 0, 0};
-static Byte final_pos_msf[3] = {0, 0, 0};
+static Byte cur_pos_msf[3];
+static Byte final_pos_msf[3];
/* What IRQ is the drive using? 0 if none. */
static int sony535_irq_used = CDU535_INTERRUPT;
tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
fi
fi
-bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED
+dep_bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL
if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ
bool 'Watchdog Timer Support' CONFIG_WATCHDOG
if [ "$CONFIG_WATCHDOG" != "n" ]; then
bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
+ tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG
tristate ' WDT Watchdog timer' CONFIG_WDT
tristate ' WDT PCI Watchdog timer' CONFIG_WDTPCI
if [ "$CONFIG_WDT" != "n" ]; then
bool ' Fan Tachometer' CONFIG_WDT_501_FAN
fi
fi
- tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG
tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT
obj-$(CONFIG_APPLICOM) += applicom.o
obj-$(CONFIG_MS_BUSMOUSE) += msbusmouse.o
obj-$(CONFIG_82C710_MOUSE) += qpmouse.o
-obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
-obj-$(CONFIG_PCWATCHDOG) += pcwd.o
-obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
-obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
-obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
obj-$(CONFIG_AMIGAMOUSE) += amigamouse.o
obj-$(CONFIG_ATARIMOUSE) += atarimouse.o
obj-$(CONFIG_ADBMOUSE) += adbmouse.o
obj-$(CONFIG_PC110_PAD) += pc110pad.o
-obj-$(CONFIG_WDT) += wdt.o
-obj-$(CONFIG_WDTPCI) += wdt_pci.o
obj-$(CONFIG_RTC) += rtc.o
obj-$(CONFIG_EFI_RTC) += efirtc.o
ifeq ($(CONFIG_PPC),)
obj-$(CONFIG_NVRAM) += nvram.o
endif
obj-$(CONFIG_TOSHIBA) += toshiba.o
-
-obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
-obj-$(CONFIG_977_WATCHDOG) += wdt977.o
-obj-$(CONFIG_I810_TCO) += i810-tco.o
obj-$(CONFIG_DS1620) += ds1620.o
obj-$(CONFIG_INTEL_RNG) += i810_rng.o
endif
endif
+# Only one watchdog can succeed. We probe the hardware watchdog
+# drivers first, then the softdog driver. This means if your hardware
+# watchdog dies or is 'borrowed' for some reason the software watchdog
+# still gives you some cover.
+
+obj-$(CONFIG_PCWATCHDOG) += pcwd.o
+obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
+obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
+obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
+obj-$(CONFIG_WDT) += wdt.o
+obj-$(CONFIG_WDTPCI) += wdt_pci.o
+obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
+obj-$(CONFIG_977_WATCHDOG) += wdt977.o
+obj-$(CONFIG_I810_TCO) += i810-tco.o
+obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+
+
# Extract lists of the multi-part drivers.
# The 'int-*' lists are the intermediate files used to build the multi's.
0
};
-#ifdef MODULE
-
-#define acq_init init_module
-
-void cleanup_module(void)
-{
- misc_deregister(&acq_miscdev);
- unregister_reboot_notifier(&acq_notifier);
- release_region(WDT_STOP,1);
- release_region(WDT_START,1);
-}
-
-#endif
-
-int __init acq_init(void)
+static int __init acq_init(void)
{
printk("WDT driver for Acquire single board computer initialising.\n");
register_reboot_notifier(&acq_notifier);
return 0;
}
+
+static void __exit acq_exit(void)
+{
+ misc_deregister(&acq_miscdev);
+ unregister_reboot_notifier(&acq_notifier);
+ release_region(WDT_STOP,1);
+ release_region(WDT_START,1);
+}
+module_init(acq_init);
+module_exit(acq_exit);
atomic_inc(&q->use_count);
if (atomic_read(&q->block_write)) {
- current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&q->write_queue, &entry);
atomic_inc(&q->block_count);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!atomic_read(&q->block_write)) break;
schedule();
if (signal_pending(current)) {
#ifndef _DRM_H_
#define _DRM_H_
+#if defined(__linux__)
#include <asm/ioctl.h> /* For _IO* macros */
+#define DRM_IOCTL_NR(n) _IOC_NR(n)
+#elif defined(__FreeBSD__)
+#include <sys/ioccom.h>
+#define DRM_IOCTL_NR(n) ((n) & 0xff)
+#endif
#define DRM_PROC_DEVICES "/proc/devices"
#define DRM_PROC_MISC "/proc/misc"
} drm_agp_info_t;
#define DRM_IOCTL_BASE 'd'
-#define DRM_IOCTL_NR(n) _IOC_NR(n)
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
#define DRM_IOR(nr,size) _IOR(DRM_IOCTL_BASE,nr,size)
#define DRM_IOW(nr,size) _IOW(DRM_IOCTL_BASE,nr,size)
struct drm_file *next;
struct drm_file *prev;
struct drm_device *dev;
+ int remove_auth_on_close;
} drm_file_t;
if (d->flags & _DRM_DMA_BLOCK) {
DRM_DEBUG("%d waiting\n", current->pid);
- current->state = TASK_INTERRUPTIBLE;
for (;;) {
- if (!last_buf->waiting
- && !last_buf->pending)
+ current->state = TASK_INTERRUPTIBLE;
+ if (!last_buf->waiting && !last_buf->pending)
break; /* finished */
schedule();
if (signal_pending(current)) {
}
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
ret = -EINTR;
/* Contention */
atomic_inc(&dev->total_sleeps);
- current->state = TASK_INTERRUPTIBLE;
schedule();
if (signal_pending(current)) {
ret = -ERESTARTSYS;
buf = i810_freelist_get(dev);
if (!buf) {
retcode = -ENOMEM;
- DRM_DEBUG("%s retcode %d\n", __FUNCTION__, retcode);
- goto out_get_buf;
+ DRM_DEBUG("retcode=%d\n", retcode);
+ return retcode;
}
retcode = i810_map_buffer(buf, filp);
if(retcode) {
i810_freelist_put(dev, buf);
- DRM_DEBUG("mapbuf failed in %s retcode %d\n",
- __FUNCTION__, retcode);
- goto out_get_buf;
+ DRM_DEBUG("mapbuf failed, retcode %d\n", retcode);
+ return retcode;
}
buf->pid = priv->pid;
buf_priv = buf->dev_private;
d->request_size = buf->total;
d->virtual = buf_priv->virtual;
-out_get_buf:
return retcode;
}
return;
}
atomic_set(&dev_priv->flush_done, 0);
- current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&dev_priv->flush_queue, &entry);
end = jiffies + (HZ*3);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
i810_dma_quiescent_emit(dev);
if (atomic_read(&dev_priv->flush_done) == 1) break;
if((signed)(end - jiffies) <= 0) {
return 0;
}
atomic_set(&dev_priv->flush_done, 0);
- current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&dev_priv->flush_queue, &entry);
end = jiffies + (HZ*3);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
i810_dma_emit_flush(dev);
if (atomic_read(&dev_priv->flush_done) == 1) break;
if((signed)(end - jiffies) <= 0) {
if (!ret) {
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
ret = -EINTR;
/* Contention */
atomic_inc(&dev->total_sleeps);
- current->state = TASK_INTERRUPTIBLE;
DRM_DEBUG("Calling lock schedule\n");
schedule();
if (signal_pending(current)) {
#define I810_NAME "i810"
#define I810_DESC "Intel I810"
-#define I810_DATE "20000910"
+#define I810_DATE "20000928"
#define I810_MAJOR 1
#define I810_MINOR 1
#define I810_PATCHLEVEL 0
DECLARE_WAITQUEUE(entry, current);
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
retcode = -EINTR;
}
/* Contention */
atomic_inc(&dev->total_sleeps);
- current->state = TASK_INTERRUPTIBLE;
schedule();
if (signal_pending(current)) {
retcode = -ERESTARTSYS;
int drm_waitlist_create(drm_waitlist_t *bl, int count)
{
- DRM_DEBUG("%d\n", count);
if (bl->count) return -EINVAL;
bl->count = count;
int drm_waitlist_destroy(drm_waitlist_t *bl)
{
- DRM_DEBUG("\n");
if (bl->rp != bl->wp) return -EINVAL;
if (bl->bufs) drm_free(bl->bufs,
(bl->count + 2) * sizeof(*bl->bufs),
unsigned long flags;
left = DRM_LEFTCOUNT(bl);
- DRM_DEBUG("put %d (%d left, rp = %p, wp = %p)\n",
- buf->idx, left, bl->rp, bl->wp);
if (!left) {
DRM_ERROR("Overflow while adding buffer %d from pid %d\n",
buf->idx, buf->pid);
if (++bl->rp >= bl->end) bl->rp = bl->bufs;
spin_unlock_irqrestore(&bl->read_lock, flags);
- DRM_DEBUG("get %d\n", buf->idx);
return buf;
}
int drm_freelist_create(drm_freelist_t *bl, int count)
{
- DRM_DEBUG("\n");
atomic_set(&bl->count, 0);
bl->next = NULL;
init_waitqueue_head(&bl->waiting);
int drm_freelist_destroy(drm_freelist_t *bl)
{
- DRM_DEBUG("\n");
atomic_set(&bl->count, 0);
bl->next = NULL;
return 0;
DRM_ERROR("Freed buffer %d: w%d, p%d, l%d\n",
buf->idx, buf->waiting, buf->pending, buf->list);
}
- DRM_DEBUG("%d, count = %d, wfh = %d, w%d, p%d\n",
- buf->idx, atomic_read(&bl->count), atomic_read(&bl->wfh),
- buf->waiting, buf->pending);
if (!bl) return 1;
#if DRM_DMA_HISTOGRAM
buf->time_freed = get_cycles();
atomic_dec(&bl->count);
buf->next = NULL;
buf->list = DRM_LIST_NONE;
- DRM_DEBUG("%d, count = %d, wfh = %d, w%d, p%d\n",
- buf->idx, atomic_read(&bl->count), atomic_read(&bl->wfh),
- buf->waiting, buf->pending);
if (buf->waiting || buf->pending) {
DRM_ERROR("Free buffer %d: w%d, p%d, l%d\n",
buf->idx, buf->waiting, buf->pending, buf->list);
if (atomic_read(&bl->count) <= bl->low_mark) /* Became low */
atomic_set(&bl->wfh, 1);
if (atomic_read(&bl->wfh)) {
- DRM_DEBUG("Block = %d, count = %d, wfh = %d\n",
- block, atomic_read(&bl->count),
- atomic_read(&bl->wfh));
if (block) {
add_wait_queue(&bl->waiting, &entry);
- current->state = TASK_INTERRUPTIBLE;
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!atomic_read(&bl->wfh)
&& (buf = drm_freelist_try(bl))) break;
schedule();
return buf;
}
- DRM_DEBUG("Count = %d, wfh = %d\n",
- atomic_read(&bl->count), atomic_read(&bl->wfh));
return drm_freelist_try(bl);
}
{
unsigned int old, new, prev;
- DRM_DEBUG("%d attempts\n", context);
do {
old = *lock;
if (old & _DRM_LOCK_HELD) new = old | _DRM_LOCK_CONT;
}
if (new == (context | _DRM_LOCK_HELD)) {
/* Have lock */
- DRM_DEBUG("%d\n", context);
return 1;
}
- DRM_DEBUG("%d unable to get lock held by %d\n",
- context, _DRM_LOCKING_CONTEXT(old));
return 0;
}
new = context | _DRM_LOCK_HELD;
prev = cmpxchg(lock, old, new);
} while (prev != old);
- DRM_DEBUG("%d => %d\n", _DRM_LOCKING_CONTEXT(old), context);
return 1;
}
unsigned int old, new, prev;
pid_t pid = dev->lock.pid;
- DRM_DEBUG("%d\n", context);
dev->lock.pid = 0;
do {
old = *lock;
atomic_inc(&q->use_count);
if (atomic_read(&q->use_count) > 1) {
atomic_inc(&q->block_write);
- current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&q->flush_queue, &entry);
atomic_inc(&q->block_count);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!DRM_BUFCOUNT(&q->waitlist)) break;
schedule();
if (signal_pending(current)) {
order = drm_order(request.size);
size = 1 << order;
agp_offset = request.agp_start;
- alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
+ alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
byte_count = 0;
buf->order = order;
buf->used = 0;
- DRM_DEBUG("offset : %ld\n", offset);
-
buf->offset = offset; /* Hrm */
buf->bus_address = dev->agp->base + agp_offset + offset;
buf->address = (void *)(agp_offset + offset + dev->agp->base);
init_waitqueue_head(&buf->dma_wait);
buf->pid = 0;
- buf->dev_private = drm_alloc(sizeof(drm_mga_buf_priv_t), DRM_MEM_BUFS);
+ buf->dev_private = drm_alloc(sizeof(drm_mga_buf_priv_t),
+ DRM_MEM_BUFS);
buf->dev_priv_size = sizeof(drm_mga_buf_priv_t);
#if DRM_DMA_HISTOGRAM
offset = offset + alignment;
entry->buf_count++;
byte_count += PAGE_SIZE << page_order;
-
- DRM_DEBUG("buffer %d @ %p\n",
- entry->buf_count, buf->address);
}
dma->buflist = drm_realloc(dma->buflist,
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
if (dev->queue_count) return -EBUSY; /* Not while in use */
- alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
+ alignment = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
total = PAGE_SIZE << page_order;
if (dma->bufs[i].buf_count) ++count;
}
- DRM_DEBUG("count = %d\n", count);
-
if (request.count >= count) {
for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
if (dma->bufs[i].buf_count) {
sizeof(dma->bufs[0]
.freelist.high_mark)))
return -EFAULT;
-
- DRM_DEBUG("%d %d %d %d %d\n",
- i,
- dma->bufs[i].buf_count,
- dma->bufs[i].buf_size,
- dma->bufs[i].freelist.low_mark,
- dma->bufs[i].freelist.high_mark);
++count;
}
}
if (!dma) return -EINVAL;
- if (copy_from_user(&request,
- (drm_buf_desc_t *)arg,
- sizeof(request)))
+ if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
return -EFAULT;
- DRM_DEBUG("%d, %d, %d\n",
- request.size, request.low_mark, request.high_mark);
order = drm_order(request.size);
if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
entry = &dma->bufs[order];
sizeof(request)))
return -EFAULT;
- DRM_DEBUG("%d\n", request.count);
for (i = 0; i < request.count; i++) {
if (copy_from_user(&idx,
&request.list[i],
if (!dma) return -EINVAL;
- DRM_DEBUG("\n");
-
spin_lock(&dev->count_lock);
if (atomic_read(&dev->buf_alloc)) {
spin_unlock(&dev->count_lock);
- DRM_DEBUG("Busy\n");
return -EBUSY;
}
++dev->buf_use; /* Can't allocate more after this call */
sizeof(request)))
return -EFAULT;
- DRM_DEBUG("mga_mapbufs\n");
- DRM_DEBUG("dma->flags : %x\n", dma->flags);
-
if (request.count >= dma->buf_count) {
if(dma->flags & _DRM_DMA_USE_AGP) {
drm_mga_private_t *dev_priv = dev->dev_private;
map = dev->maplist[dev_priv->buffer_map_idx];
if (!map) {
- DRM_DEBUG("map is null\n");
retcode = -EINVAL;
goto done;
}
static int mga_alloc_queue(drm_device_t *dev)
{
- int temp = drm_ctxbitmap_next(dev);
- DRM_DEBUG("mga_alloc_queue: %d\n", temp);
- return temp;
+ return drm_ctxbitmap_next(dev);
}
int mga_context_switch(drm_device_t *dev, int old, int new)
drm_ctx_t ctx;
int i;
- DRM_DEBUG("%d\n", DRM_RESERVED_CONTEXTS);
if (copy_from_user(&res, (drm_ctx_res_t *)arg, sizeof(res)))
return -EFAULT;
if (res.count >= DRM_RESERVED_CONTEXTS) {
ctx.handle = mga_alloc_queue(dev);
}
if (ctx.handle == -1) {
- DRM_DEBUG("Not enough free contexts.\n");
- /* Should this return -EBUSY instead? */
return -ENOMEM;
}
DRM_DEBUG("%d\n", ctx.handle);
if (copy_from_user(&ctx, (drm_ctx_t *)arg, sizeof(ctx)))
return -EFAULT;
DRM_DEBUG("%d\n", ctx.handle);
+ if(ctx.handle == DRM_KERNEL_CONTEXT+1) priv->remove_auth_on_close = 1;
+
if(ctx.handle != DRM_KERNEL_CONTEXT) {
drm_ctxbitmap_free(dev, ctx.handle);
}
{
unsigned long address;
- DRM_DEBUG("%s\n", __FUNCTION__);
address = __get_free_page(GFP_KERNEL);
if(address == 0UL) {
return 0;
}
atomic_inc(&virt_to_page(address)->count);
- set_bit(PG_locked, &virt_to_page(address)->flags);
+ set_bit(PG_reserved, &virt_to_page(address)->flags);
return address;
}
static void mga_free_page(drm_device_t *dev, unsigned long page)
{
- DRM_DEBUG("%s\n", __FUNCTION__);
-
- if(page == 0UL) {
- return;
- }
+ if(!page) return;
atomic_dec(&virt_to_page(page)->count);
- clear_bit(PG_locked, &virt_to_page(page)->flags);
- wake_up(&virt_to_page(page)->wait);
+ clear_bit(PG_reserved, &virt_to_page(page)->flags);
free_page(page);
return;
}
static void mga_delay(void)
{
- return;
+ return;
}
/* These are two age tags that will never be sent to
drm_mga_freelist_t *item;
int i;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
if(dev_priv->head == NULL) return -ENOMEM;
memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
drm_mga_freelist_t *item;
drm_mga_freelist_t *prev;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
item = dev_priv->head;
while(item) {
prev = item;
unsigned long end;
int i;
- DRM_DEBUG("%s\n", __FUNCTION__);
+ DRM_DEBUG("dispatch_status = 0x%02x\n", dev_priv->dispatch_status);
end = jiffies + (HZ*3);
while(1) {
if(!test_and_set_bit(MGA_IN_DISPATCH,
DRM_ERROR("irqs: %d wanted %d\n",
atomic_read(&dev->total_irq),
atomic_read(&dma->total_lost));
- DRM_ERROR("lockup\n");
- goto out_nolock;
+ DRM_ERROR("lockup: dispatch_status = 0x%02x,"
+ " jiffies = %lu, end = %lu\n",
+ dev_priv->dispatch_status, jiffies, end);
+ return;
}
for (i = 0 ; i < 2000 ; i++) mga_delay();
}
atomic_read(&dev->total_irq),
atomic_read(&dma->total_lost));
DRM_ERROR("lockup\n");
- goto out_status;
+ clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
+ return;
}
for (i = 0 ; i < 2000 ; i++) mga_delay();
}
sarea_priv->dirty |= MGA_DMA_FLUSH;
-out_status:
clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
-out_nolock:
+ DRM_DEBUG("exit, dispatch_status = 0x%02x\n",
+ dev_priv->dispatch_status);
}
static void mga_reset_freelist(drm_device_t *dev)
static int failed = 0;
int return_null = 0;
- DRM_DEBUG("%s : tail->age : %d last_prim_age : %d\n", __FUNCTION__,
- dev_priv->tail->age, dev_priv->last_prim_age);
-
if(failed >= 1000 && dev_priv->tail->age >= dev_priv->last_prim_age) {
- DRM_DEBUG("I'm waiting on the freelist!!! %d\n",
- dev_priv->last_prim_age);
- set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
+ DRM_DEBUG("Waiting on freelist,"
+ " tail->age = %d, last_prim_age= %d\n",
+ dev_priv->tail->age,
+ dev_priv->last_prim_age);
add_wait_queue(&dev_priv->buf_queue, &entry);
+ set_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
for (;;) {
- mga_dma_schedule(dev, 0);
current->state = TASK_INTERRUPTIBLE;
- if(!test_bit(MGA_IN_GETBUF,
- &dev_priv->dispatch_status))
+ mga_dma_schedule(dev, 0);
+ if(dev_priv->tail->age < dev_priv->last_prim_age)
break;
atomic_inc(&dev->total_sleeps);
schedule();
if (signal_pending(current)) {
++return_null;
- clear_bit(MGA_IN_GETBUF,
- &dev_priv->dispatch_status);
break;
}
}
+ clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
current->state = TASK_RUNNING;
remove_wait_queue(&dev_priv->buf_queue, &entry);
if (return_null) return NULL;
failed = 0;
return next->buf;
}
+
failed++;
return NULL;
}
drm_mga_freelist_t *head;
drm_mga_freelist_t *next;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if(buf_priv->my_freelist->age == MGA_BUF_USED) {
/* Discarded buffer, put it on the tail */
next = buf_priv->my_freelist;
next->prev = prev;
next->next = NULL;
dev_priv->tail = next;
- DRM_DEBUG("Discarded\n");
} else {
/* Normally aged buffer, put it on the head + 1,
* as the real head is a sentinal element
int i, temp, size_of_buf;
int offset = init->reserved_map_agpstart;
- DRM_DEBUG("%s\n", __FUNCTION__);
dev_priv->primary_size = ((init->primary_size + PAGE_SIZE - 1) /
PAGE_SIZE) * PAGE_SIZE;
size_of_buf = dev_priv->primary_size / MGA_NUM_PRIM_BUFS;
dev_priv->ioremap = drm_ioremap(dev->agp->base + offset,
temp);
if(dev_priv->ioremap == NULL) {
- DRM_DEBUG("Ioremap failed\n");
+ DRM_ERROR("Ioremap failed\n");
return -ENOMEM;
}
init_waitqueue_head(&dev_priv->wait_queue);
int next_idx;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
dev_priv->last_prim = prim;
/* We never check for overflow, b/c there is always room */
end = jiffies + (HZ*3);
if(sarea_priv->dirty & MGA_DMA_FLUSH) {
- DRM_DEBUG("Dma top flush\n");
while((MGA_READ(MGAREG_STATUS) & 0x00030001) != 0x00020000) {
if((signed)(end - jiffies) <= 0) {
DRM_ERROR("irqs: %d wanted %d\n",
atomic_read(&dev->total_irq),
atomic_read(&dma->total_lost));
- DRM_ERROR("lockup in fire primary "
- "(Dma Top Flush)\n");
+ DRM_ERROR("lockup (flush)\n");
goto out_prim_wait;
}
}
sarea_priv->dirty &= ~(MGA_DMA_FLUSH);
} else {
- DRM_DEBUG("Status wait\n");
while((MGA_READ(MGAREG_STATUS) & 0x00020001) != 0x00020000) {
if((signed)(end - jiffies) <= 0) {
DRM_ERROR("irqs: %d wanted %d\n",
atomic_read(&dev->total_irq),
atomic_read(&dma->total_lost));
- DRM_ERROR("lockup in fire primary "
- "(Status Wait)\n");
+ DRM_ERROR("lockup (wait)\n");
goto out_prim_wait;
}
/* This needs to reset the primary buffer if available,
* we should collect stats on how many times it bites
* it's tail */
- DRM_DEBUG("%s\n", __FUNCTION__);
next_prim_idx = dev_priv->current_prim_idx + 1;
if(next_prim_idx >= MGA_NUM_PRIM_BUFS)
if(test_and_set_bit(MGA_BUF_IN_USE, &prim_buffer->buffer_status)) {
add_wait_queue(&dev_priv->wait_queue, &entry);
- current->state = TASK_INTERRUPTIBLE;
-
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
mga_dma_schedule(dev, 0);
if(!test_and_set_bit(MGA_BUF_IN_USE,
&prim_buffer->buffer_status))
break;
}
}
- current->state = TASK_RUNNING;
+ current->state = TASK_RUNNING;
remove_wait_queue(&dev_priv->wait_queue, &entry);
if(ret) return ret;
}
prim_buffer->sec_used = 0;
prim_buffer->prim_age = dev_priv->next_prim_age++;
if(prim_buffer->prim_age == 0 || prim_buffer->prim_age == 0xffffffff) {
- mga_flush_queue(dev);
- mga_dma_quiescent(dev);
- mga_reset_freelist(dev);
- prim_buffer->prim_age = (dev_priv->next_prim_age += 2);
+ mga_flush_queue(dev);
+ mga_dma_quiescent(dev);
+ mga_reset_freelist(dev);
+ prim_buffer->prim_age = (dev_priv->next_prim_age += 2);
}
/* Reset all buffer status stuff */
static inline int mga_decide_to_fire(drm_device_t *dev)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
-
- DRM_DEBUG("%s\n", __FUNCTION__);
if(test_bit(MGA_BUF_FORCE_FIRE, &dev_priv->next_prim->buffer_status)) {
- atomic_inc(&dma->total_prio);
return 1;
}
if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) &&
dev_priv->next_prim->num_dwords) {
- atomic_inc(&dma->total_prio);
return 1;
}
if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
dev_priv->next_prim->num_dwords) {
- atomic_inc(&dma->total_prio);
return 1;
}
if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS - 1) {
if(test_bit(MGA_BUF_SWAP_PENDING,
&dev_priv->next_prim->buffer_status)) {
- atomic_inc(&dma->total_dmas);
return 1;
}
}
if(atomic_read(&dev_priv->pending_bufs) <= MGA_NUM_PRIM_BUFS / 2) {
if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 8) {
- atomic_inc(&dma->total_hit);
return 1;
}
}
if(atomic_read(&dev_priv->pending_bufs) >= MGA_NUM_PRIM_BUFS / 2) {
if(dev_priv->next_prim->sec_used >= MGA_DMA_BUF_NR / 4) {
- atomic_inc(&dma->total_missed_free);
return 1;
}
}
- atomic_inc(&dma->total_tried);
return 0;
}
int mga_dma_schedule(drm_device_t *dev, int locked)
{
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- drm_device_dma_t *dma = dev->dma;
- int retval = 0;
+ int retval = 0;
- if (test_and_set_bit(0, &dev->dma_flag)) {
- atomic_inc(&dma->total_missed_dma);
+ if (!dev_priv) return -EBUSY;
+
+ if (test_and_set_bit(0, &dev->dma_flag)) {
retval = -EBUSY;
goto sch_out_wakeup;
}
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) ||
test_bit(MGA_IN_WAIT, &dev_priv->dispatch_status) ||
test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) {
if (!locked &&
!drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT)) {
- atomic_inc(&dma->total_missed_lock);
clear_bit(0, &dev->dma_flag);
- DRM_DEBUG("Not locked\n");
retval = -EBUSY;
goto sch_out_wakeup;
}
- DRM_DEBUG("I'm locked\n");
if(!test_and_set_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status)) {
/* Fire dma buffer */
if(mga_decide_to_fire(dev)) {
- DRM_DEBUG("idx :%d\n", dev_priv->next_prim->idx);
clear_bit(MGA_BUF_FORCE_FIRE,
&dev_priv->next_prim->buffer_status);
if(dev_priv->current_prim == dev_priv->next_prim) {
} else {
clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
}
- } else {
- DRM_DEBUG("I can't get the dispatch lock\n");
}
if (!locked) {
}
}
+ clear_bit(0, &dev->dma_flag);
+
sch_out_wakeup:
if(test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status) &&
atomic_read(&dev_priv->pending_bufs) == 0) {
wake_up_interruptible(&dev_priv->flush_queue);
}
- if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status) &&
- dev_priv->tail->age < dev_priv->last_prim_age) {
- clear_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status);
- DRM_DEBUG("Waking up buf queue\n");
+ if(test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)
+ && dev_priv->tail->age < dev_priv->last_prim_age)
wake_up_interruptible(&dev_priv->buf_queue);
- } else if (test_bit(MGA_IN_GETBUF, &dev_priv->dispatch_status)) {
- DRM_DEBUG("Not waking buf_queue on %d %d\n",
- atomic_read(&dev->total_irq),
- dev_priv->last_prim_age);
- }
- clear_bit(0, &dev->dma_flag);
return retval;
}
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
drm_mga_prim_buf_t *last_prim_buffer;
- DRM_DEBUG("%s\n", __FUNCTION__);
atomic_inc(&dev->total_irq);
if((MGA_READ(MGAREG_STATUS) & 0x00000001) != 0x00000001) return;
MGA_WRITE(MGAREG_ICLEAR, 0x00000001);
dev_priv->sarea_priv->last_dispatch =
dev_priv->last_prim_age = last_prim_buffer->prim_age;
clear_bit(MGA_BUF_IN_USE, &last_prim_buffer->buffer_status);
- wake_up_interruptible(&dev_priv->wait_queue);
clear_bit(MGA_BUF_SWAP_PENDING, &last_prim_buffer->buffer_status);
clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
atomic_dec(&dev_priv->pending_bufs);
queue_task(&dev->tq, &tq_immediate);
mark_bh(IMMEDIATE_BH);
+ wake_up_interruptible(&dev_priv->wait_queue);
}
static void mga_dma_task_queue(void *device)
{
- DRM_DEBUG("%s\n", __FUNCTION__);
mga_dma_schedule((drm_device_t *)device, 0);
}
int mga_dma_cleanup(drm_device_t *dev)
{
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if(dev->dev_private) {
drm_mga_private_t *dev_priv =
(drm_mga_private_t *) dev->dev_private;
+ if (dev->irq) mga_flush_queue(dev);
+ mga_dma_quiescent(dev);
+
if(dev_priv->ioremap) {
int temp = (dev_priv->warp_ucode_size +
dev_priv->primary_size +
static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) {
drm_mga_private_t *dev_priv;
drm_map_t *sarea_map = NULL;
- int i;
-
- DRM_DEBUG("%s\n", __FUNCTION__);
dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
if(dev_priv == NULL) return -ENOMEM;
if((init->reserved_map_idx >= dev->map_count) ||
(init->buffer_map_idx >= dev->map_count)) {
mga_dma_cleanup(dev);
- DRM_DEBUG("reserved_map or buffer_map are invalid\n");
return -EINVAL;
}
dev_priv->WarpPipe = 0xff000000;
dev_priv->vertexsize = 0;
- DRM_DEBUG("chipset: %d ucode_size: %d backOffset: %x depthOffset: %x\n",
+ DRM_DEBUG("chipset=%d ucode_size=%d backOffset=%x depthOffset=%x\n",
dev_priv->chipset, dev_priv->warp_ucode_size,
dev_priv->backOffset, dev_priv->depthOffset);
DRM_DEBUG("cpp: %d sgram: %d stride: %d maccess: %x\n",
memcpy(&dev_priv->WarpIndex, &init->WarpIndex,
sizeof(drm_mga_warp_index_t) * MGA_MAX_WARP_PIPES);
- for (i = 0 ; i < MGA_MAX_WARP_PIPES ; i++)
- DRM_DEBUG("warp pipe %d: installed: %d phys: %lx size: %x\n",
- i,
- dev_priv->WarpIndex[i].installed,
- dev_priv->WarpIndex[i].phys_addr,
- dev_priv->WarpIndex[i].size);
-
if(mga_init_primary_bufs(dev, init) != 0) {
DRM_ERROR("Can not initialize primary buffers\n");
mga_dma_cleanup(dev);
drm_device_t *dev = priv->dev;
drm_mga_init_t init;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if (copy_from_user(&init, (drm_mga_init_t *)arg, sizeof(init)))
return -EFAULT;
if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
return -EFAULT;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
switch (ctl.func) {
case DRM_INST_HANDLER:
return mga_irq_install(dev, ctl.irq);
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
int ret = 0;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
- if(dev_priv == NULL) {
- return 0;
- }
+ if(!dev_priv) return 0;
if(dev_priv->next_prim->num_dwords != 0) {
- current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&dev_priv->flush_queue, &entry);
+ if (test_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status))
+ DRM_ERROR("Incorrect mga_flush_queue logic\n");
set_bit(MGA_IN_FLUSH, &dev_priv->dispatch_status);
mga_dma_schedule(dev, 0);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!test_bit(MGA_IN_FLUSH,
&dev_priv->dispatch_status))
break;
break;
}
}
- current->state = TASK_RUNNING;
+ current->state = TASK_RUNNING;
remove_wait_queue(&dev_priv->flush_queue, &entry);
}
return ret;
if(dev->dev_private == NULL) return;
if(dma->buflist == NULL) return;
- DRM_DEBUG("%s\n", __FUNCTION__);
+ DRM_DEBUG("buf_count=%d\n", dma->buf_count);
+
mga_flush_queue(dev);
for (i = 0; i < dma->buf_count; i++) {
int ret = 0;
drm_lock_t lock;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
return -EFAULT;
return -EINVAL;
}
- DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
- lock.context, current->pid, dev->lock.hw_lock->lock,
- lock.flags);
-
- if (lock.context < 0) {
- return -EINVAL;
- }
+ if (lock.context < 0) return -EINVAL;
/* Only one queue:
*/
if (!ret) {
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
ret = -EINTR;
/* Contention */
atomic_inc(&dev->total_sleeps);
- current->state = TASK_INTERRUPTIBLE;
schedule();
if (signal_pending(current)) {
ret = -ERESTARTSYS;
}
}
- DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
+ if (ret) DRM_DEBUG("%d %s\n", lock.context,
+ ret ? "interrupted" : "has lock");
return ret;
}
drm_lock_t lock;
drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
return -EFAULT;
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
- DRM_ERROR("mga_flush_ioctl called without lock held\n");
+ DRM_ERROR("lock not held\n");
return -EINVAL;
}
#define MGA_NAME "mga"
#define MGA_DESC "Matrox G200/G400"
-#define MGA_DATE "20000910"
+#define MGA_DATE "20000928"
#define MGA_MAJOR 2
#define MGA_MINOR 0
-#define MGA_PATCHLEVEL 0
+#define MGA_PATCHLEVEL 1
static drm_device_t mga_device;
drm_ctx_t mga_res_ctx;
DRM_DEBUG("\n");
+ if (dev->dev_private) mga_dma_cleanup(dev);
if (dev->irq) mga_irq_uninstall(dev);
down(&dev->struct_sem);
#ifdef MODULE
drm_parse_options(mga);
#endif
- DRM_DEBUG("doing misc_register\n");
if ((retcode = misc_register(&mga_misc))) {
DRM_ERROR("Cannot register \"%s\"\n", MGA_NAME);
return retcode;
dev->device = MKDEV(MISC_MAJOR, mga_misc.minor);
dev->name = MGA_NAME;
- DRM_DEBUG("doing mem init\n");
drm_mem_init();
- DRM_DEBUG("doing proc init\n");
drm_proc_init(dev);
- DRM_DEBUG("doing agp init\n");
dev->agp = drm_agp_init();
if(dev->agp == NULL) {
DRM_INFO("The mga drm module requires the agpgart module"
MTRR_TYPE_WRCOMB,
1);
#endif
- DRM_DEBUG("doing ctxbitmap init\n");
if((retcode = drm_ctxbitmap_init(dev))) {
DRM_ERROR("Cannot allocate memory for context bitmap.\n");
drm_proc_cleanup();
DRM_INFO("Module unloaded\n");
}
drm_ctxbitmap_cleanup(dev);
- mga_dma_cleanup(dev);
#ifdef CONFIG_MTRR
if(dev->agp && dev->agp->agp_mtrr) {
int retval;
if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
&& dev->lock.pid == current->pid) {
mga_reclaim_buffers(dev, priv->pid);
- DRM_ERROR("Process %d dead, freeing lock for context %d\n",
- current->pid,
- _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+ DRM_INFO("Process %d dead (ctx %d, d_s = 0x%02x)\n",
+ current->pid,
+ _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock),
+ dev->dev_private ?
+ ((drm_mga_private_t *)dev->dev_private)
+ ->dispatch_status
+ : 0);
+
+ if (dev->dev_private)
+ ((drm_mga_private_t *)dev->dev_private)
+ ->dispatch_status &= MGA_IN_DISPATCH;
+
drm_lock_free(dev,
&dev->lock.hw_lock->lock,
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-
- /* FIXME: may require heavy-handed reset of
- hardware at this point, possibly
- processed via a callback to the X
- server. */
} else if (dev->lock.hw_lock) {
/* The lock is required to reclaim buffers */
DECLARE_WAITQUEUE(entry, current);
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
retcode = -EINTR;
}
/* Contention */
atomic_inc(&dev->total_sleeps);
- current->state = TASK_INTERRUPTIBLE;
schedule();
if (signal_pending(current)) {
retcode = -ERESTARTSYS;
remove_wait_queue(&dev->lock.lock_queue, &entry);
if(!retcode) {
mga_reclaim_buffers(dev, priv->pid);
+ if (dev->dev_private)
+ ((drm_mga_private_t *)dev->dev_private)
+ ->dispatch_status &= MGA_IN_DISPATCH;
drm_lock_free(dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT);
}
drm_fasync(-1, filp, 0);
down(&dev->struct_sem);
+ if (priv->remove_auth_on_close == 1) {
+ drm_file_t *temp = dev->file_first;
+ while(temp) {
+ temp->authenticated = 0;
+ temp = temp->next;
+ }
+ }
if (priv->prev) priv->prev->next = priv->next;
else dev->file_first = priv->next;
if (priv->next) priv->next->prev = priv->prev;
atomic_inc(&dev->total_ioctl);
++priv->ioctl_count;
- DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n",
- current->pid, cmd, nr, dev->device, priv->authenticated);
-
if (nr >= MGA_IOCTL_COUNT) {
retcode = -EINVAL;
} else {
func = ioctl->func;
if (!func) {
- DRM_DEBUG("no function\n");
+ DRM_DEBUG("no function: pid = %d, cmd = 0x%02x,"
+ " nr = 0x%02x, dev 0x%x, auth = %d\n",
+ current->pid, cmd, nr, dev->device,
+ priv->authenticated);
retcode = -EINVAL;
} else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN))
|| (ioctl->auth_needed && !priv->authenticated)) {
return -EINVAL;
}
- DRM_DEBUG("%d frees lock (%d holds)\n",
- lock.context,
- _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
atomic_inc(&dev->total_unlocks);
if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock))
atomic_inc(&dev->total_contends);
mga_dma_schedule(dev, 1);
if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
- DRM_KERNEL_CONTEXT)) {
- DRM_ERROR("\n");
- }
+ DRM_KERNEL_CONTEXT)) DRM_ERROR("\n");
unblock_all_signals();
return 0;
} drm_mga_prim_buf_t;
typedef struct _drm_mga_freelist {
- unsigned int age;
+ __volatile__ unsigned int age;
drm_buf_t *buf;
struct _drm_mga_freelist *next;
struct _drm_mga_freelist *prev;
#define MGAREG_YTOP 0x1c98
#define MGAREG_ZORG 0x1c0c
+/* Warp registers */
+#define MGAREG_WR0 0x2d00
+#define MGAREG_WR1 0x2d04
+#define MGAREG_WR2 0x2d08
+#define MGAREG_WR3 0x2d0c
+#define MGAREG_WR4 0x2d10
+#define MGAREG_WR5 0x2d14
+#define MGAREG_WR6 0x2d18
+#define MGAREG_WR7 0x2d1c
+#define MGAREG_WR8 0x2d20
+#define MGAREG_WR9 0x2d24
+#define MGAREG_WR10 0x2d28
+#define MGAREG_WR11 0x2d2c
+#define MGAREG_WR12 0x2d30
+#define MGAREG_WR13 0x2d34
+#define MGAREG_WR14 0x2d38
+#define MGAREG_WR15 0x2d3c
+#define MGAREG_WR16 0x2d40
+#define MGAREG_WR17 0x2d44
+#define MGAREG_WR18 0x2d48
+#define MGAREG_WR19 0x2d4c
+#define MGAREG_WR20 0x2d50
+#define MGAREG_WR21 0x2d54
+#define MGAREG_WR22 0x2d58
+#define MGAREG_WR23 0x2d5c
+#define MGAREG_WR24 0x2d60
+#define MGAREG_WR25 0x2d64
+#define MGAREG_WR26 0x2d68
+#define MGAREG_WR27 0x2d6c
+#define MGAREG_WR28 0x2d70
+#define MGAREG_WR29 0x2d74
+#define MGAREG_WR30 0x2d78
+#define MGAREG_WR31 0x2d7c
+#define MGAREG_WR32 0x2d80
+#define MGAREG_WR33 0x2d84
+#define MGAREG_WR34 0x2d88
+#define MGAREG_WR35 0x2d8c
+#define MGAREG_WR36 0x2d90
+#define MGAREG_WR37 0x2d94
+#define MGAREG_WR38 0x2d98
+#define MGAREG_WR39 0x2d9c
+#define MGAREG_WR40 0x2da0
+#define MGAREG_WR41 0x2da4
+#define MGAREG_WR42 0x2da8
+#define MGAREG_WR43 0x2dac
+#define MGAREG_WR44 0x2db0
+#define MGAREG_WR45 0x2db4
+#define MGAREG_WR46 0x2db8
+#define MGAREG_WR47 0x2dbc
+#define MGAREG_WR48 0x2dc0
+#define MGAREG_WR49 0x2dc4
+#define MGAREG_WR50 0x2dc8
+#define MGAREG_WR51 0x2dcc
+#define MGAREG_WR52 0x2dd0
+#define MGAREG_WR53 0x2dd4
+#define MGAREG_WR54 0x2dd8
+#define MGAREG_WR55 0x2ddc
+#define MGAREG_WR56 0x2de0
+#define MGAREG_WR57 0x2de4
+#define MGAREG_WR58 0x2de8
+#define MGAREG_WR59 0x2dec
+#define MGAREG_WR60 0x2df0
+#define MGAREG_WR61 0x2df4
+#define MGAREG_WR62 0x2df8
+#define MGAREG_WR63 0x2dfc
+
#define PDEA_pagpxfer_enable 0x2
#define WIA_wmode_suspend 0x0
#define DC_clipdis_disable 0x0
#define DC_clipdis_enable 0x80000000
+
#define SETADD_mode_vertlist 0x0
#define MGAG200EMITTEX_SIZE 20
#define MGAG400EMITTEX0_SIZE 30
#define MGAG400EMITTEX1_SIZE 25
-#define MGAG400EMITPIPE_SIZE 55
+#define MGAG400EMITPIPE_SIZE 50
#define MGAG200EMITPIPE_SIZE 15
#define MAX_STATE_SIZE ((MGAEMITCLIP_SIZE * MGA_NR_SAREA_CLIPRECTS) + \
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int *regs = sarea_priv->ContextState;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
/* This takes 10 dwords */
PRIMGETPTR(dev_priv);
- /* Force reset of dwgctl (eliminates clip disable) */
+ /* Force reset of dwgctl on G400 (eliminates clip disable bit) */
+ if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
#if 0
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, 0);
- PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, 0);
+ PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
#else
- PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
- PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
+ PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
+ PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
+ PRIMOUTREG(MGAREG_DWGCTL, regs[MGA_CTXREG_DWGCTL]);
+ PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0x80000000);
#endif
-
+ }
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_CXBNDRY, ((box->x2) << 16) | (box->x1));
PRIMOUTREG(MGAREG_YTOP, box->y1 * dev_priv->stride / dev_priv->cpp);
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int *regs = sarea_priv->ContextState;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
/* This takes a max of 20 dwords */
PRIMGETPTR(dev_priv);
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int *regs = sarea_priv->TexState[0];
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
PRIMGETPTR(dev_priv);
PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
- PRIMOUTREG(0x2d00 + 24 * 4, regs[MGA_TEXREG_WIDTH]);
+ PRIMOUTREG(MGAREG_WR24, regs[MGA_TEXREG_WIDTH]);
- PRIMOUTREG(0x2d00 + 34 * 4, regs[MGA_TEXREG_HEIGHT]);
+ PRIMOUTREG(MGAREG_WR34, regs[MGA_TEXREG_HEIGHT]);
PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
PRIMOUTREG(MGAREG_DMAPAD, 0);
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int *regs = sarea_priv->TexState[0];
- int multitex = regs[MGA_TEXREG_CTL2] & TMC_dualtex_enable;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
PRIMGETPTR(dev_priv);
- /* This takes a max of 30 dwords */
+ /* This takes 30 dwords */
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
PRIMOUTREG(MGAREG_TEXCTL, regs[MGA_TEXREG_CTL]);
PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
- PRIMOUTREG(0x2d00 + 49 * 4, 0);
+ PRIMOUTREG(MGAREG_WR49, 0);
- PRIMOUTREG(0x2d00 + 57 * 4, 0);
- PRIMOUTREG(0x2d00 + 53 * 4, 0);
- PRIMOUTREG(0x2d00 + 61 * 4, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_WR57, 0);
+ PRIMOUTREG(MGAREG_WR53, 0);
+ PRIMOUTREG(MGAREG_WR61, 0);
+ PRIMOUTREG(MGAREG_WR52, 0x40);
- if (!multitex || 1) {
- PRIMOUTREG(0x2d00 + 52 * 4, 0x40);
- PRIMOUTREG(0x2d00 + 60 * 4, 0x40);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- }
+ PRIMOUTREG(MGAREG_WR60, 0x40);
+ PRIMOUTREG(MGAREG_WR54, regs[MGA_TEXREG_WIDTH] | 0x40);
+ PRIMOUTREG(MGAREG_WR62, regs[MGA_TEXREG_HEIGHT] | 0x40);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(0x2d00 + 54 * 4, regs[MGA_TEXREG_WIDTH] | 0x40);
- PRIMOUTREG(0x2d00 + 62 * 4, regs[MGA_TEXREG_HEIGHT] | 0x40);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
#define TMC_map1_enable 0x80000000
-static void mgaG400EmitTex1(drm_mga_private_t * dev_priv, int source )
+static void mgaG400EmitTex1(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- unsigned int *regs = sarea_priv->TexState[source];
+ unsigned int *regs = sarea_priv->TexState[1];
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
PRIMGETPTR(dev_priv);
PRIMOUTREG(MGAREG_TEXORG4, regs[MGA_TEXREG_ORG4]);
PRIMOUTREG(MGAREG_TEXWIDTH, regs[MGA_TEXREG_WIDTH]);
PRIMOUTREG(MGAREG_TEXHEIGHT, regs[MGA_TEXREG_HEIGHT]);
- PRIMOUTREG(0x2d00 + 49 * 4, 0);
+ PRIMOUTREG(MGAREG_WR49, 0);
- PRIMOUTREG(0x2d00 + 57 * 4, 0);
- PRIMOUTREG(0x2d00 + 53 * 4, 0);
- PRIMOUTREG(0x2d00 + 61 * 4, 0);
- PRIMOUTREG(0x2d00 + 52 * 4, regs[MGA_TEXREG_WIDTH] | 0x40);
+ PRIMOUTREG(MGAREG_WR57, 0);
+ PRIMOUTREG(MGAREG_WR53, 0);
+ PRIMOUTREG(MGAREG_WR61, 0);
+ PRIMOUTREG(MGAREG_WR52, regs[MGA_TEXREG_WIDTH] | 0x40);
- PRIMOUTREG(0x2d00 + 60 * 4, regs[MGA_TEXREG_HEIGHT] | 0x40);
+ PRIMOUTREG(MGAREG_WR60, regs[MGA_TEXREG_HEIGHT] | 0x40);
PRIMOUTREG(MGAREG_TEXTRANS, 0xffff);
PRIMOUTREG(MGAREG_TEXTRANSHIGH, 0xffff);
PRIMOUTREG(MGAREG_TEXCTL2, regs[MGA_TEXREG_CTL2] | 0x00008000);
PRIMADVANCE(dev_priv);
}
+#define MAGIC_FPARAM_HEX_VALUE 0x46480000
+/* This is the hex value of 12800.0f which is a magic value we must
+ * set in wr56.
+ */
+
static void mgaG400EmitPipe(drm_mga_private_t * dev_priv)
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int pipe = sarea_priv->WarpPipe;
- float fParam = 12800.0f;
- int multitex = (sarea_priv->TexState[0][MGA_TEXREG_CTL2] &
- TMC_dualtex_enable);
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
PRIMGETPTR(dev_priv);
/* This takes 50 dwords */
- /* Establish vertex size.
+ /* Establish vertex size.
*/
PRIMOUTREG(MGAREG_WIADDR2, WIA_wmode_suspend);
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DMAPAD, 0);
- if (sarea_priv->vertexsize == 10) {
- PRIMOUTREG(MGAREG_YDST, 0);
- PRIMOUTREG(MGAREG_FXLEFT, 0);
- PRIMOUTREG(MGAREG_FXRIGHT, 1);
- PRIMOUTREG(MGAREG_DWGCTL, MGA_FLUSH_CMD);
-
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 1);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
-
- if (multitex) {
- PRIMOUTREG(MGAREG_TEXCTL2, 0 | 0x00008000);
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
- PRIMOUTREG(MGAREG_TEXCTL2, 0x80 | 0x00008000);
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
- } else {
- PRIMOUTREG(MGAREG_TEXCTL2, 0 | 0x00008000);
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
- PRIMOUTREG(MGAREG_TEXCTL2, 0 | 0x00008000);
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
- }
-
+ if (pipe & MGA_T2) {
PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001e09);
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0);
PRIMOUTREG(MGAREG_WACCEPTSEQ, 0x1e000000);
} else {
- /* Flush the WARP pipe */
- PRIMOUTREG(MGAREG_YDST, 0);
- PRIMOUTREG(MGAREG_FXLEFT, 0);
- PRIMOUTREG(MGAREG_FXRIGHT, 1);
- PRIMOUTREG(MGAREG_DWGCTL, MGA_FLUSH_CMD);
-
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 1);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
+ if (dev_priv->WarpPipe & MGA_T2) {
+ /* Flush the WARP pipe */
+ PRIMOUTREG(MGAREG_YDST, 0);
+ PRIMOUTREG(MGAREG_FXLEFT, 0);
+ PRIMOUTREG(MGAREG_FXRIGHT, 1);
+ PRIMOUTREG(MGAREG_DWGCTL, MGA_FLUSH_CMD);
+
+ PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 1);
+ PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
+ PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000);
+ PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
- PRIMOUTREG(MGAREG_TEXCTL2, 0 | 0x00008000);
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
- PRIMOUTREG(MGAREG_TEXCTL2, 0 | 0x00008000);
- PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
+ PRIMOUTREG(MGAREG_TEXCTL2, 0x80 | 0x00008000);
+ PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
+ }
PRIMOUTREG(MGAREG_WVRTXSZ, 0x00001807);
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_WFLAG, 0);
PRIMOUTREG(MGAREG_WFLAG1, 0);
- PRIMOUTREG(0x2d00 + 56 * 4, *((u32 *) (&fParam)));
+ PRIMOUTREG(MGAREG_WR56, MAGIC_FPARAM_HEX_VALUE);
PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(0x2d00 + 49 * 4, 0); /* Tex stage 0 */
- PRIMOUTREG(0x2d00 + 57 * 4, 0); /* Tex stage 0 */
- PRIMOUTREG(0x2d00 + 53 * 4, 0); /* Tex stage 1 */
- PRIMOUTREG(0x2d00 + 61 * 4, 0); /* Tex stage 1 */
-
- PRIMOUTREG(0x2d00 + 54 * 4, 0x40); /* Tex stage 0 : w */
- PRIMOUTREG(0x2d00 + 62 * 4, 0x40); /* Tex stage 0 : h */
- PRIMOUTREG(0x2d00 + 52 * 4, 0x40); /* Tex stage 1 : w */
- PRIMOUTREG(0x2d00 + 60 * 4, 0x40); /* Tex stage 1 : h */
-
- if (dev_priv->WarpPipe != pipe || 1) {
- /* Dma pading required due to hw bug */
- PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
- PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
- PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
- PRIMOUTREG(MGAREG_WIADDR2,
- (u32) (dev_priv->WarpIndex[pipe].phys_addr |
- WIA_wmode_start | WIA_wagp_agp));
- }
+ PRIMOUTREG(MGAREG_WR49, 0); /* Tex stage 0 */
+ PRIMOUTREG(MGAREG_WR57, 0); /* Tex stage 0 */
+ PRIMOUTREG(MGAREG_WR53, 0); /* Tex stage 1 */
+ PRIMOUTREG(MGAREG_WR61, 0); /* Tex stage 1 */
+
+ PRIMOUTREG(MGAREG_WR54, 0x40); /* Tex stage 0 : w */
+ PRIMOUTREG(MGAREG_WR62, 0x40); /* Tex stage 0 : h */
+ PRIMOUTREG(MGAREG_WR52, 0x40); /* Tex stage 1 : w */
+ PRIMOUTREG(MGAREG_WR60, 0x40); /* Tex stage 1 : h */
+ /* Dma pading required due to hw bug */
+ PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
+ PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
+ PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
+ PRIMOUTREG(MGAREG_WIADDR2,
+ (u32) (dev_priv->WarpIndex[pipe].
+ phys_addr | WIA_wmode_start | WIA_wagp_agp));
PRIMADVANCE(dev_priv);
}
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int pipe = sarea_priv->WarpPipe;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
PRIMGETPTR(dev_priv);
PRIMOUTREG(MGAREG_WIADDR, WIA_wmode_suspend);
PRIMOUTREG(MGAREG_WVRTXSZ, 7);
PRIMOUTREG(MGAREG_WFLAG, 0);
- PRIMOUTREG(0x2d00 + 24 * 4, 0); /* tex w/h */
+ PRIMOUTREG(MGAREG_WR24, 0); /* tex w/h */
- PRIMOUTREG(0x2d00 + 25 * 4, 0x100);
- PRIMOUTREG(0x2d00 + 34 * 4, 0); /* tex w/h */
- PRIMOUTREG(0x2d00 + 42 * 4, 0xFFFF);
- PRIMOUTREG(0x2d00 + 60 * 4, 0xFFFF);
+ PRIMOUTREG(MGAREG_WR25, 0x100);
+ PRIMOUTREG(MGAREG_WR34, 0); /* tex w/h */
+ PRIMOUTREG(MGAREG_WR42, 0xFFFF);
+ PRIMOUTREG(MGAREG_WR60, 0xFFFF);
/* Dma pading required due to hw bug */
PRIMOUTREG(MGAREG_DMAPAD, 0xffffffff);
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (dev_priv->chipset == MGA_CARD_TYPE_G400) {
- int multitex = (sarea_priv->TexState[0][MGA_TEXREG_CTL2] &
- TMC_dualtex_enable);
+ int multitex = sarea_priv->WarpPipe & MGA_T2;
- dirty = ~0;
-
- if (dirty & MGA_UPLOAD_PIPE
-/* && (sarea_priv->WarpPipe != dev_priv->WarpPipe || */
-/* sarea_priv->vertexsize != dev_priv->vertexsize) */
- )
- {
+ if (sarea_priv->WarpPipe != dev_priv->WarpPipe) {
mgaG400EmitPipe(dev_priv);
dev_priv->WarpPipe = sarea_priv->WarpPipe;
- dev_priv->vertexsize = sarea_priv->vertexsize;
- sarea_priv->dirty &= ~MGA_UPLOAD_PIPE;
}
if (dirty & MGA_UPLOAD_CTX) {
sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
}
- if (dirty & MGA_UPLOAD_TEX1) {
- if (multitex)
- mgaG400EmitTex1(dev_priv, 1);
- else
- mgaG400EmitTex1(dev_priv, 0);
+ if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
+ mgaG400EmitTex1(dev_priv);
sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
}
} else {
}
}
-
/* Disallow all write destinations except the front and backbuffer.
*/
static int mgaVerifyContext(drm_mga_private_t * dev_priv)
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int *regs = sarea_priv->ContextState;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if (regs[MGA_CTXREG_DSTORG] != dev_priv->frontOffset &&
regs[MGA_CTXREG_DSTORG] != dev_priv->backOffset) {
DRM_DEBUG("BAD DSTORG: %x (front %x, back %x)\n\n",
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if ((sarea_priv->TexState[unit][MGA_TEXREG_ORG] & 0x3) == 0x1) {
DRM_DEBUG("BAD TEXREG_ORG: %x, unit %d\n",
sarea_priv->TexState[unit][MGA_TEXREG_ORG],
unsigned int dirty = sarea_priv->dirty;
int rv = 0;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
unsigned long bus_address,
unsigned int dstOrg, int length)
{
- DRM_DEBUG("%s\n", __FUNCTION__);
-
if (dstOrg < dev_priv->textureOffset ||
dstOrg + length >
(dev_priv->textureOffset + dev_priv->textureSize)) {
int use_agp = PDEA_pagpxfer_enable | 0x00000001;
u16 y2;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
y2 = length / 64;
PRIMOUTREG(MGAREG_DSTORG, destOrg);
PRIMOUTREG(MGAREG_MACCESS, 0x00000000);
- DRM_DEBUG("srcorg : %lx\n", bus_address | use_agp);
PRIMOUTREG(MGAREG_SRCORG, (u32) bus_address | use_agp);
PRIMOUTREG(MGAREG_AR5, 64);
PRIMOUTREG(MGAREG_FXBNDRY, (63 << 16));
PRIMOUTREG(MGAREG_YDSTLEN + MGAREG_MGA_EXEC, y2);
+ PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_SRCORG, 0);
PRIMOUTREG(MGAREG_PITCH, dev_priv->stride / dev_priv->cpp);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
- PRIMOUTREG(MGAREG_DMAPAD, 0);
+ PRIMOUTREG(MGAREG_DWGSYNC, 0x7000);
PRIMADVANCE(dev_priv);
}
int use_agp = PDEA_pagpxfer_enable;
int i = 0;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
- DRM_DEBUG("dispatch vertex %d addr 0x%lx, "
- "length 0x%x nbox %d dirty %x\n",
- buf->idx, address, length,
- sarea_priv->nbox, sarea_priv->dirty);
-
- DRM_DEBUG("used : %d, total : %d\n", buf->used, buf->total);
if (buf->used) {
/* WARNING: if you change any of the state functions verify
(MAX_STATE_SIZE + (5 * MGA_NR_SAREA_CLIPRECTS)));
mgaEmitState(dev_priv);
-/* length = dev_priv->vertexsize * 3 * 4; */
+#if 0
+ length = dev_priv->vertexsize * 3 * 4;
+#endif
do {
if (i < sarea_priv->nbox) {
- DRM_DEBUG("idx %d Emit box %d/%d:"
- "%d,%d - %d,%d\n",
- buf->idx,
- i, sarea_priv->nbox,
- sarea_priv->boxes[i].x1,
- sarea_priv->boxes[i].y1,
- sarea_priv->boxes[i].x2,
- sarea_priv->boxes[i].y2);
-
mgaEmitClipRect(dev_priv,
&sarea_priv->boxes[i]);
}
int use_agp = PDEA_pagpxfer_enable;
int i = 0;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
-
- DRM_DEBUG("dispatch indices %d addr 0x%x, "
- "start 0x%x end 0x%x nbox %d dirty %x\n",
- buf->idx, address, start, end,
- sarea_priv->nbox, sarea_priv->dirty);
if (start != end) {
/* WARNING: if you change any of the state functions verify
do {
if (i < sarea_priv->nbox) {
- DRM_DEBUG("idx %d Emit box %d/%d:"
- "%d,%d - %d,%d\n",
- buf->idx,
- i, sarea_priv->nbox,
- sarea_priv->boxes[i].x1,
- sarea_priv->boxes[i].y1,
- sarea_priv->boxes[i].x2,
- sarea_priv->boxes[i].y2);
-
mgaEmitClipRect(dev_priv,
&sarea_priv->boxes[i]);
}
unsigned int cmd;
int i;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (dev_priv->sgram)
cmd = MGA_CLEAR_CMD | DC_atype_blk;
for (i = 0; i < nbox; i++) {
unsigned int height = pbox[i].y2 - pbox[i].y1;
- DRM_DEBUG("dispatch clear %d,%d-%d,%d flags %x!\n",
- pbox[i].x1, pbox[i].y1, pbox[i].x2,
- pbox[i].y2, flags);
-
if (flags & MGA_FRONT) {
- DRM_DEBUG("clear front\n");
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
PRIMOUTREG(MGAREG_YDSTLEN,
}
if (flags & MGA_BACK) {
- DRM_DEBUG("clear back\n");
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_PLNWT, clear_colormask);
PRIMOUTREG(MGAREG_YDSTLEN,
}
if (flags & MGA_DEPTH) {
- DRM_DEBUG("clear depth\n");
PRIMOUTREG(MGAREG_DMAPAD, 0);
PRIMOUTREG(MGAREG_PLNWT, clear_depthmask);
PRIMOUTREG(MGAREG_YDSTLEN,
int pixel_stride = dev_priv->stride / dev_priv->cpp;
PRIMLOCALS;
- DRM_DEBUG("%s\n", __FUNCTION__);
PRIM_OVERFLOW(dev, dev_priv, (MGA_NR_SAREA_CLIPRECTS * 5) + 20);
unsigned int h = pbox[i].y2 - pbox[i].y1;
unsigned int start = pbox[i].y1 * pixel_stride;
- DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
- pbox[i].x1, pbox[i].y1, pbox[i].x2, pbox[i].y2);
-
PRIMOUTREG(MGAREG_AR0, start + pbox[i].x2 - 1);
PRIMOUTREG(MGAREG_AR3, start + pbox[i].x1);
PRIMOUTREG(MGAREG_FXBNDRY,
if (copy_from_user(&clear, (drm_mga_clear_t *) arg, sizeof(clear)))
return -EFAULT;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("mga_clear_bufs called without lock held\n");
drm_mga_private_t *dev_priv =
(drm_mga_private_t *) dev->dev_private;
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("mga_swap_bufs called without lock held\n");
drm_mga_buf_priv_t *buf_priv;
drm_mga_iload_t iload;
unsigned long bus_address;
- DRM_DEBUG("%s\n", __FUNCTION__);
- DRM_DEBUG("Starting Iload\n");
if (copy_from_user(&iload, (drm_mga_iload_t *) arg, sizeof(iload)))
return -EFAULT;
buf = dma->buflist[iload.idx];
buf_priv = buf->dev_private;
bus_address = buf->bus_address;
- DRM_DEBUG("bus_address %lx, length %d, destorg : %x\n",
- bus_address, iload.length, iload.destOrg);
if (mgaVerifyIload(dev_priv,
bus_address, iload.destOrg, iload.length)) {
drm_buf_t *buf;
drm_mga_buf_priv_t *buf_priv;
drm_mga_vertex_t vertex;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (copy_from_user(&vertex, (drm_mga_vertex_t *) arg, sizeof(vertex)))
return -EFAULT;
return -EINVAL;
}
- DRM_DEBUG("mga_vertex\n");
-
buf = dma->buflist[vertex.idx];
buf_priv = buf->dev_private;
buf_priv->dispatched = 0;
mga_freelist_put(dev, buf);
}
- DRM_DEBUG("bad state\n");
return -EINVAL;
}
drm_buf_t *buf;
drm_mga_buf_priv_t *buf_priv;
drm_mga_indices_t indices;
- DRM_DEBUG("%s\n", __FUNCTION__);
- if (copy_from_user(&indices, (drm_mga_indices_t *) arg, sizeof(indices)))
+ if (copy_from_user(&indices,
+ (drm_mga_indices_t *)arg, sizeof(indices)))
return -EFAULT;
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
return -EINVAL;
}
- DRM_DEBUG("mga_indices\n");
-
buf = dma->buflist[indices.idx];
buf_priv = buf->dev_private;
{
int i;
drm_buf_t *buf;
- DRM_DEBUG("%s\n", __FUNCTION__);
for (i = d->granted_count; i < d->request_count; i++) {
buf = mga_freelist_get(dev);
drm_device_dma_t *dma = dev->dma;
int retcode = 0;
drm_dma_t d;
- DRM_DEBUG("%s\n", __FUNCTION__);
if (copy_from_user(&d, (drm_dma_t *) arg, sizeof(d)))
return -EFAULT;
- DRM_DEBUG("%d %d: %d send, %d req\n",
- current->pid, d.context, d.send_count, d.request_count);
if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
DRM_ERROR("mga_dma called without lock held\n");
retcode = mga_dma_get_buffers(dev, &d);
}
- DRM_DEBUG("%d returning, granted = %d\n",
- current->pid, d.granted_count);
if (copy_to_user((drm_dma_t *) arg, &d, sizeof(d)))
return -EFAULT;
return retcode;
+++ /dev/null
-#include <linux/config.h>
-#include <linux/version.h>
-
-#ifndef CONFIG_SMP
-#define CONFIG_SMP 0
-#endif
-
-#ifndef CONFIG_MODVERSIONS
-#define CONFIG_MODVERSIONS 0
-#endif
-
-#ifndef CONFIG_AGP_MODULE
-#define CONFIG_AGP_MODULE 0
-#endif
-
-#ifndef CONFIG_AGP
-#define CONFIG_AGP 0
-#endif
-
-#ifndef CONFIG_FB_SIS
-#define CONFIG_FB_SIS 0
-#endif
-
-SMP = CONFIG_SMP
-MODVERSIONS = CONFIG_MODVERSIONS
-AGP = CONFIG_AGP
-AGP_MODULE = CONFIG_AGP_MODULE
-RELEASE = UTS_RELEASE
-SIS = CONFIG_FB_SIS
#define R128_NAME "r128"
#define R128_DESC "ATI Rage 128"
-#define R128_DATE "20000910"
+#define R128_DATE "20000928"
#define R128_MAJOR 1
#define R128_MINOR 0
#define R128_PATCHLEVEL 0
#endif
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
ret = -EINTR;
/* Contention */
atomic_inc(&dev->total_sleeps);
- current->state = TASK_INTERRUPTIBLE;
#if 1
current->policy |= SCHED_YIELD;
#endif
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
- *
+ *
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */
-#define R128_BASE(reg) ((unsigned long)(dev_priv->mmio->handle))
+#define R128_BASE(reg) ((u32)(dev_priv->mmio->handle))
#define R128_ADDR(reg) (R128_BASE(reg) + reg)
#define R128_DEREF(reg) *(__volatile__ int *)R128_ADDR(reg)
-/* tdfx.c -- tdfx driver -*- linux-c -*-
+/* tdfx_drv.c -- tdfx driver -*- linux-c -*-
* Created: Thu Oct 7 10:38:32 1999 by faith@precisioninsight.com
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
#define TDFX_NAME "tdfx"
#define TDFX_DESC "3dfx Banshee/Voodoo3+"
-#define TDFX_DATE "20000910"
+#define TDFX_DATE "20000928"
#define TDFX_MAJOR 1
#define TDFX_MINOR 0
#define TDFX_PATCHLEVEL 0
#endif
add_wait_queue(&dev->lock.lock_queue, &entry);
for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
if (!dev->lock.hw_lock) {
/* Device has been unregistered */
ret = -EINTR;
/* Contention */
atomic_inc(&dev->total_sleeps);
- current->state = TASK_INTERRUPTIBLE;
#if 1
current->policy |= SCHED_YIELD;
#endif
int write_access)
#endif
{
- DRM_DEBUG("0x%08lx, %d\n", address, write_access);
-
return NOPAGE_SIGBUS; /* Disallow mremap */
}
tco_timer_settimer ((unsigned char) i810_margin);
tco_timer_reload ();
- /* FIXME: no floating point math */
printk (KERN_INFO
"i810 TCO timer: V0.02, timer margin: %d sec (0x%04x)\n",
- (int) (i810_margin * 0.6), TCOBASE);
+ (int) (i810_margin * 6 / 10), TCOBASE);
return 0;
}
extern void gfx_register(void);
#endif
extern void streamable_init(void);
-extern void watchdog_init(void);
-extern void pcwatchdog_init(void);
extern int rtc_sun_init(void); /* Combines MK48T02 and MK48T08 */
extern int rtc_DP8570A_init(void);
extern int rtc_MK48T08_init(void);
#ifdef CONFIG_PC110_PAD
pc110pad_init();
#endif
-/*
- * Only one watchdog can succeed. We probe the pcwatchdog first,
- * then the wdt cards and finally the software watchdog which always
- * works. This means if your hardware watchdog dies or is 'borrowed'
- * for some reason the software watchdog still gives you some cover.
- */
-#ifdef CONFIG_PCWATCHDOG
- pcwatchdog_init();
-#endif
-#ifdef CONFIG_SOFT_WATCHDOG
- watchdog_init();
-#endif
#ifdef CONFIG_MVME16x
rtc_MK48T08_init();
#endif
return 1;
}
-void __init mixcomwd_init(void)
+static int __init mixcomwd_init(void)
{
int i;
+ int ret;
int found=0;
for (i = 0; !found && mixcomwd_ioports[i] != 0; i++) {
if (!found) {
printk("mixcomwd: No card detected, or port not available.\n");
- return;
+ return -ENODEV;
}
request_region(watchdog_port,1,"MixCOM watchdog");
- misc_register(&mixcomwd_miscdev);
+ ret = misc_register(&mixcomwd_miscdev);
+ if (ret)
+ return ret;
+
printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port);
-}
-#ifdef MODULE
-int init_module(void)
-{
- mixcomwd_init();
return 0;
-}
+}
-void cleanup_module(void)
+static void __exit mixcomwd_exit(void)
{
#ifndef CONFIG_WATCHDOG_NOWAYOUT
if(mixcomwd_timer_alive) {
release_region(watchdog_port,1);
misc_deregister(&mixcomwd_miscdev);
}
-#endif
+
+module_init(mixcomwd_init);
+module_exit(mixcomwd_exit);
&pcwd_fops
};
-#ifdef MODULE
-int init_module(void)
-#else
-int __init pcwatchdog_init(void)
-#endif
+static int __init pcwatchdog_init(void)
{
int i, found = 0;
spin_lock_init(&io_lock);
return 0;
}
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit pcwatchdog_exit(void)
{
/* Disable the board */
if (revision == PCWD_REVISION_C) {
release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
}
-#endif
+
+module_init(pcwatchdog_init);
+module_exit(pcwatchdog_exit);
* read/write read or write in current IEEE 1284 protocol
* select wait for interrupt (in readfds)
*
+ * Changes:
* Added SETTIME/GETTIME ioctl, Fred Barnes 1999.
+ *
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 2000/08/25
+ * - On error, copy_from_user and copy_to_user do not return -EFAULT,
+ * They return the positive number of bytes *not* copied due to address
+ * space errors.
*/
#include <linux/module.h>
wrote = parport_write (pp->pdev->port, kbuffer, n);
- if (wrote < 0) {
+ if (wrote <= 0) {
if (!bytes_written)
bytes_written = wrote;
break;
case PPRSTATUS:
reg = parport_read_status (port);
- return copy_to_user ((unsigned char *) arg, ®,
- sizeof (reg));
-
+ if (copy_to_user ((unsigned char *) arg, ®, sizeof (reg)))
+ return -EFAULT;
+ return 0;
case PPRDATA:
reg = parport_read_data (port);
- return copy_to_user ((unsigned char *) arg, ®,
- sizeof (reg));
-
+ if (copy_to_user ((unsigned char *) arg, ®, sizeof (reg)))
+ return -EFAULT;
+ return 0;
case PPRCONTROL:
reg = parport_read_control (port);
- return copy_to_user ((unsigned char *) arg, ®,
- sizeof (reg));
-
+ if (copy_to_user ((unsigned char *) arg, ®, sizeof (reg)))
+ return -EFAULT;
+ return 0;
case PPYIELD:
parport_yield_blocking (pp->pdev);
return 0;
#define dprintk(x...)
-static struct block_device *raw_device_bindings[256] = {};
-static int raw_device_inuse[256] = {};
-static int raw_device_sector_size[256] = {};
-static int raw_device_sector_bits[256] = {};
+static struct block_device *raw_device_bindings[256];
+static int raw_device_inuse[256];
+static int raw_device_sector_size[256];
+static int raw_device_sector_bits[256];
static ssize_t rw_raw_dev(int rw, struct file *, char *, size_t, loff_t *);
}
module_init(sbc60xxwdt_init);
-module_exit(sbc60xxwdt_unload)
+module_exit(sbc60xxwdt_unload);
* Our timer
*/
-struct timer_list watchdog_ticktock;
+static void watchdog_fire(unsigned long);
+
+static struct timer_list watchdog_ticktock = {
+ function: watchdog_fire,
+};
static int timer_alive = 0;
&softdog_fops
};
-void __init watchdog_init(void)
+static int __init watchdog_init(void)
{
- misc_register(&softdog_miscdev);
- init_timer(&watchdog_ticktock);
- watchdog_ticktock.function=watchdog_fire;
+ int ret;
+
+ ret = misc_register(&softdog_miscdev);
+
+ if (ret)
+ return ret;
+
printk("Software Watchdog Timer: 0.05, timer margin: %d sec\n", soft_margin);
-}
-#ifdef MODULE
-int init_module(void)
-{
- watchdog_init();
return 0;
-}
+}
-void cleanup_module(void)
+static void __exit watchdog_exit(void)
{
misc_deregister(&softdog_miscdev);
}
-#endif
+
+module_init(watchdog_init);
+module_exit(watchdog_exit);
static int tosh_date = 0x0000;
static int tosh_sci = 0x0000;
static int tosh_fan = 0;
-static int tosh_start = 0;
-static int tosh_extent = 0;
static int tosh_fn = 0;
MODULE_PARM(tosh_fn, "i");
-static int tosh_get_info(char *, char **, off_t, int, int);
-static int tosh_open(struct inode *ip, struct file *);
-static int tosh_release(struct inode *, struct file *);
+static int tosh_get_info(char *, char **, off_t, int);
static int tosh_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
static struct file_operations tosh_fops = {
owner: THIS_MODULE,
ioctl: tosh_ioctl,
- open: tosh_open,
- release: tosh_release,
};
static struct miscdevice tosh_device = {
&tosh_fops
};
-static struct proc_dir_entry tosh_proc_entry = {
- 0, 7, "toshiba", S_IFREG|S_IRUGO, 1, 0, 0, 33, NULL, tosh_get_info, NULL
-};
-
/*
* Read the Fn key status
*/
}
-static int tosh_open(struct inode *ip, struct file *fp)
-{
- MOD_INC_USE_COUNT;
-
- return 0;
-}
-
-
-static int tosh_release(struct inode *ip, struct file *fp)
-{
- MOD_DEC_USE_COUNT;
-
- return 0;
-}
-
-
static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
unsigned long arg)
{
/*
* Print the information for /proc/toshiba
*/
-int tosh_get_info(char *buffer, char **start, off_t fpos, int length, int dummy)
+int tosh_get_info(char *buffer, char **start, off_t fpos, int length)
{
char *temp;
int key;
unsigned short bx,cx;
unsigned long address;
- id = (0x100*(int) readb(0xffffe))+((int) readb(0xffffa));
+ id = (0x100*(int) isa_readb(0xffffe))+((int) isa_readb(0xffffa));
/* do we have a SCTTable machine identication number on our hands */
/* now twiddle with our pointer a bit */
address = 0x000f0000+bx;
- cx = readw(address);
+ cx = isa_readw(address);
address = 0x000f0009+bx+cx;
- cx = readw(address);
+ cx = isa_readw(address);
address = 0x000f000a+cx;
- cx = readw(address);
+ cx = isa_readw(address);
/* now construct our machine identification number */
/* get the BIOS version */
- major = readb(0xfe009)-'0';
- minor = ((readb(0xfe00b)-'0')*10)+(readb(0xfe00c)-'0');
+ major = isa_readb(0xfe009)-'0';
+ minor = ((isa_readb(0xfe00b)-'0')*10)+(isa_readb(0xfe00c)-'0');
tosh_bios = (major*0x100)+minor;
/* get the BIOS date */
- day = ((readb(0xffff5)-'0')*10)+(readb(0xffff6)-'0');
- month = ((readb(0xffff8)-'0')*10)+(readb(0xffff9)-'0');
- year = ((readb(0xffffb)-'0')*10)+(readb(0xffffc)-'0');
+ day = ((isa_readb(0xffff5)-'0')*10)+(isa_readb(0xffff6)-'0');
+ month = ((isa_readb(0xffff8)-'0')*10)+(isa_readb(0xffff9)-'0');
+ year = ((isa_readb(0xffffb)-'0')*10)+(isa_readb(0xffffc)-'0');
tosh_date = (((year-90) & 0x1f)<<10) | ((month & 0xf)<<6)
| ((day & 0x1f)<<1);
misc_register(&tosh_device);
/* register the proc entry */
- proc_register(&proc_root, &tosh_proc_entry);
+ create_proc_info_entry("toshiba", 0, NULL, tosh_get_info);
return 0;
}
void cleanup_module(void)
{
/* remove the proc entry */
- proc_unregister(&proc_root, tosh_proc_entry.low_ino);
+ remove_proc_entry("toshiba", NULL);
/* unregister the device file */
misc_deregister(&tosh_device);
-
- /* release ports */
- release_region(tosh_start, tosh_extent);
-
- return;
}
#endif
0
};
-#ifdef MODULE
-
-#define wdt_init init_module
-
/**
* cleanup_module:
*
* module in 60 seconds or reboot.
*/
-void cleanup_module(void)
+static void __exit wdt_exit(void)
{
misc_deregister(&wdt_miscdev);
#ifdef CONFIG_WDT_501
free_irq(irq, NULL);
}
-#endif
-
/**
* wdt_init:
*
* The open() function will actually kick the board off.
*/
-int __init wdt_init(void)
+static int __init wdt_init(void)
{
int ret;
goto out;
}
+module_init(wdt_init);
+module_exit(wdt_exit);
+
* @ptr: offset (no seek allowed)
*
* Read reports the temperature in degrees Fahrenheit. The API is in
- * farenheit. It was designed by an imperial measurement luddite.
+ * fahrenheit. It was designed by an imperial measurement luddite.
*/
static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *ptr)
/* module parameters:
*/
-static int i2c_debug=0;
-static int bit_test=0; /* see if the line-setting functions work */
-static int bit_scan=0; /* have a look at what's hanging 'round */
+static int i2c_debug;
+static int bit_test; /* see if the line-setting functions work */
+static int bit_scan; /* have a look at what's hanging 'round */
/* --- setting states on the bus with the right timing: --------------- */
};
#endif
-static int i2cproc_initialized = 0;
+static int i2cproc_initialized;
#else /* undef CONFIG_PROC_FS */
* Can we trust the reported IRQ?
*/
pciirq = dev->irq;
- if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
+ if ((dev->class & ~(0xff)) != (PCI_CLASS_STORAGE_IDE << 8)) {
printk("%s: not 100%% native mode: will probe irqs later\n", d->name);
/*
* This allows offboard ide-pci cards the enable a BIOS,
struct hpsb_host_template *tmpl;
struct hpsb_host *h;
int retval = 0;
+ unsigned long flags;
- spin_lock(&templates_lock);
+ spin_lock_irqsave(&templates_lock, flags);
for (tmpl = templates; (tmpl != NULL) && !retval; tmpl = tmpl->next) {
for (h = tmpl->hosts; h != NULL; h = h->next) {
}
}
- spin_unlock(&templates_lock);
+ spin_unlock_irqrestore(&templates_lock, flags);
return retval;
}
}
memset(h, 0, sizeof(struct hpsb_host) + hd_size);
- h->tlabel_count = 64;
INIT_LIST_HEAD(&h->pending_packets);
spin_lock_init(&h->pending_pkt_lock);
+
+ sema_init(&h->tlabel_count, 64);
spin_lock_init(&h->tlabel_lock);
- init_waitqueue_head(&h->tlabel_wait);
h->timeout_tq.routine = (void (*)(void*))abort_timedouts;
h->timeout_tq.data = h;
host->initialized = 1;
highlevel_add_host(host);
- reset_host_bus(host);
-
- //kernel_thread(hpsb_host_thread, host,
- // CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ hpsb_reset_bus(host);
}
}
#include <linux/wait.h>
#include <linux/tqueue.h>
+#include <asm/semaphore.h>
#include "ieee1394_types.h"
#include "csr.h"
/* A bitmask where a set bit means that this tlabel is in use.
* FIXME - should be handled per node instead of per bus. */
u32 tlabel_pool[2];
- int tlabel_count;
+ struct semaphore tlabel_count;
spinlock_t tlabel_lock;
- wait_queue_head_t tlabel_wait;
int reset_retries;
quadlet_t *topology_map;
}
-void reset_host_bus(struct hpsb_host *host)
+int hpsb_reset_bus(struct hpsb_host *host)
{
if (!host->initialized) {
- return;
+ return 1;
}
- hpsb_bus_reset(host);
- host->template->devctl(host, RESET_BUS, 0);
+ if (!hpsb_bus_reset(host)) {
+ host->template->devctl(host, RESET_BUS, 0);
+ return 0;
+ } else {
+ return 1;
+ }
}
-void hpsb_bus_reset(struct hpsb_host *host)
+int hpsb_bus_reset(struct hpsb_host *host)
{
- if (!host->in_bus_reset) {
- abort_requests(host);
- host->in_bus_reset = 1;
- host->irm_id = -1;
- host->busmgr_id = -1;
- host->node_count = 0;
- host->selfid_count = 0;
- } else {
+ if (host->in_bus_reset) {
HPSB_NOTICE(__FUNCTION__
" called while bus reset already in progress");
+ return 1;
}
+
+ abort_requests(host);
+ host->in_bus_reset = 1;
+ host->irm_id = -1;
+ host->busmgr_id = -1;
+ host->node_count = 0;
+ host->selfid_count = 0;
+
+ return 0;
}
if (host->reset_retries++ < 20) {
/* selfid stage did not complete without error */
HPSB_NOTICE("error in SelfID stage - resetting");
- reset_host_bus(host);
+ hpsb_reset_bus(host);
return;
} else {
HPSB_NOTICE("stopping out-of-control reset loop");
host->reset_retries = 0;
inc_hpsb_generation();
+ if (isroot) host->template->devctl(host, ACT_CYCLE_MASTER, 1);
highlevel_host_reset(host);
}
*
* The packet is sent through the host specified in the packet->host field.
* Before sending, the packet's transmit speed is automatically determined using
- * the local speed map.
+ * the local speed map when it is an async, non-broadcast packet.
*
* Possibilities for failure are that host is either not initialized, in bus
* reset, the packet's generation number doesn't match the current generation
}
packet->state = queued;
- packet->speed_code = host->speed_map[(host->node_id & NODE_MASK) * 64
- + (packet->node_id & NODE_MASK)];
+
+ if (packet->type == async && packet->node_id != ALL_NODES) {
+ packet->speed_code =
+ host->speed_map[(host->node_id & NODE_MASK) * 64
+ + (packet->node_id & NODE_MASK)];
+ }
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
switch (packet->speed_code) {
};
-void reset_host_bus(struct hpsb_host *host);
void abort_timedouts(struct hpsb_host *host);
void abort_requests(struct hpsb_host *host);
*/
int hpsb_send_packet(struct hpsb_packet *packet);
+/* Initiate bus reset on the given host. Returns 1 if bus reset already in
+ * progress, 0 otherwise. */
+int hpsb_reset_bus(struct hpsb_host *host);
/*
* The following functions are exported for host driver module usage. All of
* them directly.
*/
-/* Notify a bus reset to the core. */
-void hpsb_bus_reset(struct hpsb_host *host);
+/* Notify a bus reset to the core. Returns 1 if bus reset already in progress,
+ * 0 otherwise. */
+int hpsb_bus_reset(struct hpsb_host *host);
/*
* Hand over received selfid packet to the core. Complement check (second
#include "hosts.h"
#include "ieee1394_core.h"
#include "ieee1394_transactions.h"
-/* #include "events.h" */
#include "highlevel.h"
#include "guid.h"
EXPORT_SYMBOL(alloc_hpsb_packet);
EXPORT_SYMBOL(free_hpsb_packet);
EXPORT_SYMBOL(hpsb_send_packet);
+EXPORT_SYMBOL(hpsb_reset_bus);
EXPORT_SYMBOL(hpsb_bus_reset);
EXPORT_SYMBOL(hpsb_selfid_received);
EXPORT_SYMBOL(hpsb_selfid_complete);
EXPORT_SYMBOL(get_tlabel);
EXPORT_SYMBOL(free_tlabel);
+EXPORT_SYMBOL(fill_async_readquad);
+EXPORT_SYMBOL(fill_async_readquad_resp);
+EXPORT_SYMBOL(fill_async_readblock);
+EXPORT_SYMBOL(fill_async_readblock_resp);
+EXPORT_SYMBOL(fill_async_writequad);
+EXPORT_SYMBOL(fill_async_writeblock);
+EXPORT_SYMBOL(fill_async_write_resp);
+EXPORT_SYMBOL(fill_async_lock);
+EXPORT_SYMBOL(fill_async_lock_resp);
+EXPORT_SYMBOL(fill_iso_packet);
EXPORT_SYMBOL(hpsb_make_readqpacket);
EXPORT_SYMBOL(hpsb_make_readbpacket);
EXPORT_SYMBOL(hpsb_make_writeqpacket);
* Return value: The allocated transaction label or -1 if there was no free
* tlabel and @wait is false.
*/
-static int __get_tlabel(struct hpsb_host *host, nodeid_t nodeid)
+int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait)
{
int tlabel;
+ unsigned long flags;
- if (host->tlabel_count) {
- host->tlabel_count--;
-
- if (host->tlabel_pool[0] != ~0) {
- tlabel = ffz(host->tlabel_pool[0]);
- host->tlabel_pool[0] |= 1 << tlabel;
- } else {
- tlabel = ffz(host->tlabel_pool[1]);
- host->tlabel_pool[1] |= 1 << tlabel;
- tlabel += 32;
- }
- return tlabel;
+ if (wait) {
+ down(&host->tlabel_count);
+ } else {
+ if (down_trylock(&host->tlabel_count)) return -1;
}
- return -1;
-}
-
-int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait)
-{
- unsigned long flags;
- int tlabel;
- wait_queue_t wq;
spin_lock_irqsave(&host->tlabel_lock, flags);
- tlabel = __get_tlabel(host, nodeid);
- if (tlabel != -1 || !wait) {
- spin_unlock_irqrestore(&host->tlabel_lock, flags);
- return tlabel;
- }
-
- init_waitqueue_entry(&wq, current);
- add_wait_queue(&host->tlabel_wait, &wq);
-
- for (;;) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- tlabel = __get_tlabel(host, nodeid);
- if (tlabel != -1) break;
-
- spin_unlock_irqrestore(&host->tlabel_lock, flags);
- schedule();
- spin_lock_irqsave(&host->tlabel_lock, flags);
+ if (host->tlabel_pool[0] != ~0) {
+ tlabel = ffz(host->tlabel_pool[0]);
+ host->tlabel_pool[0] |= 1 << tlabel;
+ } else {
+ tlabel = ffz(host->tlabel_pool[1]);
+ host->tlabel_pool[1] |= 1 << tlabel;
+ tlabel += 32;
}
spin_unlock_irqrestore(&host->tlabel_lock, flags);
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&host->tlabel_wait, &wq);
return tlabel;
}
host->tlabel_pool[1] &= ~(1 << (tlabel-32));
}
- host->tlabel_count++;
-
spin_unlock_irqrestore(&host->tlabel_lock, flags);
- wake_up(&host->tlabel_wait);
+ up(&host->tlabel_count);
}
return order;
}
-
+#include <linux/mm.h>
#include <linux/pci.h>
inline static int pci_enable_device(struct pci_dev *dev)
{
BUG();
}
-struct scatterlist {};
+#include <asm/scatterlist.h>
extern inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
int nents, int direction)
{
* . Apple PowerBook detection
* Daniel Kobras <daniel.kobras@student.uni-tuebingen.de>
* . Reset the board properly before leaving + misc cleanups
+ * Leon van Stuivenberg <leonvs@iae.nl>
+ * . Bug fixes
*/
#include <linux/config.h>
return -1;
}
- size = ((self_id_count&0x0000EFFC)>>2) - 1;
+ size = ((self_id_count&0x00001FFC)>>2) - 1;
q++;
while (size > 0) {
* FIXME: check that the packet data buffer
* do not cross a page boundary
*/
+ if (cross_bound((unsigned long)packet->data,
+ packet->data_size)>0) {
+ /* FIXME: do something about it */
+ PRINT(KERN_ERR, ohci->id, __FUNCTION__
+ ": packet data addr: %p size %d bytes "
+ "cross page boundary",
+ packet->data, packet->data_size);
+ }
+
d->prg_cpu[idx]->end.address =
pci_map_single(ohci->dev, packet->data,
packet->data_size, PCI_DMA_TODEVICE);
unsigned char tcode;
unsigned long flags;
- if (packet->data_size >= ohci->max_packet_size) {
+ if (packet->data_size > ohci->max_packet_size) {
PRINT(KERN_ERR, ohci->id,
"transmit packet size = %d too big",
packet->data_size);
u32 nodeId = reg_read(ohci, OHCI1394_NodeID);
if ((nodeId & (1<<30)) && (nodeId & 0x3f)) {
/*
- * enable cycleTimer cycleMaster cycleSource
+ * enable cycleTimer, cycleMaster
*/
DBGMSG(ohci->id, "Cycle master enabled");
reg_write(ohci, OHCI1394_LinkControlSet,
- 0x00700000);
+ 0x00300000);
}
} else {
/* disable cycleTimer, cycleMaster, cycleSource */
break;
case ISO_LISTEN_CHANNEL:
+ {
+ int *isochannels, offset= OHCI1394_IRMultiChanMaskLoSet;
+ unsigned int channel= (unsigned int)arg;
+ unsigned int channelbit= channel;
+ u32 setMask= 0x00000001;
+
+ /* save people from themselves */
+ if (channel > 63)
+ break;
+
+ if (channel > 31) {
+ isochannels= &(((int*)&ohci->IR_channel_usage)[0]);
+ channelbit-= 32;
+ offset= OHCI1394_IRMultiChanMaskHiSet;
+ }
+ else
+ isochannels= &(((int*)&ohci->IR_channel_usage)[1]);
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
+ while(channelbit--) setMask= setMask << 1;
- if (!test_and_set_bit(arg, &ohci->IR_channel_usage)) {
- DBGMSG(ohci->id,
- "listening enabled on channel %d", arg);
-
- if (arg > 31) {
- u32 setMask= 0x00000001;
- arg-= 32;
- while(arg--) setMask= setMask << 1;
- reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
- setMask);
- } else {
- u32 setMask= 0x00000001;
- while(arg--) setMask= setMask << 1;
- reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
- setMask);
- }
+ spin_lock_irqsave(&ohci->IR_channel_lock, flags);
- }
+ if (!test_and_set_bit(channelbit, isochannels))
+ reg_write(ohci, offset, setMask);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
+ DBGMSG(ohci->id, "listening enabled on channel %u", channel);
break;
-
+ }
case ISO_UNLISTEN_CHANNEL:
+ {
+ int *isochannels, offset= OHCI1394_IRMultiChanMaskLoClear;
+ unsigned int channel= (unsigned int)arg;
+ unsigned int channelbit= channel;
+ u32 clearMask= 0x00000001;
+
+ /* save people from themselves */
+ if (channel > 63)
+ break;
+
+ if (channel > 31) {
+ isochannels= &(((int*)&ohci->IR_channel_usage)[0]);
+ channelbit-= 32;
+ offset= OHCI1394_IRMultiChanMaskHiClear;
+ }
+ else
+ isochannels= &(((int*)&ohci->IR_channel_usage)[1]);
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
+ while(channelbit--) clearMask= clearMask << 1;
- if (test_and_clear_bit(arg, &ohci->IR_channel_usage)) {
- DBGMSG(ohci->id,
- "listening disabled on iso channel %d", arg);
-
- if (arg > 31) {
- u32 clearMask= 0x00000001;
- arg-= 32;
- while(arg--) clearMask= clearMask << 1;
- reg_write(ohci,
- OHCI1394_IRMultiChanMaskHiClear,
- clearMask);
- } else {
- u32 clearMask= 0x00000001;
- while(arg--) clearMask= clearMask << 1;
- reg_write(ohci,
- OHCI1394_IRMultiChanMaskLoClear,
- clearMask);
- }
+ spin_lock_irqsave(&ohci->IR_channel_lock, flags);
- }
+ if (!test_and_clear_bit(channelbit, isochannels))
+ reg_write(ohci, offset, clearMask);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
+ DBGMSG(ohci->id, "listening disabled on channel %u", channel);
break;
-
+ }
default:
- PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet\n",
+ PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
cmd);
break;
}
{
struct ti_ohci *ohci;
unsigned long flags;
+ struct hpsb_packet *nextpacket;
if (d==NULL) {
PRINT_G(KERN_ERR, "dma_trm_reset called with NULL arg");
PRINT(KERN_INFO, ohci->id,
"AT dma reset ctx=%d, aborting transmission",
d->ctx);
+ nextpacket = d->fifo_first->xnext;
hpsb_packet_sent(ohci->host, d->fifo_first, ACKX_ABORTED);
- d->fifo_first = d->fifo_first->xnext;
+ d->fifo_first = nextpacket;
}
d->fifo_first = d->fifo_last = NULL;
PRINT(KERN_INFO, ohci->id,
"AT dma reset ctx=%d, aborting transmission",
d->ctx);
+ nextpacket = d->pending_first->xnext;
hpsb_packet_sent(ohci->host, d->pending_first,
ACKX_ABORTED);
- d->pending_first = d->pending_first->xnext;
+ d->pending_first = nextpacket;
}
d->pending_first = d->pending_last = NULL;
}
if (event & OHCI1394_selfIDComplete) {
if (host->in_bus_reset) {
+ /*
+ * Begin Fix (JSG): Check to make sure our
+ * node id is valid
+ */
+ node_id = reg_read(ohci, OHCI1394_NodeID);
+ if (!(node_id & 0x80000000)) {
+ mdelay(1); /* phy is upset -
+ * this happens once in
+ * a while on hot-plugs...
+ * give it a ms to recover
+ */
+ }
+ /* End Fix (JSG) */
+
node_id = reg_read(ohci, OHCI1394_NodeID);
if (node_id & 0x80000000) { /* NodeID valid */
phyid = node_id & 0x0000003f;
{
struct dma_trm_ctx *d = (struct dma_trm_ctx*)data;
struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
- struct hpsb_packet *packet;
+ struct hpsb_packet *packet, *nextpacket;
unsigned long flags;
u32 ack;
+ size_t datasize;
spin_lock_irqsave(&d->lock, flags);
while (d->fifo_first) {
packet = d->fifo_first;
- if (packet->data_size)
+ datasize = d->fifo_first->data_size;
+ if (datasize)
ack = d->prg_cpu[d->sent_ind]->end.status>>16;
else
ack = d->prg_cpu[d->sent_ind]->begin.status>>16;
/* this packet hasn't been sent yet*/
break;
- DBGMSG(ohci->id,
- "Packet sent to node %d ack=0x%X spd=%d ctx=%d",
- (packet->header[0]>>16)&0x3f, ack&0x1f, (ack>>5)&0x3,
- d->ctx);
+#ifdef OHCI1394_DEBUG
+ if (datasize)
+ DBGMSG(ohci->id,
+ "Packet sent to node %d tcode=0x%X tLabel="
+ "0x%02X ack=0x%X spd=%d dataLength=%d ctx=%d",
+ (d->prg_cpu[d->sent_ind]->data[1]>>16)&0x3f,
+ (d->prg_cpu[d->sent_ind]->data[0]>>4)&0xf,
+ (d->prg_cpu[d->sent_ind]->data[0]>>10)&0x3f,
+ ack&0x1f, (ack>>5)&0x3,
+ d->prg_cpu[d->sent_ind]->data[3]>>16,
+ d->ctx);
+ else
+ DBGMSG(ohci->id,
+ "Packet sent to node %d tcode=0x%X tLabel="
+ "0x%02X ack=0x%X spd=%d data=0x%08X ctx=%d",
+ (d->prg_cpu[d->sent_ind]->data[1]>>16)&0x3f,
+ (d->prg_cpu[d->sent_ind]->data[0]>>4)&0xf,
+ (d->prg_cpu[d->sent_ind]->data[0]>>10)&0x3f,
+ ack&0x1f, (ack>>5)&0x3,
+ d->prg_cpu[d->sent_ind]->data[3],
+ d->ctx);
+#endif
+
+ nextpacket = packet->xnext;
hpsb_packet_sent(ohci->host, packet, ack&0xf);
- if (packet->data_size)
+ if (datasize)
pci_unmap_single(ohci->dev,
d->prg_cpu[d->sent_ind]->end.address,
- packet->data_size, PCI_DMA_TODEVICE);
+ datasize, PCI_DMA_TODEVICE);
d->sent_ind = (d->sent_ind+1)%d->num_desc;
d->free_prgs++;
- d->fifo_first = d->fifo_first->xnext;
+ d->fifo_first = nextpacket;
}
if (d->fifo_first==NULL) d->fifo_last=NULL;
FAIL("failed to allocate buffer config rom");
}
- DBGMSG(ohci->id, "The 1st byte at offset 0x404 is: 0x%02x",
- *((char *)ohci->csr_config_rom_cpu+4));
-
/*
* self-id dma buffer allocation
* FIXME: some early chips may need 8KB alignment for the
- * selfid buffer
+ * selfid buffer... if you have problems a temporary fic
+ * is to allocate 8192 bytes instead of 2048
*/
ohci->selfid_buf_cpu =
pci_alloc_consistent(ohci->dev, 2048, &ohci->selfid_buf_bus);
if (ohci->selfid_buf_cpu == NULL) {
FAIL("failed to allocate DMA buffer for self-id packets");
}
- if ((unsigned long)ohci->selfid_buf_cpu & 0xfff)
+ if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff)
PRINT(KERN_INFO, ohci->id, "Selfid buffer %p not aligned on "
- "8Kb boundary", ohci->selfid_buf_cpu);
+ "8Kb boundary... may cause pb on some CXD3222 chip",
+ ohci->selfid_buf_cpu);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
+ ohci->registers = ioremap_nocache(dev->base_address[0],
+ OHCI1394_REGISTER_SIZE);
+#else
+ ohci->registers = ioremap_nocache(dev->resource[0].start,
+ OHCI1394_REGISTER_SIZE);
+#endif
+
+ if (ohci->registers == NULL) {
+ FAIL("failed to remap registers - card not accessible");
+ }
+
+ PRINT(KERN_INFO, ohci->id, "remapped memory spaces reg 0x%p",
+ ohci->registers);
ohci->ar_req_context =
alloc_dma_rcv_ctx(ohci, 0, AR_REQ_NUM_DESC,
OHCI1394_AsReqRcvContextControlClear,
OHCI1394_AsReqRcvCommandPtr);
- if (ohci->ar_req_context == NULL) return 1;
+ if (ohci->ar_req_context == NULL) {
+ FAIL("failed to allocate AR Req context");
+ }
ohci->ar_resp_context =
alloc_dma_rcv_ctx(ohci, 1, AR_RESP_NUM_DESC,
ohci->IR_channel_usage= 0x0000000000000000;
spin_lock_init(&ohci->IR_channel_lock);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
- ohci->registers = ioremap_nocache(dev->base_address[0],
- OHCI1394_REGISTER_SIZE);
-#else
- ohci->registers = ioremap_nocache(dev->resource[0].start,
- OHCI1394_REGISTER_SIZE);
-#endif
-
- if (ohci->registers == NULL) {
- FAIL("failed to remap registers - card not accessible");
- }
-
- PRINT(KERN_INFO, ohci->id, "remapped memory spaces reg 0x%p",
- ohci->registers);
-
if (!request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
OHCI1394_DRIVER_NAME, ohci)) {
PRINT(KERN_INFO, ohci->id, "allocated interrupt %d", dev->irq);
ohci_init_config_rom(ohci);
+ DBGMSG(ohci->id, "The 1st byte at offset 0x404 is: 0x%02x",
+ *((char *)ohci->csr_config_rom_cpu+4));
+
return 0;
#undef FAIL
}
create_proc_read_entry ("ohci1394", 0, NULL, ohci1394_read_proc, NULL);
#else
if (proc_register(&proc_root, &ohci_proc_entry)) {
- PRINT_G(KERN_ERR, "unable to register proc file\n");
+ PRINT_G(KERN_ERR, "unable to register proc file");
return -EIO;
}
#endif
#endif
#endif
- PRINT_G(KERN_INFO, "removed " OHCI1394_DRIVER_NAME " module\n");
+ PRINT_G(KERN_INFO, "removed " OHCI1394_DRIVER_NAME " module");
}
int init_module(void)
memset(cards, 0, MAX_OHCI1394_CARDS * sizeof (struct ti_ohci));
if (hpsb_register_lowlevel(get_ohci_template())) {
- PRINT_G(KERN_ERR, "registering failed\n");
+ PRINT_G(KERN_ERR, "registering failed");
return -ENXIO;
}
return 0;
#define OHCI1394_MAX_SELF_ID_ERRORS 16
#define AR_REQ_NUM_DESC 4 /* number of AR req descriptors */
-#define AR_REQ_BUF_SIZE 4096 /* size of AR req buffers */
-#define AR_REQ_SPLIT_BUF_SIZE 4096 /* split packet buffer */
+#define AR_REQ_BUF_SIZE PAGE_SIZE /* size of AR req buffers */
+#define AR_REQ_SPLIT_BUF_SIZE PAGE_SIZE /* split packet buffer */
#define AR_RESP_NUM_DESC 4 /* number of AR resp descriptors */
-#define AR_RESP_BUF_SIZE 4096 /* size of AR resp buffers */
-#define AR_RESP_SPLIT_BUF_SIZE 4096 /* split packet buffer */
+#define AR_RESP_BUF_SIZE PAGE_SIZE /* size of AR resp buffers */
+#define AR_RESP_SPLIT_BUF_SIZE PAGE_SIZE /* split packet buffer */
#define IR_NUM_DESC 16 /* number of IR descriptors */
-#define IR_BUF_SIZE 4096 /* 6480 bytes/buffer */
-#define IR_SPLIT_BUF_SIZE 4096 /* split packet buffer */
+#define IR_BUF_SIZE PAGE_SIZE /* 4096 bytes/buffer */
+#define IR_SPLIT_BUF_SIZE PAGE_SIZE /* split packet buffer */
#define AT_REQ_NUM_DESC 32 /* number of AT req descriptors */
#define AT_RESP_NUM_DESC 32 /* number of AT resp descriptors */
u32 status;
};
+/*
+ * FIXME:
+ * It is important that a single at_dma_prg does not cross a page boundary
+ * The proper way to do it would be to do the check dynamically as the
+ * programs are inserted into the AT fifo.
+ */
struct at_dma_prg {
struct dma_cmd begin;
quadlet_t data[4];
struct dma_cmd end;
+ quadlet_t pad[4]; /* FIXME: quick hack for memory alignment */
};
/* DMA receive context */
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/*
- * Lynx DMA usage:
- *
- * 0 is used for Lynx local bus transfers
- * 1 is async/selfid receive
- * 2 is iso receive
- * 3 is async transmit
- */
-
-
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#define PRINT_GD(level, fmt, args...) printk(level "pcilynx: " fmt "\n" , ## args)
#define PRINTD(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args)
#else
-#define PRINT_GD(level, fmt, args...)
-#define PRINTD(level, card, fmt, args...)
+#define PRINT_GD(level, fmt, args...) do {} while (0)
+#define PRINTD(level, card, fmt, args...) do {} while (0)
#endif
static struct ti_lynx cards[MAX_PCILYNX_CARDS];
spin_lock_irqsave(&lynx->phy_reg_lock, flags);
+ reg_write(lynx, LINK_PHY, LINK_PHY_READ | LINK_PHY_ADDR(addr));
do {
- reg_write(lynx, LINK_PHY, LINK_PHY_READ | LINK_PHY_ADDR(addr));
retval = reg_read(lynx, LINK_PHY);
if (i > 10000) {
lsid = 0x80400000 | ((phyreg[0] & 0xfc) << 22);
lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */
lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */
- /* lsid |= (phyreg[6] & 0x01) << 11; *//* contender (phy dependent) */
- lsid |= 1 << 11; /* set contender (hack) */
+ lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */
+ /* lsid |= 1 << 11; *//* set contender (hack) */
lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */
- //for (i = 0; i < (phyreg[2] & 0xf); i++) { /* ports */
- for (i = 0; i < (phyreg[2] & 0x1f); i++) { /* ports */
+ for (i = 0; i < (phyreg[2] & 0xf); i++) { /* ports */
if (phyreg[3 + i] & 0x4) {
lsid |= (((phyreg[3 + i] & 0x8) | 0x10) >> 3)
<< (6 - i*2);
hpsb_selfid_received(host, lsid);
}
+ if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER);
+
hpsb_selfid_complete(host, phyid, isroot);
}
-/* This must be called with the async.queue_lock held. */
-static void send_next_async(struct ti_lynx *lynx)
+/* This must be called with the respective queue_lock held. */
+static void send_next(struct ti_lynx *lynx, int what)
{
struct ti_pcl pcl;
- struct hpsb_packet *packet = lynx->async.queue;
+ struct lynx_send_data *d;
+ struct hpsb_packet *packet;
- lynx->async.header_dma = pci_map_single(lynx->dev, packet->header,
- packet->header_size,
- PCI_DMA_TODEVICE);
+ d = (what == iso ? &lynx->iso_send : &lynx->async);
+ packet = d->queue;
+
+ d->header_dma = pci_map_single(lynx->dev, packet->header,
+ packet->header_size, PCI_DMA_TODEVICE);
if (packet->data_size) {
- lynx->async.data_dma = pci_map_single(lynx->dev, packet->data,
- packet->data_size,
- PCI_DMA_TODEVICE);
+ d->data_dma = pci_map_single(lynx->dev, packet->data,
+ packet->data_size,
+ PCI_DMA_TODEVICE);
} else {
- lynx->async.data_dma = 0;
+ d->data_dma = 0;
}
pcl.next = PCL_NEXT_INVALID;
pcl.async_error_next = PCL_NEXT_INVALID;
#ifdef __BIG_ENDIAN
- pcl.buffer[0].control = PCL_CMD_XMT | packet->speed_code << 14
- | packet->header_size;
+ pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size;
#else
- pcl.buffer[0].control = PCL_CMD_XMT | packet->speed_code << 14
- | packet->header_size | PCL_BIGENDIAN;
+ pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size
+ | PCL_BIGENDIAN;
#endif
- pcl.buffer[0].pointer = lynx->async.header_dma;
+ pcl.buffer[0].pointer = d->header_dma;
pcl.buffer[1].control = PCL_LAST_BUFF | packet->data_size;
- pcl.buffer[1].pointer = lynx->async.data_dma;
+ pcl.buffer[1].pointer = d->data_dma;
+
+ switch (packet->type) {
+ case async:
+ pcl.buffer[0].control |= PCL_CMD_XMT;
+ break;
+ case iso:
+ pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
+ break;
+ case raw:
+ pcl.buffer[0].control |= PCL_CMD_UNFXMT;
+ break;
+ }
if (!packet->data_be) {
pcl.buffer[1].control |= PCL_BIGENDIAN;
}
- put_pcl(lynx, lynx->async.pcl, &pcl);
- run_pcl(lynx, lynx->async.pcl_start, 3);
+ put_pcl(lynx, d->pcl, &pcl);
+ run_pcl(lynx, d->pcl_start, d->channel);
}
pcl.async_error_next = pcl_bus(lynx, lynx->async.pcl);
put_pcl(lynx, lynx->async.pcl_start, &pcl);
+ pcl.next = pcl_bus(lynx, lynx->iso_send.pcl);
+ pcl.async_error_next = PCL_NEXT_INVALID;
+ put_pcl(lynx, lynx->iso_send.pcl_start, &pcl);
+
pcl.next = PCL_NEXT_INVALID;
pcl.async_error_next = PCL_NEXT_INVALID;
pcl.buffer[0].control = PCL_CMD_RCV | 4;
}
put_pcl(lynx, lynx->iso_rcv.pcl_start, &pcl);
- /* 85 bytes for each FIFO - FIXME - optimize or make configurable */
- /* reg_write(lynx, FIFO_SIZES, 0x00555555); */
- reg_write(lynx, FIFO_SIZES, 0x002020c0);
+ /* FIFO sizes from left to right: ITF=48 ATF=48 GRF=160 */
+ reg_write(lynx, FIFO_SIZES, 0x003030a0);
/* 20 byte threshold before triggering PCI transfer */
reg_write(lynx, DMA_GLOBAL_REGISTER, 0x2<<24);
- /* 69 byte threshold on both send FIFOs before transmitting */
- reg_write(lynx, FIFO_XMIT_THRESHOLD, 0x4545);
+ /* threshold on both send FIFOs before transmitting:
+ FIFO size - cache line size - 1 */
+ i = reg_read(lynx, PCI_LATENCY_CACHELINE) & 0xff;
+ i = 0x30 - i - 1;
+ reg_write(lynx, FIFO_XMIT_THRESHOLD, (i << 8) | i);
reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_1394);
+
reg_write(lynx, LINK_INT_ENABLE, LINK_INT_PHY_TIMEOUT
| LINK_INT_PHY_REG_RCVD | LINK_INT_PHY_BUSRESET
| LINK_INT_ISO_STUCK | LINK_INT_ASYNC_STUCK
| LINK_INT_GRF_OVERFLOW | LINK_INT_ITF_UNDERFLOW
| LINK_INT_ATF_UNDERFLOW);
- reg_write(lynx, DMA1_WORD0_CMP_VALUE, 0);
- reg_write(lynx, DMA1_WORD0_CMP_ENABLE, 0xa<<4);
- reg_write(lynx, DMA1_WORD1_CMP_VALUE, 0);
- reg_write(lynx, DMA1_WORD1_CMP_ENABLE, DMA_WORD1_CMP_MATCH_NODE_BCAST
- | DMA_WORD1_CMP_MATCH_BROADCAST | DMA_WORD1_CMP_MATCH_LOCAL
- | DMA_WORD1_CMP_MATCH_BUS_BCAST | DMA_WORD1_CMP_ENABLE_SELF_ID
- | DMA_WORD1_CMP_ENABLE_MASTER);
+ reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ASYNC_RCV), 0);
+ reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ASYNC_RCV), 0xa<<4);
+ reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ASYNC_RCV), 0);
+ reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ASYNC_RCV),
+ DMA_WORD1_CMP_MATCH_NODE_BCAST | DMA_WORD1_CMP_MATCH_BROADCAST
+ | DMA_WORD1_CMP_MATCH_LOCAL | DMA_WORD1_CMP_MATCH_BUS_BCAST
+ | DMA_WORD1_CMP_ENABLE_SELF_ID | DMA_WORD1_CMP_ENABLE_MASTER);
- run_pcl(lynx, lynx->rcv_pcl_start, 1);
+ run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV);
reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ISO_RCV), 0);
reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ISO_RCV), 0x9<<4);
| LINK_CONTROL_TX_ISO_EN | LINK_CONTROL_RX_ISO_EN
| LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN
| LINK_CONTROL_RESET_TX | LINK_CONTROL_RESET_RX
- | LINK_CONTROL_CYCSOURCE | LINK_CONTROL_CYCTIMEREN);
+ | LINK_CONTROL_CYCTIMEREN);
/* attempt to enable contender bit -FIXME- would this work elsewhere? */
reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
}
}
-
-/*
- * FIXME - does not support iso/raw transmits yet and will choke on them.
- */
static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
{
struct ti_lynx *lynx = host->hostdata;
- struct hpsb_packet *p;
+ struct lynx_send_data *d;
unsigned long flags;
if (packet->data_size >= 4096) {
return 0;
}
+ switch (packet->type) {
+ case async:
+ case raw:
+ d = &lynx->async;
+ break;
+ case iso:
+ d = &lynx->iso_send;
+ break;
+ default:
+ PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
+ packet->type);
+ return 0;
+ }
+
packet->xnext = NULL;
if (packet->tcode == TCODE_WRITEQ
|| packet->tcode == TCODE_READQ_RESPONSE) {
cpu_to_be32s(&packet->header[3]);
}
- spin_lock_irqsave(&lynx->async.queue_lock, flags);
+ spin_lock_irqsave(&d->queue_lock, flags);
- if (lynx->async.queue == NULL) {
- lynx->async.queue = packet;
- send_next_async(lynx);
+ if (d->queue == NULL) {
+ d->queue = packet;
+ d->queue_last = packet;
+ send_next(lynx, packet->type);
} else {
- p = lynx->async.queue;
- while (p->xnext != NULL) {
- p = p->xnext;
- }
-
- p->xnext = packet;
+ d->queue_last->xnext = packet;
+ d->queue_last = packet;
}
- spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
+ spin_unlock_irqrestore(&d->queue_lock, flags);
return 1;
}
case CANCEL_REQUESTS:
spin_lock_irqsave(&lynx->async.queue_lock, flags);
- reg_write(lynx, DMA3_CHAN_CTRL, 0);
+ reg_write(lynx, DMA_CHAN_CTRL(CHANNEL_ASYNC_SEND), 0);
packet = lynx->async.queue;
lynx->async.queue = NULL;
static int mem_open(struct inode*, struct file*);
static int mem_release(struct inode*, struct file*);
static unsigned int aux_poll(struct file*, struct poll_table_struct*);
+static loff_t mem_llseek(struct file*, loff_t, int);
static ssize_t mem_read (struct file*, char*, size_t, loff_t*);
static ssize_t mem_write(struct file*, const char*, size_t, loff_t*);
static struct file_operations aux_ops = {
OWNER_THIS_MODULE
- /* FIXME: should have custom llseek with bounds checking */
- read: mem_read,
- write: mem_write,
- poll: aux_poll,
- open: mem_open,
- release: mem_release,
+ read: mem_read,
+ write: mem_write,
+ poll: aux_poll,
+ llseek: mem_llseek,
+ open: mem_open,
+ release: mem_release,
};
static int mem_open(struct inode *inode, struct file *file)
{
int cid = MINOR(inode->i_rdev);
- enum { rom, aux, ram } type;
+ enum { t_rom, t_aux, t_ram } type;
struct memdata *md;
V22_COMPAT_MOD_INC_USE_COUNT;
V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENXIO;
}
- type = aux;
+ type = t_aux;
} else if (cid < PCILYNX_MINOR_RAM_START) {
cid -= PCILYNX_MINOR_ROM_START;
if (cid >= num_of_cards || !cards[cid].local_rom) {
V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENXIO;
}
- type = rom;
+ type = t_rom;
} else {
/* WARNING: Know what you are doing when opening RAM.
* It is currently used inside the driver! */
V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENXIO;
}
- type = ram;
+ type = t_ram;
}
- md = (struct memdata *)vmalloc(sizeof(struct memdata));
+ md = (struct memdata *)kmalloc(sizeof(struct memdata), SLAB_KERNEL);
if (md == NULL) {
V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENOMEM;
md->cid = cid;
switch (type) {
- case rom:
+ case t_rom:
md->type = rom;
break;
- case ram:
+ case t_ram:
md->type = ram;
break;
- case aux:
+ case t_aux:
atomic_set(&md->aux_intr_last_seen,
atomic_read(&cards[cid].aux_intr_seen));
md->type = aux;
{
struct memdata *md = (struct memdata *)file->private_data;
- vfree(md);
+ kfree(md);
V22_COMPAT_MOD_DEC_USE_COUNT;
return 0;
return mask;
}
+loff_t mem_llseek(struct file *file, loff_t offs, int orig)
+{
+ loff_t newoffs;
+
+ switch (orig) {
+ case 0:
+ newoffs = offs;
+ break;
+ case 1:
+ newoffs = offs + file->f_pos;
+ break;
+ case 2:
+ newoffs = PCILYNX_MAX_MEMORY + 1 + offs;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (newoffs < 0 || newoffs > PCILYNX_MAX_MEMORY + 1) return -EINVAL;
+
+ file->f_pos = newoffs;
+ return newoffs;
+}
/*
* do not DMA if count is too small because this will have a serious impact
int i;
DECLARE_WAITQUEUE(wait, current);
- //printk("buf 0x%08x %x count %d offset %d\n", physbuf, physbuf % 3, count, offset);
-
count &= ~3;
count = MIN(count, 53196);
retval = count;
PRINT(KERN_WARNING, md->lynx->id, "DMA ALREADY ACTIVE!");
}
- switch (md->type) {
- case rom:
- reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_ROM | offset);
- break;
- case ram:
- reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_RAM | offset);
- break;
- case aux:
- reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_AUX | offset);
- break;
- }
+ reg_write(md->lynx, LBUS_ADDR, md->type | offset);
pcl = edit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp);
pcl->buffer[0].control = PCL_CMD_LBUS_TO_PCI | MIN(count, 4092);
if ((off + count) > PCILYNX_MAX_MEMORY + 1) {
count = PCILYNX_MAX_MEMORY + 1 - off;
}
- if (count <= 0) {
+ if (count == 0) {
return 0;
}
{
struct ti_lynx *lynx = (struct ti_lynx *)dev_id;
struct hpsb_host *host = lynx->host;
- u32 intmask = reg_read(lynx, PCI_INT_STATUS);
- u32 linkint = reg_read(lynx, LINK_INT_STATUS);
+ u32 intmask;
+ u32 linkint;
+
+ linkint = reg_read(lynx, LINK_INT_STATUS);
+ intmask = reg_read(lynx, PCI_INT_STATUS);
+
+ PRINTD(KERN_DEBUG, lynx->id, "interrupt: 0x%08x / 0x%08x", intmask,
+ linkint);
- reg_write(lynx, PCI_INT_STATUS, intmask);
reg_write(lynx, LINK_INT_STATUS, linkint);
- //printk("-%d- one interrupt: 0x%08x / 0x%08x\n", lynx->id, intmask, linkint);
+ reg_write(lynx, PCI_INT_STATUS, intmask);
#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
if (intmask & PCI_INT_AUX_INT) {
wake_up_interruptible(&lynx->aux_intr_wait);
}
- if (intmask & PCI_INT_DMA0_HLT) {
+ if (intmask & PCI_INT_DMA_HLT(CHANNEL_LOCALBUS)) {
wake_up_interruptible(&lynx->mem_dma_intr_wait);
}
#endif
mark_bh(IMMEDIATE_BH);
}
- if (intmask & PCI_INT_DMA3_HLT) {
- /* async send DMA completed */
+ if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_SEND)) {
u32 ack;
struct hpsb_packet *packet;
spin_lock(&lynx->async.queue_lock);
- ack = reg_read(lynx, DMA3_CHAN_STAT);
+ ack = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_SEND));
packet = lynx->async.queue;
lynx->async.queue = packet->xnext;
}
if (lynx->async.queue != NULL) {
- send_next_async(lynx);
+ send_next(lynx, async);
}
spin_unlock(&lynx->async.queue_lock);
hpsb_packet_sent(host, packet, ack);
}
- if (intmask & (PCI_INT_DMA1_HLT | PCI_INT_DMA1_PCL)) {
+ if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_SEND)) {
+ struct hpsb_packet *packet;
+
+ spin_lock(&lynx->iso_send.queue_lock);
+
+ packet = lynx->iso_send.queue;
+ lynx->iso_send.queue = packet->xnext;
+
+ pci_unmap_single(lynx->dev, lynx->iso_send.header_dma,
+ packet->header_size, PCI_DMA_TODEVICE);
+ if (packet->data_size) {
+ pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
+ packet->data_size, PCI_DMA_TODEVICE);
+ }
+
+ if (lynx->iso_send.queue != NULL) {
+ send_next(lynx, iso);
+ }
+
+ spin_unlock(&lynx->iso_send.queue_lock);
+
+ hpsb_packet_sent(host, packet, ACK_COMPLETE);
+ }
+
+ if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_RCV)) {
/* general receive DMA completed */
- int stat = reg_read(lynx, DMA1_CHAN_STAT);
+ int stat = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_RCV));
PRINTD(KERN_DEBUG, lynx->id, "received packet size %d",
stat & 0x1fff);
hpsb_packet_received(host, q_data, stat & 0x1fff, 0);
}
- run_pcl(lynx, lynx->rcv_pcl_start, 1);
+ run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV);
}
}
}
pci_set_master(dev);
- if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ,
- PCILYNX_DRIVER_NAME, lynx)) {
- PRINT(KERN_INFO, lynx->id, "allocated interrupt %d", dev->irq);
- lynx->state = have_intr;
- } else {
- FAIL("failed to allocate shared interrupt %d", dev->irq);
- }
-
#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
lynx->pcl_mem = pci_alloc_consistent(dev, LOCALRAM_SIZE,
&lynx->pcl_mem_dma);
}
#endif
+ reg_write(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
+
+ if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ,
+ PCILYNX_DRIVER_NAME, lynx)) {
+ PRINT(KERN_INFO, lynx->id, "allocated interrupt %d", dev->irq);
+ lynx->state = have_intr;
+ } else {
+ FAIL("failed to allocate shared interrupt %d", dev->irq);
+ }
+
/* alloc_pcl return values are not checked, it is expected that the
* provided PCL space is sufficient for the initial allocations */
#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
lynx->rcv_pcl_start = alloc_pcl(lynx);
lynx->async.pcl = alloc_pcl(lynx);
lynx->async.pcl_start = alloc_pcl(lynx);
+ lynx->iso_send.pcl = alloc_pcl(lynx);
+ lynx->iso_send.pcl_start = alloc_pcl(lynx);
for (i = 0; i < NUM_ISORCV_PCL; i++) {
lynx->iso_rcv.pcl[i] = alloc_pcl(lynx);
lynx->iso_rcv.tq.routine = (void (*)(void*))iso_rcv_bh;
lynx->iso_rcv.tq.data = lynx;
lynx->iso_rcv.lock = SPIN_LOCK_UNLOCKED;
+
+ lynx->async.queue_lock = SPIN_LOCK_UNLOCKED;
+ lynx->async.channel = CHANNEL_ASYNC_SEND;
+ lynx->iso_send.queue_lock = SPIN_LOCK_UNLOCKED;
+ lynx->iso_send.channel = CHANNEL_ISO_SEND;
PRINT(KERN_INFO, lynx->id, "remapped memory spaces reg 0x%p, rom 0x%p, "
"ram 0x%p, aux 0x%p", lynx->registers, lynx->local_rom,
int i;
switch (lynx->state) {
+ case have_intr:
+ free_irq(lynx->dev->irq, lynx);
case have_iomappings:
reg_write(lynx, PCI_INT_ENABLE, 0);
reg_write(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
pci_free_consistent(lynx->dev, 65536, lynx->mem_dma_buffer,
lynx->mem_dma_buffer_dma);
#endif
- case have_pcl_mem:
+ case have_pcl_mem:
#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem,
lynx->pcl_mem_dma);
#endif
- case have_intr:
- free_irq(lynx->dev->irq, lynx);
case clear:
/* do nothing - already freed */
}
#define ISORCV_PER_PAGE (PAGE_SIZE / MAX_ISORCV_SIZE)
#define ISORCV_PAGES (NUM_ISORCV_PCL / ISORCV_PER_PAGE)
-/* only iso rcv and localbus use these definitions so far */
#define CHANNEL_LOCALBUS 0
#define CHANNEL_ASYNC_RCV 1
#define CHANNEL_ISO_RCV 2
#define CHANNEL_ASYNC_SEND 3
+#define CHANNEL_ISO_SEND 4
typedef int pcl_t;
dma_addr_t rcv_page_dma;
int rcv_active;
- struct {
+ struct lynx_send_data {
pcl_t pcl_start, pcl;
- struct hpsb_packet *queue;
+ struct hpsb_packet *queue, *queue_last;
spinlock_t queue_lock;
dma_addr_t header_dma, data_dma;
- } async;
+ int channel;
+ } async, iso_send;
struct {
pcl_t pcl[NUM_ISORCV_PCL];
struct ti_lynx *lynx;
int cid;
atomic_t aux_intr_last_seen;
- enum { rom, aux, ram } type;
+ /* enum values are the same as LBUS_ADDR_SEL_* values below */
+ enum { rom = 0x10000, aux = 0x20000, ram = 0 } type;
};
/* chip register definitions follow */
+#define PCI_LATENCY_CACHELINE 0x0c
+
#define MISC_CONTROL 0x40
#define MISC_CONTROL_SWRESET (1<<0)
#define PCL_LAST_CMD (PCL_LAST_BUFF)
#define PCL_WAITSTAT (1<<17)
#define PCL_BIGENDIAN (1<<16)
+#define PCL_ISOMODE (1<<12)
#define _(x) (__constant_cpu_to_be32(x))
#include "raw1394.h"
+#if BITS_PER_LONG == 64
+#define int2ptr(x) ((void *)x)
+#define ptr2int(x) ((u64)x)
+#else
+#define int2ptr(x) ((void *)(u32)x)
+#define ptr2int(x) ((u64)(u32)x)
+#endif
+
+
static devfs_handle_t devfs_handle = NULL;
LIST_HEAD(host_info_list);
req->file_info = fi;
req->req.type = RAW1394_REQ_BUS_RESET;
req->req.generation = get_hpsb_generation();
- req->req.misc = (host->node_id << 16)
+ req->req.misc = (host->node_id << 16)
| host->node_count;
+ if (fi->protocol_version > 3) {
+ req->req.misc |= ((host->irm_id
+ & NODE_MASK) << 8);
+ }
+
queue_complete_req(req);
}
req->req.type = RAW1394_REQ_ISO_RECEIVE;
req->req.generation = get_hpsb_generation();
req->req.misc = 0;
- req->req.recvb = (u64)fi->iso_buffer;
+ req->req.recvb = ptr2int(fi->iso_buffer);
req->req.length = MIN(length, fi->iso_buffer_length);
list_add_tail(&req->list, &reqs);
req->req.type = RAW1394_REQ_FCP_REQUEST;
req->req.generation = get_hpsb_generation();
req->req.misc = nodeid | (direction << 16);
- req->req.recvb = (u64)fi->fcp_buffer;
+ req->req.recvb = ptr2int(fi->fcp_buffer);
req->req.length = length;
list_add_tail(&req->list, &reqs);
req = list_entry(lh, struct pending_request, list);
if (req->req.length) {
- if (copy_to_user((void *)req->req.recvb, req->data,
+ if (copy_to_user(int2ptr(req->req.recvb), req->data,
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
}
static int state_opened(struct file_info *fi, struct pending_request *req)
{
if (req->req.type == RAW1394_REQ_INITIALIZE) {
- if (req->req.misc == RAW1394_KERNELAPI_VERSION) {
+ switch (req->req.misc) {
+ case RAW1394_KERNELAPI_VERSION:
+ case 3:
fi->state = initialized;
+ fi->protocol_version = req->req.misc;
req->req.error = RAW1394_ERROR_NONE;
req->req.generation = get_hpsb_generation();
- } else {
+ break;
+
+ default:
req->req.error = RAW1394_ERROR_COMPAT;
req->req.misc = RAW1394_KERNELAPI_VERSION;
}
req->req.error = RAW1394_ERROR_NONE;
req->req.misc = (fi->host->node_id << 16)
| fi->host->node_count;
+ if (fi->protocol_version > 3) {
+ req->req.misc |=
+ (fi->host->irm_id & NODE_MASK) << 8;
+ }
} else {
req->req.error = RAW1394_ERROR_INVALID_ARG;
}
} else {
fi->listen_channels |= 1ULL << channel;
hpsb_listen_channel(hl_handle, fi->host, channel);
- fi->iso_buffer = (void *)req->req.recvb;
+ fi->iso_buffer = int2ptr(req->req.recvb);
fi->iso_buffer_length = req->req.length;
}
} else {
if (fi->fcp_buffer) {
req->req.error = RAW1394_ERROR_ALREADY;
} else {
- fi->fcp_buffer = (u8 *)req->req.recvb;
+ fi->fcp_buffer = (u8 *)int2ptr(req->req.recvb);
}
} else {
if (!fi->fcp_buffer) {
break;
case RAW1394_REQ_ASYNC_WRITE:
- if (copy_from_user(req->data, (void *)req->req.sendb,
+ if (copy_from_user(req->data, int2ptr(req->req.sendb),
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
break;
}
}
- if (copy_from_user(req->data, (void *)req->req.sendb,
+ if (copy_from_user(req->data, int2ptr(req->req.sendb),
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
break;
if (req->req.length == 4) {
quadlet_t x;
- if (copy_from_user(&x, (void *)req->req.sendb, 4)) {
+ if (copy_from_user(&x, int2ptr(req->req.sendb), 4)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
}
req->req.length);
if (!packet) return -ENOMEM;
- if (copy_from_user(packet->data, (void *)req->req.sendb,
+ if (copy_from_user(packet->data, int2ptr(req->req.sendb),
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
}
req->req.misc);
if (!packet) return -ENOMEM;
- if (copy_from_user(packet->data, (void *)req->req.sendb,
+ if (copy_from_user(packet->data, int2ptr(req->req.sendb),
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
break;
return sizeof(struct raw1394_request);
}
+static int handle_iso_send(struct file_info *fi, struct pending_request *req,
+ int channel)
+{
+ struct hpsb_packet *packet;
+
+ packet = alloc_hpsb_packet(req->req.length);
+ if (!packet) return -ENOMEM;
+ req->packet = packet;
+
+ fill_iso_packet(packet, req->req.length, channel & 0x3f,
+ (req->req.misc >> 16) & 0x3, req->req.misc & 0xf);
+ packet->type = iso;
+ packet->speed_code = req->req.address & 0x3;
+ packet->host = fi->host;
+
+ if (copy_from_user(packet->data, int2ptr(req->req.sendb),
+ req->req.length)) {
+ req->req.error = RAW1394_ERROR_MEMFAULT;
+ req->req.length = 0;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
+ }
+
+ req->tq.data = req;
+ req->tq.routine = (void (*)(void*))queue_complete_req;
+ req->req.length = 0;
+ queue_task(&req->tq, &packet->complete_tq);
+
+ if (!hpsb_send_packet(packet)) {
+ req->req.error = RAW1394_ERROR_SEND_ERROR;
+ queue_complete_req(req);
+ }
+
+ return sizeof(struct raw1394_request);
+}
+
static int state_connected(struct file_info *fi, struct pending_request *req)
{
int node = req->req.address >> 48;
req->req.error = RAW1394_ERROR_NONE;
+ if (req->req.type == RAW1394_REQ_ISO_SEND) {
+ return handle_iso_send(fi, req, node);
+ }
+
if (req->req.generation != get_hpsb_generation()) {
req->req.error = RAW1394_ERROR_GENERATION;
req->req.generation = get_hpsb_generation();
return sizeof(struct raw1394_request);
}
- if (req->req.type == RAW1394_REQ_ISO_LISTEN) {
+ switch (req->req.type) {
+ case RAW1394_REQ_ISO_LISTEN:
handle_iso_listen(fi, req);
return sizeof(struct raw1394_request);
- }
- if (req->req.type == RAW1394_REQ_FCP_LISTEN) {
+ case RAW1394_REQ_FCP_LISTEN:
handle_fcp_listen(fi, req);
return sizeof(struct raw1394_request);
+
+ case RAW1394_REQ_RESET_BUS:
+ hpsb_reset_bus(fi->host);
+ return sizeof(struct raw1394_request);
}
if (req->req.length == 0) {
struct pending_request *req;
int done = 0, i;
- lock_kernel();
+ 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();
+ unlock_kernel();
return 0;
}
#define RAW1394_DEVICE_MAJOR 171
#define RAW1394_DEVICE_NAME "raw1394"
-#define RAW1394_KERNELAPI_VERSION 3
+#define RAW1394_KERNELAPI_VERSION 4
/* state: opened */
#define RAW1394_REQ_INITIALIZE 1
#define RAW1394_REQ_ASYNC_WRITE 101
#define RAW1394_REQ_LOCK 102
#define RAW1394_REQ_LOCK64 103
+#define RAW1394_REQ_ISO_SEND 104
#define RAW1394_REQ_ISO_LISTEN 200
#define RAW1394_REQ_FCP_LISTEN 201
+#define RAW1394_REQ_RESET_BUS 202
/* kernel to user */
#define RAW1394_REQ_BUS_RESET 10000
struct list_head list;
enum { opened, initialized, connected } state;
+ unsigned int protocol_version;
struct hpsb_host *host;
#define ISO_RECEIVE 0
#define ISO_TRANSMIT 1
+#ifndef virt_to_page
+#define virt_to_page(x) MAP_NR(x)
+#endif
+
struct it_dma_prg {
struct dma_cmd begin;
quadlet_t data[4];
int cmdPtr;
int ctxMatch;
wait_queue_head_t waitq;
+ spinlock_t lock;
};
struct video_card {
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-#define page_address(x) ((void *) (x))
+#define page_address(x) (x)
#endif
/* Given PGD from the address space's page table, return the kernel
pte = *ptep;
if(pte_present(pte)) {
ret = (unsigned long) page_address(pte_page(pte));
- ret |= (adr & (PAGE_SIZE - 1));
+ ret |= (adr & (PAGE_SIZE - 1));
}
}
}
void * mem;
unsigned long adr, page;
- mem=vmalloc(size);
+ mem=vmalloc_32(size);
if (mem)
{
memset(mem, 0, size); /* Clear the ram out,
d->packet_size = packet_size;
- if (PAGE_SIZE % packet_size || packet_size>2048) {
+ if (PAGE_SIZE % packet_size || packet_size>4096) {
PRINT(KERN_ERR, ohci->id,
"Packet size %d not yet supported\n",
packet_size);
}
memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
+ spin_lock_init(&d->lock);
+
PRINT(KERN_INFO, ohci->id, "Iso %s DMA: %d buffers "
"of size %d allocated for a frame size %d, each with %d prgs",
(type==ISO_RECEIVE) ? "receive" : "transmit",
return -EFAULT;
}
+ spin_lock(&d->lock);
for (i=0;i<d->num_desc;i++) {
if (d->ir_prg[i][d->nb_cmd-1].status & 0xFFFF0000) {
reset_ir_status(d, i);
d->buffer_status[i] = VIDEO1394_BUFFER_READY;
}
}
+ spin_unlock(&d->lock);
if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq);
return 0;
}
return -EFAULT;
}
+ spin_lock(&d->lock);
for (i=0;i<d->num_desc;i++) {
if (d->it_prg[i][d->nb_cmd-1].end.status & 0xFFFF0000) {
d->it_prg[i][d->nb_cmd-1].end.status = 0;
d->buffer_status[i] = VIDEO1394_BUFFER_READY;
}
}
+ spin_unlock(&d->lock);
if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq);
return 0;
}
{
struct video_card *video = &video_cards[MINOR(inode->i_rdev)];
struct ti_ohci *ohci= video->ohci;
+ unsigned long flags;
switch(cmd)
{
return -EFAULT;
}
- if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
+ spin_lock_irqsave(&d->lock,flags);
+
+ if (d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED) {
PRINT(KERN_ERR, ohci->id,
"buffer %d is already used",v.buffer);
+ spin_unlock_irqrestore(&d->lock,flags);
return -EFAULT;
}
d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;
+ spin_unlock_irqrestore(&d->lock,flags);
+
if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
{
DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx);
return -EFAULT;
}
+ /*
+ * I change the way it works so that it returns
+ * the last received frame.
+ */
+ spin_lock_irqsave(&d->lock, flags);
switch(d->buffer_status[v.buffer]) {
case VIDEO1394_BUFFER_READY:
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
- return 0;
+ break;
case VIDEO1394_BUFFER_QUEUED:
#if 1
while(d->buffer_status[v.buffer]!=
VIDEO1394_BUFFER_READY) {
+ spin_unlock_irqrestore(&d->lock, flags);
interruptible_sleep_on(&d->waitq);
- if(signal_pending(current)) return -EINTR;
+ spin_lock_irqsave(&d->lock, flags);
+ if(signal_pending(current)) {
+ spin_unlock_irqrestore(&d->lock,flags);
+ return -EINTR;
+ }
}
#else
if (wait_event_interruptible(d->waitq,
return -EINTR;
#endif
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
- return 0;
+ break;
default:
PRINT(KERN_ERR, ohci->id,
"buffer %d is not queued",v.buffer);
+ spin_unlock_irqrestore(&d->lock, flags);
return -EFAULT;
}
+
+ /*
+ * Look ahead to see how many more buffers have been received
+ */
+ i=0;
+ while (d->buffer_status[(v.buffer+1)%d->num_desc]==
+ VIDEO1394_BUFFER_READY) {
+ v.buffer=(v.buffer+1)%d->num_desc;
+ i++;
+ }
+ spin_unlock_irqrestore(&d->lock, flags);
+
+ v.buffer=i;
+ if(copy_to_user((void *)arg, &v, sizeof(v)))
+ return -EFAULT;
+
+ return 0;
}
case VIDEO1394_TALK_QUEUE_BUFFER:
{
return -EFAULT;
}
+ spin_lock_irqsave(&d->lock,flags);
+
if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
PRINT(KERN_ERR, ohci->id,
"buffer %d is already used",v.buffer);
+ spin_unlock_irqrestore(&d->lock,flags);
return -EFAULT;
}
d->it_prg[d->last_buffer][d->nb_cmd-1].end.branchAddress = 0;
+ spin_unlock_irqrestore(&d->lock,flags);
+
if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
{
DBGMSG(ohci->id, "Starting iso transmit DMA ctx=%d",
#define VIDEO1394_DRIVER_NAME "video1394"
-#define VIDEO1394_MAX_SIZE 0x400000
+#define VIDEO1394_MAX_SIZE 0x4000000
enum {
VIDEO1394_BUFFER_FREE = 0,
#ifdef MODULE
#include "idi.h"
-void EtdM_DIDD_Write(DESCRIPTOR *, int);
-EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Read);
-EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Write);
+void DIVA_DIDD_Write(DESCRIPTOR *, int);
+EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read);
+EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Write);
EXPORT_SYMBOL_NOVERS(DivasPrintf);
#define Divas_init init_module
+#else
+#define Divas_init eicon_init
#endif
extern char *file_check(void);
{
printk(KERN_DEBUG "DIVA Server Driver - initialising\n");
- printk(KERN_DEBUG "DIVA Server Driver - Version 2.0.12 (%s)\n",file_check());
+ printk(KERN_DEBUG "DIVA Server Driver - Version 2.0.15 (%s)\n",file_check());
#if !defined(CONFIG_PCI)
MOD_DEC_USE_COUNT;
}
-#else
-Divas_setup(char *str, int *ints)
-{
-}
#endif
dia_config_t *DivasConfig(card_t *, dia_config_t *);
static
-DESCRIPTOR DIDD_Table[16];
-static
-int DIDD_Length = 0;
+DESCRIPTOR DIDD_Table[32];
-void EtdM_DIDD_Read( DESCRIPTOR *table, int *tablelength )
+void DIVA_DIDD_Read( DESCRIPTOR *table, int tablelength )
{
- int table_size = sizeof(DIDD_Table);
+ bzero(table, tablelength);
+
+ if (tablelength > sizeof(DIDD_Table))
+ tablelength = sizeof(DIDD_Table);
- bcopy((caddr_t)DIDD_Table, (caddr_t)table, table_size);
+ if(tablelength % sizeof(DESCRIPTOR)) {
+ tablelength /= sizeof(DESCRIPTOR);
+ tablelength *= sizeof(DESCRIPTOR);
+ }
- *tablelength = DIDD_Length;
+ if (tablelength > 0)
+ bcopy((caddr_t)DIDD_Table, (caddr_t)table, tablelength);
return;
}
static
-void EtdM_DIDD_Write(DESCRIPTOR *table, int tablelength)
+void DIVA_DIDD_Write(DESCRIPTOR *table, int tablelength)
{
- int table_size = sizeof(DIDD_Table);
-
- bcopy((caddr_t)table, (caddr_t)DIDD_Table, table_size);
+ if (tablelength > sizeof(DIDD_Table))
+ tablelength = sizeof(DIDD_Table);
- DIDD_Length = tablelength;
+ bcopy((caddr_t)table, (caddr_t)DIDD_Table, tablelength);
return;
}
static
void init_idi_tab(void)
{
- int length = 0;
+ DESCRIPTOR d[32];
- DESCRIPTOR d[16];
+ bzero(d, sizeof(d));
- EtdM_DIDD_Read(d, &length);
-
- d[length].type = IDI_DIMAINT; /* identify the DIMAINT entry */
- d[length].channels = 0; /* zero channels associated with dimaint*/
- d[length].features = 0; /* no features associated with dimaint */
- d[length].request = (IDI_CALL) DivasPrintf;
- length++;
+ d[0].type = IDI_DIMAINT; /* identify the DIMAINT entry */
+ d[0].channels = 0; /* zero channels associated with dimaint*/
+ d[0].features = 0; /* no features associated with dimaint */
+ d[0].request = (IDI_CALL) DivasPrintf;
- EtdM_DIDD_Write(d, length);
+ DIVA_DIDD_Write(d, sizeof(d));
return;
}
static int idi_register(card_t *card, byte channels)
{
- DESCRIPTOR d[16];
+ DESCRIPTOR d[32];
int length, num_entities;
DPRINTF(("divas: registering card with IDI"));
bzero(card->e_tbl, sizeof(E_INFO) * num_entities);
card->e_max = num_entities;
- EtdM_DIDD_Read(d, &length);
+ DIVA_DIDD_Read(d, sizeof(d));
+
+ for(length=0; length < DIM(d); length++)
+ if (d[length].type == 0) break;
- if (length == DIM(d))
+ if (length >= DIM(d))
{
KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full"));
return -1;
{
case DIA_CARD_TYPE_DIVA_SERVER:
d[length].type = IDI_ADAPTER_PR;
- d[length].serial = card->serial_no;
+ /* d[length].serial = card->serial_no; */
break;
case DIA_CARD_TYPE_DIVA_SERVER_B:
d[length].type = IDI_ADAPTER_MAESTRA;
- d[length].serial = card->serial_no;
+ /* d[length].serial = card->serial_no; */
break;
// 4BRI is treated as 4 BRI adapters
case DIA_CARD_TYPE_DIVA_SERVER_Q:
d[length].type = IDI_ADAPTER_MAESTRA;
- d[length].serial = card->cfg.serial;
+ /* d[length].serial = card->cfg.serial; */
}
d[length].features = 0;
length++;
- EtdM_DIDD_Write(d, length);
+ DIVA_DIDD_Write(d, sizeof(d));
return 0;
}
-/* $Id: eicon_mod.c,v 1.35 2000/08/12 18:00:47 armin Exp $
+/* $Id: eicon_mod.c,v 1.37 2000/09/02 11:16:47 armin Exp $
*
* ISDN lowlevel-module for Eicon active cards.
*
#define DRIVERNAME "Eicon active ISDN driver"
#define DRIVERRELEASE "2.0"
-#define DRIVERPATCH ".14"
+#define DRIVERPATCH ".15"
#include <linux/config.h>
static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains
start of card-list */
-static char *eicon_revision = "$Revision: 1.35 $";
+static char *eicon_revision = "$Revision: 1.37 $";
extern char *eicon_pci_revision;
extern char *eicon_isa_revision;
spinlock_t eicon_lock;
-DESCRIPTOR idi_d[16];
-int idi_dlength;
+DESCRIPTOR idi_d[32];
/* Parameters to be set by insmod */
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
dia_start_t dstart;
+ int idi_length = 0;
#endif
#endif
isdn_ctrl cmd;
(unsigned long) a);
if (((c->arg - EICON_IOCTL_DIA_OFFSET)==DIA_IOCTL_START) && (!ret)) {
if (card->type != EICON_CTYPE_MAESTRAQ) {
- EtdM_DIDD_Read(idi_d, &idi_dlength);
- card->d = &idi_d[idi_dlength - 1];
+ DIVA_DIDD_Read(idi_d, sizeof(idi_d));
+ for(idi_length = 0; idi_length < 32; idi_length++) {
+ if (idi_d[idi_length].type == 0) break;
+ }
+ if ((idi_length < 1) || (idi_length >= 32)) {
+ eicon_log(card, 1, "eicon: invalid idi table length.\n");
+ break;
+ }
+ card->d = &idi_d[idi_length - 1];
card->flags |= EICON_FLAGS_LOADED;
card->flags |= EICON_FLAGS_RUNNING;
eicon_pci_init_conf(card);
cmd.driver = card->myid;
cmd.arg = 0;
card->interface.statcallb(&cmd);
- eicon_log(card, 1, "Eicon: %s started, %d channels (feat. 0x%x, SerNo. %d)\n",
+ eicon_log(card, 1, "Eicon: %s started, %d channels (feat. 0x%x)\n",
(card->type == EICON_CTYPE_MAESTRA) ? "BRI" : "PRI",
- card->d->channels, card->d->features, card->d->serial);
+ card->d->channels, card->d->features);
} else {
int i;
- EtdM_DIDD_Read(idi_d, &idi_dlength);
+ DIVA_DIDD_Read(idi_d, sizeof(idi_d));
+ for(idi_length = 0; idi_length < 32; idi_length++)
+ if (idi_d[idi_length].type == 0) break;
+ if ((idi_length < 1) || (idi_length >= 32)) {
+ eicon_log(card, 1, "eicon: invalid idi table length.\n");
+ break;
+ }
for(i = 3; i >= 0; i--) {
if (!(card = eicon_findnpcicard(dstart.card_id - i)))
return -EINVAL;
card->flags |= EICON_FLAGS_LOADED;
card->flags |= EICON_FLAGS_RUNNING;
- card->d = &idi_d[idi_dlength - (i+1)];
+ card->d = &idi_d[idi_length - (i+1)];
eicon_pci_init_conf(card);
if (card->d->channels > 1) {
cmd.command = ISDN_STAT_ADDCH;
cmd.driver = card->myid;
cmd.arg = 0;
card->interface.statcallb(&cmd);
- eicon_log(card, 1, "Eicon: %d/4BRI started, %d channels (feat. 0x%x, SerNo. %d)\n",
- 4-i, card->d->channels, card->d->features, card->d->serial);
+ eicon_log(card, 1, "Eicon: %d/4BRI started, %d channels (feat. 0x%x)\n",
+ 4-i, card->d->channels, card->d->features);
}
}
}
}
#ifdef CONFIG_ISDN_DRV_EICON_PCI
-void EtdM_DIDD_Write(DESCRIPTOR *, int);
-EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Read);
-EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Write);
+void DIVA_DIDD_Write(DESCRIPTOR *, int);
+EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read);
+EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Write);
EXPORT_SYMBOL_NOVERS(DivasPrintf);
#else
int DivasCardNext;
byte type;
byte channels;
word features;
- dword serial;
+ /* dword serial; */
IDI_CALL request;
} DESCRIPTOR;
-extern void EtdM_DIDD_Read(DESCRIPTOR *, int *);
+extern void DIVA_DIDD_Read(DESCRIPTOR *, int);
/* descriptor type field coding */
#define IDI_ADAPTER_S 1
# For changes and modifications in these files please
# read ../../../Documentation/isdn/README.eicon
#
-9b0e381d4558af3a6eba66843e1ee5d9 common.c
+34bfe8d08d337a97c699ac8326f1d9b6 common.c
dbb92cba52db31ff8325a252b3f595c3 idi.c
15687687ef82f099966ed42772001cd3 bri.c
c3e3b720c3351b66635bd548195e29e8 pri.c
}
#endif
-void md__init md_run_setup(void)
+int md__init md_run_setup(void)
{
#ifdef CONFIG_AUTODETECT_RAID
mdk_rdev_t *rdev;
#ifdef CONFIG_MD_BOOT
md_setup_drive();
#endif
-
+ return 0;
}
static int get_version (void * arg)
if (!(md_setup_args.set & (1 << minor)))
continue;
printk("md: Loading md%d.\n", minor);
+ if (mddev_map[minor].mddev) {
+ printk(".. md%d already autodetected - use raid=noautodetect\n", minor);
+ continue;
+ }
mddev = alloc_mddev(MKDEV(MD_MAJOR,minor));
if (md_setup_args.pers[minor]) {
/* non-persistent */
obj-$(CONFIG_COMX_PROTO_FR) += comx-proto-fr.o
obj-$(CONFIG_COSA) += syncppp.o cosa.o
obj-$(CONFIG_LANMEDIA) += syncppp.o
+obj-$(CONFIG_SYNCLINK_SYNCPPP) += syncppp.o
obj-$(CONFIG_X25_ASY) += x25_asy.o
ifeq ($(CONFIG_LANMEDIA),y)
chipset level fix */
-int isa_dma_bridge_buggy = 0; /* Exported */
+int isa_dma_bridge_buggy; /* Exported */
static void __init quirk_isa_dma_hangs(struct pci_dev *dev)
{
}
}
-int pci_pci_problems = 0;
+int pci_pci_problems;
/*
* Chipsets where PCI->PCI transfers vanish or hang
#define ISAPNP_DEBUG
#endif
-struct resource *pidxr_res = NULL;
-struct resource *pnpwrp_res = NULL;
-struct resource *isapnp_rdp_res = NULL;
+struct resource *pidxr_res;
+struct resource *pnpwrp_res;
+struct resource *isapnp_rdp_res;
-int isapnp_disable = 0; /* Disable ISA PnP */
-int isapnp_rdp = 0; /* Read Data Port */
+int isapnp_disable; /* Disable ISA PnP */
+int isapnp_rdp; /* Read Data Port */
int isapnp_reset = 1; /* reset all PnP cards (deactivate) */
-int isapnp_skip_pci_scan = 0; /* skip PCI resource scanning */
+int isapnp_skip_pci_scan; /* skip PCI resource scanning */
int isapnp_verbose = 1; /* verbose mode */
int isapnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
int isapnp_reserve_dma[8] = { [0 ... 7] = -1 }; /* reserve (don't use) some DMA */
static unsigned char isapnp_checksum_value;
static DECLARE_MUTEX(isapnp_cfg_mutex);
-static int isapnp_detected = 0;
+static int isapnp_detected;
/* some prototypes */
* out_of_space hacks, D. Gilbert (dpg) 990608
*/
+#define REVISION "Revision: 1.00"
+#define VERSION "Id: scsi.c 1.00 2000/09/26"
+
#include <linux/config.h>
#include <linux/module.h>
#endif
/*
- * This entry point should be called by a loadable module if it is trying
- * add a low level scsi driver to the system.
+ * This entry point should be called by a driver if it is trying
+ * to add a low level scsi driver to the system.
*/
static int scsi_register_host(Scsi_Host_Template * tpnt)
{
}
+/* This function should be called by drivers which needs to register
+ * with the midlevel scsi system. As of 2.4.0-test9pre3 this is our
+ * main device/hosts register function /mathiasen
+ */
int scsi_register_module(int module_type, void *ptr)
{
switch (module_type) {
}
}
+/* Reverse the actions taken above
+ */
void scsi_unregister_module(int module_type, void *ptr)
{
switch (module_type) {
}
#endif /* CONFIG_PROC_FS */
-static int scsi_host_no_init (char *str)
+static int __init scsi_host_no_init (char *str)
{
static int next_no = 0;
char *temp;
return 1;
}
-#ifndef MODULE
-__setup("scsihosts=", scsi_host_no_init);
-#endif
-
static char *scsihosts;
MODULE_PARM(scsihosts, "s");
+MODULE_DESCRIPTION("SCSI core");
+
+#ifndef MODULE
+int __init scsi_setup(char *str)
+{
+ scsihosts = str;
+ return 1;
+}
+
+__setup("scsihosts=", scsi_setup);
+#endif
static int __init init_scsi(void)
{
struct proc_dir_entry *generic;
+ printk(KERN_INFO "SCSI subsystem driver " REVISION "\n");
+
if( scsi_init_minimal_dma_pool() != 0 )
{
return 1;
#endif
scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL);
- scsi_host_no_init (scsihosts);
+ if (scsihosts)
+ printk("scsi: host order: %s\n", scsihosts);
+ scsi_host_no_init (scsihosts);
/*
* This is where the processing takes place for most everything
* when commands are completed.
struct hd_struct *sd;
-static Scsi_Disk *rscsi_disks = NULL;
+static Scsi_Disk *rscsi_disks;
static int *sd_sizes;
static int *sd_blocksizes;
static int *sd_hardsizes; /* Hardware sector size */
* their size, and reads partition table entries for them.
*/
-static int sd_registered = 0;
+static int sd_registered;
static int sd_init()
{
return cgc->stat;
}
-static int sr_registered = 0;
+static int sr_registered;
static int sr_init()
{
{0x83847605, "SigmaTel STAC9704" , NULL},
{0x83847608, "SigmaTel STAC9708" , NULL},
{0x83847609, "SigmaTel STAC9721/23" , sigmatel_init},
+ {0x54524103, "TriTech TR?????" , NULL},
{0x54524106, "TriTech TR28026" , NULL},
{0x54524108, "TriTech TR28028" , NULL},
+ {0x54524123, "TriTech TR?????" , NULL},
{0x574D4C00, "Wolfson WM9704" , NULL},
{0x00000000, NULL, NULL}
};
unsigned int value;
} mixer_defaults[SOUND_MIXER_NRDEVICES] = {
/* all values 0 -> 100 in bytes */
- {SOUND_MIXER_VOLUME, 0x3232},
- {SOUND_MIXER_BASS, 0x3232},
- {SOUND_MIXER_TREBLE, 0x3232},
- {SOUND_MIXER_PCM, 0x3232},
- {SOUND_MIXER_SPEAKER, 0x3232},
- {SOUND_MIXER_LINE, 0x3232},
- {SOUND_MIXER_MIC, 0x3232},
- {SOUND_MIXER_CD, 0x3232},
- {SOUND_MIXER_ALTPCM, 0x3232},
- {SOUND_MIXER_IGAIN, 0x3232},
- {SOUND_MIXER_LINE1, 0x3232},
- {SOUND_MIXER_PHONEIN, 0x3232},
- {SOUND_MIXER_PHONEOUT, 0x3232},
- {SOUND_MIXER_VIDEO, 0x3232},
+ {SOUND_MIXER_VOLUME, 0x4343},
+ {SOUND_MIXER_BASS, 0x4343},
+ {SOUND_MIXER_TREBLE, 0x4343},
+ {SOUND_MIXER_PCM, 0x4343},
+ {SOUND_MIXER_SPEAKER, 0x4343},
+ {SOUND_MIXER_LINE, 0x4343},
+ {SOUND_MIXER_MIC, 0x4343},
+ {SOUND_MIXER_CD, 0x4343},
+ {SOUND_MIXER_ALTPCM, 0x4343},
+ {SOUND_MIXER_IGAIN, 0x4343},
+ {SOUND_MIXER_LINE1, 0x4343},
+ {SOUND_MIXER_PHONEIN, 0x4343},
+ {SOUND_MIXER_PHONEOUT, 0x4343},
+ {SOUND_MIXER_VIDEO, 0x4343},
{-1,0}
};
unsigned char offset;
int scale;
} ac97_hw[SOUND_MIXER_NRDEVICES]= {
- [SOUND_MIXER_VOLUME] = {AC97_MASTER_VOL_STEREO,63},
- [SOUND_MIXER_BASS] = {AC97_MASTER_TONE, 15},
- [SOUND_MIXER_TREBLE] = {AC97_MASTER_TONE, 15},
- [SOUND_MIXER_PCM] = {AC97_PCMOUT_VOL, 31},
- [SOUND_MIXER_SPEAKER] = {AC97_PCBEEP_VOL, 15},
- [SOUND_MIXER_LINE] = {AC97_LINEIN_VOL, 31},
- [SOUND_MIXER_MIC] = {AC97_MIC_VOL, 31},
- [SOUND_MIXER_CD] = {AC97_CD_VOL, 31},
- [SOUND_MIXER_ALTPCM] = {AC97_HEADPHONE_VOL, 63},
- [SOUND_MIXER_IGAIN] = {AC97_RECORD_GAIN, 31},
- [SOUND_MIXER_LINE1] = {AC97_AUX_VOL, 31},
- [SOUND_MIXER_PHONEIN] = {AC97_PHONE_VOL, 15},
- [SOUND_MIXER_PHONEOUT] = {AC97_MASTER_VOL_MONO, 63},
- [SOUND_MIXER_VIDEO] = {AC97_VIDEO_VOL, 31},
+ [SOUND_MIXER_VOLUME] = {AC97_MASTER_VOL_STEREO,64},
+ [SOUND_MIXER_BASS] = {AC97_MASTER_TONE, 16},
+ [SOUND_MIXER_TREBLE] = {AC97_MASTER_TONE, 16},
+ [SOUND_MIXER_PCM] = {AC97_PCMOUT_VOL, 32},
+ [SOUND_MIXER_SPEAKER] = {AC97_PCBEEP_VOL, 16},
+ [SOUND_MIXER_LINE] = {AC97_LINEIN_VOL, 32},
+ [SOUND_MIXER_MIC] = {AC97_MIC_VOL, 32},
+ [SOUND_MIXER_CD] = {AC97_CD_VOL, 32},
+ [SOUND_MIXER_ALTPCM] = {AC97_HEADPHONE_VOL, 64},
+ [SOUND_MIXER_IGAIN] = {AC97_RECORD_GAIN, 16},
+ [SOUND_MIXER_LINE1] = {AC97_AUX_VOL, 32},
+ [SOUND_MIXER_PHONEIN] = {AC97_PHONE_VOL, 32},
+ [SOUND_MIXER_PHONEOUT] = {AC97_MASTER_VOL_MONO, 64},
+ [SOUND_MIXER_VIDEO] = {AC97_VIDEO_VOL, 32},
};
/* the following tables allow us to go from OSS <-> ac97 quickly. */
{
u16 val;
int ret = 0;
+ int scale;
struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
val = codec->codec_read(codec , mh->offset);
- if (AC97_STEREO_MASK & (1 << oss_channel)) {
+ if (val & AC97_MUTE) {
+ ret = 0;
+ } else if (AC97_STEREO_MASK & (1 << oss_channel)) {
/* nice stereo mixers .. */
int left,right;
right = (right * 100) / mh->scale;
left = (left * 100) / mh->scale;
} else {
- right = 100 - ((right * 100) / mh->scale);
- left = 100 - ((left * 100) / mh->scale);
+ /* these may have 5 or 6 bit resolution */
+ if(oss_channel == SOUND_MIXER_VOLUME || oss_channel == SOUND_MIXER_ALTPCM)
+ scale = (1 << codec->bit_resolution);
+ else
+ scale = mh->scale;
+
+ right = 100 - ((right * 100) / scale);
+ left = 100 - ((left * 100) / scale);
}
ret = left | (right << 8);
} else if (oss_channel == SOUND_MIXER_SPEAKER) {
} else if (oss_channel == SOUND_MIXER_PHONEIN) {
ret = 100 - (((val & 0x1f) * 100) / mh->scale);
} else if (oss_channel == SOUND_MIXER_PHONEOUT) {
- ret = 100 - (((val & 0x1f) * 100) / mh->scale);
+ scale = (1 << codec->bit_resolution);
+ ret = 100 - (((val & 0x1f) * 100) / scale);
} else if (oss_channel == SOUND_MIXER_MIC) {
ret = 100 - (((val & 0x1f) * 100) / mh->scale);
/* the low bit is optional in the tone sliders and masking
unsigned int left, unsigned int right)
{
u16 val = 0;
+ int scale;
struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
#ifdef DEBUG
if (AC97_STEREO_MASK & (1 << oss_channel)) {
/* stereo mixers */
- if (oss_channel == SOUND_MIXER_IGAIN) {
- right = (right * mh->scale) / 100;
- left = (left * mh->scale) / 100;
+ if (left == 0 && right == 0) {
+ val = AC97_MUTE;
} else {
- right = ((100 - right) * mh->scale) / 100;
- left = ((100 - left) * mh->scale) / 100;
- }
- val = (left << 8) | right;
+ if (oss_channel == SOUND_MIXER_IGAIN) {
+ right = (right * mh->scale) / 100;
+ left = (left * mh->scale) / 100;
+ } else {
+ /* these may have 5 or 6 bit resolution */
+ if (oss_channel == SOUND_MIXER_VOLUME ||
+ oss_channel == SOUND_MIXER_ALTPCM)
+ scale = (1 << codec->bit_resolution);
+ else
+ scale = mh->scale;
+
+ right = ((100 - right) * scale) / 100;
+ left = ((100 - left) * scale) / 100;
+ }
+ val = (left << 8) | right;
+ }
+ } else if (oss_channel == SOUND_MIXER_BASS) {
+ val = codec->codec_read(codec , mh->offset) & ~0x0f00;
+ val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00;
+ } else if (oss_channel == SOUND_MIXER_TREBLE) {
+ val = codec->codec_read(codec , mh->offset) & ~0x000f;
+ val |= (((100 - left) * mh->scale) / 100) & 0x000e;
+ } else if(left == 0) {
+ val = AC97_MUTE;
} else if (oss_channel == SOUND_MIXER_SPEAKER) {
val = (((100 - left) * mh->scale) / 100) << 1;
} else if (oss_channel == SOUND_MIXER_PHONEIN) {
val = (((100 - left) * mh->scale) / 100);
} else if (oss_channel == SOUND_MIXER_PHONEOUT) {
- val = (((100 - left) * mh->scale) / 100);
+ scale = (1 << codec->bit_resolution);
+ val = (((100 - left) * scale) / 100);
} else if (oss_channel == SOUND_MIXER_MIC) {
val = codec->codec_read(codec , mh->offset) & ~0x801f;
val |= (((100 - left) * mh->scale) / 100);
/* the low bit is optional in the tone sliders and masking
it lets us avoid the 0xf 'bypass'.. */
- } else if (oss_channel == SOUND_MIXER_BASS) {
- val = codec->codec_read(codec , mh->offset) & ~0x0f00;
- val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00;
- } else if (oss_channel == SOUND_MIXER_TREBLE) {
- val = codec->codec_read(codec , mh->offset) & ~0x000f;
- val |= (((100 - left) * mh->scale) / 100) & 0x000e;
}
#ifdef DEBUG
printk(" 0x%04x", val);
id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
for (i = 0; i < arraysize(ac97_codec_ids); i++) {
if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
+ codec->type = ac97_codec_ids[i].id;
codec->name = ac97_codec_ids[i].name;
codec->codec_init = ac97_codec_ids[i].init;
break;
}
if (codec->name == NULL)
codec->name = "Unknown";
- printk(KERN_INFO "ac97_codec: AC97%s codec, id: 0x%04x:0x%04x (%s)\n",
- audio ? " audio" : (modem ? " modem" : ""),
+ printk(KERN_INFO "ac97_codec: AC97 %s codec, vendor id1: 0x%04x, "
+ "id2: 0x%04x (%s)\n", audio ? "Audio" : (modem ? "Modem" : ""),
id1, id2, codec->name);
return ac97_init_mixer(codec);
if (!(cap & 0x10))
codec->supported_mixers &= ~SOUND_MASK_ALTPCM;
+ /* detect bit resolution */
+ codec->codec_write(codec, AC97_MASTER_VOL_STEREO, 0x2020);
+ if(codec->codec_read(codec, AC97_MASTER_VOL_STEREO) == 0x1f1f)
+ codec->bit_resolution = 5;
+ else
+ codec->bit_resolution = 6;
+
/* generic OSS to AC97 wrapper */
codec->read_mixer = ac97_read_mixer;
codec->write_mixer = ac97_write_mixer;
codec->recmask_io = ac97_recmask_io;
codec->mixer_ioctl = ac97_mixer_ioctl;
- /* initialize volume level */
- codec->codec_write(codec, AC97_MASTER_VOL_STEREO, 0L);
- codec->codec_write(codec, AC97_PCMOUT_VOL, 0L);
-
/* codec specific initialization for 4-6 channel output or secondary codec stuff */
if (codec->codec_init != NULL) {
codec->codec_init(codec);
- Module informations added.
- Removed aedsp16_delay_10msec(), now using mdelay(10)
- All data and funcs moved to .*.init section.
+ v1.3
+ Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/09/27
+ - got rid of check_region
Known Problems:
- Audio Excel DSP 16 III don't work with this driver.
*/
-#define VERSION "1.2" /* Version of Audio Excel DSP 16 driver */
+#define VERSION "1.3" /* Version of Audio Excel DSP 16 driver */
#undef AEDSP16_DEBUG 1 /* Define this to enable debug code */
#undef AEDSP16_DEBUG_MORE 1 /* Define this to enable more debug */
if (ae_config.init & INIT_MSS)
return FALSE;
/*
- * We must check the CONFIG_AEDSP16_BASE region too because these are the I/O
- * ports to access card's control registers.
+ * We must allocate the CONFIG_AEDSP16_BASE region too because these are the
+ * I/O ports to access card's control registers.
*/
if (!(ae_config.init & INIT_MPU401)) {
- if (check_region(ae_config.base_io, IOBASE_REGION_SIZE)) {
+ if (!request_region(ae_config.base_io, IOBASE_REGION_SIZE,
+ "aedsp16 (base)")) {
printk(
"AEDSP16 BASE I/O port region is already in use.\n");
return FALSE;
}
}
-/*
- * We must allocate the CONFIG_AEDSP16_BASE region too because these are the
- * I/O ports to access card's control registers.
- */
- if (!(ae_config.init & INIT_MPU401))
- request_region(ae_config.base_io, IOBASE_REGION_SIZE,
- "aedsp16 (base)");
-
ae_config.init |= INIT_MSS;
DBG(("done.\n"));
return FALSE;
/*
- * We must check the CONFIG_AEDSP16_BASE region too because these are the I/O
+ * We must request the CONFIG_AEDSP16_BASE region too because these are the I/O
* ports to access card's control registers.
*/
if (!(ae_config.init & (INIT_MSS | INIT_SBPRO))) {
- if (check_region(ae_config.base_io, IOBASE_REGION_SIZE)) {
+ if (!request_region(ae_config.base_io, IOBASE_REGION_SIZE,
+ "aedsp16 (base)")) {
printk(
"AEDSP16 BASE I/O port region is already in use.\n");
return FALSE;
}
}
- if (!(ae_config.init & (INIT_MSS | INIT_SBPRO)))
- request_region(ae_config.base_io, IOBASE_REGION_SIZE,
- "aedsp16 (base)");
-
ae_config.init |= INIT_MPU401;
DBG(("done.\n"));
continue;
s->irq = pcidev->irq;
- if (check_region(s->iobase, CM_EXTENT_CODEC)) {
+ if (!request_region(s->iobase, CM_EXTENT_CODEC, "cmpci")) {
printk(KERN_ERR "cmpci: io ports %#x-%#x in use\n", s->iobase, s->iobase+CM_EXTENT_CODEC-1);
goto err_region5;
}
- request_region(s->iobase, CM_EXTENT_CODEC, "cmpci");
- if (check_region(s->iomidi, CM_EXTENT_MIDI)) {
+ if (!request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci Midi")) {
printk(KERN_WARNING "cmpci: io ports %#x-%#x in use, midi disabled.\n", s->iomidi, s->iomidi+CM_EXTENT_MIDI-1);
s->iomidi = 0;
}
else
{
- request_region(s->iomidi, CM_EXTENT_MIDI, "cmpci Midi");
/* set IO based at 0x330 */
outb(inb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3) & ~0x60, s->iobase + CODEC_CMI_LEGACY_CTRL + 3);
}
- if (check_region(s->iosynth, CM_EXTENT_SYNTH)) {
+ if (!request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM")) {
printk(KERN_WARNING "cmpci: io ports %#x-%#x in use, synth disabled.\n", s->iosynth, s->iosynth+CM_EXTENT_SYNTH-1);
s->iosynth = 0;
}
else
{
- request_region(s->iosynth, CM_EXTENT_SYNTH, "cmpci FM");
/* enable FM */
outb(inb(s->iobase + CODEC_CMI_MISC_CTRL + 2) | 8, s->iobase + CODEC_CMI_MISC_CTRL);
}
* Tropez+ (WaveFront) support
* Christoph Hellwig Adapted to module_init/module_exit,
* simple cleanups
+ * Arnaldo C. de Melo got rid of attach_uart401
*/
#include <linux/config.h>
hw_config2.driver_use_2 = 0;
hw_config2.card_subtype = 0;
- if (probe_uart401(&hw_config2))
+ if (probe_uart401(&hw_config2, THIS_MODULE))
{
mpu_detected = 1;
- attach_uart401(&hw_config2, THIS_MODULE);
}
else
{
return -ERESTARTSYS;
down(&s->open_sem);
}
- if (check_region(s->sbbase, FMSYNTH_EXTENT)) {
+ if (!request_region(s->sbbase, FMSYNTH_EXTENT, "ESS Solo1")) {
up(&s->open_sem);
printk(KERN_ERR "solo1: FM synth io ports in use, opl3 loaded?\n");
return -EBUSY;
}
- request_region(s->sbbase, FMSYNTH_EXTENT, "ESS Solo1");
/* init the stuff */
outb(1, s->sbbase);
outb(0x20, s->sbbase+1); /* enable waveforms */
* Paul Grayson Added support for Midi on later Mozart cards.
* 25-Nov-1999
* Christoph Hellwig Adapted to module_init/module_exit.
+ * Arnaldo C. de Melo got rid of attach_uart401 21-Sep-2000
*/
#include <linux/config.h>
request_region(hw_config->io_base, 4, "MAD16 WSS config");
}
-static void __init attach_mad16_mpu(struct address_info *hw_config)
-{
-#ifdef CONFIG_MAD16_OLDCARD
-
- if (mad_read(MC1_PORT) & 0x20)
- hw_config->io_base = 0x240;
- else
- hw_config->io_base = 0x220;
-
- hw_config->name = "Mad16/Mozart";
- sb_dsp_init(hw_config, THIS_MODULE);
- return;
-#endif
-
- if (!already_initialized)
- return;
-
- hw_config->driver_use_1 = SB_MIDI_ONLY;
- hw_config->name = "Mad16/Mozart";
- attach_uart401(hw_config, THIS_MODULE);
-}
-
static int __init probe_mad16_mpu(struct address_info *hw_config)
{
static int mpu_attached = 0;
mad_write(MC3_PORT, tmp | 0x04);
hw_config->driver_use_1 = SB_MIDI_ONLY;
- return sb_dsp_detect(hw_config, 0, 0, NULL);
+ if (!sb_dsp_detect(hw_config, 0, 0, NULL))
+ return 0;
+
+ if (mad_read(MC1_PORT) & 0x20)
+ hw_config->io_base = 0x240;
+ else
+ hw_config->io_base = 0x220;
+
+ hw_config->name = "Mad16/Mozart";
+ sb_dsp_init(hw_config, THIS_MODULE);
+ return 1;
#else
/* assuming all later Mozart cards are identified as
* either 82C928 or Mozart. If so, following code attempts
}
mad_write(MC8_PORT, tmp); /* write MPU port parameters */
-
- return probe_uart401(hw_config);
+ goto probe_401;
#endif
}
tmp = mad_read(MC6_PORT) & 0x83;
}
}
mad_write(MC6_PORT, tmp); /* Write MPU401 config */
-
- return probe_uart401(hw_config);
+#ifndef CONFIG_MAD16_OLDCARD
+probe_401:
+#endif
+ hw_config->driver_use_1 = SB_MIDI_ONLY;
+ hw_config->name = "Mad16/Mozart";
+ return probe_uart401(hw_config, THIS_MODULE);
}
static void __exit unload_mad16(struct address_info *hw_config)
attach_mad16(&cfg);
found_mpu = probe_mad16_mpu(&cfg_mpu);
-
- if (found_mpu)
- attach_mad16_mpu(&cfg_mpu);
-
return 0;
}
*/
/* From uart401.c */
-int probe_uart401 (struct address_info *hw_config);
-void attach_uart401 (struct address_info *hw_config, struct module *owner);
+int probe_uart401 (struct address_info *hw_config, struct module *owner);
void unload_uart401 (struct address_info *hw_config);
void uart401intr (int irq, void *dev_id, struct pt_regs * dummy);
* Changes:
* Alan Cox Modularisation
* Christoph Hellwig Adapted to module_init/module_exit
+ * Arnaldo C. de Melo got rid of attach_uart401
*
* FIXME:
* Check for install of mpu etc is wrong, should check result of the mss stuff
}
-static void __init attach_opl3sa_mpu(struct address_info *hw_config)
-{
- hw_config->name = "OPL3-SA (MPU401)";
- attach_uart401(hw_config, THIS_MODULE);
-}
-
static int __init probe_opl3sa_mpu(struct address_info *hw_config)
{
unsigned char conf;
DDB(printk("OPL3-SA: MPU mode already initialized\n"));
return 0;
}
- if (check_region(hw_config->io_base, 4))
- {
- printk(KERN_ERR "OPL3-SA: MPU I/O port conflict (%x)\n", hw_config->io_base);
- return 0;
- }
if (hw_config->irq > 10)
{
printk(KERN_ERR "OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq);
opl3sa_write(0x03, conf);
mpu_initialized = 1;
+ hw_config->name = "OPL3-SA (MPU401)";
- return probe_uart401(hw_config);
+ return probe_uart401(hw_config, THIS_MODULE);
}
static void __exit unload_opl3sa_wss(struct address_info *hw_config)
found_mpu=probe_opl3sa_mpu(&cfg_mpu);
attach_opl3sa_wss(&cfg);
- if(found_mpu)
- attach_opl3sa_mpu(&cfg_mpu);
-
return 0;
}
/* From sb_common.c */
void sb_dsp_disable_midi(int port);
void sb_dsp_disable_recording(int port);
-void attach_sbmpu (struct address_info *hw_config, struct module *owner);
-int probe_sbmpu (struct address_info *hw_config);
+int probe_sbmpu (struct address_info *hw_config, struct module *owner);
void unload_sbmpu (struct address_info *hw_config);
void unload_sb16(struct address_info *hw_info);
*
* 12-08-2000 Added Creative SB32 PnP (CTL009F).
* Kasatenko Ivan Alex. <skywriter@rnc.ru>
+ *
+ * 21-09-2000 Got rid of attach_sbmpu
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/config.h>
return(NULL);
/* Cards with separate OPL3 device (ALS, CMI, etc.)
- * This is just to activate the device... */
+ * This is just to activate the device so the OPL module can use it */
if(sb_isapnp_list[slot].opl_vendor || sb_isapnp_list[slot].opl_function) {
if((opl_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].opl_vendor, sb_isapnp_list[slot].opl_function, NULL))) {
int ret = opl_dev[card]->prepare(opl_dev[card]);
return 0;
}
-int __init sb_isapnp_probe(struct address_info *hw_config, struct address_info *mpu_config, int card)
+static int __init sb_isapnp_probe(struct address_info *hw_config, struct address_info *mpu_config, int card)
{
static int first = 1;
int i;
static int __init init_sb(void)
{
- int card, max = multiple ? SB_CARDS_MAX : 1;
+ int card, max = (multiple && isapnp) ? SB_CARDS_MAX : 1;
printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
* single driver! */
if(isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) {
if(!sb_cards_num) {
+ /* Found no ISAPnP cards, so check for a non-pnp
+ * card and set the detection loop for 1 cycle
+ */
printk(KERN_NOTICE "sb: No ISAPnP cards found, trying standard ones...\n");
isapnp = 0;
+ max = 1;
} else
+ /* found all the ISAPnP cards so exit the
+ * detection loop. */
break;
}
#endif
cfg[card].card_subtype = type;
- if (!probe_sb(&cfg[card]))
- return -ENODEV;
+ if (!probe_sb(&cfg[card])) {
+ /* if one or more cards already registered, don't
+ * return an error but print a warning. Note, this
+ * should never really happen unless the hardware
+ * or ISAPnP screwed up. */
+ if (sb_cards_num) {
+ printk(KERN_WARNING "sb.c: There was a " \
+ "problem probing one of your SoundBlaster " \
+ "ISAPnP soundcards. Continuing.\n");
+ card--;
+ sb_cards_num--;
+ continue;
+ } else
+ return -ENODEV;
+ }
attach_sb_card(&cfg[card]);
if(cfg[card].slots[0]==-1)
if (!isapnp)
cfg_mpu[card].io_base = mpu_io;
- if (probe_sbmpu(&cfg_mpu[card]))
+ if (probe_sbmpu(&cfg_mpu[card], THIS_MODULE))
sbmpu[card] = 1;
- if (sbmpu[card])
- attach_sbmpu(&cfg_mpu[card], THIS_MODULE);
}
if(isapnp)
* 2000/01/18 - separated sb_card and sb_common -
* Jeff Garzik <jgarzik@mandrakesoft.com>
*
+ * 2000/09/18 - got rid of attach_uart401
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/config.h>
return 1;
}
-void attach_sbmpu(struct address_info *hw_config, struct module *owner)
-{
- if (last_sb->model == MDL_ESS) {
-#if defined(CONFIG_SOUND_MPU401)
- attach_mpu401(hw_config, owner);
- if (last_sb->irq == -hw_config->irq) {
- last_sb->midi_irq_cookie=(void *)hw_config->slots[1];
- }
-#endif
- return;
- }
- attach_uart401(hw_config, THIS_MODULE);
- last_sb->midi_irq_cookie=midi_devs[hw_config->slots[4]]->devc;
-}
-
-int probe_sbmpu(struct address_info *hw_config)
+int probe_sbmpu(struct address_info *hw_config, struct module *owner)
{
sb_devc *devc = last_devc;
+ int ret;
if (last_devc == NULL)
return 0;
return 0;
hw_config->name = "ESS1xxx MPU";
devc->midi_irq_cookie = -1;
- return probe_mpu401(hw_config);
+ if (!probe_mpu401(hw_config))
+ return 0;
+ attach_mpu401(hw_config, owner);
+ if (last_sb->irq == -hw_config->irq)
+ last_sb->midi_irq_cookie=(void *)hw_config->slots[1];
+ return 1;
}
#endif
- if (check_region(hw_config->io_base, 4))
- {
- printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base);
- return 0;
- }
switch (devc->model)
{
case MDL_SB16:
default:
return 0;
}
- return probe_uart401(hw_config);
+
+ ret = probe_uart401(hw_config, owner);
+ if (ret)
+ last_sb->midi_irq_cookie=midi_devs[hw_config->slots[4]]->devc;
+ return ret;
}
void unload_sbmpu(struct address_info *hw_config)
EXPORT_SYMBOL(sb_dsp_unload);
EXPORT_SYMBOL(sb_dsp_disable_midi);
EXPORT_SYMBOL(sb_be_quiet);
-EXPORT_SYMBOL(attach_sbmpu);
EXPORT_SYMBOL(probe_sbmpu);
EXPORT_SYMBOL(unload_sbmpu);
EXPORT_SYMBOL(smw_free);
#include "sound_config.h"
-static volatile int initialized = 0, opened = 0, tmr_running = 0;
+static volatile int initialized, opened, tmr_running;
static volatile time_t tmr_offs, tmr_ctr;
static volatile unsigned long ticks_offs;
static volatile int curr_tempo, curr_timebase;
static unsigned long prev_event_time;
static volatile unsigned long usecs_per_tmr; /* Length of the current interval */
-static struct sound_lowlev_timer *tmr = NULL;
+static struct sound_lowlev_timer *tmr;
static unsigned long tmr2ticks(int tmr_value)
{
* Changes
* Alan Cox Modularisation, cleanup.
* Christoph Hellwig Adapted to module_init/module_exit
+ * Arnaldo C. de Melo Got rid of attach_uart401
*/
#include <linux/config.h>
sb_be_quiet = old_quiet;
}
-static void __init attach_trix_mpu(struct address_info *hw_config)
-{
- hw_config->name = "AudioTrix Pro";
- attach_uart401(hw_config, THIS_MODULE);
-}
-
static int __init probe_trix_mpu(struct address_info *hw_config)
{
unsigned char conf;
DDB(printk("Trix: MPU mode already initialized\n"));
return 0;
}
- if (check_region(hw_config->io_base, 4))
- {
- printk(KERN_ERR "AudioTrix: MPU I/O port conflict (%x)\n", hw_config->io_base);
- return 0;
- }
if (hw_config->irq > 9)
{
printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
conf |= irq_bits[hw_config->irq] << 4;
trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
mpu_initialized = 1;
- return probe_uart401(hw_config);
+ hw_config->name = "AudioTrix Pro";
+ return probe_uart401(hw_config, THIS_MODULE);
}
static void __exit unload_trix_wss(struct address_info *hw_config)
attach_trix_sb(&cfg2);
}
- if (cfg_mpu.io_base != -1) {
+ if (cfg_mpu.io_base != -1)
mpu = probe_trix_mpu(&cfg_mpu);
- if (mpu)
- attach_trix_mpu(&cfg_mpu);
- }
return 0;
}
* interrupt allocation. Protect against bogus unload
* Fixed to allow IRQ > 15
* Christoph Hellwig Adapted to module_init/module_exit
+ * Arnaldo C. de Melo got rid of check_region
*
* Status:
* Untested
}
uart401_devc;
-static uart401_devc *detected_devc = NULL;
-
#define DATAPORT (devc->base)
#define COMDPORT (devc->base+1)
#define STATPORT (devc->base+1)
restore_flags(flags);
}
-void attach_uart401(struct address_info *hw_config, struct module *owner)
-{
- uart401_devc *devc;
- char *name = "MPU-401 (UART) MIDI";
-
-
- if (hw_config->name)
- name = hw_config->name;
-
- if (detected_devc == NULL)
- return;
-
-
- devc = (uart401_devc *) kmalloc(sizeof(uart401_devc), GFP_KERNEL);
- if (devc == NULL)
- {
- printk(KERN_WARNING "uart401: Can't allocate memory\n");
- return;
- }
- memcpy((char *) devc, (char *) detected_devc, sizeof(uart401_devc));
- detected_devc = NULL;
-
- devc->irq = hw_config->irq;
- if (devc->irq < 0)
- {
- devc->share_irq = 1;
- devc->irq *= -1;
- }
- else
- devc->share_irq = 0;
-
- if (!devc->share_irq)
- {
- if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0)
- {
- printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq);
- devc->share_irq = 1;
- }
- }
- devc->my_dev = sound_alloc_mididev();
-
- request_region(hw_config->io_base, 4, "MPU-401 UART");
- enter_uart_mode(devc);
-
- if (devc->my_dev == -1)
- {
- printk(KERN_INFO "uart401: Too many midi devices detected\n");
- kfree(devc);
- return;
- }
- conf_printf(name, hw_config);
-
- std_midi_synth.midi_dev = devc->my_dev;
- midi_devs[devc->my_dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
- if (midi_devs[devc->my_dev] == NULL)
- {
- printk(KERN_ERR "uart401: Failed to allocate memory\n");
- sound_unload_mididev(devc->my_dev);
- kfree(devc);
- devc=NULL;
- return;
- }
- memcpy((char *) midi_devs[devc->my_dev], (char *) &uart401_operations,
- sizeof(struct midi_operations));
-
- if (owner)
- midi_devs[devc->my_dev]->owner = owner;
-
- midi_devs[devc->my_dev]->devc = devc;
- midi_devs[devc->my_dev]->converter = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
- if (midi_devs[devc->my_dev]->converter == NULL)
- {
- printk(KERN_WARNING "uart401: Failed to allocate memory\n");
- kfree(midi_devs[devc->my_dev]);
- sound_unload_mididev(devc->my_dev);
- kfree(devc);
- devc=NULL;
- return;
- }
- memcpy((char *) midi_devs[devc->my_dev]->converter, (char *) &std_midi_synth,
- sizeof(struct synth_operations));
-
- strcpy(midi_devs[devc->my_dev]->info.name, name);
- midi_devs[devc->my_dev]->converter->id = "UART401";
- hw_config->slots[4] = devc->my_dev;
- sequencer_init();
- devc->opened = 0;
-}
-
static int reset_uart401(uart401_devc * devc)
{
int ok, timeout, n;
return ok;
}
-int probe_uart401(struct address_info *hw_config)
+int probe_uart401(struct address_info *hw_config, struct module *owner)
{
+ uart401_devc *devc;
+ char *name = "MPU-401 (UART) MIDI";
int ok = 0;
unsigned long flags;
- static uart401_devc hw_info;
- uart401_devc *devc = &hw_info;
DDB(printk("Entered probe_uart401()\n"));
/* Default to "not found" */
hw_config->slots[4] = -1;
- detected_devc = NULL;
- if (check_region(hw_config->io_base, 4))
+ if (!request_region(hw_config->io_base, 4, "MPU-401 UART")) {
+ printk(KERN_INFO "uart401: could not request_region(%d, 4)\n", hw_config->io_base);
return 0;
+ }
+
+ devc = kmalloc(sizeof(uart401_devc), GFP_KERNEL);
+ if (!devc) {
+ printk(KERN_WARNING "uart401: Can't allocate memory\n");
+ goto cleanup_region;
+ }
devc->base = hw_config->io_base;
devc->irq = hw_config->irq;
ok = reset_uart401(devc);
restore_flags(flags);
- if (ok)
- detected_devc = devc;
+ if (!ok)
+ goto cleanup_devc;
- return ok;
+ if (hw_config->name)
+ name = hw_config->name;
+
+ if (devc->irq < 0) {
+ devc->share_irq = 1;
+ devc->irq *= -1;
+ } else
+ devc->share_irq = 0;
+
+ if (!devc->share_irq)
+ if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0) {
+ printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq);
+ devc->share_irq = 1;
+ }
+ devc->my_dev = sound_alloc_mididev();
+ enter_uart_mode(devc);
+
+ if (devc->my_dev == -1) {
+ printk(KERN_INFO "uart401: Too many midi devices detected\n");
+ goto cleanup_irq;
+ }
+ conf_printf(name, hw_config);
+ std_midi_synth.midi_dev = devc->my_dev;
+ midi_devs[devc->my_dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
+ if (!midi_devs[devc->my_dev]) {
+ printk(KERN_ERR "uart401: Failed to allocate memory\n");
+ goto cleanup_unload_mididev;
+ }
+ memcpy(midi_devs[devc->my_dev], &uart401_operations, sizeof(struct midi_operations));
+
+ if (owner)
+ midi_devs[devc->my_dev]->owner = owner;
+
+ midi_devs[devc->my_dev]->devc = devc;
+ midi_devs[devc->my_dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
+ if (!midi_devs[devc->my_dev]->converter) {
+ printk(KERN_WARNING "uart401: Failed to allocate memory\n");
+ goto cleanup_midi_devs;
+ }
+ memcpy(midi_devs[devc->my_dev]->converter, &std_midi_synth, sizeof(struct synth_operations));
+ strcpy(midi_devs[devc->my_dev]->info.name, name);
+ midi_devs[devc->my_dev]->converter->id = "UART401";
+ hw_config->slots[4] = devc->my_dev;
+ sequencer_init();
+ devc->opened = 0;
+ return 1;
+cleanup_midi_devs:
+ kfree(midi_devs[devc->my_dev]);
+cleanup_unload_mididev:
+ sound_unload_mididev(devc->my_dev);
+cleanup_irq:
+ if (!devc->share_irq)
+ free_irq(devc->irq, devc);
+cleanup_devc:
+ kfree(devc);
+cleanup_region:
+ release_region(hw_config->io_base, 4);
+ return 0;
}
void unload_uart401(struct address_info *hw_config)
sound_unload_mididev(hw_config->slots[4]);
}
-EXPORT_SYMBOL(attach_uart401);
EXPORT_SYMBOL(probe_uart401);
EXPORT_SYMBOL(unload_uart401);
EXPORT_SYMBOL(uart401intr);
to others */
if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1) {
printk(KERN_INFO "MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997");
- if (probe_uart401(&cfg_mpu) == 0)
+ if (!probe_uart401(&cfg_mpu, THIS_MODULE))
return -ENODEV;
- attach_uart401(&cfg_mpu, THIS_MODULE);
}
return 0;
* We currently support a mixer device, but it is currently non-functional.
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
in 724hwmcode.h.
* fixed wrong legacy_io setting on YMF744/YMF754 .
+ Thu Sep 21 05:32:51 BRT 2000 0.0.5
+ * got rid of attach_uart401 and attach_sbmpu
+ Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/module.h>
#define PFX "ymf_sb: "
-#define YMFSB_VERSION "0.0.4"
+#define YMFSB_VERSION "0.0.5"
#define YMFSB_CARD_NAME "YMF7xx Legacy Audio driver " YMFSB_VERSION
#ifdef SUPPORT_UART401_MIDI
#if 0
# define ymf7xxsb_probe_midi probe_uart401
-# define ymf7xxsb_attach_midi attach_uart401
# define ymf7xxsb_unload_midi unload_uart401
#else
# define ymf7xxsb_probe_midi probe_sbmpu
-# define ymf7xxsb_attach_midi attach_sbmpu
# define ymf7xxsb_unload_midi unload_sbmpu
#endif
#endif
/* register legacy MIDI */
if ( mpu_io > 0 && 0)
{
- if (!ymf7xxsb_probe_midi (&mpu_data[cards])) {
+ if (!ymf7xxsb_probe_midi (&mpu_data[cards], THIS_MODULE)) {
printk (KERN_ERR PFX
"MIDI probe @ 0x%X failed, aborting\n",
mpu_io);
ymf7xxsb_unload_sb (&sb_data[cards], 0);
return -ENODEV;
}
- ymf7xxsb_attach_midi (&mpu_data[cards], THIS_MODULE);
}
#endif
SUB_DIRS :=
MOD_SUB_DIRS := $(SUB_DIRS)
-MOD_IN_SUB_DIRS := $(SUB_DIRS)
ALL_SUB_DIRS := $(SUB_DIRS) serial storage
# The target object and module list name.
obj-y += serial/usb-serial.o
else
ifeq ($(CONFIG_USB_SERIAL),m)
- MOD_IN_SUB_DIRS += serial
+ MOD_SUB_DIRS += serial
endif
endif
obj-y += storage/storage.o
else
ifeq ($(CONFIG_USB_STORAGE),m)
- MOD_IN_SUB_DIRS += storage
+ MOD_SUB_DIRS += storage
endif
endif
obj-m := $(filter-out $(obj-y), $(obj-m))
int-m := $(filter-out $(int-y), $(int-m))
-# Take multi-part drivers out of obj-y and put components in.
-
-obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
-
# Translate to Rules.make lists.
O_OBJS := $(filter-out $(export-objs), $(obj-y))
kfree (buf);
return -EFAULT;
} else
- memset (arg, 0, size);
+ memset (buf, 0, size);
}
/* ioctl to device */
delay = HUB_LONG_RESET_TIME;
}
+ hub->children[port] = NULL;
usb_hub_port_disable(hub, port);
up(&usb_address0_sem);
}
/* Driver for Freecom USB/IDE adaptor
*
- * $Id: freecom.c,v 1.11 2000/09/15 23:06:40 mdharm Exp $
+ * $Id: freecom.c,v 1.12 2000/09/22 01:16:17 mdharm Exp $
*
* Freecom v0.1:
*
* (http://www.freecom.de/)
*/
+#include <linux/config.h>
#include "transport.h"
#include "protocol.h"
#include "usb.h"
/* These are the packet types. The low bit indicates that this command
* should wait for an interrupt. */
#define FCM_PACKET_ATAPI 0x21
+#define FCM_PACKET_STATUS 0x20
/* Receive data from the IDE interface. The ATAPI packet has already
* waited, so the data should be immediately available. */
#endif
/* The ATAPI Command always goes out first. */
- fcb->Type = FCM_PACKET_ATAPI;
+ fcb->Type = FCM_PACKET_ATAPI | 0x00;
fcb->Timeout = 0;
memcpy (fcb->Atapi, srb->cmnd, 12);
memset (fcb->Filler, 0, sizeof (fcb->Filler));
}
pdump ((void *) fst, partial);
+
+ /* while we haven't recieved the IRQ */
+ while (!(fst->Status & 0x2)) {
+ /* send a command to re-fetch the status */
+ US_DEBUGP("Re-attempting to get status...\n");
+
+ fcb->Type = FCM_PACKET_STATUS;
+ fcb->Timeout = 0;
+ memset (fcb->Atapi, 0, 12);
+ memset (fcb->Filler, 0, sizeof (fcb->Filler));
+
+ /* Send it out. */
+ result = usb_stor_bulk_msg (us, fcb, opipe,
+ FCM_PACKET_LENGTH, &partial);
+
+ /* The Freecom device will only fail if there is something wrong in
+ * USB land. It returns the status in its own registers, which
+ * come back in the bulk pipe. */
+ if (result != 0) {
+ US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
+ result, partial);
+
+ /* -ENOENT -- we canceled this transfer */
+ if (result == -ENOENT) {
+ US_DEBUGP("us_transfer_partial(): transfer aborted\n");
+ return US_BULK_TRANSFER_ABORTED;
+ }
+
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* actually get the status info */
+ result = usb_stor_bulk_msg (us, fst, ipipe,
+ FCM_PACKET_LENGTH, &partial);
+ printk (KERN_DEBUG "bar Status result %d %d\n", result, partial);
+ /* -ENOENT -- we canceled this transfer */
+ if (result == -ENOENT) {
+ US_DEBUGP("us_transfer_partial(): transfer aborted\n");
+ return US_BULK_TRANSFER_ABORTED;
+ }
+
+ pdump ((void *) fst, partial);
+ }
+
if (partial != 4 || result != 0) {
return USB_STOR_TRANSPORT_ERROR;
}
{
int result, value;
int counter;
+ char buffer[33];
/* Allocate a buffer for us. The upper usb transport code will
* free this for us when cleaning up. */
}
}
+ result = usb_stor_control_msg(us, usb_rcvctrlpipe(us->pusb_dev, 0),
+ 0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20);
+ buffer[32] = '\0';
+ US_DEBUGP("String returned from FC init is: %s\n", buffer);
+
result = freecom_ide_write (us, 0x06, 0xA0);
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
/* Driver for USB Mass Storage compliant devices
* SCSI layer glue code
*
- * $Id: scsiglue.c,v 1.11 2000/09/12 01:18:08 mdharm Exp $
+ * $Id: scsiglue.c,v 1.13 2000/09/28 21:54:30 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
{
struct us_data *us = (struct us_data *)psh->hostdata[0];
- US_DEBUGP("us_release() called for host %s\n", us->htmplt.name);
+ US_DEBUGP("release() called for host %s\n", us->htmplt.name);
/* Kill the control threads
*
/* we use the usb_reset_device() function to handle this for us */
US_DEBUGP("bus_reset() called\n");
- result = usb_reset_device(us->pusb_dev) ? FAILED : SUCCESS;
- /* did the reset work? */
- if (result < 0)
+ /* attempt to reset the port */
+ if (usb_reset_device(us->pusb_dev) < 0)
return FAILED;
/* FIXME: This needs to lock out driver probing while it's working
struct usb_interface *intf =
&us->pusb_dev->actconfig->interface[i];
+ /* if this is an unclaimed interface, skip it */
+ if (!intf->driver) {
+ continue;
+ }
+
US_DEBUGP("Examinging driver %s...", intf->driver->name);
/* skip interfaces which we've claimed */
- if (intf->driver && !strncmp(intf->driver->name,
- "usb-storage", 12)) {
- US_DEBUGPX("skipping.\n");
+ if (intf->driver == &usb_storage_driver) {
+ US_DEBUGPX("skipping ourselves.\n");
continue;
}
-
+
/* simulate a disconnect and reconnect for all interfaces */
- if (intf->driver) {
- US_DEBUGPX("simulating disconnect/reconnect.\n");
- down(&intf->driver->serialize);
- intf->driver->disconnect(us->pusb_dev,
- intf->private_data);
- intf->driver->probe(us->pusb_dev, i);
- up(&intf->driver->serialize);
- }
+ US_DEBUGPX("simulating disconnect/reconnect.\n");
+ down(&intf->driver->serialize);
+ intf->driver->disconnect(us->pusb_dev, intf->private_data);
+ intf->driver->probe(us->pusb_dev, i);
+ up(&intf->driver->serialize);
}
US_DEBUGP("bus_reset() complete\n");
us = us->next;
}
+ /* release our lock on the data structures */
+ up(&us_list_semaphore);
+
/* if we couldn't find it, we return an error */
if (!us) {
- up(&us_list_semaphore);
return -ESRCH;
}
/* show the GUID of the device */
SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
- /* release our lock on the data structures */
- up(&us_list_semaphore);
-
/*
* Calculate start of next buffer, and return value.
*/
/* Driver for SCM Microsystems USB-ATAPI cable
*
- * $Id: shuttle_usbat.c,v 1.8 2000/09/08 23:20:41 groovyjava Exp $
- *
- * SCM driver v0.2:
- *
- * Removed any reference to maxlen for bulk transfers.
- * Changed scm_bulk_transport to allow for transfers without commands.
- * Changed hp8200e transport to use the request_bufflen field in the
- * SCSI command for the length of the transfer, rather than calculating
- * it ourselves based on the command.
- *
- * SCM driver v0.1:
- *
- * First release - hp8200e.
+ * $Id: shuttle_usbat.c,v 1.10 2000/09/24 00:03:08 groovyjava Exp $
*
* Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
* as well. This driver is only guaranteed to work with the ATAPI
* translation.
*
- * The only peripherals that I know of (as of 14 Jul 2000) that uses this
- * device is the Hewlett-Packard 8200e CD-Writer Plus.
+ * The only peripheral that I know of (as of 8 Sep 2000) that uses this
+ * device is the Hewlett-Packard 8200e/8210e CD-Writer Plus.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
int result;
- // If data is going to be sent or received with the URB,
- // then allocate a buffer for it. If data is to be sent,
- // copy the data into the buffer.
-/*
- if (xfer_len > 0) {
- buffer = kmalloc(xfer_len, GFP_KERNEL);
- if (!(command[0] & USB_DIR_IN))
- memcpy(buffer, xfer_data, xfer_len);
- }
-*/
// Send the URB to the device and wait for a response.
/* Why are request and request type reversed in this call? */
xfer_data, xfer_len);
- // If data was sent or received with the URB, free the buffer we
- // allocated earlier, but not before reading the data out of the
- // buffer if we wanted to receive data.
-/*
- if (xfer_len > 0) {
- if (command[0] & USB_DIR_IN)
- memcpy(xfer_data, buffer, xfer_len);
- kfree(buffer);
- }
-*/
// Check the return code for the command.
if (result < 0) {
int result = USB_STOR_TRANSPORT_GOOD;
int transferred = 0;
- // unsigned char execute[8] = {
- // 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- // };
int i;
struct scatterlist *sg;
- // char string[64];
- // int pipe;
-
-/*
- if (command_len != 0) {
- // Fix up the command's data length
-
- command[6] = len&0xFF;
- command[7] = (len>>8)&0xFF;
-
-
-
- result = usbat_send_control(us,
- execute,
- command,
- command_len);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
- }
-*/
if (len==0)
return USB_STOR_TRANSPORT_GOOD;
-
/* transfer the data payload for the command, if there is any */
-
if (command_len != 0)
direction = (command[0]&0x80) ? SCSI_DATA_READ :
SCSI_DATA_WRITE;
-/*
- if (direction == SCSI_DATA_WRITE) {
-
- // Debug-print the first 48 bytes of the write transfer
-
- if (!use_sg) {
- string[0] = 0;
- for (i=0; i<len && i<48; i++) {
- sprintf(string+strlen(string), "%02X ",
- data[i]);
- if ((i%16)==15) {
- US_DEBUGP("%s\n", string);
- string[0] = 0;
- }
- }
- if (string[0]!=0)
- US_DEBUGP("%s\n", string);
- }
- }
-*/
-
- //US_DEBUGP("SCM data %s transfer %d sg buffers %d\n",
- // ( direction==SCSI_DATA_READ ? "in" : "out"),
- // len, use_sg);
if (!use_sg)
result = usbat_raw_bulk(us, direction, data, len);
unsigned char *content) {
int result;
- // unsigned char command[8] = {
- // 0xC0, access, reg, 0x00, 0x00, 0x00, 0x00, 0x00
- // };
result = usbat_send_control(us,
usb_rcvctrlpipe(us->pusb_dev,0),
content,
1);
- // result = usbat_send_control(us, command, content, 1);
-
return result;
}
unsigned char content) {
int result;
- // unsigned char command[8] = {
- // 0x40, access|0x01, reg, content, 0x00, 0x00, 0x00, 0x00
- // };
result = usbat_send_control(us,
usb_sndctrlpipe(us->pusb_dev,0),
NULL,
0);
- // result = usbat_send_control(us, command, NULL, 0);
-
return result;
}
command,
8);
- // result = usbat_bulk_transport(us, command, 8, 0, NULL, 0, 0);
-
return result;
}
result = usbat_bulk_transport(us,
NULL, 0, SCSI_DATA_READ, content, len, use_sg);
- // result = usbat_bulk_transport(us,
- // command, 8, 0, content, len, use_sg);
-
return result;
}
* an error condition.
*/
-int usbat_wait_not_busy(struct us_data *us) {
+int usbat_wait_not_busy(struct us_data *us, int minutes) {
int i;
int result;
unsigned char status;
/* Synchronizing cache on a CDR could take a heck of a long time,
- but probably not more than 10 minutes or so */
+ * but probably not more than 10 minutes or so. On the other hand,
+ * doing a full blank on a CDRW at speed 1 will take about 75
+ * minutes!
+ */
- for (i=0; i<1800; i++) {
+ for (i=0; i<1200+minutes*60; i++) {
result = usbat_read(us, USBAT_ATA, 0x17, &status);
- // US_DEBUGP("SCM: Write ATA data status is %02X\n", status);
-
if (result!=USB_STOR_TRANSPORT_GOOD)
return result;
if (status&0x01) // check condition
return USB_STOR_TRANSPORT_FAILED;
if (status&0x20) // device fault
return USB_STOR_TRANSPORT_FAILED;
- if ((status&0x80)!=0x80) // not busy
- break;
+
+ if ((status&0x80)!=0x80) { // not busy
+ US_DEBUGP("Waited not busy for %d steps\n", i);
+ return USB_STOR_TRANSPORT_GOOD;
+ }
if (i<500)
wait_ms(10); // 5 seconds
wait_ms(50); // 10 seconds
else if (i<1200)
wait_ms(100); // 50 seconds
- else if (i<1800)
- wait_ms(1000); // 10 minutes
+ else
+ wait_ms(1000); // X minutes
}
- if (i==1800)
- return USB_STOR_TRANSPORT_FAILED;
-
- US_DEBUGP("Waited not busy for %d steps\n", i);
- return USB_STOR_TRANSPORT_GOOD;
+ US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
+ minutes);
+ return USB_STOR_TRANSPORT_FAILED;
}
int usbat_write_block(struct us_data *us,
unsigned char reg,
unsigned char *content,
unsigned short len,
- int use_sg) {
+ int use_sg,
+ int minutes) {
int result;
unsigned char command[8] = {
if (result != USB_STOR_TRANSPORT_GOOD)
return result;
- // result = usbat_bulk_transport(us,
- // command, 8, 0, content, len, use_sg);
-
- return usbat_wait_not_busy(us);
+ return usbat_wait_not_busy(us, minutes);
}
int usbat_rw_block_test(struct us_data *us,
int direction,
unsigned char *content,
unsigned short len,
- int use_sg) {
+ int use_sg,
+ int minutes) {
int result;
} else if (result != US_BULK_TRANSFER_GOOD)
return result;
else
- return usbat_wait_not_busy(us);
+ return usbat_wait_not_busy(us, minutes);
}
- US_DEBUGP("Bummer! %s bulk data 10 times failed.\n",
+ US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
direction==SCSI_DATA_WRITE ? "Writing" : "Reading");
return USB_STOR_TRANSPORT_FAILED;
}
+/*
+ * Write data to multiple registers at once. Not meant for large
+ * transfers of data!
+ */
+
int usbat_multiple_write(struct us_data *us,
unsigned char access,
unsigned char *registers,
result = usbat_bulk_transport(us,
NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0);
- // result = usbat_bulk_transport(us, cmd, 8, 0,
- // data, num_registers*2, 0);
-
if (result!=USB_STOR_TRANSPORT_GOOD)
return result;
- return usbat_wait_not_busy(us);
+ return usbat_wait_not_busy(us, 0);
}
int usbat_read_user_io(struct us_data *us,
unsigned char *data_flags) {
- // unsigned char command[8] = {
- // 0xC0, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- // };
int result;
result = usbat_send_control(us,
data_flags,
1);
- // result = usbat_send_control(us, command, data_flags, 1);
-
return result;
}
unsigned char enable_flags,
unsigned char data_flags) {
- // unsigned char command[8] = {
- // 0x40, 0x82, enable_flags, data_flags, 0x00, 0x00, 0x00, 0x00
- // };
int result;
result = usbat_send_control(us,
NULL,
0);
- // result = usbat_send_control(us, command, NULL, 0);
-
return result;
}
int sg_segment = 0;
int sg_offset = 0;
+ US_DEBUGP("handle_read10: transfersize %d\n",
+ srb->transfersize);
+
if (srb->request_bufflen < 0x10000) {
result = usbat_rw_block_test(us, USBAT_ATA,
0x10, 0x17, 0xFD, 0x30,
SCSI_DATA_READ,
srb->request_buffer,
- srb->request_bufflen, srb->use_sg);
+ srb->request_bufflen, srb->use_sg, 1);
return result;
}
* (see linux/drivers/scsi/sr.c).
*/
+ if (data[7+0] == GPCMD_READ_CD) {
+ len = short_pack(data[7+9], data[7+8]);
+ len <<= 16;
+ len |= data[7+7];
+ srb->transfersize = srb->request_bufflen/len;
+ }
+
len = (65535/srb->transfersize) * srb->transfersize;
US_DEBUGP("Max read is %d bytes\n", len);
data[7+3] = LSB_of(sector>>16);
data[7+4] = MSB_of(sector&0xFFFF);
data[7+5] = LSB_of(sector&0xFFFF);
+ if (data[7+0] == GPCMD_READ_CD)
+ data[7+6] = 0;
data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
data[7+8] = LSB_of(len / srb->transfersize); // num sectors
0x10, 0x17, 0xFD, 0x30,
SCSI_DATA_READ,
buffer,
- len, 0);
+ len, 0, 1);
if (result != USB_STOR_TRANSPORT_GOOD)
break;
unsigned int len;
int i;
char string[64];
- // struct scatterlist *sg;
-
- /* This table tells us:
- X = command not supported
- L = return length in cmnd[4] (8 bits).
- H = return length in cmnd[7] and cmnd[8] (16 bits).
- D = return length in cmnd[6] to cmnd[9] (32 bits).
- B = return length/blocksize in cmnd[6] to cmnd[8].
- T = return length in cmnd[6] to cmnd[8] (24 bits).
- 0-9 = fixed return length
- W = 24 bytes
- h = return length/2048 in cmnd[7-8].
- */
-
- // static char *lengths =
-
- /* 0123456789ABCDEF 0123456789ABCDEF */
-
- // "0XXL0XXXXXXXXXXX" "XXLXXXXXXXX0XX0X" /* 00-1F */
- // "XXXXX8XXhXH0XXX0" "XXXXX0XXXXXXXXXX" /* 20-3F */
- // "XXHHL0X0XXH0XX0X" "XHH00HXX0TH0H0XX" /* 40-5F */
- // "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */
- // "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */
- // "X0XXX0XXDXDXXXXX" "XXXXXXXXX000XHBX" /* A0-BF */
- // "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */
- // "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */
-
-/* if (us->flags & US_FL_NEED_INIT) {
- US_DEBUGP("8200e: initializing\n");
- init_8200e(us);
- us->flags &= ~US_FL_NEED_INIT;
- } */
len = srb->request_bufflen;
-/* if (srb->sc_data_direction == SCSI_DATA_WRITE)
- len = srb->request_bufflen;
- else {
-
- switch (lengths[srb->cmnd[0]]) {
-
- case 'L':
- len = srb->cmnd[4];
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- len = lengths[srb->cmnd[0]]-'0';
- break;
- case 'H':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- break;
- case 'h':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- len <<= 11; // *2048
- break;
- case 'T':
- len = (((unsigned int)srb->cmnd[6])<<16) |
- (((unsigned int)srb->cmnd[7])<<8) |
- srb->cmnd[8];
- break;
- case 'D':
- len = (((unsigned int)srb->cmnd[6])<<24) |
- (((unsigned int)srb->cmnd[7])<<16) |
- (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
- case 'W':
- len = 24;
- break;
- case 'B':
- // Let's try using the command structure's
- // request_bufflen here
- len = srb->request_bufflen;
- break;
- default:
- US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n",
- srb->cmnd[0]);
- return USB_STOR_TRANSPORT_ERROR;
- }
- } */
-
- // US_DEBUGP("XXXXXXXXXXXXXXXX req_bufflen %d, len %d, bufflen %d\n",
- // srb->request_bufflen, len, srb->bufflen);
-
/* Send A0 (ATA PACKET COMMAND).
Note: I guess we're never going to get any of the ATA
commands... just ATA Packet Commands.
0x10, 0x17, 0xFD, 0x30,
SCSI_DATA_WRITE,
srb->request_buffer,
- len, srb->use_sg);
+ len, srb->use_sg, 10);
if (result == USB_STOR_TRANSPORT_GOOD) {
transferred += len;
return result;
- } else if (srb->cmnd[0] == READ_10) {
+ } else if (srb->cmnd[0] == READ_10 ||
+ srb->cmnd[0] == GPCMD_READ_CD) {
return usbat_handle_read10(us, registers, data, srb);
// Write the 12-byte command header.
+ // If the command is BLANK then set the timer for 75 minutes.
+ // Otherwise set it for 10 minutes.
+
+ // NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
+ // AT SPEED 4 IS UNRELIABLE!!!
+
if ( (result = usbat_write_block(us,
- USBAT_ATA, 0x10, srb->cmnd, 12, 0)) !=
+ USBAT_ATA, 0x10, srb->cmnd, 12, 0,
+ srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=
USB_STOR_TRANSPORT_GOOD) {
return result;
}
}
}
- // US_DEBUGP("Command result %d\n", result);
-
return result;
}
/* Driver for SCM Microsystems USB-ATAPI cable
* Header File
*
- * $Id: shuttle_usbat.h,v 1.4 2000/08/25 00:13:51 mdharm Exp $
+ * $Id: shuttle_usbat.h,v 1.5 2000/09/17 14:44:52 groovyjava Exp $
*
* Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
int use_sg);
extern int usbat_write_block(struct us_data *us, unsigned char access,
unsigned char reg, unsigned char *content, unsigned short len,
- int use_sg);
+ int use_sg, int minutes);
extern int usbat_multiple_write(struct us_data *us, unsigned char access,
unsigned char *registers, unsigned char *data_out,
unsigned short num_registers);
/* Driver for USB Mass Storage compliant devices
*
- * $Id: transport.c,v 1.25 2000/09/13 21:48:26 mdharm Exp $
+ * $Id: transport.c,v 1.27 2000/09/28 21:54:30 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+#include <linux/config.h>
#include "transport.h"
#include "protocol.h"
#include "usb.h"
#include "debug.h"
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/malloc.h>
/* issue the auto-sense command */
temp_result = us->transport(us->srb, us);
if (temp_result != USB_STOR_TRANSPORT_GOOD) {
- us->transport_reset(us);
US_DEBUGP("-- auto-sense failure\n");
+
+ /* we skip the reset if this happens to be a
+ * multi-target device, since failure of an
+ * auto-sense is perfectly valid
+ */
+ if (!(us->flags & US_FL_SCM_MULT_TARG)) {
+ us->transport_reset(us);
+ }
srb->result = DID_ERROR << 16;
return;
}
/* send it to out endpoint */
US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
le32_to_cpu(bcb.Signature), bcb.Tag,
- (bcb.Lun >> 4), (bcb.Lun & 0xFF),
+ (bcb.Lun >> 4), (bcb.Lun & 0x0F),
bcb.DataTransferLength, bcb.Flags, bcb.Length);
result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN,
&partial);
/* Driver for USB Mass Storage compliant devices
*
- * $Id: usb.c,v 1.44 2000/09/14 22:56:36 mdharm Exp $
+ * $Id: usb.c,v 1.46 2000/09/25 23:25:12 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
static void * storage_probe(struct usb_device *dev, unsigned int ifnum);
static void storage_disconnect(struct usb_device *dev, void *ptr);
-static struct usb_driver storage_driver = {
+struct usb_driver usb_storage_driver = {
name: "usb-storage",
probe: storage_probe,
disconnect: storage_disconnect,
{ 0x03ee, 0x0000, 0x0000, 0x0245,
"Mitsumi",
"CD-R/RW Drive",
- US_SC_8020, US_PR_CBI, NULL,
- US_FL_SINGLE_LUN},
+ US_SC_8020, US_PR_CBI, NULL, 0},
{ 0x03f0, 0x0107, 0x0200, 0x0200,
"HP",
"CD-Writer+",
- US_SC_8070, US_PR_CB, NULL,
- 0},
+ US_SC_8070, US_PR_CB, NULL, 0},
#ifdef CONFIG_USB_STORAGE_HP8200e
{ 0x03f0, 0x0207, 0x0001, 0x0001,
"HP",
"CD-Writer+ 8200e",
- US_SC_8070, US_PR_SCM_ATAPI, init_8200e,
- US_FL_SINGLE_LUN},
+ US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0},
#endif
{ 0x04e6, 0x0001, 0x0200, 0x0200,
"Matshita",
"LS-120",
- US_SC_8020, US_PR_CB, NULL,
- US_FL_SINGLE_LUN},
+ US_SC_8020, US_PR_CB, NULL, 0},
{ 0x04e6, 0x0002, 0x0100, 0x0100,
"Shuttle",
{ 0x04e6, 0x0009, 0x0200, 0x0200,
"Shuttle",
"eUSB ATA/ATAPI Adapter",
- US_SC_8020, US_PR_CB, NULL,
- US_FL_SINGLE_LUN},
+ US_SC_8020, US_PR_CB, NULL, 0},
{ 0x04e6, 0x000a, 0x0200, 0x0200,
"Shuttle",
"eUSB CompactFlash Adapter",
- US_SC_8020, US_PR_CB, NULL,
- US_FL_SINGLE_LUN},
+ US_SC_8020, US_PR_CB, NULL, 0},
{ 0x04e6, 0x000B, 0x0100, 0x0100,
"Shuttle",
{ 0x04e6, 0x0101, 0x0200, 0x0200,
"Shuttle",
"CD-RW Device",
- US_SC_8020, US_PR_CB, NULL,
- US_FL_SINGLE_LUN},
+ US_SC_8020, US_PR_CB, NULL, 0},
{ 0x054c, 0x0010, 0x0106, 0x0210,
"Sony",
{ 0x059f, 0xa601, 0x0200, 0x0200,
"LaCie",
"USB Hard Disk",
- US_SC_RBC, US_PR_CB, NULL,
- 0 },
+ US_SC_RBC, US_PR_CB, NULL, 0 },
{ 0x05ab, 0x0031, 0x0100, 0x0100,
"In-System",
"USB/IDE Bridge (ATAPI ONLY!)",
- US_SC_8070, US_PR_BULK, NULL,
- 0 },
+ US_SC_8070, US_PR_BULK, NULL, 0 },
{ 0x0644, 0x0000, 0x0100, 0x0100,
"TEAC",
"Floppy Drive",
- US_SC_UFI, US_PR_CB, NULL,
- 0 },
+ US_SC_UFI, US_PR_CB, NULL, 0 },
#ifdef CONFIG_USB_STORAGE_SDDR09
{ 0x066b, 0x0105, 0x0100, 0x0100,
US_FL_SINGLE_LUN | US_FL_START_STOP },
#endif
- { 0x0693, 0x0005, 0x0100, 0x0100,
- "Hagiwara",
- "Flashgate",
- US_SC_SCSI, US_PR_BULK, NULL,
- 0 },
-
{ 0x0693, 0x0002, 0x0100, 0x0100,
"Hagiwara",
"FlashGate SmartMedia",
- US_SC_SCSI, US_PR_BULK, NULL,
- 0 },
+ US_SC_SCSI, US_PR_BULK, NULL, 0 },
+
+ { 0x0693, 0x0005, 0x0100, 0x0100,
+ "Hagiwara",
+ "Flashgate",
+ US_SC_SCSI, US_PR_BULK, NULL, 0 },
{ 0x0781, 0x0001, 0x0200, 0x0200,
"Sandisk",
{ 0x07ab, 0xfc01, 0x0921, 0x0921,
"Freecom",
"USB-IDE",
- US_SC_QIC, US_PR_FREECOM, freecom_init, US_FL_SINGLE_LUN },
+ US_SC_QIC, US_PR_FREECOM, freecom_init, 0},
#endif
{ 0x07af, 0x0005, 0x0100, 0x0100,
dev->descriptor.idProduct, "0");
}
- /* lock access to the data structures */
- down(&us_list_semaphore);
-
/*
* Now check if we have seen this GUID before
* We're looking for a device with a matching GUID that isn't
if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data),
GFP_KERNEL)) == NULL) {
printk(KERN_WARNING USB_STORAGE "Out of memory\n");
- up(&us_list_semaphore);
return NULL;
}
memset(ss, 0, sizeof(struct us_data));
ss->transport_name = "EUSB/SDDR09";
ss->transport = sddr09_transport;
ss->transport_reset = usb_stor_CB_reset;
- ss->max_lun = 1;
+ ss->max_lun = 0;
break;
#endif
default:
ss->transport_name = "Unknown";
- up(&us_list_semaphore);
kfree(ss->current_urb);
kfree(ss);
return NULL;
case US_SC_8020:
ss->protocol_name = "8020i";
ss->proto_handler = usb_stor_ATAPI_command;
+ ss->max_lun = 0;
break;
case US_SC_QIC:
ss->protocol_name = "QIC-157";
ss->proto_handler = usb_stor_qic157_command;
+ ss->max_lun = 0;
break;
case US_SC_8070:
ss->protocol_name = "8070i";
ss->proto_handler = usb_stor_ATAPI_command;
+ ss->max_lun = 0;
break;
case US_SC_SCSI:
default:
ss->protocol_name = "Unknown";
- up(&us_list_semaphore);
kfree(ss->current_urb);
kfree(ss);
return NULL;
ss->htmplt.module = THIS_MODULE;
scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt));
+ /* lock access to the data structures */
+ down(&us_list_semaphore);
+
/* put us in the list */
ss->next = us_list;
us_list = ss;
- }
- /* release the data structure lock */
- up(&us_list_semaphore);
+ /* release the data structure lock */
+ up(&us_list_semaphore);
+ }
printk(KERN_DEBUG
"WARNING: USB Mass Storage data integrity not assured\n");
my_host_number = 0;
/* register the driver, return -1 if error */
- if (usb_register(&storage_driver) < 0)
+ if (usb_register(&usb_storage_driver) < 0)
return -1;
/* we're all set */
* This eliminates races with probes and disconnects
*/
US_DEBUGP("-- calling usb_deregister()\n");
- usb_deregister(&storage_driver) ;
+ usb_deregister(&usb_storage_driver) ;
- /* lock access to the data structures */
- down(&us_list_semaphore);
-
/* While there are still virtual hosts, unregister them
- *
- * Note that the us_release() routine will destroy the local data
- * structure. So we have to peel these off the top of the list
- * and keep updating the head pointer as we go.
+ * Note that it's important to do this completely before removing
+ * the structures because of possible races with the /proc
+ * interface
+ */
+ for (next = us_list; next; next = next->next) {
+ US_DEBUGP("-- calling scsi_unregister_module()\n");
+ scsi_unregister_module(MODULE_SCSI_HA, &(next->htmplt));
+ }
+
+ /* While there are still structures, free them. Note that we are
+ * now race-free, since these structures can no longer be accessed
+ * from either the SCSI command layer or the /proc interface
*/
while (us_list) {
/* keep track of where the next one is */
next = us_list->next;
- US_DEBUGP("-- calling scsi_unregister_module()\n");
- scsi_unregister_module(MODULE_SCSI_HA, &(us_list->htmplt));
-
- /* Now that scsi_unregister_module is done with the host
- * template, we can free the us_data structure (the host
- * template is inline in this structure). */
-
/* If there's extra data in the us_data structure then
* free that first */
-
if (us_list->extra) {
- if (us_list->extra_destructor)
+ /* call the destructor routine, if it exists */
+ if (us_list->extra_destructor) {
+ US_DEBUGP("-- calling extra_destructor()\n");
us_list->extra_destructor(us_list->extra);
+ }
+
+ /* destroy the extra data */
+ US_DEBUGP("-- freeing the data structure\n");
kfree(us_list->extra);
}
+
+ /* free the structure itself */
kfree (us_list);
/* advance the list pointer */
us_list = next;
}
-
- /* unlock the data structures */
- up(&us_list_semaphore);
}
module_init(usb_stor_init);
/* Driver for USB Mass Storage compliant devices
* Main Header File
*
- * $Id: usb.h,v 1.8 2000/08/25 00:13:51 mdharm Exp $
+ * $Id: usb.h,v 1.9 2000/09/25 23:25:12 mdharm Exp $
*
* Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
typedef int (*trans_reset)(struct us_data*);
typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
+typedef void (*extra_data_destructor)(void *); /* extra data destructor */
/* we allocate one of these for every device that we remember */
struct us_data {
struct semaphore queue_exclusion; /* to protect data structs */
struct us_unusual_dev *unusual_dev; /* If unusual device */
void *extra; /* Any extra data */
- void (*extra_destructor)(void *); /* extra data destructor */
+ extra_data_destructor extra_destructor;/* extra data destructor */
};
/* The list of structures and the protective lock for them */
extern struct us_data *us_list;
extern struct semaphore us_list_semaphore;
-/* Function to fill an inquiry response. See usb.c for details */
+/* The structure which defines our driver */
+struct usb_driver usb_storage_driver;
+/* Function to fill an inquiry response. See usb.c for details */
extern void fill_inquiry_response(struct us_data *us,
unsigned char *data, unsigned int data_len);
-
#endif
* if dispsw->cursor is NULL, use Atari alike software cursor
*/
-static int cursor_drawn = 0;
+static int cursor_drawn;
#define CURSOR_DRAW_DELAY (1)
#define MAC_CURSOR_BLINK_RATE (32)
#define DEFAULT_CURSOR_BLINK_RATE (20)
-static int vbl_cursor_cnt = 0;
-static int cursor_on = 0;
+static int vbl_cursor_cnt;
+static int cursor_on;
static int cursor_blink_rate;
static inline void cursor_undrawn(void)
/*
* On the Macintoy, there may or may not be a working VBL int. We need to probe
*/
-static int vbl_detected = 0;
+static int vbl_detected;
static void fbcon_vbl_detect(int irq, void *dummy, struct pt_regs *fp)
{
struct fb_info *registered_fb[FB_MAX];
-int num_registered_fb = 0;
+int num_registered_fb;
extern int fbcon_softback_size;
-static int first_fb_vc = 0;
+static int first_fb_vc;
static int last_fb_vc = MAX_NR_CONSOLES-1;
static int fbcon_is_default = 1;
};
/* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */
-static unsigned int mem = 0; /* "matrox:mem:xxxxxM" */
+static unsigned int mem; /* "matrox:mem:xxxxxM" */
static int option_precise_width = 1; /* cannot be changed, option_precise_width==0 must imply noaccel */
-static int inv24 = 0; /* "matrox:inv24" */
+static int inv24; /* "matrox:inv24" */
static int cross4MB = -1; /* "matrox:cross4MB" */
-static int disabled = 0; /* "matrox:disabled" */
-static int noaccel = 0; /* "matrox:noaccel" */
-static int nopan = 0; /* "matrox:nopan" */
-static int no_pci_retry = 0; /* "matrox:nopciretry" */
-static int novga = 0; /* "matrox:novga" */
-static int nobios = 0; /* "matrox:nobios" */
+static int disabled; /* "matrox:disabled" */
+static int noaccel; /* "matrox:noaccel" */
+static int nopan; /* "matrox:nopan" */
+static int no_pci_retry; /* "matrox:nopciretry" */
+static int novga; /* "matrox:novga" */
+static int nobios; /* "matrox:nobios" */
static int noinit = 1; /* "matrox:init" */
-static int inverse = 0; /* "matrox:inverse" */
+static int inverse; /* "matrox:inverse" */
static int hwcursor = 1; /* "matrox:nohwcursor" */
static int blink = 1; /* "matrox:noblink" */
-static int sgram = 0; /* "matrox:sgram" */
+static int sgram; /* "matrox:sgram" */
#ifdef CONFIG_MTRR
static int mtrr = 1; /* "matrox:nomtrr" */
#endif
-static int grayscale = 0; /* "matrox:grayscale" */
-static unsigned int fastfont = 0; /* "matrox:fastfont:xxxxx" */
+static int grayscale; /* "matrox:grayscale" */
+static unsigned int fastfont; /* "matrox:fastfont:xxxxx" */
static int dev = -1; /* "matrox:dev:xxxxx" */
static unsigned int vesa = ~0; /* "matrox:vesa:xxxxx" */
static int depth = -1; /* "matrox:depth:xxxxx" */
-static unsigned int xres = 0; /* "matrox:xres:xxxxx" */
-static unsigned int yres = 0; /* "matrox:yres:xxxxx" */
+static unsigned int xres; /* "matrox:xres:xxxxx" */
+static unsigned int yres; /* "matrox:yres:xxxxx" */
static unsigned int upper = ~0; /* "matrox:upper:xxxxx" */
static unsigned int lower = ~0; /* "matrox:lower:xxxxx" */
-static unsigned int vslen = 0; /* "matrox:vslen:xxxxx" */
+static unsigned int vslen; /* "matrox:vslen:xxxxx" */
static unsigned int left = ~0; /* "matrox:left:xxxxx" */
static unsigned int right = ~0; /* "matrox:right:xxxxx" */
-static unsigned int hslen = 0; /* "matrox:hslen:xxxxx" */
-static unsigned int pixclock = 0; /* "matrox:pixclock:xxxxx" */
+static unsigned int hslen; /* "matrox:hslen:xxxxx" */
+static unsigned int pixclock; /* "matrox:pixclock:xxxxx" */
static int sync = -1; /* "matrox:sync:xxxxx" */
-static unsigned int fv = 0; /* "matrox:fv:xxxxx" */
-static unsigned int fh = 0; /* "matrox:fh:xxxxxk" */
-static unsigned int maxclk = 0; /* "matrox:maxclk:xxxxM" */
-static int dfp = 0; /* "matrox:dfp */
+static unsigned int fv; /* "matrox:fv:xxxxx" */
+static unsigned int fh; /* "matrox:fh:xxxxxk" */
+static unsigned int maxclk; /* "matrox:maxclk:xxxxM" */
+static int dfp; /* "matrox:dfp */
static int memtype = -1; /* "matrox:memtype:xxx" */
static char fontname[64]; /* "matrox:font:xxxxx" */
#
# Makefile for the Linux filesystems.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile.
+# 14 Sep 2000, Christoph Hellwig <hch@caldera.de>
+# Rewritten to use lists instead of if-statements.
+#
-FILESYSTEMS = $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
O_TARGET := fs.o
-O_OBJS = open.o read_write.o devices.o file_table.o buffer.o \
+
+export-objs := filesystems.o
+mod-subdirs := nls
+
+obj-y := open.o read_write.o devices.o file_table.o buffer.o \
super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
ioctl.o readdir.o select.o fifo.o locks.o \
dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
- $(BINFMTS) $(FILESYSTEMS)
-OX_OBJS := filesystems.o
-
-ALL_SUB_DIRS := coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
- hpfs sysv smbfs ncpfs ufs efs affs romfs autofs hfs lockd \
- nfsd nls devpts devfs adfs partitions qnx4 udf bfs cramfs \
- openpromfs autofs4 ramfs jffs
-
-SUB_DIRS :=
+ filesystems.o
ifeq ($(CONFIG_QUOTA),y)
-O_OBJS += dquot.o
+obj=ADy += dquot.o
else
-O_OBJS += noquot.o
-endif
-
-ifdef CONFIG_PROC_FS
-SUB_DIRS += proc
+obj-y += noquot.o
endif
-SUB_DIRS += partitions
+subdir-$(CONFIG_PROC_FS) += proc
+subdir-y += partitions
# Do not add any filesystems before this line
+subdir-$(CONFIG_EXT2_FS) += ext2
+subdir-$(CONFIG_CRAMFS) += cramfs
+subdir-$(CONFIG_RAMFS) += ramfs
+subdir-$(CONFIG_CODA_FS) += coda
+subdir-$(CONFIG_MINIX_FS) += minix
+subdir-$(CONFIG_FAT_FS) += fat
+subdir-$(CONFIG_MSDOS_FS) += msdos
+subdir-$(CONFIG_VFAT_FS) += vfat
+subdir-$(CONFIG_BFS_FS) += bfs
+subdir-$(CONFIG_ISO9660_FS) += isofs
+subdir-$(CONFIG_DEVFS_FS) += devfs
+subdir-$(CONFIG_HFS_FS) += hfs
+subdir-$(CONFIG_NFS_FS) += nfs
+subdir-$(CONFIG_NFSD) += nfsd
+subdir-$(CONFIG_LOCKD) += lockd
+subdir-$(CONFIG_NLS) += nls
+subdir-$(CONFIG_UMSDOS_FS) += umsdos
+subdir-$(CONFIG_SYSV_FS) += sysv
+subdir-$(CONFIG_SMB_FS) += smbfs
+subdir-$(CONFIG_NCP_FS) += ncpfs
+subdir-$(CONFIG_HPFS_FS) += hpfs
+subdir-$(CONFIG_NTFS_FS) += ntfs
+subdir-$(CONFIG_UFS_FS) += ufs
+subdir-$(CONFIG_EFS_FS) += efs
+subdir-$(CONFIG_JFFS_FS) += jffs
+subdir-$(CONFIG_AFFS_FS) += affs
+subdir-$(CONFIG_ROMFS_FS) += romfs
+subdir-$(CONFIG_QNX4FS_FS) += qnx4
+subdir-$(CONFIG_UDF_FS) += udf
+subdir-$(CONFIG_AUTOFS_FS) += autofs
+subdir-$(CONFIG_AUTOFS4_FS) += autofs4
+subdir-$(CONFIG_ADFS_FS) += adfs
+subdir-$(CONFIG_DEVPTS_FS) += devpts
+subdir-$(CONFIG_SUN_OPENPROMFS) += openpromfs
+
+
+obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
+obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o
+obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o
-ifeq ($(CONFIG_EXT2_FS),y)
-SUB_DIRS += ext2
-else
- ifeq ($(CONFIG_EXT2_FS),m)
- MOD_SUB_DIRS += ext2
- endif
-endif
-
-ifeq ($(CONFIG_CRAMFS),y)
-SUB_DIRS += cramfs
-else
- ifeq ($(CONFIG_CRAMFS),m)
- MOD_SUB_DIRS += cramfs
- endif
-endif
-
-ifeq ($(CONFIG_RAMFS),y)
-SUB_DIRS += ramfs
-else
- ifeq ($(CONFIG_RAMFS),m)
- MOD_SUB_DIRS += ramfs
- endif
-endif
-
-ifeq ($(CONFIG_CODA_FS),y)
-SUB_DIRS += coda
-else
- ifeq ($(CONFIG_CODA_FS),m)
- MOD_SUB_DIRS += coda
- endif
-endif
-
-ifeq ($(CONFIG_MINIX_FS),y)
-SUB_DIRS += minix
-else
- ifeq ($(CONFIG_MINIX_FS),m)
- MOD_SUB_DIRS += minix
- endif
-endif
-
-ifeq ($(CONFIG_FAT_FS),y)
-SUB_DIRS += fat
-else
- ifeq ($(CONFIG_FAT_FS),m)
- MOD_SUB_DIRS += fat
- endif
-endif
-
-ifeq ($(CONFIG_MSDOS_FS),y)
-SUB_DIRS += msdos
-else
- ifeq ($(CONFIG_MSDOS_FS),m)
- MOD_SUB_DIRS += msdos
- endif
-endif
-
-ifeq ($(CONFIG_VFAT_FS),y)
-SUB_DIRS += vfat
-else
- ifeq ($(CONFIG_VFAT_FS),m)
- MOD_SUB_DIRS += vfat
- endif
-endif
-
-ifeq ($(CONFIG_BFS_FS),y)
-SUB_DIRS += bfs
-else
- ifeq ($(CONFIG_BFS_FS),m)
- MOD_SUB_DIRS += bfs
- endif
-endif
-
-ifeq ($(CONFIG_ISO9660_FS),y)
-SUB_DIRS += isofs
-else
- ifeq ($(CONFIG_ISO9660_FS),m)
- MOD_SUB_DIRS += isofs
- endif
-endif
-
-ifdef CONFIG_DEVFS_FS
-SUB_DIRS += devfs
-endif
-
-ifeq ($(CONFIG_HFS_FS),y)
-SUB_DIRS += hfs
-else
- ifeq ($(CONFIG_HFS_FS),m)
- MOD_SUB_DIRS += hfs
- endif
-endif
-
-ifeq ($(CONFIG_NFS_FS),y)
-SUB_DIRS += nfs
-else
- ifeq ($(CONFIG_NFS_FS),m)
- MOD_SUB_DIRS += nfs
- endif
-endif
-
-ifeq ($(CONFIG_NFSD),y)
-CONFIG_LOCKD := y
-SUB_DIRS += nfsd
-else
- ifeq ($(CONFIG_NFSD),m)
- MOD_SUB_DIRS += nfsd
- endif
-endif
-
-ifeq ($(CONFIG_LOCKD),y)
-SUB_DIRS += lockd
-else
- ifeq ($(CONFIG_LOCKD),m)
- MOD_SUB_DIRS := lockd $(MOD_SUB_DIRS)
- endif
-endif
-
-# Since CONFIG_NLS might be set to y while there are modules
-# to be build in the nls/ directory, we need to enter the nls
-# directory every time, but with different rules.
-ifeq ($(CONFIG_NLS),y)
-SUB_DIRS += nls
-MOD_IN_SUB_DIRS += nls
-else
- ifeq ($(CONFIG_NLS),m)
- MOD_SUB_DIRS += nls
- endif
-endif
-
-ifeq ($(CONFIG_UMSDOS_FS),y)
-SUB_DIRS += umsdos
-else
- ifeq ($(CONFIG_UMSDOS_FS),m)
- MOD_SUB_DIRS += umsdos
- endif
-endif
-
-ifeq ($(CONFIG_SYSV_FS),y)
-SUB_DIRS += sysv
-else
- ifeq ($(CONFIG_SYSV_FS),m)
- MOD_SUB_DIRS += sysv
- endif
-endif
-
-ifeq ($(CONFIG_SMB_FS),y)
-SUB_DIRS += smbfs
-else
- ifeq ($(CONFIG_SMB_FS),m)
- MOD_SUB_DIRS += smbfs
- endif
-endif
-
-ifeq ($(CONFIG_NCP_FS),y)
-SUB_DIRS += ncpfs
-else
- ifeq ($(CONFIG_NCP_FS),m)
- MOD_SUB_DIRS += ncpfs
- endif
-endif
-
-ifeq ($(CONFIG_HPFS_FS),y)
-SUB_DIRS += hpfs
-else
- ifeq ($(CONFIG_HPFS_FS),m)
- MOD_SUB_DIRS += hpfs
- endif
-endif
-
-ifeq ($(CONFIG_NTFS_FS),y)
-SUB_DIRS += ntfs
-else
- ifeq ($(CONFIG_NTFS_FS),m)
- MOD_SUB_DIRS += ntfs
- endif
-endif
-
-ifeq ($(CONFIG_UFS_FS),y)
-SUB_DIRS += ufs
-else
- ifeq ($(CONFIG_UFS_FS),m)
- MOD_SUB_DIRS += ufs
- endif
-endif
-
-ifeq ($(CONFIG_EFS_FS),y)
-SUB_DIRS += efs
-else
- ifeq ($(CONFIG_EFS_FS),m)
- MOD_SUB_DIRS += efs
- endif
-endif
-
-ifeq ($(CONFIG_JFFS_FS),y)
-SUB_DIRS += jffs
-else
- ifeq ($(CONFIG_JFFS_FS),m)
- MOD_SUB_DIRS += jffs
- endif
-endif
-
-ifeq ($(CONFIG_AFFS_FS),y)
-SUB_DIRS += affs
-else
- ifeq ($(CONFIG_AFFS_FS),m)
- MOD_SUB_DIRS += affs
- endif
-endif
-
-ifeq ($(CONFIG_ROMFS_FS),y)
-SUB_DIRS += romfs
-else
- ifeq ($(CONFIG_ROMFS_FS),m)
- MOD_SUB_DIRS += romfs
- endif
-endif
-
-ifeq ($(CONFIG_QNX4FS_FS),y)
-SUB_DIRS += qnx4
-else
- ifeq ($(CONFIG_QNX4FS_FS),m)
- MOD_SUB_DIRS += qnx4
- endif
-endif
-
-ifeq ($(CONFIG_UDF_FS),y)
-SUB_DIRS += udf
-else
- ifeq ($(CONFIG_UDF_FS),m)
- MOD_SUB_DIRS += udf
- endif
-endif
-
-ifeq ($(CONFIG_AUTOFS_FS),y)
-SUB_DIRS += autofs
-else
- ifeq ($(CONFIG_AUTOFS_FS),m)
- MOD_SUB_DIRS += autofs
- endif
-endif
-
-ifeq ($(CONFIG_AUTOFS4_FS),y)
-SUB_DIRS += autofs4
-else
- ifeq ($(CONFIG_AUTOFS4_FS),m)
- MOD_SUB_DIRS += autofs4
- endif
-endif
-
-ifeq ($(CONFIG_ADFS_FS),y)
-SUB_DIRS += adfs
-else
- ifeq ($(CONFIG_ADFS_FS),m)
- MOD_SUB_DIRS += adfs
- endif
-endif
-
-ifeq ($(CONFIG_DEVPTS_FS),y)
-SUB_DIRS += devpts
-else
- ifeq ($(CONFIG_DEVPTS_FS),m)
- MOD_SUB_DIRS += devpts
- endif
-endif
+# binfmt_script is always there
+obj-y += binfmt_script.o
-ifeq ($(CONFIG_SUN_OPENPROMFS),y)
-SUB_DIRS += openpromfs
-else
- ifeq ($(CONFIG_SUN_OPENPROMFS),m)
- MOD_SUB_DIRS += openpromfs
- endif
-endif
+obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
-ifeq ($(CONFIG_BINFMT_AOUT),y)
-BINFMTS += binfmt_aout.o
-else
- ifeq ($(CONFIG_BINFMT_AOUT),m)
- M_OBJS += binfmt_aout.o
- endif
-endif
+# persistent filesystems
+obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
-ifeq ($(CONFIG_BINFMT_EM86),y)
-BINFMTS += binfmt_em86.o
-else
- ifeq ($(CONFIG_BINFMT_EM86),m)
- M_OBJS += binfmt_em86.o
- endif
-endif
-ifeq ($(CONFIG_BINFMT_MISC),y)
-BINFMTS += binfmt_misc.o
-else
- ifeq ($(CONFIG_BINFMT_MISC),m)
- M_OBJS += binfmt_misc.o
- endif
-endif
+# Subdirectories that should be entered when MAKING_MODULES=1, even if set to 'y'.
+both-m := $(filter $(mod-subdirs), $(subdir-y))
-# binfmt_script is always there
-BINFMTS += binfmt_script.o
+# Translate to Rules.make lists.
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS := $(filter $(export-objs), $(obj-y))
+M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
-ifeq ($(CONFIG_BINFMT_ELF),y)
-BINFMTS += binfmt_elf.o
-else
- ifeq ($(CONFIG_BINFMT_ELF),m)
- M_OBJS += binfmt_elf.o
- endif
-endif
+SUB_DIRS := $(subdir-y)
+MOD_SUB_DIRS := $(sort $(subdir-m) $(both-m))
+ALL_SUB_DIRS := $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-))
include $(TOPDIR)/Rules.make
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/fs.h>
-#include <linux/ext2_fs.h>
#include <linux/fcntl.h>
#include <linux/sched.h>
#include <linux/stat.h>
static struct {
const char *name;
struct block_device_operations *bdops;
-} blkdevs[MAX_BLKDEV] = {
- { NULL, NULL },
-};
+} blkdevs[MAX_BLKDEV];
int get_blkdev_list(char * p)
{
#include "inflate/zlib.h"
static z_stream stream;
-static int initialized = 0;
+static int initialized;
/* Returns length of decompressed data. */
int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
* ...
* 6 - base-level: try to shrink a bit.
*/
-int shrink_dcache_memory(int priority, unsigned int gfp_mask)
+void shrink_dcache_memory(int priority, unsigned int gfp_mask)
{
int count = 0;
* block allocations, but for now:
*/
if (!(gfp_mask & __GFP_IO))
- return 0;
+ return;
if (priority)
count = dentry_stat.nr_unused / priority;
+
prune_dcache(count);
- /* FIXME: kmem_cache_shrink here should tell us
- the number of pages freed, and it should
- work in a __GFP_DMA/__GFP_HIGHMEM behaviour
- to free only the interesting pages in
- function of the needs of the current allocation. */
kmem_cache_shrink(dentry_cache);
-
- return 0;
}
#define NAME_ALLOC_LEN(len) ((len+16) & ~15)
};
static rwlock_t chrdevs_lock = RW_LOCK_UNLOCKED;
-static struct device_struct chrdevs[MAX_CHRDEV] = {
- { NULL, NULL },
-};
+static struct device_struct chrdevs[MAX_CHRDEV];
extern int get_blkdev_list(char *);
blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE_BITS);
else
blocks = (inode->i_blocks >> 1);
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ if (!transfer_to[cnt])
+ continue;
if (check_idq(transfer_to[cnt], 1) == NO_QUOTA ||
check_bdq(transfer_to[cnt], blocks, 0) == NO_QUOTA) {
cnt = MAXQUOTAS;
goto put_all;
}
+ }
if ((error = notify_change(dentry, iattr)))
goto put_all;
#include <linux/config.h>
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
#include <linux/locks.h>
#include <linux/quotaops.h>
*/
#include <linux/fs.h>
-
+#include <linux/ext2_fs.h>
static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
*/
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
static unsigned char ext2_filetype_table[] = {
DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
*/
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
#include <linux/sched.h>
static loff_t ext2_file_lseek(struct file *, loff_t, int);
*/
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
#include <linux/config.h>
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
#include <linux/locks.h>
#include <linux/quotaops.h>
*/
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
#include <linux/sched.h>
*/
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
*/
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
#include <linux/locks.h>
#include <linux/quotaops.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/locks.h>
*/
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
{
#include <linux/module.h>
#include <linux/nfsd/interface.h>
-#ifdef CONFIG_CODA_FS
-extern int init_coda(void);
-#endif
-
#ifdef CONFIG_DEVPTS_FS
extern int init_devpts_fs(void);
#endif
init_nfs_fs();
#endif
-#ifdef CONFIG_CODA_FS
- init_coda();
-#endif
-
#ifdef CONFIG_DEVPTS_FS
init_devpts_fs();
#endif
dispose_list(freeable);
}
-int shrink_icache_memory(int priority, int gfp_mask)
+void shrink_icache_memory(int priority, int gfp_mask)
{
int count = 0;
* in clear_inode() and friends..
*/
if (!(gfp_mask & __GFP_IO))
- return 0;
+ return;
if (priority)
count = inodes_stat.nr_unused / priority;
+
prune_icache(count);
- /* FIXME: kmem_cache_shrink here should tell us
- the number of pages freed, and it should
- work in a __GFP_DMA/__GFP_HIGHMEM behaviour
- to free only the interesting pages in
- function of the needs of the current allocation. */
kmem_cache_shrink(inode_cachep);
-
- return 0;
}
/*
*/
static void clean_inode(struct inode *inode)
{
- static struct address_space_operations empty_aops = {};
- static struct inode_operations empty_iops = {};
- static struct file_operations empty_fops = {};
+ static struct address_space_operations empty_aops;
+ static struct inode_operations empty_iops;
+ static struct file_operations empty_fops;
memset(&inode->u, 0, sizeof(inode->u));
inode->i_sock = 0;
inode->i_op = &empty_iops;
#define NLM_HOST_ADDR(sv) (&(sv)->s_nlmclnt->cl_xprt->addr)
static struct nlm_host * nlm_hosts[NLM_HOST_NRHASH];
-static unsigned long next_gc = 0;
-static int nrhosts = 0;
+static unsigned long next_gc;
+static int nrhosts;
static DECLARE_MUTEX(nlm_host_sema);
#define ALLOWED_SIGS (sigmask(SIGKILL))
extern struct svc_program nlmsvc_program;
-struct nlmsvc_binding * nlmsvc_ops = NULL;
+struct nlmsvc_binding * nlmsvc_ops;
static DECLARE_MUTEX(nlmsvc_sema);
-static unsigned int nlmsvc_users = 0;
-static pid_t nlmsvc_pid = 0;
-unsigned long nlmsvc_grace_period = 0;
-unsigned long nlmsvc_timeout = 0;
+static unsigned int nlmsvc_users;
+static pid_t nlmsvc_pid;
+unsigned long nlmsvc_grace_period;
+unsigned long nlmsvc_timeout;
static DECLARE_MUTEX_LOCKED(lockd_start);
static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
* Currently the following can be set only at insmod time.
* Ideally, they would be accessible through the sysctl interface.
*/
-unsigned long nlm_grace_period = 0;
+unsigned long nlm_grace_period;
unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
/*
INIT_LIST_HEAD(&waiter->fl_list);
list_del(&waiter->fl_link);
INIT_LIST_HEAD(&waiter->fl_link);
+ waiter->fl_next = NULL;
}
/* Insert waiter into blocker's block list.
locks_delete_block(waiter);
}
list_add_tail(&waiter->fl_list, &blocker->fl_block);
+ waiter->fl_next = blocker;
list_add(&waiter->fl_link, &blocked_list);
}
next_task:
if (caller_owner == blocked_owner && caller_pid == blocked_pid)
return 1;
- while (tmp != &blocked_list) {
+ list_for_each(tmp, &blocked_list) {
struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link);
- tmp = tmp->next;
if ((fl->fl_owner == blocked_owner)
&& (fl->fl_pid == blocked_pid)) {
fl = fl->fl_next;
- if (fl) {
- blocked_owner = fl->fl_owner;
- blocked_pid = fl->fl_pid;
- }
+ blocked_owner = fl->fl_owner;
+ blocked_pid = fl->fl_pid;
goto next_task;
}
}
# Note 2! The CFLAGS definitions are now in the main makefile.
O_TARGET := minix.o
-O_OBJS := bitmap.o truncate.o namei.o inode.o file.o dir.o fsync.o
+O_OBJS := bitmap.o itree_v1.o itree_v2.o namei.o inode.o file.o dir.o
M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make
if (!minix_test_and_clear_bit(bit,bh->b_data))
printk("free_block (%s:%d): bit already cleared\n",
kdevname(sb->s_dev), block);
- else
- DQUOT_FREE_BLOCK(sb, inode, 1);
mark_buffer_dirty(bh);
return;
}
return 0;
}
repeat:
- if(DQUOT_ALLOC_BLOCK(sb, inode, 1))
- return -EDQUOT;
-
j = 8192;
bh = NULL;
for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++) {
return 0;
if (minix_test_and_set_bit(j,bh->b_data)) {
printk("new_block: bit already set");
- DQUOT_FREE_BLOCK(sb, inode, 1);
goto repeat;
}
mark_buffer_dirty(bh);
return;
}
- DQUOT_FREE_INODE(inode->i_sb, inode);
- DQUOT_DROP(inode);
-
bh = inode->i_sb->u.minix_sb.s_imap[ino >> 13];
minix_clear_inode(inode);
clear_inode(inode);
mark_inode_dirty(inode);
unlock_super(sb);
- if(DQUOT_ALLOC_INODE(sb, inode)) {
- sb->dq_op->drop(inode);
- inode->i_nlink = 0;
- iput(inode);
- *error = -EDQUOT;
- return NULL;
- }
-
*error = 0;
return inode;
}
* We have mostly NULLs here: the current defaults are OK for
* the minix filesystem.
*/
+static int minix_sync_file(struct file *, struct dentry *, int);
+
struct file_operations minix_file_operations = {
read: generic_file_read,
write: generic_file_write,
struct inode_operations minix_file_inode_operations = {
truncate: minix_truncate,
};
+
+static int minix_sync_file(struct file * file,
+ struct dentry *dentry,
+ int datasync)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if (INODE_VERSION(inode) == MINIX_V1)
+ return V1_minix_sync_file(inode);
+ else
+ return V2_minix_sync_file(inode);
+}
+++ /dev/null
-/*
- * linux/fs/minix/fsync.c
- *
- * Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
- * from
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * Copyright (C) 1996 Gertjan van Wingerde (gertjan@cs.vu.nl)
- * Minix V2 fs support
- *
- * minix fsync primitive
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/locks.h>
-#include <linux/smp_lock.h>
-
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define blocksize BLOCK_SIZE
-
-/*
- * The functions for minix V1 fs file synchronization.
- */
-static int V1_sync_block (struct inode * inode, unsigned short * block, int wait)
-{
- struct buffer_head * bh;
- unsigned short tmp;
-
- if (!*block)
- return 0;
- tmp = *block;
- bh = get_hash_table(inode->i_dev, *block, blocksize);
- if (!bh)
- return 0;
- if (*block != tmp) {
- brelse (bh);
- return 1;
- }
- if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- brelse(bh);
- return -1;
- }
- if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
- {
- brelse(bh);
- return 0;
- }
- ll_rw_block(WRITE, 1, &bh);
- atomic_dec(&bh->b_count);
- return 0;
-}
-
-static int V1_sync_iblock (struct inode * inode, unsigned short * iblock,
- struct buffer_head **bh, int wait)
-{
- int rc;
- unsigned short tmp;
-
- *bh = NULL;
- tmp = *iblock;
- if (!tmp)
- return 0;
- rc = V1_sync_block (inode, iblock, wait);
- if (rc)
- return rc;
- *bh = bread(inode->i_dev, tmp, blocksize);
- if (tmp != *iblock) {
- brelse(*bh);
- *bh = NULL;
- return 1;
- }
- if (!*bh)
- return -1;
- return 0;
-}
-
-static int V1_sync_direct(struct inode *inode, int wait)
-{
- int i;
- int rc, err = 0;
-
- for (i = 0; i < 7; i++) {
- rc = V1_sync_block (inode,
- (unsigned short *) inode->u.minix_i.u.i1_data + i, wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- return err;
-}
-
-static int V1_sync_indirect(struct inode *inode, unsigned short *iblock, int wait)
-{
- int i;
- struct buffer_head * ind_bh;
- int rc, err = 0;
-
- rc = V1_sync_iblock (inode, iblock, &ind_bh, wait);
- if (rc || !ind_bh)
- return rc;
-
- for (i = 0; i < 512; i++) {
- rc = V1_sync_block (inode,
- ((unsigned short *) ind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(ind_bh);
- return err;
-}
-
-static int V1_sync_dindirect(struct inode *inode, unsigned short *diblock,
- int wait)
-{
- int i;
- struct buffer_head * dind_bh;
- int rc, err = 0;
-
- rc = V1_sync_iblock (inode, diblock, &dind_bh, wait);
- if (rc || !dind_bh)
- return rc;
-
- for (i = 0; i < 512; i++) {
- rc = V1_sync_indirect (inode,
- ((unsigned short *) dind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(dind_bh);
- return err;
-}
-
-static int V1_minix_sync_file(struct inode * inode, struct file * file)
-{
- int wait, err = 0;
-
- lock_kernel();
- for (wait=0; wait<=1; wait++)
- {
- err |= V1_sync_direct(inode, wait);
- err |= V1_sync_indirect(inode, inode->u.minix_i.u.i1_data + 7, wait);
- err |= V1_sync_dindirect(inode, inode->u.minix_i.u.i1_data + 8, wait);
- }
- err |= minix_sync_inode (inode);
- unlock_kernel();
- return (err < 0) ? -EIO : 0;
-}
-
-/*
- * The functions for minix V2 fs file synchronization.
- */
-static int V2_sync_block (struct inode * inode, unsigned long * block, int wait)
-{
- struct buffer_head * bh;
- unsigned long tmp;
-
- if (!*block)
- return 0;
- tmp = *block;
- bh = get_hash_table(inode->i_dev, *block, blocksize);
- if (!bh)
- return 0;
- if (*block != tmp) {
- brelse (bh);
- return 1;
- }
- if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
- brelse(bh);
- return -1;
- }
- if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
- {
- brelse(bh);
- return 0;
- }
- ll_rw_block(WRITE, 1, &bh);
- atomic_dec(&bh->b_count);
- return 0;
-}
-
-static int V2_sync_iblock (struct inode * inode, unsigned long * iblock,
- struct buffer_head **bh, int wait)
-{
- int rc;
- unsigned long tmp;
-
- *bh = NULL;
- tmp = *iblock;
- if (!tmp)
- return 0;
- rc = V2_sync_block (inode, iblock, wait);
- if (rc)
- return rc;
- *bh = bread(inode->i_dev, tmp, blocksize);
- if (tmp != *iblock) {
- brelse(*bh);
- *bh = NULL;
- return 1;
- }
- if (!*bh)
- return -1;
- return 0;
-}
-
-static int V2_sync_direct(struct inode *inode, int wait)
-{
- int i;
- int rc, err = 0;
-
- for (i = 0; i < 7; i++) {
- rc = V2_sync_block (inode,
- (unsigned long *)inode->u.minix_i.u.i2_data + i, wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- return err;
-}
-
-static int V2_sync_indirect(struct inode *inode, unsigned long *iblock, int wait)
-{
- int i;
- struct buffer_head * ind_bh;
- int rc, err = 0;
-
- rc = V2_sync_iblock (inode, iblock, &ind_bh, wait);
- if (rc || !ind_bh)
- return rc;
-
- for (i = 0; i < 256; i++) {
- rc = V2_sync_block (inode,
- ((unsigned long *) ind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(ind_bh);
- return err;
-}
-
-static int V2_sync_dindirect(struct inode *inode, unsigned long *diblock,
- int wait)
-{
- int i;
- struct buffer_head * dind_bh;
- int rc, err = 0;
-
- rc = V2_sync_iblock (inode, diblock, &dind_bh, wait);
- if (rc || !dind_bh)
- return rc;
-
- for (i = 0; i < 256; i++) {
- rc = V2_sync_indirect (inode,
- ((unsigned long *) dind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(dind_bh);
- return err;
-}
-
-static int V2_sync_tindirect(struct inode *inode, unsigned long *tiblock,
- int wait)
-{
- int i;
- struct buffer_head * tind_bh;
- int rc, err = 0;
-
- rc = V2_sync_iblock (inode, tiblock, &tind_bh, wait);
- if (rc || !tind_bh)
- return rc;
-
- for (i = 0; i < 256; i++) {
- rc = V2_sync_dindirect (inode,
- ((unsigned long *) tind_bh->b_data) + i,
- wait);
- if (rc > 0)
- break;
- if (rc)
- err = rc;
- }
- brelse(tind_bh);
- return err;
-}
-
-static int V2_minix_sync_file(struct inode * inode, struct file * file)
-{
- int wait, err = 0;
-
- lock_kernel();
- for (wait=0; wait<=1; wait++)
- {
- err |= V2_sync_direct(inode, wait);
- err |= V2_sync_indirect(inode,
- (unsigned long *) inode->u.minix_i.u.i2_data + 7, wait);
- err |= V2_sync_dindirect(inode,
- (unsigned long *) inode->u.minix_i.u.i2_data + 8, wait);
- err |= V2_sync_tindirect(inode,
- (unsigned long *) inode->u.minix_i.u.i2_data + 9, wait);
- }
- err |= minix_sync_inode (inode);
- unlock_kernel();
- return (err < 0) ? -EIO : 0;
-}
-
-/*
- * The function which is called for file synchronization. File may be
- * NULL
- */
-
-int minix_sync_file(struct file * file, struct dentry *dentry, int datasync)
-{
- struct inode *inode = dentry->d_inode;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return -EINVAL;
-
- if (INODE_VERSION(inode) == MINIX_V1)
- return V1_minix_sync_file(inode, file);
- else
- return V2_minix_sync_file(inode, file);
-}
return 0;
}
-/*
- * The minix V1 fs bmap functions.
- */
-#define V1_inode_bmap(inode,nr) (((unsigned short *)(inode)->u.minix_i.u.i1_data)[(nr)])
-
-static int V1_block_bmap(struct buffer_head * bh, int nr)
-{
- int tmp;
-
- if (!bh)
- return 0;
- tmp = ((unsigned short *) bh->b_data)[nr];
- brelse(bh);
- return tmp;
-}
-
-static int V1_minix_block_map(struct inode * inode, long block)
-{
- int i, ret;
-
- ret = 0;
- lock_kernel();
- if (block < 0) {
- printk("minix_bmap: block<0");
- goto out;
- }
- if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
- printk("minix_bmap: block>big");
- goto out;
- }
- if (block < 7) {
- ret = V1_inode_bmap(inode,block);
- goto out;
- }
- block -= 7;
- if (block < 512) {
- i = V1_inode_bmap(inode,7);
- if (!i)
- goto out;
- ret = V1_block_bmap(bread(inode->i_dev, i,
- BLOCK_SIZE), block);
- goto out;
- }
- block -= 512;
- i = V1_inode_bmap(inode,8);
- if (!i)
- goto out;
- i = V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>9);
- if (!i)
- goto out;
- ret = V1_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block & 511);
-out:
- unlock_kernel();
- return ret;
-}
-
-/*
- * The minix V2 fs bmap functions.
- */
-#define V2_inode_bmap(inode,nr) (((unsigned int *)(inode)->u.minix_i.u.i2_data)[(nr)])
-static int V2_block_bmap(struct buffer_head * bh, int nr)
-{
- int tmp;
-
- if (!bh)
- return 0;
- tmp = ((unsigned int *) bh->b_data)[nr];
- brelse(bh);
- return tmp;
-}
-
-static int V2_minix_block_map(struct inode * inode, int block)
-{
- int i, ret;
-
- ret = 0;
- lock_kernel();
- if (block < 0) {
- printk("minix_bmap: block<0");
- goto out;
- }
- if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
- printk("minix_bmap: block>big");
- goto out;
- }
- if (block < 7) {
- ret = V2_inode_bmap(inode,block);
- goto out;
- }
- block -= 7;
- if (block < 256) {
- i = V2_inode_bmap(inode, 7);
- if (!i)
- goto out;
- ret = V2_block_bmap(bread(inode->i_dev, i,
- BLOCK_SIZE), block);
- goto out;
- }
- block -= 256;
- if (block < (256 * 256)) {
- i = V2_inode_bmap(inode, 8);
- if (!i)
- goto out;
- i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block >> 8);
- if (!i)
- goto out;
- ret = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block & 255);
- goto out;
- }
- block -= (256 * 256);
- i = V2_inode_bmap(inode, 9);
- if (!i)
- goto out;
- i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block >> 16);
- if (!i)
- goto out;
- i = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- (block >> 8) & 255);
- if (!i)
- goto out;
- ret = V2_block_bmap(bread(inode->i_dev, i, BLOCK_SIZE),
- block & 255);
-out:
- unlock_kernel();
- return ret;
-}
-
-/*
- * The minix V1 fs getblk functions.
- */
-static struct buffer_head * V1_inode_getblk(struct inode * inode, int nr,
- int new_block, int *err,
- int metadata, int *phys, int *new)
-{
- int tmp;
- unsigned short *p;
- struct buffer_head * result;
-
- p = inode->u.minix_i.u.i1_data + nr;
-repeat:
- tmp = *p;
- if (tmp) {
- if (metadata) {
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp == *p)
- return result;
- brelse(result);
- goto repeat;
- } else {
- *phys = tmp;
- return NULL;
- }
- }
-
- tmp = minix_new_block(inode);
- if (!tmp) {
- *err = -ENOSPC;
- return NULL;
- }
- if (metadata) {
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
- memset(result->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(result, 1);
- mark_buffer_dirty(result);
- } else {
- if (*p) {
- /*
- * Nobody is allowed to change block allocation
- * state from under us:
- */
- BUG();
- minix_free_block(inode, tmp);
- goto repeat;
- }
- *phys = tmp;
- result = NULL;
- *err = 0;
- *new = 1;
- }
- *p = tmp;
-
- inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
- return result;
-}
-
-static struct buffer_head * V1_block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int new_block, int *err,
- int metadata, int *phys, int *new)
-{
- int tmp;
- unsigned short *p;
- struct buffer_head * result;
-
- result = NULL;
- if (!bh)
- goto out;
- if (!buffer_uptodate(bh)) {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- goto out;
- }
- p = nr + (unsigned short *) bh->b_data;
-repeat:
- tmp = *p;
- if (tmp) {
- if (metadata) {
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (tmp == *p)
- goto out;
- brelse(result);
- goto repeat;
- } else {
- *phys = tmp;
- goto out;
- }
- }
-
- tmp = minix_new_block(inode);
- if (!tmp)
- goto out;
- if (metadata) {
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
- memset(result->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(result, 1);
- mark_buffer_dirty(result);
- } else {
- *phys = tmp;
- *new = 1;
- }
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
-
- *p = tmp;
- mark_buffer_dirty(bh);
- *err = 0;
-out:
- brelse(bh);
- return result;
-}
-
-static int V1_get_block(struct inode * inode, long block,
- struct buffer_head *bh_result, int create)
-{
- int ret, err, new, phys, ptr;
- struct buffer_head *bh;
-
- if (!create) {
- phys = V1_minix_block_map(inode, block);
- if (phys) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- }
- return 0;
- }
-
- err = -EIO;
- new = 0;
- ret = 0;
- bh = NULL;
-
- lock_kernel();
- if (block < 0)
- goto abort_negative;
- if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)
- goto abort_too_big;
-
- err = 0;
- ptr = block;
- /*
- * ok, these macros clean the logic up a bit and make
- * it much more readable:
- */
-#define GET_INODE_DATABLOCK(x) \
- V1_inode_getblk(inode, x, block, &err, 0, &phys, &new)
-#define GET_INODE_PTR(x) \
- V1_inode_getblk(inode, x, block, &err, 1, NULL, NULL)
-#define GET_INDIRECT_DATABLOCK(x) \
- V1_block_getblk(inode, bh, x, block, &err, 0, &phys, &new)
-#define GET_INDIRECT_PTR(x) \
- V1_block_getblk(inode, bh, x, block, &err, 1, NULL, NULL)
-
- if (ptr < 7) {
- bh = GET_INODE_DATABLOCK(ptr);
- goto out;
- }
- ptr -= 7;
- if (ptr < 512) {
- bh = GET_INODE_PTR(7);
- goto get_indirect;
- }
- ptr -= 512;
- bh = GET_INODE_PTR(8);
- bh = GET_INDIRECT_PTR((ptr >> 9) & 511);
-get_indirect:
- bh = GET_INDIRECT_DATABLOCK(ptr & 511);
-
-#undef GET_INODE_DATABLOCK
-#undef GET_INODE_PTR
-#undef GET_INDIRECT_DATABLOCK
-#undef GET_INDIRECT_PTR
-
-out:
- if (err)
- goto abort;
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- if (new)
- bh_result->b_state |= (1UL << BH_New);
-abort:
- unlock_kernel();
- return err;
-
-abort_negative:
- printk("minix_getblk: block<0");
- goto abort;
-
-abort_too_big:
- printk("minix_getblk: block>big");
- goto abort;
-}
-
-/*
- * The minix V2 fs getblk functions.
- */
-static struct buffer_head * V2_inode_getblk(struct inode * inode, int nr,
- int new_block, int *err,
- int metadata, int *phys, int *new)
-{
- int tmp;
- unsigned int *p;
- struct buffer_head * result;
-
- p = (unsigned int *) inode->u.minix_i.u.i2_data + nr;
-repeat:
- tmp = *p;
- if (tmp) {
- if (metadata) {
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp == *p)
- return result;
- brelse(result);
- goto repeat;
- } else {
- *phys = tmp;
- return NULL;
- }
- }
-
- tmp = minix_new_block(inode);
- if (!tmp) {
- *err = -ENOSPC;
- return NULL;
- }
- if (metadata) {
- result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
- memset(result->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(result, 1);
- mark_buffer_dirty(result);
- } else {
- if (*p) {
- /*
- * Nobody is allowed to change block allocation
- * state from under us:
- */
- BUG();
- minix_free_block(inode, tmp);
- goto repeat;
- }
- *phys = tmp;
- result = NULL;
- *err = 0;
- *new = 1;
- }
- *p = tmp;
-
- inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
- return result;
-}
-
-static struct buffer_head * V2_block_getblk(struct inode * inode,
- struct buffer_head * bh, int nr, int new_block, int *err,
- int metadata, int *phys, int *new)
-{
- int tmp;
- unsigned int *p;
- struct buffer_head * result;
-
- result = NULL;
- if (!bh)
- goto out;
- if (!buffer_uptodate(bh)) {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- goto out;
- }
- p = nr + (unsigned int *) bh->b_data;
-repeat:
- tmp = *p;
- if (tmp) {
- if (metadata) {
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (tmp == *p)
- goto out;
- brelse(result);
- goto repeat;
- } else {
- *phys = tmp;
- goto out;
- }
- }
-
- tmp = minix_new_block(inode);
- if (!tmp)
- goto out;
- if (metadata) {
- result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
- memset(result->b_data, 0, BLOCK_SIZE);
- mark_buffer_uptodate(result, 1);
- mark_buffer_dirty(result);
- } else {
- *phys = tmp;
- *new = 1;
- }
- if (*p) {
- minix_free_block(inode, tmp);
- brelse(result);
- goto repeat;
- }
-
- *p = tmp;
- mark_buffer_dirty(bh);
- *err = 0;
-out:
- brelse(bh);
- return result;
-}
-
-static int V2_get_block(struct inode * inode, long block,
- struct buffer_head *bh_result, int create)
-{
- int ret, err, new, phys, ptr;
- struct buffer_head * bh;
-
- if (!create) {
- phys = V2_minix_block_map(inode, block);
- if (phys) {
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- }
- return 0;
- }
-
- err = -EIO;
- new = 0;
- ret = 0;
- bh = NULL;
-
- lock_kernel();
- if (block < 0)
- goto abort_negative;
- if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)
- goto abort_too_big;
-
- err = 0;
- ptr = block;
- /*
- * ok, these macros clean the logic up a bit and make
- * it much more readable:
- */
-#define GET_INODE_DATABLOCK(x) \
- V2_inode_getblk(inode, x, block, &err, 0, &phys, &new)
-#define GET_INODE_PTR(x) \
- V2_inode_getblk(inode, x, block, &err, 1, NULL, NULL)
-#define GET_INDIRECT_DATABLOCK(x) \
- V2_block_getblk(inode, bh, x, block, &err, 0, &phys, &new)
-#define GET_INDIRECT_PTR(x) \
- V2_block_getblk(inode, bh, x, block, &err, 1, NULL, NULL)
-
- if (ptr < 7) {
- bh = GET_INODE_DATABLOCK(ptr);
- goto out;
- }
- ptr -= 7;
- if (ptr < 256) {
- bh = GET_INODE_PTR(7);
- goto get_indirect;
- }
- ptr -= 256;
- if (ptr < 256*256) {
- bh = GET_INODE_PTR(8);
- goto get_double;
- }
- ptr -= 256*256;
- bh = GET_INODE_PTR(9);
- bh = GET_INDIRECT_PTR((ptr >> 16) & 255);
-get_double:
- bh = GET_INDIRECT_PTR((ptr >> 8) & 255);
-get_indirect:
- bh = GET_INDIRECT_DATABLOCK(ptr & 255);
-
-#undef GET_INODE_DATABLOCK
-#undef GET_INODE_PTR
-#undef GET_INDIRECT_DATABLOCK
-#undef GET_INDIRECT_PTR
-
-out:
- if (err)
- goto abort;
- bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = phys;
- bh_result->b_state |= (1UL << BH_Mapped);
- if (new)
- bh_result->b_state |= (1UL << BH_New);
-abort:
- unlock_kernel();
- return err;
-
-abort_negative:
- printk("minix_getblk: block<0");
- goto abort;
-
-abort_too_big:
- printk("minix_getblk: block>big");
- goto abort;
-}
-
static int minix_get_block(struct inode *inode, long block,
struct buffer_head *bh_result, int create)
{
if (INODE_VERSION(inode) == MINIX_V1)
- return V1_get_block(inode, block, bh_result, create);
+ return V1_minix_get_block(inode, block, bh_result, create);
else
- return V2_get_block(inode, block, bh_result, create);
+ return V2_minix_get_block(inode, block, bh_result, create);
}
/*
return err;
}
+/*
+ * The function that is called for file truncation.
+ */
+void minix_truncate(struct inode * inode)
+{
+ if (INODE_VERSION(inode) == MINIX_V1)
+ V1_minix_truncate(inode);
+ else
+ V2_minix_truncate(inode);
+}
+
static DECLARE_FSTYPE_DEV(minix_fs_type,"minix",minix_read_super);
static int __init init_minix_fs(void)
--- /dev/null
+/* Generic part */
+
+typedef struct {
+ block_t *p;
+ block_t key;
+ struct buffer_head *bh;
+} Indirect;
+
+static inline void add_chain(Indirect *p, struct buffer_head *bh, block_t *v)
+{
+ p->key = *(p->p = v);
+ p->bh = bh;
+}
+
+static inline int verify_chain(Indirect *from, Indirect *to)
+{
+ while (from <= to && from->key == *from->p)
+ from++;
+ return (from > to);
+}
+
+static inline block_t *block_end(struct buffer_head *bh)
+{
+ return (block_t *)((char*)bh->b_data + BLOCK_SIZE);
+}
+
+static inline Indirect *get_branch(struct inode *inode,
+ int depth,
+ int *offsets,
+ Indirect chain[DEPTH],
+ int *err)
+{
+ kdev_t dev = inode->i_dev;
+ Indirect *p = chain;
+ struct buffer_head *bh;
+
+ *err = 0;
+ /* i_data is not going away, no lock needed */
+ add_chain (chain, NULL, i_data(inode) + *offsets);
+ if (!p->key)
+ goto no_block;
+ while (--depth) {
+ bh = bread(dev, block_to_cpu(p->key), BLOCK_SIZE);
+ if (!bh)
+ goto failure;
+ /* Reader: pointers */
+ if (!verify_chain(chain, p))
+ goto changed;
+ add_chain(++p, bh, (block_t *)bh->b_data + *++offsets);
+ /* Reader: end */
+ if (!p->key)
+ goto no_block;
+ }
+ return NULL;
+
+changed:
+ *err = -EAGAIN;
+ goto no_block;
+failure:
+ *err = -EIO;
+no_block:
+ return p;
+}
+
+static int alloc_branch(struct inode *inode,
+ int num,
+ int *offsets,
+ Indirect *branch)
+{
+ int n = 0;
+ int i;
+ int parent = minix_new_block(inode);
+
+ branch[0].key = cpu_to_block(parent);
+ if (parent) for (n = 1; n < num; n++) {
+ struct buffer_head *bh;
+ /* Allocate the next block */
+ int nr = minix_new_block(inode);
+ if (!nr)
+ break;
+ branch[n].key = cpu_to_block(nr);
+ bh = getblk(inode->i_dev, parent, BLOCK_SIZE);
+ if (!buffer_uptodate(bh))
+ wait_on_buffer(bh);
+ memset(bh->b_data, 0, BLOCK_SIZE);
+ branch[n].bh = bh;
+ branch[n].p = (block_t*) bh->b_data + offsets[n];
+ *branch[n].p = branch[n].key;
+ mark_buffer_uptodate(bh, 1);
+ mark_buffer_dirty(bh);
+ parent = nr;
+ }
+ if (n == num)
+ return 0;
+
+ /* Allocation failed, free what we already allocated */
+ for (i = 1; i < n; i++)
+ bforget(branch[i].bh);
+ for (i = 0; i < n; i++)
+ minix_free_block(inode, block_to_cpu(branch[i].key));
+ return -ENOSPC;
+}
+
+static inline int splice_branch(struct inode *inode,
+ Indirect chain[DEPTH],
+ Indirect *where,
+ int num)
+{
+ int i;
+
+ /* Verify that place we are splicing to is still there and vacant */
+
+ /* Writer: pointers */
+ if (!verify_chain(chain, where-1) || *where->p)
+ /* Writer: end */
+ goto changed;
+
+ /* That's it */
+
+ *where->p = where->key;
+
+ /* Writer: end */
+
+ /* We are done with atomic stuff, now do the rest of housekeeping */
+
+ inode->i_ctime = CURRENT_TIME;
+
+ /* had we spliced it onto indirect block? */
+ if (where->bh)
+ mark_buffer_dirty(where->bh);
+
+ mark_inode_dirty(inode);
+ return 0;
+
+changed:
+ for (i = 1; i < num; i++)
+ bforget(where[i].bh);
+ for (i = 0; i < num; i++)
+ minix_free_block(inode, block_to_cpu(where[i].key));
+ return -EAGAIN;
+}
+
+static inline int get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
+{
+ int err = -EIO;
+ int offsets[DEPTH];
+ Indirect chain[DEPTH];
+ Indirect *partial;
+ int left;
+ int depth = block_to_path(inode, block, offsets);
+
+ if (depth == 0)
+ goto out;
+
+ lock_kernel();
+reread:
+ partial = get_branch(inode, depth, offsets, chain, &err);
+
+ /* Simplest case - block found, no allocation needed */
+ if (!partial) {
+got_it:
+ bh_result->b_dev = inode->i_dev;
+ bh_result->b_blocknr = block_to_cpu(chain[depth-1].key);
+ bh_result->b_state |= (1UL << BH_Mapped);
+ /* Clean up and exit */
+ partial = chain+depth-1; /* the whole chain */
+ goto cleanup;
+ }
+
+ /* Next simple case - plain lookup or failed read of indirect block */
+ if (!create || err == -EIO) {
+cleanup:
+ while (partial > chain) {
+ brelse(partial->bh);
+ partial--;
+ }
+ unlock_kernel();
+out:
+ return err;
+ }
+
+ /*
+ * Indirect block might be removed by truncate while we were
+ * reading it. Handling of that case (forget what we've got and
+ * reread) is taken out of the main path.
+ */
+ if (err == -EAGAIN)
+ goto changed;
+
+ left = (chain + depth) - partial;
+ err = alloc_branch(inode, left, offsets+(partial-chain), partial);
+ if (err)
+ goto cleanup;
+
+ if (splice_branch(inode, chain, partial, left) < 0)
+ goto changed;
+
+ bh_result->b_state |= (1UL << BH_New);
+ goto got_it;
+
+changed:
+ while (partial > chain) {
+ bforget(partial->bh);
+ partial--;
+ }
+ goto reread;
+}
+
+static inline int all_zeroes(block_t *p, block_t *q)
+{
+ while (p < q)
+ if (*p++)
+ return 0;
+ return 1;
+}
+
+static Indirect *find_shared(struct inode *inode,
+ int depth,
+ int offsets[DEPTH],
+ Indirect chain[DEPTH],
+ block_t *top)
+{
+ Indirect *partial, *p;
+ int k, err;
+
+ *top = 0;
+ for (k = depth; k > 1 && !offsets[k-1]; k--)
+ ;
+ partial = get_branch(inode, k, offsets, chain, &err);
+ /* Writer: pointers */
+ if (!partial)
+ partial = chain + k-1;
+ if (!partial->key && *partial->p)
+ /* Writer: end */
+ goto no_top;
+ for (p=partial;p>chain && all_zeroes((block_t*)p->bh->b_data,p->p);p--)
+ ;
+ if (p == chain + k - 1 && p > chain) {
+ p->p--;
+ } else {
+ *top = *p->p;
+ *p->p = 0;
+ }
+ /* Writer: end */
+
+ while(partial > p)
+ {
+ brelse(partial->bh);
+ partial--;
+ }
+no_top:
+ return partial;
+}
+
+static inline void free_data(struct inode *inode, block_t *p, block_t *q)
+{
+ unsigned long nr;
+
+ for ( ; p < q ; p++) {
+ nr = block_to_cpu(*p);
+ if (nr) {
+ *p = 0;
+ minix_free_block(inode, nr);
+ }
+ }
+}
+
+static void free_branches(struct inode *inode, block_t *p, block_t *q, int depth)
+{
+ struct buffer_head * bh;
+ unsigned long nr;
+
+ if (depth--) {
+ for ( ; p < q ; p++) {
+ nr = block_to_cpu(*p);
+ if (!nr)
+ continue;
+ *p = 0;
+ bh = bread (inode->i_dev, nr, BLOCK_SIZE);
+ if (!bh)
+ continue;
+ free_branches(inode, (block_t*)bh->b_data,
+ block_end(bh), depth);
+ bforget(bh);
+ minix_free_block(inode, nr);
+ mark_inode_dirty(inode);
+ }
+ } else
+ free_data(inode, p, q);
+}
+
+static inline void truncate (struct inode * inode)
+{
+ block_t *idata = i_data(inode);
+ int offsets[DEPTH];
+ Indirect chain[DEPTH];
+ Indirect *partial;
+ block_t nr = 0;
+ int n;
+ int first_whole;
+ long iblock;
+
+ iblock = (inode->i_size + BLOCK_SIZE-1) >> 10;
+ block_truncate_page(inode->i_mapping, inode->i_size, get_block);
+
+ n = block_to_path(inode, iblock, offsets);
+ if (!n)
+ return;
+
+ if (n == 1) {
+ free_data(inode, idata+offsets[0], idata + DIRECT);
+ first_whole = 0;
+ goto do_indirects;
+ }
+
+ first_whole = offsets[0] + 1 - DIRECT;
+ partial = find_shared(inode, n, offsets, chain, &nr);
+ if (nr) {
+ if (partial == chain)
+ mark_inode_dirty(inode);
+ else
+ mark_buffer_dirty(partial->bh);
+ free_branches(inode, &nr, &nr+1, (chain+n-1) - partial);
+ }
+ /* Clear the ends of indirect blocks on the shared branch */
+ while (partial > chain) {
+ free_branches(inode, partial->p + 1, block_end(partial->bh),
+ (chain+n-1) - partial);
+ mark_buffer_dirty(partial->bh);
+ brelse (partial->bh);
+ partial--;
+ }
+do_indirects:
+ /* Kill the remaining (whole) subtrees */
+ while (first_whole < DEPTH-1) {
+ nr = idata[DIRECT+first_whole];
+ if (nr) {
+ idata[DIRECT+first_whole] = 0;
+ mark_inode_dirty(inode);
+ free_branches(inode, &nr, &nr+1, first_whole+1);
+ }
+ first_whole++;
+ }
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(inode);
+}
+
+static int sync_block (struct inode * inode, block_t block, int wait)
+{
+ struct buffer_head * bh;
+
+ if (!block)
+ return 0;
+ bh = get_hash_table(inode->i_dev, block_to_cpu(block), BLOCK_SIZE);
+ if (!bh)
+ return 0;
+ if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
+ brelse(bh);
+ return -1;
+ }
+ if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh))
+ {
+ brelse(bh);
+ return 0;
+ }
+ ll_rw_block(WRITE, 1, &bh);
+ atomic_dec(&bh->b_count);
+ return 0;
+}
+
+static int sync_indirect(struct inode *inode, block_t iblock, int depth,
+ int wait)
+{
+ struct buffer_head * ind_bh = NULL;
+ int rc, err = 0;
+
+ if (!iblock)
+ return 0;
+
+ rc = sync_block (inode, iblock, wait);
+ if (rc)
+ return rc;
+
+ ind_bh = bread(inode->i_dev, block_to_cpu(iblock), BLOCK_SIZE);
+ if (!ind_bh)
+ return -1;
+
+ if (--depth) {
+ block_t *p = (block_t*)ind_bh->b_data;
+ block_t *end = block_end(ind_bh);
+ while (p < end) {
+ rc = sync_indirect (inode, *p++, depth, wait);
+ if (rc > 0)
+ break;
+ if (rc)
+ err = rc;
+ }
+ }
+ brelse(ind_bh);
+ return err;
+}
+
+static inline int sync_file(struct inode * inode)
+{
+ int wait, err = 0, i;
+ block_t *idata = i_data(inode);
+
+ lock_kernel();
+ err = generic_buffer_fdatasync(inode, 0, ~0UL);
+ for (wait=0; wait<=1; wait++)
+ for (i=1; i<DEPTH; i++)
+ err |= sync_indirect(inode, idata[DIRECT+i-1], i, wait);
+ err |= minix_sync_inode (inode);
+ unlock_kernel();
+ return (err < 0) ? -EIO : 0;
+}
--- /dev/null
+#include <linux/sched.h>
+#include <linux/locks.h>
+#include <linux/minix_fs.h>
+#include <linux/smp_lock.h>
+
+enum {DEPTH = 3, DIRECT = 7}; /* Only double indirect */
+
+typedef u16 block_t; /* 16 bit, host order */
+
+static inline unsigned long block_to_cpu(block_t n)
+{
+ return n;
+}
+
+static inline block_t cpu_to_block(unsigned long n)
+{
+ return n;
+}
+
+static inline block_t *i_data(struct inode *inode)
+{
+ return (block_t *)inode->u.minix_i.u.i1_data;
+}
+
+static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
+{
+ int n = 0;
+
+ if (block < 0) {
+ printk("minix_bmap: block<0");
+ } else if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
+ printk("minix_bmap: block>big");
+ } else if (block < 7) {
+ offsets[n++] = block;
+ } else if ((block -= 7) < 512) {
+ offsets[n++] = 7;
+ offsets[n++] = block;
+ } else {
+ block -= 512;
+ offsets[n++] = 8;
+ offsets[n++] = block>>9;
+ offsets[n++] = block & 511;
+ }
+ return n;
+}
+
+#include "itree_common.c"
+
+int V1_minix_get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
+{
+ return get_block(inode, block, bh_result, create);
+}
+
+void V1_minix_truncate(struct inode * inode)
+{
+ truncate(inode);
+}
+
+int V1_minix_sync_file(struct inode * inode)
+{
+ return sync_file(inode);
+}
--- /dev/null
+#include <linux/sched.h>
+#include <linux/locks.h>
+#include <linux/minix_fs.h>
+#include <linux/smp_lock.h>
+
+enum {DIRECT = 7, DEPTH = 4}; /* Have triple indirect */
+
+typedef u32 block_t; /* 32 bit, host order */
+
+static inline unsigned long block_to_cpu(block_t n)
+{
+ return n;
+}
+
+static inline block_t cpu_to_block(unsigned long n)
+{
+ return n;
+}
+
+static inline block_t *i_data(struct inode *inode)
+{
+ return (block_t *)inode->u.minix_i.u.i2_data;
+}
+
+static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
+{
+ int n = 0;
+
+ if (block < 0) {
+ printk("minix_bmap: block<0");
+ } else if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
+ printk("minix_bmap: block>big");
+ } else if (block < 7) {
+ offsets[n++] = block;
+ } else if ((block -= 7) < 256) {
+ offsets[n++] = 7;
+ offsets[n++] = block;
+ } else if ((block -= 256) < 256*256) {
+ offsets[n++] = 8;
+ offsets[n++] = block>>8;
+ offsets[n++] = block & 255;
+ } else {
+ block -= 256*256;
+ offsets[n++] = 9;
+ offsets[n++] = block>>16;
+ offsets[n++] = (block>>8) & 255;
+ offsets[n++] = block & 255;
+ }
+ return n;
+}
+
+#include "itree_common.c"
+
+int V2_minix_get_block(struct inode * inode, long block,
+ struct buffer_head *bh_result, int create)
+{
+ return get_block(inode, block, bh_result, create);
+}
+
+void V2_minix_truncate(struct inode * inode)
+{
+ truncate(inode);
+}
+
+int V2_minix_sync_file(struct inode * inode)
+{
+ return sync_file(inode);
+}
if (!bh)
goto end_rmdir;
inode = dentry->d_inode;
- DQUOT_INIT(inode);
if (!empty_dir(inode)) {
retval = -ENOTEMPTY;
retval = -ENOENT;
inode = dentry->d_inode;
- DQUOT_INIT(inode);
bh = minix_find_entry(dir, dentry->d_name.name,
dentry->d_name.len, &de);
if (!bh || de->inode != inode->i_ino)
if (!new_inode) {
brelse(new_bh);
new_bh = NULL;
- } else {
- DQUOT_INIT(new_inode);
}
}
if (S_ISDIR(old_inode->i_mode)) {
+++ /dev/null
-/*
- * linux/fs/truncate.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * Copyright (C) 1996 Gertjan van Wingerde (gertjan@cs.vu.nl)
- * Minix V2 fs support.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/minix_fs.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-
-#define DIRECT_BLOCK ((inode->i_size + 1023) >> 10)
-#define INDIRECT_BLOCK(offset) (DIRECT_BLOCK-offset)
-#define V1_DINDIRECT_BLOCK(offset) ((DIRECT_BLOCK-offset)>>9)
-#define V2_DINDIRECT_BLOCK(offset) ((DIRECT_BLOCK-offset)>>8)
-#define TINDIRECT_BLOCK(offset) ((DIRECT_BLOCK-(offset))>>8)
-
-/*
- * Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**, especially as I don't do any locking.
- *
- * The code may look a bit weird, but that's just because I've tried to
- * handle things like file-size changes in a somewhat graceful manner.
- * Anyway, truncating a file at the same time somebody else writes to it
- * is likely to result in pretty weird behaviour...
- *
- * The new code handles normal truncates (size = 0) as well as the more
- * general case (size = XXX). I hope.
- */
-
-#define DATA_BUFFER_USED(bh) \
- (atomic_read(&bh->b_count) > 1 || buffer_locked(bh))
-
-/*
- * The functions for minix V1 fs truncation.
- */
-static int V1_trunc_direct(struct inode * inode)
-{
- unsigned short * p;
- struct buffer_head * bh;
- int i, tmp;
- int retry = 0;
-
-repeat:
- for (i = DIRECT_BLOCK ; i < 7 ; i++) {
- p = i + inode->u.minix_i.u.i1_data;
- if (!(tmp = *p))
- continue;
- bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < DIRECT_BLOCK) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != *p) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *p = 0;
- mark_inode_dirty(inode);
- bforget(bh);
- minix_free_block(inode,tmp);
- }
- return retry;
-}
-
-static int V1_trunc_indirect(struct inode * inode, int offset, unsigned short * p)
-{
- struct buffer_head * bh;
- int i, tmp;
- struct buffer_head * ind_bh;
- unsigned short * ind;
- int retry = 0;
-
- tmp = *p;
- if (!tmp)
- return 0;
- ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(ind_bh);
- return 1;
- }
- if (!ind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = INDIRECT_BLOCK(offset) ; i < 512 ; i++) {
- if (i < 0)
- i = 0;
- if (i < INDIRECT_BLOCK(offset))
- goto repeat;
- ind = i+(unsigned short *) ind_bh->b_data;
- tmp = *ind;
- if (!tmp)
- continue;
- bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < INDIRECT_BLOCK(offset)) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != *ind) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *ind = 0;
- mark_buffer_dirty(ind_bh);
- bforget(bh);
- minix_free_block(inode,tmp);
- }
- ind = (unsigned short *) ind_bh->b_data;
- for (i = 0; i < 512; i++)
- if (*(ind++))
- break;
- if (i >= 512) {
- if (atomic_read(&ind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- minix_free_block(inode,tmp);
- }
- }
- brelse(ind_bh);
- return retry;
-}
-
-static int V1_trunc_dindirect(struct inode * inode, int offset, unsigned short *p)
-{
- int i, tmp;
- struct buffer_head * dind_bh;
- unsigned short * dind;
- int retry = 0;
-
- if (!(tmp = *p))
- return 0;
- dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(dind_bh);
- return 1;
- }
- if (!dind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = V1_DINDIRECT_BLOCK(offset) ; i < 512 ; i ++) {
- if (i < 0)
- i = 0;
- if (i < V1_DINDIRECT_BLOCK(offset))
- goto repeat;
- dind = i+(unsigned short *) dind_bh->b_data;
- retry |= V1_trunc_indirect(inode,offset+(i<<9),dind);
- mark_buffer_dirty(dind_bh);
- }
- dind = (unsigned short *) dind_bh->b_data;
- for (i = 0; i < 512; i++)
- if (*(dind++))
- break;
- if (i >= 512) {
- if (atomic_read(&dind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- mark_inode_dirty(inode);
- minix_free_block(inode,tmp);
- }
- }
- brelse(dind_bh);
- return retry;
-}
-
-static void V1_minix_truncate(struct inode * inode)
-{
- int retry;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
- while (1) {
- retry = V1_trunc_direct(inode);
- retry |= V1_trunc_indirect(inode, 7, inode->u.minix_i.u.i1_data + 7);
- retry |= V1_trunc_dindirect(inode, 7+512, inode->u.minix_i.u.i1_data + 8);
- if (!retry)
- break;
- current->counter = 0;
- schedule();
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
-}
-
-/*
- * The functions for minix V2 fs truncation.
- */
-static int V2_trunc_direct(struct inode * inode)
-{
- unsigned long * p;
- struct buffer_head * bh;
- int i, tmp;
- int retry = 0;
-
-repeat:
- for (i = DIRECT_BLOCK ; i < 7 ; i++) {
- p = (unsigned long *) inode->u.minix_i.u.i2_data + i;
- if (!(tmp = *p))
- continue;
- bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < DIRECT_BLOCK) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != *p) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *p = 0;
- mark_inode_dirty(inode);
- bforget(bh);
- minix_free_block(inode,tmp);
- }
- return retry;
-}
-
-static int V2_trunc_indirect(struct inode * inode, int offset, unsigned long * p)
-{
- struct buffer_head * bh;
- int i, tmp;
- struct buffer_head * ind_bh;
- unsigned long * ind;
- int retry = 0;
-
- tmp = *p;
- if (!tmp)
- return 0;
- ind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(ind_bh);
- return 1;
- }
- if (!ind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = INDIRECT_BLOCK(offset) ; i < 256 ; i++) {
- if (i < 0)
- i = 0;
- if (i < INDIRECT_BLOCK(offset))
- goto repeat;
- ind = i+(unsigned long *) ind_bh->b_data;
- tmp = *ind;
- if (!tmp)
- continue;
- bh = get_hash_table(inode->i_dev,tmp,BLOCK_SIZE);
- if (i < INDIRECT_BLOCK(offset)) {
- brelse(bh);
- goto repeat;
- }
- if ((bh && DATA_BUFFER_USED(bh)) || tmp != *ind) {
- retry = 1;
- brelse(bh);
- continue;
- }
- *ind = 0;
- mark_buffer_dirty(ind_bh);
- bforget(bh);
- minix_free_block(inode,tmp);
- }
- ind = (unsigned long *) ind_bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(ind++))
- break;
- if (i >= 256) {
- if (atomic_read(&ind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- minix_free_block(inode,tmp);
- }
- }
- brelse(ind_bh);
- return retry;
-}
-
-static int V2_trunc_dindirect(struct inode * inode, int offset, unsigned long *p)
-{
- int i, tmp;
- struct buffer_head * dind_bh;
- unsigned long * dind;
- int retry = 0;
-
- if (!(tmp = *p))
- return 0;
- dind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(dind_bh);
- return 1;
- }
- if (!dind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = V2_DINDIRECT_BLOCK(offset) ; i < 256 ; i ++) {
- if (i < 0)
- i = 0;
- if (i < V2_DINDIRECT_BLOCK(offset))
- goto repeat;
- dind = i+(unsigned long *) dind_bh->b_data;
- retry |= V2_trunc_indirect(inode,offset+(i<<8),dind);
- mark_buffer_dirty(dind_bh);
- }
- dind = (unsigned long *) dind_bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(dind++))
- break;
- if (i >= 256) {
- if (atomic_read(&dind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- mark_inode_dirty(inode);
- minix_free_block(inode,tmp);
- }
- }
- brelse(dind_bh);
- return retry;
-}
-
-static int V2_trunc_tindirect(struct inode * inode, int offset, unsigned long * p)
-{
- int i, tmp;
- struct buffer_head * tind_bh;
- unsigned long * tind;
- int retry = 0;
-
- if (!(tmp = *p))
- return 0;
- tind_bh = bread(inode->i_dev, tmp, BLOCK_SIZE);
- if (tmp != *p) {
- brelse(tind_bh);
- return 1;
- }
- if (!tind_bh) {
- *p = 0;
- return 0;
- }
-repeat:
- for (i = TINDIRECT_BLOCK(offset) ; i < 256 ; i ++) {
- if (i < 0)
- i = 0;
- if (i < TINDIRECT_BLOCK(offset))
- goto repeat;
- tind = i+(unsigned long *) tind_bh->b_data;
- retry |= V2_trunc_dindirect(inode,offset+(i<<8),tind);
- mark_buffer_dirty(tind_bh);
- }
- tind = (unsigned long *) tind_bh->b_data;
- for (i = 0; i < 256; i++)
- if (*(tind++))
- break;
- if (i >= 256) {
- if (atomic_read(&tind_bh->b_count) != 1)
- retry = 1;
- else {
- tmp = *p;
- *p = 0;
- mark_inode_dirty(inode);
- minix_free_block(inode,tmp);
- }
- }
- brelse(tind_bh);
- return retry;
-}
-
-static void V2_minix_truncate(struct inode * inode)
-{
- int retry;
-
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
- while (1) {
- retry = V2_trunc_direct(inode);
- retry |= V2_trunc_indirect(inode,7,
- (unsigned long *) inode->u.minix_i.u.i2_data + 7);
- retry |= V2_trunc_dindirect(inode, 7+256,
- (unsigned long *) inode->u.minix_i.u.i2_data + 8);
- retry |= V2_trunc_tindirect(inode, 7+256+256*256,
- (unsigned long *) inode->u.minix_i.u.i2_data + 9);
- if (!retry)
- break;
- run_task_queue(&tq_disk);
- current->policy |= SCHED_YIELD;
- schedule();
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
-}
-
-/*
- * The function that is called for file truncation.
- */
-void minix_truncate(struct inode * inode)
-{
- if (INODE_VERSION(inode) == MINIX_V1)
- V1_minix_truncate(inode);
- else
- V2_minix_truncate(inode);
-}
unsigned int count;
};
-static struct nfs_unlinkdata *nfs_deletes = NULL;
+static struct nfs_unlinkdata *nfs_deletes;
static struct rpc_wait_queue nfs_delete_queue = RPC_INIT_WAITQ("nfs_delete_queue");
/**
struct svc_client * h_client;
};
static struct svc_clnthash * clnt_hash[CLIENT_HASHMAX];
-static svc_client * clients = NULL;
-static int initialized = 0;
+static svc_client * clients;
+static int initialized;
-static int hash_lock = 0;
-static int want_lock = 0;
-static int hash_count = 0;
+static int hash_lock;
+static int want_lock;
+static int hash_count;
static DECLARE_WAIT_QUEUE_HEAD( hash_wait );
#include <linux/errno.h>
#include <linux/locks.h>
#include <linux/fs.h>
+#include <linux/ext2_fs.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/net.h>
static int nfsctl_ugidupdate(struct nfsctl_ugidmap *data);
#endif
-static int initialized = 0;
+static int initialized;
int exp_procfs_exports(char *buffer, char **start, off_t offset,
int length, int *eof, void *data);
|| !S_ISDIR(dentry->d_inode->i_mode)) {
goto err_dentry;
}
- if ((!dentry->d_flags & DCACHE_NFSD_DISCONNECTED))
+ if (!(dentry->d_flags & DCACHE_NFSD_DISCONNECTED))
found = 1;
tmp = splice(result, dentry);
err = PTR_ERR(tmp);
extern struct svc_program nfsd_program;
static void nfsd(struct svc_rqst *rqstp);
-struct timeval nfssvc_boot = { 0, 0 };
-static struct svc_serv *nfsd_serv = NULL;
-static int nfsd_busy = 0;
+struct timeval nfssvc_boot;
+static struct svc_serv *nfsd_serv;
+static int nfsd_busy;
static unsigned long nfsd_last_call;
struct nfsd_list {
#include <asm/uaccess.h>
+#define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
+
int vfs_statfs(struct super_block *sb, struct statfs *buf)
{
int retval = -ENODEV;
if (!res) {
res = permission(nd.dentry->d_inode, mode);
/* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode))
+ if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
+ && !special_file(nd.dentry->d_inode->i_mode))
res = -EROFS;
path_release(&nd);
}
#ifdef CONFIG_DEVFS_FS
printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
#else
- if (hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7)
+ if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
+ (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
else
printk(" %s", disk_name(hd, minor, buf));
- if (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7)
- printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
- else
- printk(" %s", disk_name(hd, minor, buf));
#endif
}
return 0;
}
-static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
+static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8];
static int make_inode_number(void)
{
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->fsuid;
- if (test_opt (sb, GRPID))
- inode->i_gid = dir->i_gid;
- else if (dir->i_mode & S_ISGID)
- {
+ if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
mode |= S_ISGID;
#define F_EXLCK 16 /* or 3 */
#define F_SHLCK 32 /* or 4 */
+#define F_INPROGRESS 16
+
/* operations for bsd flock(), also used by the kernel implementation */
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_NB 4 /* or'd with one of the above to prevent
blocking */
#define LOCK_UN 8 /* remove lock */
-
+#define LOCK_MAND 32 /* This is a mandatory flock */
+#define LOCK_READ 64 /* ... Which allows concurrent read operations */
+#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
+#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
+
struct flock {
short l_type;
short l_whence;
#ifdef __KERNEL__
#define flock64 flock
#endif
+#define F_LINUX_SPECIFIC_BASE 1024
#endif
#define RLIMIT_AS 7 /* address space limit(?) */
#define RLIMIT_NPROC 8 /* max number of processes */
#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
+#define RLIMIT_LOCKS 10 /* maximum file locks held */
-#define RLIM_NLIMITS 10
+#define RLIM_NLIMITS 11
/*
* SuS says limits have to be unsigned. Fine, it's unsigned, but
{LONG_MAX, LONG_MAX}, /* RLIMIT_AS */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_NPROC */ \
{LONG_MAX, LONG_MAX}, /* RLIMIT_MEMLOCK */ \
+ {LONG_MAX, LONG_MAX}, /* RLIMIT_LOCKS */ \
}
#endif /* __KERNEL__ */
#include <linux/config.h>
-#ifdef CONFIG_SMP
typedef struct { volatile int counter; } atomic_t;
-#else
-typedef struct { int counter; } atomic_t;
-#endif
#define ATOMIC_INIT(i) { (i) }
extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
-extern __inline__ int atomic_add_return(int a, volatile atomic_t *v)
+static __inline__ int atomic_add_return(int a, atomic_t *v)
{
int t;
add %0,%2,%0\n\
stwcx. %0,0,%3\n\
bne- 1b"
- : "=&r" (t), "=m" (*v)
- : "r" (a), "r" (v), "m" (*v)
+ : "=&r" (t), "=m" (v->counter)
+ : "r" (a), "r" (v), "m" (v->counter)
: "cc");
return t;
}
-extern __inline__ int atomic_sub_return(int a, volatile atomic_t *v)
+static __inline__ int atomic_sub_return(int a, atomic_t *v)
{
int t;
subf %0,%2,%0\n\
stwcx. %0,0,%3\n\
bne- 1b"
- : "=&r" (t), "=m" (*v)
- : "r" (a), "r" (v), "m" (*v)
+ : "=&r" (t), "=m" (v->counter)
+ : "r" (a), "r" (v), "m" (v->counter)
: "cc");
return t;
}
-extern __inline__ int atomic_inc_return(volatile atomic_t *v)
+static __inline__ int atomic_inc_return(atomic_t *v)
{
int t;
addic %0,%0,1\n\
stwcx. %0,0,%2\n\
bne- 1b"
- : "=&r" (t), "=m" (*v)
- : "r" (v), "m" (*v)
+ : "=&r" (t), "=m" (v->counter)
+ : "r" (v), "m" (v->counter)
: "cc");
return t;
}
-extern __inline__ int atomic_dec_return(volatile atomic_t *v)
+static __inline__ int atomic_dec_return(atomic_t *v)
{
int t;
addic %0,%0,-1\n\
stwcx. %0,0,%2\n\
bne 1b"
- : "=&r" (t), "=m" (*v)
- : "r" (v), "m" (*v)
+ : "=&r" (t), "=m" (v->counter)
+ : "r" (v), "m" (v->counter)
: "cc");
return t;
#include <linux/config.h>
#include <asm/byteorder.h>
-extern void set_bit(int nr, volatile void *addr);
-extern void clear_bit(int nr, volatile void *addr);
-extern void change_bit(int nr, volatile void *addr);
-extern int test_and_set_bit(int nr, volatile void *addr);
-extern int test_and_clear_bit(int nr, volatile void *addr);
-extern int test_and_change_bit(int nr, volatile void *addr);
-
/*
- * Arguably these bit operations don't imply any memory barrier or
- * SMP ordering, but in fact a lot of drivers expect them to imply
- * both, since they do on x86 cpus.
+ * The test_and_*_bit operations are taken to imply a memory barrier
+ * on SMP systems.
*/
#ifdef CONFIG_SMP
#define SMP_WMB "eieio\n"
* These used to be if'd out here because using : "cc" as a constraint
* resulted in errors from egcs. Things may be OK with gcc-2.95.
*/
-extern __inline__ void set_bit(int nr, volatile void * addr)
+static __inline__ void set_bit(int nr, volatile void * addr)
{
unsigned long old;
unsigned long mask = 1 << (nr & 0x1f);
unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
- __asm__ __volatile__(SMP_WMB "\
+ __asm__ __volatile__("\
1: lwarx %0,0,%3
or %0,%0,%2
stwcx. %0,0,%3
- bne 1b"
- SMP_MB
+ bne- 1b"
: "=&r" (old), "=m" (*p)
: "r" (mask), "r" (p), "m" (*p)
: "cc" );
}
-extern __inline__ void clear_bit(int nr, volatile void *addr)
+/*
+ * non-atomic version
+ */
+static __inline__ void __set_bit(int nr, volatile void *addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ *p |= mask;
+}
+
+/*
+ * clear_bit doesn't imply a memory barrier
+ */
+#define smp_mb__before_clear_bit() smp_mb()
+#define smp_mb__after_clear_bit() smp_mb()
+
+static __inline__ void clear_bit(int nr, volatile void *addr)
{
unsigned long old;
unsigned long mask = 1 << (nr & 0x1f);
unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
- __asm__ __volatile__(SMP_WMB "\
+ __asm__ __volatile__("\
1: lwarx %0,0,%3
andc %0,%0,%2
stwcx. %0,0,%3
- bne 1b"
- SMP_MB
+ bne- 1b"
: "=&r" (old), "=m" (*p)
: "r" (mask), "r" (p), "m" (*p)
: "cc");
}
-extern __inline__ void change_bit(int nr, volatile void *addr)
+static __inline__ void change_bit(int nr, volatile void *addr)
{
unsigned long old;
unsigned long mask = 1 << (nr & 0x1f);
unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
- __asm__ __volatile__(SMP_WMB "\
+ __asm__ __volatile__("\
1: lwarx %0,0,%3
xor %0,%0,%2
stwcx. %0,0,%3
- bne 1b"
- SMP_MB
+ bne- 1b"
: "=&r" (old), "=m" (*p)
: "r" (mask), "r" (p), "m" (*p)
: "cc");
}
-extern __inline__ int test_and_set_bit(int nr, volatile void *addr)
+/*
+ * test_and_*_bit do imply a memory barrier (?)
+ */
+static __inline__ int test_and_set_bit(int nr, volatile void *addr)
{
unsigned int old, t;
unsigned int mask = 1 << (nr & 0x1f);
SMP_MB
: "=&r" (old), "=&r" (t), "=m" (*p)
: "r" (mask), "r" (p), "m" (*p)
- : "cc");
+ : "cc", "memory");
return (old & mask) != 0;
}
-extern __inline__ int test_and_clear_bit(int nr, volatile void *addr)
+/*
+ * non-atomic version
+ */
+static __inline__ int __test_and_set_bit(int nr, volatile void *addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long old = *p;
+
+ *p = old | mask;
+ return (old & mask) != 0;
+}
+
+static __inline__ int test_and_clear_bit(int nr, volatile void *addr)
{
unsigned int old, t;
unsigned int mask = 1 << (nr & 0x1f);
SMP_MB
: "=&r" (old), "=&r" (t), "=m" (*p)
: "r" (mask), "r" (p), "m" (*p)
- : "cc");
+ : "cc", "memory");
return (old & mask) != 0;
}
-extern __inline__ int test_and_change_bit(int nr, volatile void *addr)
+/*
+ * non-atomic version
+ */
+static __inline__ int __test_and_clear_bit(int nr, volatile void *addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long old = *p;
+
+ *p = old & ~mask;
+ return (old & mask) != 0;
+}
+
+static __inline__ int test_and_change_bit(int nr, volatile void *addr)
{
unsigned int old, t;
unsigned int mask = 1 << (nr & 0x1f);
SMP_MB
: "=&r" (old), "=&r" (t), "=m" (*p)
: "r" (mask), "r" (p), "m" (*p)
- : "cc");
+ : "cc", "memory");
return (old & mask) != 0;
}
+#else /* __INLINE_BITOPS */
+
+extern void set_bit(int nr, volatile void *addr);
+extern void clear_bit(int nr, volatile void *addr);
+extern void change_bit(int nr, volatile void *addr);
+extern int test_and_set_bit(int nr, volatile void *addr);
+extern int test_and_clear_bit(int nr, volatile void *addr);
+extern int test_and_change_bit(int nr, volatile void *addr);
+
#endif /* __INLINE_BITOPS */
-extern __inline__ int test_bit(int nr, __const__ volatile void *addr)
+static __inline__ int test_bit(int nr, __const__ volatile void *addr)
{
__const__ unsigned int *p = (__const__ unsigned int *) addr;
}
/* Return the bit position of the most significant 1 bit in a word */
-extern __inline__ int __ilog2(unsigned int x)
+static __inline__ int __ilog2(unsigned int x)
{
int lz;
return 31 - lz;
}
-extern __inline__ int ffz(unsigned int x)
+static __inline__ int ffz(unsigned int x)
{
if ((x = ~x) == 0)
return 32;
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
-extern __inline__ int ffs(int x)
+static __inline__ int ffs(int x)
{
return __ilog2(x & -x) + 1;
}
#define find_first_zero_bit(addr, size) \
find_next_zero_bit((addr), (size), 0)
-extern __inline__ unsigned long find_next_zero_bit(void * addr,
+static __inline__ unsigned long find_next_zero_bit(void * addr,
unsigned long size, unsigned long offset)
{
unsigned int * p = ((unsigned int *) addr) + (offset >> 5);
#define _EXT2_HAVE_ASM_BITOPS_
#ifdef __KERNEL__
-/*
- * test_and_{set,clear}_bit guarantee atomicity without
- * disabling interrupts.
- */
-#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr)
-#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr)
-#else
-extern __inline__ int ext2_set_bit(int nr, void * addr)
-{
- int mask;
- unsigned char *ADDR = (unsigned char *) addr;
- int oldbit;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- oldbit = (*ADDR & mask) ? 1 : 0;
- *ADDR |= mask;
- return oldbit;
-}
-
-extern __inline__ int ext2_clear_bit(int nr, void * addr)
-{
- int mask;
- unsigned char *ADDR = (unsigned char *) addr;
- int oldbit;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- oldbit = (*ADDR & mask) ? 1 : 0;
- *ADDR = *ADDR & ~mask;
- return oldbit;
-}
-#endif /* __KERNEL__ */
+#define ext2_set_bit(nr, addr) __test_and_set_bit((nr) ^ 0x18, addr)
+#define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 0x18, addr)
-extern __inline__ int ext2_test_bit(int nr, __const__ void * addr)
+static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
{
__const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
#define ext2_find_first_zero_bit(addr, size) \
ext2_find_next_zero_bit((addr), (size), 0)
-extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
+static __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
unsigned long size, unsigned long offset)
{
unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
+#endif /* __KERNEL__ */
+
#endif /* _PPC_BITOPS_H */
#define set_mb(var, value) do { var = value; mb(); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+#ifdef CONFIG_SMP
+#define smp_mb() mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+#else
+#define smp_mb() __asm__ __volatile__("": : :"memory")
+#define smp_rmb() __asm__ __volatile__("": : :"memory")
+#define smp_wmb() __asm__ __volatile__("": : :"memory")
+#endif /* CONFIG_SMP */
+
extern void xmon_irq(int, void *, struct pt_regs *);
extern void xmon(struct pt_regs *excp);
extern void cvt_df(double *from, float *to, unsigned long *fpscr);
extern int call_rtas(const char *, int, int, unsigned long *, ...);
extern int abs(int);
+extern void cacheable_memzero(void *p, unsigned int nb);
struct device_node;
extern void note_scsi_host(struct device_node *, void *);
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-extern unsigned long xchg_u64(void *ptr, unsigned long val);
-extern unsigned long xchg_u32(void *ptr, unsigned long val);
+static __inline__ unsigned long
+xchg_u32(volatile void *p, unsigned long val)
+{
+ unsigned long prev;
+
+ __asm__ __volatile__ ("
+1: lwarx %0,0,%2
+ stwcx. %3,0,%2
+ bne- 1b"
+ : "=&r" (prev), "=m" (*(volatile unsigned long *)p)
+ : "r" (p), "r" (val), "m" (*(volatile unsigned long *)p)
+ : "cc", "memory");
+
+ return prev;
+}
/*
* This function doesn't exist, so you'll get a linker error
* if something tries to do an invalid xchg().
- *
- * This only works if the compiler isn't horribly bad at optimizing.
- * gcc-2.5.8 reportedly can't handle this, but as that doesn't work
- * too well on the alpha anyway..
*/
extern void __xchg_called_with_bad_pointer(void);
switch (size) {
case 4:
return (unsigned long )xchg_u32(ptr, x);
+#if 0 /* xchg_u64 doesn't exist on 32-bit PPC */
case 8:
return (unsigned long )xchg_u64(ptr, x);
+#endif /* 0 */
}
__xchg_called_with_bad_pointer();
return x;
return (void *) xchg_u32(m, (unsigned long) val);
}
-#endif
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static __inline__ unsigned long
+__cmpxchg_u32(volatile int *p, int old, int new)
+{
+ int prev;
+
+ __asm__ __volatile__ ("
+1: lwarx %0,0,%2
+ cmpw 0,%0,%3
+ bne 2f
+ stwcx. %4,0,%2
+ bne- 1b\n"
+#ifdef CONFIG_SMP
+" sync\n"
+#endif /* CONFIG_SMP */
+"2:"
+ : "=&r" (prev), "=m" (*p)
+ : "r" (p), "r" (old), "r" (new), "m" (*p)
+ : "cc", "memory");
+
+ return prev;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+ if something tries to do an invalid cmpxchg(). */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+ switch (size) {
+ case 4:
+ return __cmpxchg_u32(ptr, old, new);
+#if 0 /* we don't have __cmpxchg_u64 on 32-bit PPC */
+ case 8:
+ return __cmpxchg_u64(ptr, old, new);
+#endif /* 0 */
+ }
+ __cmpxchg_called_with_bad_pointer();
+ return old;
+}
+
+#define cmpxchg(ptr,o,n) \
+ ({ \
+ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, sizeof(*(ptr))); \
+ })
+
+#endif /* __PPC_SYSTEM_H */
char *name;
int id;
int dev_mixer;
+ int type;
/* codec specific init/reset routines, used mainly for 4 or 6 channel support */
int (*codec_init) (struct ac97_codec *codec);
int supported_mixers;
int stereo_mixers;
int record_sources;
-
+
+ int bit_resolution;
+
/* OSS mixer interface */
int (*read_mixer) (struct ac97_codec *codec, int oss_channel);
void (*write_mixer)(struct ac97_codec *codec, int oss_channel,
#define shrink_dcache() prune_dcache(0)
struct zone_struct;
/* dcache memory management */
-extern int shrink_dcache_memory(int, unsigned int);
+extern void shrink_dcache_memory(int, unsigned int);
extern void prune_dcache(int);
/* icache memory management (defined in linux/fs/inode.c) */
-extern int shrink_icache_memory(int, int);
+extern void shrink_icache_memory(int, int);
extern void prune_icache(int);
/* only used at mount-time */
#define EM_IA_64 50 /* HP/Intel IA-64 */
+#define EM_X8664 62 /* AMD x86-64 */
+
/*
* This is an interim value that we will use until the committee comes
* up with a final number.
#ifndef _LINUX_EXT2_FS_SB
#define _LINUX_EXT2_FS_SB
-#include <linux/ext2_fs.h>
-
/*
* The following is not needed anymore since the descriptors buffer
* heads are now dynamically allocated
extern struct buffer_head * minix_getblk(struct inode *, int, int);
extern struct buffer_head * minix_bread(struct inode *, int, int);
+extern void V1_minix_truncate(struct inode *);
+extern void V2_minix_truncate(struct inode *);
extern void minix_truncate(struct inode *);
extern int minix_sync_inode(struct inode *);
-extern int minix_sync_file(struct file *, struct dentry *, int);
+extern int V1_minix_sync_file(struct inode *);
+extern int V2_minix_sync_file(struct inode *);
+extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int);
+extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int);
extern struct address_space_operations minix_aops;
extern struct inode_operations minix_file_inode_operations;
#define VM_RAND_READ 0x00010000 /* App will not benefit from clustered reads */
#define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */
+#define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */
#define VM_STACK_FLAGS 0x00000177
#define PCI_DEVICE_ID_LAVA_QUAD_B 0x0202 /* 2x 16650, half of 4 port */
#define PCI_DEVICE_ID_LAVA_SSERIAL 0x0500 /* 1x 16550 */
#define PCI_DEVICE_ID_LAVA_PORT_650 0x0600 /* 1x 16650 */
-
-#define PCI_VENDOR_ID_SYBA 0x1592
-#define PCI_DEVICE_ID_SYBA_2P_EPP 0x0782
-#define PCI_DEVICE_ID_SYBA_1P_ECP 0x0783
-
#define PCI_DEVICE_ID_LAVA_PARALLEL 0x8000
#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A 0x8002 /* The Lava Dual Parallel is */
#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B 0x8003 /* two PCI devices on a card */
#define PCI_VENDOR_ID_AFAVLAB 0x14db
#define PCI_DEVICE_ID_AFAVLAB_TK9902 0x2120
+#define PCI_VENDOR_ID_SYBA 0x1592
+#define PCI_DEVICE_ID_SYBA_2P_EPP 0x0782
+#define PCI_DEVICE_ID_SYBA_1P_ECP 0x0783
+
#define PCI_VENDOR_ID_MORETON 0x15aa
#define PCI_DEVICE_ID_RASTEL_2PORT 0x2000
extern int md_notify_reboot(struct notifier_block *this,
unsigned long code, void *x);
extern int md_error (kdev_t mddev, kdev_t rdev);
-extern void md_run_setup(void);
+extern int md_run_setup(void);
extern void md_print_devices (void);
extern kmem_cache_t *fs_cachep;
extern kmem_cache_t *sigact_cachep;
-#ifdef CONFIG_SMP
-extern unsigned long slab_cache_drain_mask;
-extern void slab_drain_local_cache(void);
-#else
-#define slab_cache_drain_mask 0
-#define slab_drain_local_cache() do { } while (0)
-#endif
-
#endif /* __KERNEL__ */
#endif /* _LINUX_SLAB_H */
/* Endpoint descriptor */
struct usb_endpoint_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bEndpointAddress;
- __u8 bmAttributes;
- __u16 wMaxPacketSize;
- __u8 bInterval;
- __u8 bRefresh;
- __u8 bSynchAddress;
+ __u8 bLength __attribute__ ((packed));
+ __u8 bDescriptorType __attribute__ ((packed));
+ __u8 bEndpointAddress __attribute__ ((packed));
+ __u8 bmAttributes __attribute__ ((packed));
+ __u16 wMaxPacketSize __attribute__ ((packed));
+ __u8 bInterval __attribute__ ((packed));
+ __u8 bRefresh __attribute__ ((packed));
+ __u8 bSynchAddress __attribute__ ((packed));
unsigned char *extra; /* Extra descriptors */
int extralen;
-} __attribute__ ((packed));
+};
/* Interface descriptor */
struct usb_interface_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u8 bInterfaceNumber;
- __u8 bAlternateSetting;
- __u8 bNumEndpoints;
- __u8 bInterfaceClass;
- __u8 bInterfaceSubClass;
- __u8 bInterfaceProtocol;
- __u8 iInterface;
+ __u8 bLength __attribute__ ((packed));
+ __u8 bDescriptorType __attribute__ ((packed));
+ __u8 bInterfaceNumber __attribute__ ((packed));
+ __u8 bAlternateSetting __attribute__ ((packed));
+ __u8 bNumEndpoints __attribute__ ((packed));
+ __u8 bInterfaceClass __attribute__ ((packed));
+ __u8 bInterfaceSubClass __attribute__ ((packed));
+ __u8 bInterfaceProtocol __attribute__ ((packed));
+ __u8 iInterface __attribute__ ((packed));
struct usb_endpoint_descriptor *endpoint;
unsigned char *extra; /* Extra descriptors */
int extralen;
-} __attribute__ ((packed));
+};
struct usb_interface {
struct usb_interface_descriptor *altsetting;
/* Configuration descriptor information.. */
struct usb_config_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u16 wTotalLength;
- __u8 bNumInterfaces;
- __u8 bConfigurationValue;
- __u8 iConfiguration;
- __u8 bmAttributes;
- __u8 MaxPower;
+ __u8 bLength __attribute__ ((packed));
+ __u8 bDescriptorType __attribute__ ((packed));
+ __u16 wTotalLength __attribute__ ((packed));
+ __u8 bNumInterfaces __attribute__ ((packed));
+ __u8 bConfigurationValue __attribute__ ((packed));
+ __u8 iConfiguration __attribute__ ((packed));
+ __u8 bmAttributes __attribute__ ((packed));
+ __u8 MaxPower __attribute__ ((packed));
struct usb_interface *interface;
unsigned char *extra; /* Extra descriptors */
int extralen;
-} __attribute__ ((packed));
+};
/* String descriptor */
struct usb_string_descriptor {
/* Not "fast" counterpart! On architectures without
cpu clock "fast" routine is absolutely useless in this
situation. do_gettimeofday still says something on slow-slow-slow
- boxes, though it eats more cpu time than the sobject of
+ boxes, though it eats more cpu time than the subject of
investigation :-) :-)
*/
do_gettimeofday(pstamp);
static inline int prev_goodness(struct task_struct * p, int this_cpu, struct mm_struct *this_mm)
{
if (p->policy & SCHED_YIELD) {
- p->policy &= ~SCHED_YIELD;
- return 0;
+ /*
+ * select the current process after every other
+ * runnable process, but before the idle thread.
+ * Also, dont trigger a counter recalculation.
+ */
+ return -1;
}
return goodness(p, this_cpu, this_mm);
}
static inline void __schedule_tail(struct task_struct *prev)
{
#ifdef CONFIG_SMP
+ int yield;
unsigned long flags;
/*
* cache.
*/
spin_lock_irqsave(&runqueue_lock, flags);
+ yield = prev->policy & SCHED_YIELD;
+ prev->policy &= ~SCHED_YIELD;
prev->has_cpu = 0;
if (prev->state == TASK_RUNNING)
goto running_again;
* current process as well.)
*/
running_again:
- if (prev != idle_task(smp_processor_id()))
+ if ((prev != idle_task(smp_processor_id())) && !yield)
reschedule_idle(prev);
goto out_unlock;
+#else
+ prev->policy &= ~SCHED_YIELD;
#endif /* CONFIG_SMP */
}
asmlinkage long sys_sched_yield(void)
{
- spin_lock_irq(&runqueue_lock);
+ /*
+ * This process can only be rescheduled by us,
+ * so this is safe without any locking.
+ */
if (current->policy == SCHED_OTHER)
current->policy |= SCHED_YIELD;
current->need_resched = 1;
- move_last_runqueue(current);
- spin_unlock_irq(&runqueue_lock);
return 0;
}
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
-#include <linux/slab.h>
#include <asm/uaccess.h>
kstat.per_cpu_system[cpu] += system;
} else if (local_bh_count(cpu) || local_irq_count(cpu) > 1)
kstat.per_cpu_system[cpu] += system;
-
- if (slab_cache_drain_mask & (1UL << cpu))
- slab_drain_local_cache();
}
/*
/* We can't remap across vm area boundaries */
if (old_len > vma->vm_end - addr)
goto out;
+ if (vma->vm_flags & VM_DONTEXPAND) {
+ if (new_len > old_len)
+ goto out;
+ }
if (vma->vm_flags & VM_LOCKED) {
unsigned long locked = current->mm->locked_vm << PAGE_SHIFT;
locked += new_len - old_len;
kmem_cache_free(cachep->slabp_cache, slabp);
}
-
/**
* kmem_cache_create - Create a cache.
* @name: A string which is used in /proc/slabinfo to identify this cache.
}
#ifdef CONFIG_SMP
-static DECLARE_MUTEX(cache_drain_sem);
-static kmem_cache_t *cache_to_drain = NULL;
-static DECLARE_WAIT_QUEUE_HEAD(cache_drain_wait);
-unsigned long slab_cache_drain_mask;
-
/*
- * Waits for all CPUs to execute slab_drain_local_cache().
- * Caller must be holding cache_drain_sem.
+ * Waits for all CPUs to execute func().
*/
-static void slab_drain_all_sync(void)
+static void smp_call_function_all_cpus(void (*func) (void *arg), void *arg)
{
- DECLARE_WAITQUEUE(wait, current);
-
local_irq_disable();
- slab_drain_local_cache();
+ func(arg);
local_irq_enable();
- add_wait_queue(&cache_drain_wait, &wait);
- current->state = TASK_UNINTERRUPTIBLE;
- while (slab_cache_drain_mask != 0UL)
- schedule();
- current->state = TASK_RUNNING;
- remove_wait_queue(&cache_drain_wait, &wait);
+ if (smp_call_function(func, arg, 1, 1))
+ BUG();
+}
+typedef struct ccupdate_struct_s
+{
+ kmem_cache_t *cachep;
+ cpucache_t *new[NR_CPUS];
+} ccupdate_struct_t;
+
+static void do_ccupdate_local(void *info)
+{
+ ccupdate_struct_t *new = (ccupdate_struct_t *)info;
+ cpucache_t *old = cc_data(new->cachep);
+
+ cc_data(new->cachep) = new->new[smp_processor_id()];
+ new->new[smp_processor_id()] = old;
}
+static void free_block (kmem_cache_t* cachep, void** objpp, int len);
+
static void drain_cpu_caches(kmem_cache_t *cachep)
{
- unsigned long cpu_mask = 0;
+ ccupdate_struct_t new;
int i;
- for (i = 0; i < smp_num_cpus; i++)
- cpu_mask |= (1UL << cpu_logical_map(i));
+ memset(&new.new,0,sizeof(new.new));
- down(&cache_drain_sem);
+ new.cachep = cachep;
- cache_to_drain = cachep;
- slab_cache_drain_mask = cpu_mask;
- slab_drain_all_sync();
- cache_to_drain = NULL;
+ down(&cache_chain_sem);
+ smp_call_function_all_cpus(do_ccupdate_local, (void *)&new);
- up(&cache_drain_sem);
+ for (i = 0; i < smp_num_cpus; i++) {
+ cpucache_t* ccold = new.new[cpu_logical_map(i)];
+ if (!ccold || (ccold->avail == 0))
+ continue;
+ local_irq_disable();
+ free_block(cachep, cc_entry(ccold), ccold->avail);
+ local_irq_enable();
+ ccold->avail = 0;
+ }
+ smp_call_function_all_cpus(do_ccupdate_local, (void *)&new);
+ up(&cache_chain_sem);
}
+
#else
#define drain_cpu_caches(cachep) do { } while (0)
#endif
#ifdef CONFIG_SMP
-typedef struct ccupdate_struct_s
-{
- kmem_cache_t *cachep;
- cpucache_t *new[NR_CPUS];
-} ccupdate_struct_t;
-
-static ccupdate_struct_t *ccupdate_state = NULL;
-
-/* Called from per-cpu timer interrupt. */
-void slab_drain_local_cache(void)
-{
- if (ccupdate_state != NULL) {
- ccupdate_struct_t *new = ccupdate_state;
- cpucache_t *old = cc_data(new->cachep);
-
- cc_data(new->cachep) = new->new[smp_processor_id()];
- new->new[smp_processor_id()] = old;
- } else {
- kmem_cache_t *cachep = cache_to_drain;
- cpucache_t *cc = cc_data(cachep);
-
- if (cc && cc->avail) {
- free_block(cachep, cc_entry(cc), cc->avail);
- cc->avail = 0;
- }
- }
-
- clear_bit(smp_processor_id(), &slab_cache_drain_mask);
- if (slab_cache_drain_mask == 0)
- wake_up(&cache_drain_wait);
-}
-
-static void do_ccupdate(ccupdate_struct_t *data)
-{
- unsigned long cpu_mask = 0;
- int i;
-
- for (i = 0; i < smp_num_cpus; i++)
- cpu_mask |= (1UL << cpu_logical_map(i));
-
- down(&cache_drain_sem);
-
- ccupdate_state = data;
- slab_cache_drain_mask = cpu_mask;
- slab_drain_all_sync();
- ccupdate_state = NULL;
-
- up(&cache_drain_sem);
-}
-
/* called with cache_chain_sem acquired. */
static int kmem_tune_cpucache (kmem_cache_t* cachep, int limit, int batchcount)
{
for (i = 0; i< smp_num_cpus; i++) {
cpucache_t* ccnew;
-
ccnew = kmalloc(sizeof(void*)*limit+
sizeof(cpucache_t), GFP_KERNEL);
if (!ccnew)
cachep->batchcount = batchcount;
spin_unlock_irq(&cachep->spinlock);
- do_ccupdate(&new);
+ smp_call_function_all_cpus(do_ccupdate_local, (void *)&new);
for (i = 0; i < smp_num_cpus; i++) {
cpucache_t* ccold = new.new[cpu_logical_map(i)];
#include <asm/pgalloc.h>
rwlock_t vmlist_lock = RW_LOCK_UNLOCKED;
-struct vm_struct * vmlist = NULL;
+struct vm_struct * vmlist;
static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned long size)
{
set_pte(page_table, swp_entry_to_pte(entry));
drop_pte:
UnlockPage(page);
- vma->vm_mm->rss--;
+ mm->rss--;
flush_tlb_page(vma, address);
deactivate_page(page);
page_cache_release(page);
struct file *file = vma->vm_file;
if (file) get_file(file);
pte_clear(page_table);
- vma->vm_mm->rss--;
+ mm->rss--;
flush_tlb_page(vma, address);
- vmlist_access_unlock(vma->vm_mm);
+ vmlist_access_unlock(mm);
error = swapout(page, file);
UnlockPage(page);
if (file) fput(file);
add_to_swap_cache(page, entry);
/* Put the swap entry into the pte after the page is in swapcache */
- vma->vm_mm->rss--;
+ mm->rss--;
set_pte(page_table, swp_entry_to_pte(entry));
flush_tlb_page(vma, address);
- vmlist_access_unlock(vma->vm_mm);
+ vmlist_access_unlock(mm);
/* OK, do a physical asynchronous write to swap. */
rw_swap_page(WRITE, page, 0);
do {
int result;
- vma->vm_mm->swap_address = address + PAGE_SIZE;
+ mm->swap_address = address + PAGE_SIZE;
result = try_to_swap_out(mm, vma, address, pte, gfp_mask);
if (result)
return result;
if (vma->vm_flags & VM_LOCKED)
return 0;
- pgdir = pgd_offset(vma->vm_mm, address);
+ pgdir = pgd_offset(mm, address);
end = vma->vm_end;
if (address >= end)
* refill_inactive() almost never fail when there's
* really plenty of memory free.
*/
- count -= shrink_dcache_memory(priority, gfp_mask);
- count -= shrink_icache_memory(priority, gfp_mask);
- /*
- * Not currently working, see fixme in shrink_?cache_memory
- * In the inner funtions there is a comment:
- * "To help debugging, a zero exit status indicates
- * all slabs were released." (-arca?)
- * lets handle it in a primitive but working way...
- * if (count <= 0)
- * goto done;
- */
+ shrink_dcache_memory(priority, gfp_mask);
+ shrink_icache_memory(priority, gfp_mask);
/* Try to get rid of some shared memory pages.. */
while (shm_swap(priority, gfp_mask)) {
* the inode and dentry cache whenever we do this.
*/
if (free_shortage() || inactive_shortage()) {
- ret += shrink_dcache_memory(6, gfp_mask);
- ret += shrink_icache_memory(6, gfp_mask);
+ shrink_dcache_memory(6, gfp_mask);
+ shrink_icache_memory(6, gfp_mask);
ret += refill_inactive(gfp_mask, user);
} else {
/*
#
# Makefile for the linux networking.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
+# 2 Sep 2000, Christoph Hellwig <hch@caldera.de>
+# Rewritten to use lists instead of if-statements.
#
-# Note 2! The CFLAGS definition is now in the main makefile...
-MOD_SUB_DIRS := ipv4
-ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \
- netrom rose lapb x25 wanrouter netlink sched packet sunrpc \
- econet irda decnet atm khttpd ipv4/netfilter ipv6/netfilter
-SUB_DIRS := core ethernet
+O_TARGET := network.o
-ifeq ($(CONFIG_NET),y)
-SUB_DIRS += 802 sched
-endif
-
-ifeq ($(CONFIG_INET),y)
-SUB_DIRS += ipv4
-ifeq ($(CONFIG_NETFILTER),y)
-SUB_DIRS += ipv4/netfilter
-MOD_SUB_DIRS += ipv4/netfilter
-endif
-endif
+mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda atm
+export-objs := netsyms.o
-ifeq ($(CONFIG_UNIX),y)
-SUB_DIRS += unix
-else
- ifeq ($(CONFIG_UNIX),m)
- MOD_SUB_DIRS += unix
- endif
-endif
+subdir-y := core ethernet
+subdir-m := ipv4 # hum?
-ifeq ($(CONFIG_IPV6),y)
-SUB_DIRS += ipv6
-ifeq ($(CONFIG_NETFILTER),y)
-SUB_DIRS += ipv6/netfilter
-MOD_SUB_DIRS += ipv6/netfilter
-endif
-else
- ifeq ($(CONFIG_IPV6),m)
- MOD_SUB_DIRS += ipv6
- ifeq ($(CONFIG_NETFILTER),y)
- MOD_SUB_DIRS += ipv6/netfilter
- endif
- endif
-endif
-ifeq ($(CONFIG_KHTTPD),y)
-SUB_DIRS += khttpd
-else
- ifeq ($(CONFIG_KHTTPD),m)
- MOD_SUB_DIRS += khttpd
- endif
-endif
+subdir-$(CONFIG_NET) += 802 sched
+subdir-$(CONFIG_INET) += ipv4
+subdir-$(CONFIG_NETFILTER) += ipv4/netfilter
+subdir-$(CONFIG_UNIX) += unix
+subdir-$(CONFIG_IPV6) += ipv6
-ifeq ($(CONFIG_NETLINK),y)
-SUB_DIRS += netlink
- ifeq ($(CONFIG_NETLINK_DEV),m)
- MOD_SUB_DIRS += netlink
- endif
+ifneq ($(CONFIG_IPV6),n)
+ifneq ($(CONFIG_IPV6),)
+subdir-$(CONFIG_NETFILTER) += ipv6/netfilter
endif
-
-ifeq ($(CONFIG_PACKET),y)
-SUB_DIRS += packet
-else
- ifeq ($(CONFIG_PACKET),m)
- MOD_SUB_DIRS += packet
- endif
endif
-ifeq ($(CONFIG_NET_SCHED),y)
- MOD_SUB_DIRS += sched
-endif
+subdir-$(CONFIG_KHTTPD) += khttpd
+subdir-$(CONFIG_NETLINK) += netlink
+subdir-$(CONFIG_PACKET) += packet
+subdir-$(CONFIG_NET_SCHED) += sched
+subdir-$(CONFIG_BRIDGE) += bridge
+subdir-$(CONFIG_IPX) += ipx
+subdir-$(CONFIG_ATALK) += appletalk
+subdir-$(CONFIG_WAN_ROUTER) += wanrouter
+subdir-$(CONFIG_X25) += x25
+subdir-$(CONFIG_LAPB) += lapb
+subdir-$(CONFIG_NETROM) += netrom
+subdir-$(CONFIG_ROSE) += rose
+subdir-$(CONFIG_AX25) += ax25
+subdir-$(CONFIG_IRDA) += irda
+subdir-$(CONFIG_SUNRPC) += sunrpc
+subdir-$(CONFIG_ATM) += atm
+subdir-$(CONFIG_DECNET) += decnet
+subdir-$(CONFIG_ECONET) += econet
-ifeq ($(CONFIG_BRIDGE),y)
-SUB_DIRS += bridge
-else
- ifeq ($(CONFIG_BRIDGE),m)
- MOD_SUB_DIRS += bridge
- endif
-endif
-ifeq ($(CONFIG_IPX),y)
-SUB_DIRS += ipx
-# SPX can be still a module
-MOD_SUB_DIRS += ipx
-else
- ifeq ($(CONFIG_IPX),m)
- MOD_SUB_DIRS += ipx
- endif
-endif
-
-ifeq ($(CONFIG_ATALK),y)
-SUB_DIRS += appletalk
-else
- ifeq ($(CONFIG_ATALK),m)
- MOD_SUB_DIRS += appletalk
- endif
-endif
-
-ifeq ($(CONFIG_WAN_ROUTER),y)
-SUB_DIRS += wanrouter
-else
- ifeq ($(CONFIG_WAN_ROUTER),m)
- MOD_SUB_DIRS += wanrouter
- endif
-endif
-
-ifeq ($(CONFIG_X25),y)
-SUB_DIRS += x25
-else
- ifeq ($(CONFIG_X25),m)
- MOD_SUB_DIRS += x25
- endif
-endif
-
-ifeq ($(CONFIG_LAPB),y)
-SUB_DIRS += lapb
-else
- ifeq ($(CONFIG_LAPB),m)
- MOD_SUB_DIRS += lapb
- endif
-endif
-
-ifeq ($(CONFIG_NETROM),y)
-SUB_DIRS += netrom
-else
- ifeq ($(CONFIG_NETROM),m)
- MOD_SUB_DIRS += netrom
- endif
-endif
-
-ifeq ($(CONFIG_ROSE),y)
-SUB_DIRS += rose
-else
- ifeq ($(CONFIG_ROSE),m)
- MOD_SUB_DIRS += rose
- endif
-endif
-
-ifeq ($(CONFIG_AX25),y)
-SUB_DIRS += ax25
-else
- ifeq ($(CONFIG_AX25),m)
- MOD_SUB_DIRS += ax25
- endif
-endif
-
-ifeq ($(CONFIG_IRDA),y)
-SUB_DIRS += irda
-# There might be some irda features that are compiled as modules
-MOD_IN_SUB_DIRS += irda
-else
- ifeq ($(CONFIG_IRDA),m)
- MOD_SUB_DIRS += irda
- endif
-endif
-
-ifeq ($(CONFIG_SUNRPC),y)
-SUB_DIRS += sunrpc
-else
- ifeq ($(CONFIG_SUNRPC),m)
- MOD_SUB_DIRS += sunrpc
- endif
-endif
-
-ifeq ($(CONFIG_ATM),y)
-SUB_DIRS += atm
-ifeq ($(CONFIG_ATM_LANE),m)
- MOD_ATM = atm
-endif
-ifeq ($(CONFIG_ATM_MPOA),m)
- MOD_ATM = atm
-endif
-MOD_SUB_DIRS += $(MOD_ATM)
+obj-y := socket.o protocols.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y))))
+ifeq ($(CONFIG_NET),y)
+obj-$(CONFIG_MODULES) += netsyms.o
+obj-$(CONFIG_SYSCTL) += sysctl_net.o
endif
-ifeq ($(CONFIG_DECNET),y)
-SUB_DIRS += decnet
-else
- ifeq ($(CONFIG_DECNET),m)
- MOD_SUB_DIRS += decnet
- endif
-endif
-ifeq ($(CONFIG_ECONET),y)
-SUB_DIRS += econet
-else
- ifeq ($(CONFIG_ECONET),m)
- MOD_SUB_DIRS += econet
- endif
-endif
+# Subdirectories that should be entered when MAKING_MODULES=1, even if set to 'y'.
+both-m := $(filter $(mod-subdirs), $(subdir-y))
-# We must attach netsyms.o to socket.o, as otherwise there is nothing
-# to pull the object file from the archive.
+# Translate to Rules.make lists.
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS := $(filter $(export-objs), $(obj-y))
+M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
-ifeq ($(CONFIG_NET),y)
-ifeq ($(CONFIG_MODULES),y)
-OX_OBJS := netsyms.o
-endif
-endif
+SUB_DIRS := $(subdir-y)
+MOD_SUB_DIRS := $(sort $(subdir-m) $(both-m))
+ALL_SUB_DIRS := $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-))
-O_TARGET := network.o
-O_OBJS := socket.o protocols.o $(join $(SUB_DIRS), $(patsubst %,/%.o,$(notdir $(SUB_DIRS))))
-
-M_OBJS :=
-
-ifeq ($(CONFIG_SYSCTL),y)
-ifeq ($(CONFIG_NET),y)
-O_OBJS += sysctl_net.o
-endif
-endif
include $(TOPDIR)/Rules.make
static rwlock_t peer_pool_lock = RW_LOCK_UNLOCKED;
#define PEER_MAXDEPTH 40 /* sufficient for about 2^27 nodes */
-static volatile int peer_total = 0;
+static volatile int peer_total;
int inet_peer_threshold = 65536 + 128; /* start to throw entries more
* aggressively at this stage */
int inet_peer_minttl = 120 * HZ; /* TTL under high load: 120 sec */
int inet_peer_maxttl = 10 * 60 * HZ; /* usual time to live: 10 min */
-struct inet_peer *inet_peer_unused_head = NULL,
+struct inet_peer *inet_peer_unused_head,
**inet_peer_unused_tailp = &inet_peer_unused_head;
spinlock_t inet_peer_unused_lock = SPIN_LOCK_UNLOCKED;
#define PEER_MAX_CLEANUP_WORK 30
struct inet_protocol *inet_protocol_base = IPPROTO_PREVIOUS;
-struct inet_protocol *inet_protos[MAX_INET_PROTOS] =
-{
- NULL
-};
+struct inet_protocol *inet_protos[MAX_INET_PROTOS];
/*
* Add a protocol handler to the hash tables
int ip_rt_min_pmtu = 512+20+20;
int ip_rt_min_advmss = 536;
-static unsigned long rt_deadline = 0;
+static unsigned long rt_deadline;
#define RTprint(a...) printk(KERN_DEBUG a)
atomic_t tcp_orphan_count = ATOMIC_INIT(0);
-int sysctl_tcp_mem[3] = { 0, };
+int sysctl_tcp_mem[3];
int sysctl_tcp_wmem[3] = { 4*1024, 16*1024, 128*1024 };
int sysctl_tcp_rmem[3] = { 4*1024, 87380, 87380*2 };
* First half of the table is for sockets not in TIME_WAIT, second half
* is for TIME_WAIT sockets only.
*/
-struct tcp_ehash_bucket *tcp_ehash = NULL;
+struct tcp_ehash_bucket *tcp_ehash;
/* Ok, let's try this, I give up, we do need a local binding
* TCP hash as well as the others for fast bind/connect.
*/
-struct tcp_bind_hashbucket *tcp_bhash = NULL;
+struct tcp_bind_hashbucket *tcp_bhash;
-int tcp_bhash_size = 0;
-int tcp_ehash_size = 0;
+int tcp_bhash_size;
+int tcp_ehash_size;
/* All sockets in TCP_LISTEN state will be in here. This is the only table
* where wildcard'd TCP sockets can exist. Hash function here is just local
* port number.
*/
-struct sock *tcp_listening_hash[TCP_LHTABLE_SIZE] = { NULL, };
+struct sock *tcp_listening_hash[TCP_LHTABLE_SIZE];
char __tcp_clean_cacheline_pad[(SMP_CACHE_BYTES -
(((sizeof(void *) * (TCP_LHTABLE_SIZE + 2)) +
(sizeof(int) * 2)) % SMP_CACHE_BYTES))] = { 0, };
int sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL;
int sysctl_tcp_retries1 = TCP_RETR1;
int sysctl_tcp_retries2 = TCP_RETR2;
-int sysctl_tcp_orphan_retries = 0;
+int sysctl_tcp_orphan_retries;
static void tcp_write_timer(unsigned long);
static void tcp_delack_timer(unsigned long);
rwlock_t udp_hash_lock = RW_LOCK_UNLOCKED;
/* Shared by v4/v6 udp. */
-int udp_port_rover = 0;
+int udp_port_rover;
static int udp_v4_get_port(struct sock *sk, unsigned short snum)
{
#ifdef RPC_DEBUG
#define RPCDBG_FACILITY RPCDBG_SCHED
-static int rpc_task_id = 0;
+static int rpc_task_id;
#endif
/*
/*
* All RPC tasks are linked into this list
*/
-static struct rpc_task * all_tasks = NULL;
+static struct rpc_task * all_tasks;
/*
* rpciod-related stuff
static DECLARE_WAIT_QUEUE_HEAD(rpciod_idle);
static DECLARE_WAIT_QUEUE_HEAD(rpciod_killer);
static DECLARE_MUTEX(rpciod_sema);
-static unsigned int rpciod_users = 0;
-static pid_t rpciod_pid = 0;
-static int rpc_inhibit = 0;
+static unsigned int rpciod_users;
+static pid_t rpciod_pid;
+static int rpc_inhibit;
/*
* Spinlock for wait queues. Access to the latter also has to be
* This is the last-ditch buffer for NFS swap requests
*/
static u32 swap_buffer[PAGE_SIZE >> 2];
-static int swap_buffer_used = 0;
+static int swap_buffer_used;
/*
* Make allocation of the swap_buffer SMP-safe
/*
* Declare the debug flags here
*/
-unsigned int rpc_debug = 0;
-unsigned int nfs_debug = 0;
-unsigned int nfsd_debug = 0;
-unsigned int nlm_debug = 0;
+unsigned int rpc_debug;
+unsigned int nfs_debug;
+unsigned int nfsd_debug;
+unsigned int nlm_debug;
#ifdef RPC_DEBUG
-static struct ctl_table_header *sunrpc_table_header = NULL;
+static struct ctl_table_header *sunrpc_table_header;
static ctl_table sunrpc_table[];
void
*/
void grow_config(int len)
{
- if (str_config == NULL) {
- len_config = 0;
- size_config = 4096;
- str_config = malloc(4096);
- if (str_config == NULL)
- { perror("malloc"); exit(1); }
- }
-
while (len_config + len > size_config) {
+ if (size_config == 0)
+ size_config = 2048;
str_config = realloc(str_config, size_config *= 2);
if (str_config == NULL)
{ perror("malloc config"); exit(1); }
*/
void grow_precious(int len)
{
- if (str_precious == NULL) {
- len_precious = 0;
- size_precious = 4096;
- str_precious = malloc(4096);
- if (str_precious == NULL)
- { perror("malloc precious"); exit(1); }
- }
-
while (len_precious + len > size_precious) {
+ if (size_precious == 0)
+ size_precious = 2048;
str_precious = realloc(str_precious, size_precious *= 2);
if (str_precious == NULL)
{ perror("malloc"); exit(1); }