Note that the BSD compression code will always be compiled as a
module; it is called bsd_comp.o and will show up in the directory
modules once you have said "make modules". If unsure, say N.
+
+PPP over Ethernet (EXPERIMENTAL)
+CONFIG_PPPOE
+ Support for PPP over Ethernet.
+
+ This driver requires a specially patched pppd daemon. The patch to
+ pppd, along with binaries of a patched pppd package can be found at:
+ http://www.math.uwaterloo.ca/~mostrows
Wireless LAN (non-hamradio)
CONFIG_NET_RADIO
If unsure, say N.
+Enable automatic mounting at boot
+CONFIG_DEVFS_MOUNT
+ This option appears if you have CONFIG_DEVFS_FS enabled. Setting
+ this to 'Y' will make the kernel automatically mount devfs onto /dev
+ when the system is booted, before the init thread is started.
+ You can override this with the "devfs=nomount" boot option.
+
+ If unsure, say N.
+
Debug devfs
CONFIG_DEVFS_DEBUG
If you say Y here, then the /dev file system code will generate
- Don't kill existing block ops in <devfs_read_inode>
- Restore auto-ownership for /dev/pty/m*
+===============================================================================
+Changes for patch v163
+
+Work sponsored by SGI
+
+- Don't create missing directories in <devfs_find_handle>
+
+- Removed Documentation/filesystems/devfs/mk-devlinks
+
+- Updated Documentation/filesystems/devfs/README
+===============================================================================
+Changes for patch v164
+
+Work sponsored by SGI
+
+- Fixed CONFIG_DEVFS breakage in drivers/char/serial.c introduced in
+ linux-2.3.99-pre6-7
+===============================================================================
+Changes for patch v165
+
+Work sponsored by SGI
+
+- Ported to kernel 2.3.99-pre6
+===============================================================================
+Changes for patch v166
+
+Work sponsored by SGI
+
+- Added CONFIG_DEVFS_MOUNT
+===============================================================================
+Changes for patch v167
+
+Work sponsored by SGI
+
+- Updated Documentation/filesystems/devfs/README
+
+- Updated sample modules.conf
-/* -*- auto-fill -*- */
+Devfs (Device File System) FAQ
- Device File System (devfs) Overview
- Richard Gooch <rgooch@atnf.csiro.au>
+Linux Devfs (Device File System) FAQ
+Richard Gooch
+1-MAY-2000
- 3-MAR-2000
+-----------------------------------------------------------------------------
+NOTE: the master copy of this document is available online at:
-Conventions used in this document <section>
-=================================
-
-Each section in this document will have the string "<section>" at the
-right-hand side of the section title. Each subsection will have
-"<subsection>" at the right-hand side. These strings are meant to make
-it easier to search through the document.
-
-NOTE that the master copy of this document is available online at:
-http://www.atnf.csiro.au/~rgooch/linux/docs/devfs.txt
+http://www.atnf.csiro.au/~rgooch/linux/docs/devfs.html
+and looks much better than the text version distributed with the
+kernel sources.
There is also an optional daemon that may be used with devfs. You can
find out more about it at:
+
http://www.atnf.csiro.au/~rgooch/linux/
-NEWFLASH: The official 2.3.46 kernel has included the devfs
-patch. Future patches will be released which build on this.
+NEWFLASH: The official 2.3.46 kernel has
+included the devfs patch. Future patches will be released which
+build on this.
+
+A mailing list is available which you may subscribe to. Send
+email
+to majordomo@oss.sgi.com with the following line in the
+body of the message:
+subscribe devfs
+The list is archived at
+
+http://oss.sgi.com/projects/devfs/archive/.
+
+-----------------------------------------------------------------------------
+
+Contents
+
+
+What is it?
+
+Why do it?
+
+Who else does it?
+
+How it works
+
+Operational issues (essential reading)
+
+Instructions for the impatient
+Permissions persistence accross reboots
+Dealing with drivers without devfs support
+All the way with Devfs
+Other Issues
+Kernel Naming Scheme
+Devfsd Naming Scheme
+SCSI Host Probing Issues
+
+
+
+Device drivers currently ported
+
+Allocation of Device Numbers
+
+Questions and Answers
+
+Making things work
+Alternatives to devfs
+
+
+Other resources
+
+-----------------------------------------------------------------------------
-What is it? <section>
-===========
+
+What is it?
Devfs is an alternative to "real" character and block special devices
on your root filesystem. Kernel device drivers can register devices by
name rather than major and minor numbers. These devices will appear in
-the devfs automatically, with whatever default ownership and
-protection the driver specified.
+devfs automatically, with whatever default ownership and
+protection the driver specified. A daemon (devfsd) can be used to
+override these defaults.
-NOTE that devfs is entirely optional. If you prefer the old disc-based
-device nodes, then simply leave CONFIG_DEVFS_FS=n (the default). In
-this case, nothing will change.
-ALSO NOTE that if you do enable devfs, the defaults are such that full
-compatibility is maintained with the old devices names.
+NOTE that devfs is entirely optional. If you prefer the old
+disc-based device nodes, then simply leave CONFIG_DEVFS_FS=n (the
+default). In this case, nothing will change. ALSO NOTE that if you do
+enable devfs, the defaults are such that full compatibility is
+maintained with the old devices names.
There are two aspects to devfs: one is the underlying device
namespace, which is a namespace just like any mounted filesystem. The
other aspect is the filesystem code which provides a view of the
-device namespace. The reason I make a distinction is because the devfs
+device namespace. The reason I make a distinction is because devfs
can be mounted many times, with each mount showing the same device
namespace. Changes made are global to all mounted devfs filesystems.
Also, because the devfs namespace exists without any devfs mounts, you
devfs namespace.
The cost of devfs is a small increase in kernel code size and memory
-usage. On a typical machine, the cost is under 0.2 percent. On a
-modest system with 64 MBytes of RAM, the cost is under 0.1 percent.
-The accusations of "bloatware" levelled at devfs are not justified.
+usage. About 7 pages of code (some of that in __init sections) and 49
+bytes for each entry in the namespace (93 bytes if you access the
+inode). A modest system has only a couple of hundred device entries,
+so this costs a few more pages. Compare this with the suggestion to
+put /dev on a ramdisc.
+
+On a typical machine, the cost is under 0.2 percent. On a modest
+system with 64 MBytes of RAM, the cost is under 0.1 percent. The
+accusations of "bloatware" levelled at devfs are not justified.
+
+-----------------------------------------------------------------------------
-Why do it? <section>
-==========
+Why do it?
There are several problems that devfs addresses. Some of these
problems are more serious than others (depending on your point of
are complex and likely to be fragile, or to use a simple and efficient
devfs which is robust.
-Major&minor allocation <subsection>
-----------------------
+There have been many counter-proposals to devfs, all seeking to
+provide some of the benefits without actually implementing devfs. So
+far there has been an absence of code and no proposed alternative has
+been able to provide all the features that devfs does. Further,
+alternative proposals require far more complexity in user-space (and
+still deliver less functionality than devfs). Some people have the
+mantra of reducing "kernel bloat", but don't consider the effects on
+user-space.
+
+A good solution limits the total complexity of kernel-space and
+user-space.
+
+
+Major&minor allocation
+
The existing scheme requires the allocation of major and minor device
numbers for each and every device. This means that a central
co-ordinating authority is required to issue these device numbers
of the device, there is far less potential for namespace conflict.
Solving this requires a kernel change.
-/dev management <subsection>
----------------
+/dev management
+
Because you currently access devices through device nodes, these must
be created by the system administrator. For standard devices you can
usually find a MAKEDEV programme which creates all these (hundreds!)
duplication of information, which is not good practice.
Solving this requires a kernel change.
-/dev growth <subsection>
------------
+/dev growth
+
A typical /dev has over 1200 nodes! Most of these devices simply don't
exist because the hardware is not available. A huge /dev increases the
time to access devices (I'm just referring to the dentry lookup times
and the time taken to read inodes off disc: the next subsection shows
some more horrors).
+
An example of how big /dev can grow is if we consider SCSI devices:
+
host 6 bits (say up to 64 hosts on a really big machine)
channel 4 bits (say up to 16 SCSI buses per host)
id 4 bits
lun 3 bits
partition 6 bits
TOTAL 23 bits
+
+
This requires 8 Mega (1024*1024) inodes if we want to store all
possible device nodes. Even if we scrap everything but id,partition
and assume a single host adapter with a single SCSI bus and only one
available and created them when they were available. This programme
would need to be run every time a new module was loaded, which would
slow things down a lot.
+
There is an existing programme called scsidev which will automatically
create device nodes for SCSI devices. It can do this by scanning files
in /proc/scsi. Unfortunately, to extend this idea to other device
also provides this information). Furthermore, such a system would
likely be implemented in an ad-hoc fashion, as different drivers will
provide their information in different ways.
+
Devfs is much cleaner, because it (natually) has a uniform mechanism
to provide this information: the device nodes themselves!
-Node to driver file_operations translation <subsection>
-------------------------------------------
-There is an important difference between the way disc-based c&b nodes
-and devfs entries make the connection between an entry in /dev and the
-actual device driver.
+
+Node to driver file_operations translation
+
+There is an important difference between the way disc-based character
+and block nodes and devfs entries make the connection between an entry
+in /dev and the actual device driver.
With the current 8 bit major and minor numbers the connection between
disc-based c&b nodes and per-major drivers is done through a
But why do that search at all if you don't have to? Once again, it
seems pointless.
-Note that the devfs doesn't use the major&minor system. For devfs
+Note thate devfs doesn't use the major&minor system. For devfs
entries, the connection is done when you lookup the /dev entry. When
devfs_register() is called, an internal table is appended which has
the entry name and the file_operations. If the dentry cache doesn't
unnecessary entries in a disc-based /dev, the number of conceivable
entries remains the same: you just limit yourself in order to save
space.
+
Devfs provides a fast connection between a VFS node and the device
driver, in a scalable way.
-/dev as a system administration tool <subsection>
-------------------------------------
+/dev as a system administration tool
+
Right now /dev contains a list of conceivable devices, most of which I
don't have. A devfs would only show those devices available on my
system. This means that listing /dev would be a handy way of checking
what devices were available.
-Major&minor size <subsection>
-----------------
+Major&minor size
+
Existing major and minor numbers are limited to 8 bits each. This is
now a limiting factor for some drivers, particularly the SCSI disc
driver, which consumes a single major number. Only 16 discs are
compatibility which you would have with increasing major and minor
number sizes. See the section on "Allocation of Device Numbers" for
details on maintaining compatibility with userspace.
+
Solving this requires a kernel change.
-Read-only root filesystem <subsection>
-------------------------
+Since writing this, the kernel has been modified so that the SCSI disc
+driver has more major numbers allocated to it and now supports up to
+128 discs. Since these major numbers are non-contiguous (a result of
+unplanned expansion), the implementation is a little more cumbersome
+than originally.
+
+Just like the changes to IPv4 to fix impending limitations in the
+address space, people find ways around the limitations. In the long
+run, however, solutions like IPv6 or devfs can't be put off forever.
+
+Read-only root filesystem
+
Having your device nodes on the root filesystem means that you can't
operate properly with a read-only root filesystem. This is because you
want to change ownerships and protections of tty devices. Existing
practice prevents you using a CD-ROM as your root filesystem for a
*real* system. Sure, you can boot off a CD-ROM, but you can't change
tty ownerships, so it's only good for installing.
+
Also, you can't use a shared NFS root filesystem for a cluster of
discless Linux machines (having tty ownerships changed on a common
/dev is not good). Nor can you embed your root filesystem in a
ROM-FS.
+
You can get around this by creating a RAMDISC at boot time, making
an ext2 filesystem in it, mounting it somewhere and copying the
contents of /dev into it, then unmounting it and mounting it over
-/dev. A devfs is a cleaner way of solving this.
+/dev.
+
+A devfs is a cleaner way of solving this.
+
+Non-Unix root filesystem
-Non-Unix root filesystem <subsection>
-------------------------
Non-Unix filesystems (such as NTFS) can't be used for a root
filesystem because they variously don't support character and block
special files or symbolic links. You can't have a separate disc-based
nodes), and then construct a new /dev in another RAMDISC, and finally
switch to your non-Unix root filesystem. This requires clever boot
scripts and a fragile and conceptually complex boot procedure.
+
Devfs solves this in a robust and conceptually simple way.
-PTY security <subsection>
-------------
+PTY security
+
Current pseudo-tty (pty) devices are owned by root and read-writable
by everyone. The user of a pty-pair cannot change
ownership/protections without being suid-root.
+
This could be solved with a secure user-space daemon which runs as
root and does the actual creation of pty-pairs. Such a daemon would
require modification to *every* programme that wants to use this new
mechanism. It also slows down creation of pty-pairs.
+
An alternative is to create a new open_pty() syscall which does much
the same thing as the user-space daemon. Once again, this requires
modifications to pty-handling programmes.
+
The devfs solution allows a device driver to "tag" certain device
files so that when an unopened device is opened, the ownerships are
changed to the current euid and egid of the opening process, and the
ptys. It doesn't support old-style pty devices, nor does it have all
the other features of devfs.
-Intelligent device management <subsection>
------------------------------
+Intelligent device management
+
Devfs implements a simple yet powerful protocol for communication with
a device management daemon (devfsd) which runs in user space. It is
possible to send a message (either synchronously or asynchronously) to
entries, opening and closing devices, looking up inodes, scanning
directories and more. This has many possibilities. Some of these are
already implemented.
-See: http://www.atnf.csiro.au/~rgooch/linux/
+
+See:
+http://www.atnf.csiro.au/~rgooch/linux/
Device entry registration events can be used by devfsd to change
permissions of newly-created device nodes. This is one mechanism to
system conditions instead of just the UID and GID.
Inode lookup events can be used to authenticate module autoload
-requests. Instead of using kmod directly, the event can be sent to
+requests. Instead of using kmod directly, the event is sent to
devfsd which can implement an arbitrary authentication before loading
the module itself.
Inode lookup events can also be used to construct arbitrary
namespaces, without having to resort to populating devfs with symlinks
to devices that don't exist.
-Speculative Device Scanning <subsection>
----------------------------
+Speculative Device Scanning
+
Consider an application (like cdparanoia) that wants to find all
CD-ROM devices on the system (SCSI, IDE and other types), whether or
not their respective modules are loaded. The application must
solution like scsidev could reduce the number of /dev/sr* entries (but
of course that also requires all that inefficient directory scanning).
-With devfs, the application can open the /dev/sr directory (which
-triggers the module autoloading if required), and proceed to read
-/dev/sr. Since only the available devices will have entries, there are
-no inefficencies in directory scanning or device openings.
+With devfs, the application can open the /dev/sr directory
+(which triggers the module autoloading if required), and proceed to
+read /dev/sr. Since only the available devices will have
+entries, there are no inefficencies in directory scanning or device
+openings.
+-----------------------------------------------------------------------------
-Who else does it? <section>
-=================
+Who else does it?
-FreeBSD-current now has a devfs implementation. Solaris 2 has a
-pseudo-devfs (something akin to scsidev but for all devices, with some
-unspecified kernel support). BeOS, Plan9 and QNX also have it. SGI's
-IRIX 6.4 and above also have a device filesystem.
+FreeBSD has a devfs implementation. Solaris 2 has a pseudo-devfs
+(something akin to scsidev but for all devices, with some unspecified
+kernel support). BeOS, Plan9 and QNX also have it. SGI's IRIX 6.4 and
+above also have a device filesystem.
While we shouldn't just automatically do something because others do
it, we should not ignore the work of others either. FreeBSD has a lot
of competent people working on it, so their opinion should not be
blithely ignored.
+-----------------------------------------------------------------------------
+
+
+How it works
-How it works <section>
-============
+Registering device entries
-Registering device entries <subsection>
---------------------------
For every entry (device node) in a devfs-based /dev a driver must call
devfs_register(). This adds the name of the device entry, the
file_operations structure pointer and a few other things to an
time. When a device entry is registered, it automagically appears in
any mounted devfs'.
-Inode lookup <subsection>
-------------
+Inode lookup
+
When a lookup operation on an entry is performed and if there is no
-driver information for that entry devfs will attempt to call devfsd or
-kmod. If still no driver information can be found then a negative
+driver information for that entry devfs will attempt to call
+devfsd. If still no driver information can be found then a negative
dentry is yielded and the next stage operation will be called by the
VFS (such as create() or mknod() inode methods). If driver information
can be found, an inode is created (if one does not exist already) and
all is well.
-Manually creating device nodes <subsection>
-------------------------------
+Manually creating device nodes
+
The mknod() method allows you to create an ordinary named pipe in the
devfs, or you can create a character or block special inode if one
does not already exist. You may wish to create a character or block
the protections on a device even before the driver is loaded. Once you
create an inode it appears in the directory listing.
-Unregistering device entries <subsection>
-----------------------------
-A device driver calls devfs_unregister() to unregister an entry.
-
-Chroot() gaols <subsection>
---------------
-The semantics of inode creation are different when the devfs is
-mounted with the "explicit" option. Now, when a device entry is
-registered, it will not appear until you use mknod() to create the
-device. It doesn't matter if you mknod() before or after the device is
-registered with devfs_register(). The purpose of this behaviour is to
-support chroot(2) gaols, where you want to mount a minimal devfs
-inside the gaol. Only the devices you specifically want to be
-available (through your mknod() setup) will be accessible.
+Unregistering device entries
+A device driver calls devfs_unregister() to unregister an entry.
-Persistence of ownership/permissions across reboots <section>
-===================================================
+Chroot() gaols
+
+The semantics of inode creation are different when devfs is mounted
+with the "explicit" option. Now, when a device entry is registered, it
+will not appear until you use mknod() to create the device. It doesn't
+matter if you mknod() before or after the device is registered with
+devfs_register(). The purpose of this behaviour is to support
+chroot(2) gaols, where you want to mount a minimal devfs inside the
+gaol. Only the devices you specifically want to be available (through
+your mknod() setup) will be accessible.
+
+-----------------------------------------------------------------------------
+
+
+Operational issues
+
+
+Instructions for the impatient
+
+Nobody likes reading documentation. People just want to get in there
+and play. So this section tells you quickly the steps you need to take
+to run with devfs mounted over /dev. Skip these steps and you will end
+up with a nearly unbootable system. Subsequent sections describe the
+issues in more detail, and discuss non-essential configuration
+options.
+
+Devfsd
+OK, if you're reading this, I assume you want to play with
+devfs. First you need to compile devfsd, the device management daemon,
+available at
+http://www.atnf.csiro.au/~rgooch/linux/.
+Because the kernel has a naming scheme
+which is quite different from the old naming scheme, you need to
+install devfsd so that software and configuration files that use the
+old naming scheme will not break.
+
+Compile and install devfsd. You will be provided with a default
+configuration file /etc/devfsd.conf which will provide
+compatibility symlinks for the old naming scheme. Don't change this
+config file unless you know what you're doing. Even if you think you
+do know what you're doing, don't change it until you've followed all
+the steps below and booted a devfs-enabled system and verified that it
+works.
+
+Now edit your main system boot script so that devfsd is started at the
+very beginning (before any filesystem
+checks). /etc/rc.d/rc.sysinit is often the main boot script
+on systems with SysV-style boot scripts. On systems with BSD-style
+boot scripts it is often /etc/rc. Also check
+/sbin/rc.
+
+NOTE that the line you put into the boot
+script should be exactly:
+
+/sbin/devfsd /dev
+
+DO NOT use some special daemon-launching
+programme, otherwise the boot script may not wait for devfsd to finish
+initialising.
+
+System Libraries
+There may still be some problems because of broken software making
+assumptions about device names. In particular, some software does not
+handle devices which are symbolic links. If you are running a libc 5
+based system, install libc 5.4.44 (if you have libc 5.4.46, go back to
+libc 5.4.44, which is actually correct). If you are running a glibc
+based system, make sure you have glibc 2.1.3 or later.
+
+/etc/securetty
+PAM (Pluggable Authentication Modules) is supposed to be a flexible
+mechanism for providing better user authentication and access to
+services. Unfortunately, it's also fragile, complex and undocumented
+(check out RedHat 6.1, and probably other distributions as well). PAM
+has problems with symbolic links. Append the following lines to your
+/etc/securetty file:
+
+1
+2
+3
+4
+5
+6
+7
+8
+
+This may potentially weaken security by allowing root logins over the
+network (a password is still required, though). However, since there
+are problems with dealing with symlinks, I'm suspicious of the level
+of security offered in any case.
+
+XFree86
+While not essential, it's probably a good idea to upgrade to XFree86
+4.0, as patches went in to make it more devfs-friendly. If you don't,
+you'll probably need to apply the following patch to
+/etc/security/console.perms so that ordinary users can run
+startx.
+
+--- /etc/security/console.perms.orig Sat Apr 17 16:26:47 1999
++++ /etc/security/console.perms Fri Feb 25 23:53:55 2000
+@@ -14,7 +14,7 @@
+ # man 5 console.perms
+
+ # file classes -- these are regular expressions
+-=tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9]
++=tty[0-9][0-9]* [0-9][0-9]* :[0-9]\.[0-9] :[0-9]
+
+ # device classes -- these are shell-style globs
+ =/dev/fd[0-1]*
+
+
+Disable devpts
+I've had a report of devpts mounted on /dev/pts not working
+correctly. Since devfs will also manage /dev/pts, there is no
+need to mount devpts as well. You should either edit your
+/etc/fstab so devpts is not mounted, or disable devfs from
+your kernel configuration.
+
+Unsupported drivers
+Not all drivers have devfs support. If you depend on one of these
+drivers, you will need to create a script or tarfile that you can use
+at boot time to create device nodes as appropriate. There is a
+section which describes this. Another
+section lists the drivers which have
+devfs support.
+
+/dev/mouse
+
+Many disributions configure /dev/mouse to be the mouse device
+for XFree86 and GPM. I actually think this is a bad idea, because it
+adds another level of indirection. When looking at a config file, if
+you see /dev/mouse you're left wondering which mouse
+is being referred to. Hence I recommend putting the actual mouse
+device (for example /dev/psaux) into your
+/etc/X11/XF86Config file (and similarly for the GPM
+configuration file).
+
+Alternatively, use the same technique used for unsupported drivers
+described above.
+
+The Kernel
+Finally, you need to make sure devfs is compiled into your
+kernel. Set CONFIG_DEVFS_FS=y and recompile your kernel. Next, you
+need to make sure devfs is mounted. The best solution is to pass
+devfs=mount at the kernel boot command line. You can edit
+/etc/lilo.conf and add the line:
+
+append = "devfs=mount"
+
+
+This will make the kernel mount devfs at boot time onto /dev.
+
+Now you've finished all the steps required. You're now ready to boot
+your shiny new kernel. Enjoy.
+
+Changing the configuration
+
+OK, you've now booted a devfs-enabled system, and everything works.
+Now you may feel like changing the configuration (common targets are
+/etc/fstab and /etc/devfsd.conf). Since you have a
+system that works, if you make any changes and it doesn't work, you
+now know that you only have to restore your configuration files to the
+default and it will work again.
+
+
+Permissions persistence across reboots
If you don't use mknod(2) to create a device file, nor use chmod(2) or
chown(2) to change the ownerships/permissions, the inode ctime will
remain at 0 (the epoch, 12 am, 1-JAN-1970, GMT). Anything with a ctime
later than this has had it's ownership/permissions changed. Hence, a
simple script or programme may be used to tar up all changed inodes,
-prior to shutdown.
-
-Upon bootup, simply untar the previously created tarfile, and all your
-ownerships/permissions will be retained. For the paranoid, you can
-save your permissions periodically using a cron job.
-
-NOTE: tar will first unlink(2) an inode before creating a new device
-node. The unlink(2) has the effect of breaking the connection between
-a devfs entry and the device driver. If you use the "devfs=only" boot
-option, you lose access to the device driver, requiring you to reload
-the module. I consider this a bug in tar (there is no real need to
+prior to shutdown. Although effective, many consider this approach a
+kludge.
+
+A much better approach is to use devfsd to save and restore
+permissions. It may be configured to record changes in permissions and
+will save them in a database (in fact a directory tree), and restore
+these upon boot. This is an efficient method and results in immediate
+saving of current permissions (unlike the tar approach, which save
+permissions at some unspecified future time).
+
+The default configuration file supplied with devfsd has config entries
+which you may uncomment to enable persistence management.
+
+If you decide to use the tar approach anyway, be aware that tar will
+first unlink(2) an inode before creating a new device node. The
+unlink(2) has the effect of breaking the connection between a devfs
+entry and the device driver. If you use the "devfs=only" boot option,
+you lose access to the device driver, requiring you to reload the
+module. I consider this a bug in tar (there is no real need to
unlink(2) the inode first).
-I've provided a script called "rc.devfs" in this directory which you
-can use to save and restore permissions.
-
-Alternatively, you can use the device management daemon (devfsd) to
-control the permissions of device nodes. This has the advantage of
-being able to store permissions for whole groups of devices with a
-single configuration entry, rather than one (tar) entry per device
-node. Devfsd also receives inode change events, so you could easily
-implement a simple permissions database.
+Alternatively, you can use devfsd to provide more sophisticated
+management of device permissions. You can use devfsd to store
+permissions for whole groups of devices with a single configuration
+entry, rather than the conventional single entry per device entry.
-Installation during the transition phase <section>
-========================================
+Dealing with drivers without devfs support
Currently, not all device drivers in the kernel have been modified to
-use devfs. If you want to boot between kernels with and without devfs
-support, this section discusses some options. Either way is safe,
-although some people will have different preferences.
-
-Note that your old-style (i.e. node-based) chroot /gaol/dev
-directories which you manually created will still work, unless you
-pass the "devfs=only" boot option.
-
-Fail-safe Approach with devfs mounted on /dev <subsection>
----------------------------------------------
-The default is for devfs to be mounted onto /dev at boot time.
-Device drivers which do not yet have devfs support will not
-automagically appear in the devfs. The simplest way to create device
-nodes for these drivers is to unpack a tarfile containing the required
+use devfs. Device drivers which do not yet have devfs support will not
+automagically appear in devfs. The simplest way to create device nodes
+for these drivers is to unpack a tarfile containing the required
device nodes. You can do this in your boot scripts. All your drivers
will now work as before.
can mount devfs directly over /dev without loosing most functionality
(i.e. loosing access to various devices). As of 22-JAN-1998 (devfs
patch version 10) I am now running this way. All the devices I have
-are available in the devfs, so I don't lose anything.
+are available in devfs, so I don't lose anything.
WARNING: if your configuration requires the old-style device names
(i.e. /dev/hda1 or /dev/sda1), you must install devfsd and configure
as devfs can manage /dev/pts itself. This saves you some RAM, as you
don't need to compile and install devpts. Note that some versions of
glibc have a bug with Unix98 pty handling on devfs systems. Contact
-the glibc maintainers for a fix.
+the glibc maintainers for a fix. Glibc 2.1.3 should have the fix.
Note also that apart from editing /etc/fstab, other things will need
to be changed if you *don't* install devfsd. Some software (like the X
You can then slowly migrate your system to using the new device names
(for example, by starting with /etc/fstab), and then limiting the
compatibility entries that devfsd creates.
+
MAKE SURE YOU INSTALL DEVFSD BEFORE YOU BOOT A DEVFS-ENABLED KERNEL!
Now that devfs has gone into the 2.3.46 kernel, I'm getting a lot of
bugs/false assumptions in other code (i.e. glibc, X server) and submit
that to the respective maintainers, that would be great.
-Fail-safe Approach with real /dev inodes <subsection>
-----------------------------------------
-This method involves more work, and is no longer recommended now that
-a large number of drivers have devfs support. You will need to use the
-"devfs=nomount" boot option.
-
-Copy the contents of /dev to /devfs. Then remove entries in /dev
-which are now available in devfs and make them symbolic links to the
-entries in /devfs. Finally, edit your /etc/fstab or boot scripts so
-that devfs is mounted over /devfs on bootup. If devfs is supported,
-accessing devices supported by devfs will follow the symlinks to
-devfs. If devfs is not supported, accessing those same devices will
-follow the symlinks to /devfs which contains only old-style device
-nodes. Devices not supported by devfs will be found directly on /dev.
-Simple! You can also follow this principle for chroot gaols.
-
-I've provided a demonstration script called "mk-devlinks" in this
-directory which you can use to create symlinks in /dev and
-/devfs. Note that this script is out of date and should not be run
-without modification.
-
-All the way with Devfs <section>
-======================
+All the way with Devfs
The devfs kernel patch creates a rationalised device tree. As stated
above, if you want to keep using the old /dev naming scheme, you just
library or use Unix98 ptys instead). It's just a matter of putting in
the correct regular expression into /dev/devfsd.conf.
-
-Other Issues <section>
-============
-
-Another thing to take note of is whether your init programme creates a
-Unix socket /dev/telinit. Some versions of init create /dev/telinit so
-that the <telinit> programme can communicate with the init process. If
-you have such a system you need to make sure that devfs is mounted
-over /dev *before* init starts. In other words, you can't leave the
-mounting of devfs to /etc/rc, since this is executed after init.
-Other versions of init require a named pipe /dev/initctl which must
-exist *before* init starts. Once again, you need to mount devfs and
-then create the named pipe *before* init starts.
-
-The default behaviour now is to mount devfs onto /dev at boot time.
-You can disable this with the "devfs=nomount" boot option, but you can
-then get harmless but annoying messages about not being able to open
-an initial console.
+There are other choices of naming schemes that you may prefer. For
+example, I don't use the kernel-supplied
+names, because they are too verbose. A common misconception is
+that the kernel-supplied names are meant to be used directly in
+configuration files. This is not the case. They are designed to
+reflect the layout of the devices attached and to provide easy
+classification.
+
+If you like the kernel-supplied names, that's fine. If you don't then
+you should be using devfsd to construct a namespace more to your
+liking. Devfsd has built-in code to construct a
+namespace that is both logical and easy to
+manage. In essence, it creates a convenient abbreviation of the
+kernel-supplied namespace.
+
+You are of course free to build your own namespace. Devfsd has all the
+infrastructure required to make this easy for you. All you need do is
+write a script. You can even write some C code and devfsd can load the
+shared object as a callable extension.
+
+
+Other Issues
+
+The init programme
+Another thing to take note of is whether your init programme
+creates a Unix socket /dev/telinit. Some versions of init
+create /dev/telinit so that the telinit programme can
+communicate with the init process. If you have such a system you need
+to make sure that devfs is mounted over /dev *before* init
+starts. In other words, you can't leave the mounting of devfs to
+/etc/rc, since this is executed after init. Other
+versions of init require a named pipe /dev/initctl
+which must exist *before* init starts. Once again, you need to
+mount devfs and then create the named pipe *before* init
+starts.
+
+The default behaviour now is not to mount devfs onto /dev at boot time.
+You can correct this with the "devfs=mount" boot option. This solves
+any problems with init, and also prevents the dreaded:
+
+Cannot open initial console
+
+message.
If you have automatic mounting of devfs onto /dev then you may need to
create /dev/initctl in your boot scripts. The following lines should
[control-D]
# chmod a+x init
-Note that newer versions of init create /dev/initctl automatically, so
-you don't have to worry about this.
+Note that newer versions of init create /dev/initctl
+automatically, so you don't have to worry about this.
+
+Module autoloading
+Another thing to note is that if you want to support module
+autoloading then you need to edit your /etc/modules.conf so
+that things work properly. You should include the sample
+modules.conf file in the
+Documentation/filesystems/devfs directory into your
+/etc/modules.conf to ensure correct operation.
-Using kmod (module autoloading) <subsection>
--------------------------------
-Another thing to note is that if you are using kmod then you need to
-edit your /etc/modules.conf so that things work properly. You should
-include the sample modules.conf file in the
-Documentation/filesystems/devfs directory into your /etc/modules.conf
-to ensure correct operation.
+You will also need to configure devfsd to enable module
+autoloading. The following lines should be placed in your
+/etc/devfsd.conf:
-Mounting root off a devfs device <subsection>
---------------------------------
+LOOKUP .* MODLOAD
+
+
+Mounting root off a devfs device
If you wish to mount root off a devfs device when you pass the
-"devfs=only" boot option, then you need to pass in the "root=<device>"
+"devfs=only" boot option, then you need to pass in the "root="
option to the kernel when booting. If you use LILO, then you must have
this in lilo.conf:
-append = "root=<device>"
+
+append = "root="
Surprised? Yep, so was I. It turns out if you have (as most people
do):
-root = <device>
-then LILO will determine the device number of <device> and will write
+root =
+
+
+then LILO will determine the device number of and will write
that device number into a special place in the kernel image before
starting the kernel, and the kernel will use that device number to
mount the root filesystem. So, using the "append" variety ensures that
Note that this isn't an issue if you don't pass "devfs=only".
-TTY issues <subsection>
-----------
-You may replace your tty devices in /dev with symbolic links to /devfs
-however you will then find that programmes which depend on ttyname(3)
-will no longer work properly. The <tty> programme is a good
-example. I've written a patch to libc 5.4.43 which fixes this. This
-has been included in libc 5.4.44 and glibc 2.1.?
+TTY issues
+The ttyname(3) function in some versions of the C library makes
+false assumptions about device entries which are symbolic links. The
+tty(1) programme is one that depends on this function. I've
+written a patch to libc 5.4.43 which fixes this. This has been
+included in libc 5.4.44 and a similar fix is in glibc 2.1.3.
-Device drivers currently ported <section>
-===============================
+Kernel Naming Scheme
-- All miscellaneous character devices support devfs (this is done
- transparently through misc_register())
-
-- SCSI discs and generic hard discs
+The kernel provides a default naming scheme. This scheme is designed
+to make it easy to search for specific devices or device types, and to
+view the available devices. Some device types (such as hard discs),
+have a directory of entries, making it easy to see what devices of
+that class are available. Often, the entries are symbolic links into a
+directory tree that reflects the topology of available devices. The
+topological tree is useful for finding how your devices are arranged.
-- Character memory devices (null, zero, full and so on)
- Thanks to C. Scott Ananian <cananian@alumni.princeton.edu>
-
-- Loop devices (/dev/loop?)
-
-- TTY devices (console, serial ports, terminals and pseudo-terminals)
- Thanks to C. Scott Ananian <cananian@alumni.princeton.edu>
-
-- SCSI tapes (/dev/scsi and /dev/tapes)
-
-- SCSI CD-ROMs (/dev/scsi and /dev/cdroms)
-
-- SCSI generic devices (/dev/scsi)
-
-- RAMDISCS (/dev/ram?)
-
-- Meta Devices (/dev/md*)
-
-- Floppy discs (/dev/floppy)
-
-- Parallel port printers (/dev/printers)
-
-- Sound devices (/dev/sound)
- Thanks to Eric Dumas <dumas@linux.eu.org> and
- C. Scott Ananian <cananian@alumni.princeton.edu>
-
-- Joysticks (/dev/joysticks)
-
-- Sparc keyboard (/dev/kbd)
-
-- DSP56001 digital signal processor (/dev/dsp56k)
-
-- Apple Desktop Bus (/dev/adb)
-
-- Coda network file system (/dev/cfs*)
-
-- Virtual console capture devices (/dev/vcc)
- Thanks to Dennis Hou <smilax@mindmeld.yi.org>
-
-- Frame buffer devices (/dev/fb)
-
-- Video capture devices (/dev/v4l)
-
-
-Naming Scheme <section>
-=============
-
-Disc Devices <subsection>
-------------
+Disc Devices
All discs, whether SCSI, IDE or whatever, are placed under the
/dev/discs hierarchy:
+
/dev/discs/disc0 first disc
/dev/discs/disc1 second disc
+
Each of these entries is a symbolic link to the directory for that
device. The device directory contains:
+
disc for the whole disc
part* for individual partitions
-CD-ROM Devices <subsection>
---------------
+
+CD-ROM Devices
All CD-ROMs, whether SCSI, IDE or whatever, are placed under the
/dev/cdroms hierarchy:
+
/dev/cdroms/cdrom0 first CD-ROM
/dev/cdroms/cdrom1 second CD-ROM
+
Each of these entries is a symbolic link to the real device entry for
that device.
-Tape Devices <subsection>
-------------
+Tape Devices
All tapes, whether SCSI, IDE or whatever, are placed under the
/dev/tapes hierarchy:
+
/dev/tapes/tape0 first tape
/dev/tapes/tape1 second tape
+
Each of these entries is a symbolic link to the directory for that
device. The device directory contains:
+
mt for mode 0
mtl for mode 1
mtm for mode 2
mtmn for mode 2, no rewind
mtan for mode 3, no rewind
-SCSI Devices <subsection>
-------------
+
+SCSI Devices
+
To uniquely identify any SCSI device requires the following
information:
+
controller (host adapter)
bus (SCSI channel)
target (SCSI ID)
unit (Logical Unit Number)
-All SCSI devices are placed under /dev/scsi (assuming devfs is mounted
-on /dev). Hence, a SCSI device with the following parameters:
-c=1,b=2,t=3,u=4 would appear as:
+
+All SCSI devices are placed under /dev/scsi (assuming devfs
+is mounted on /dev). Hence, a SCSI device with the following
+parameters: c=1,b=2,t=3,u=4 would appear as:
+
/dev/scsi/host1/bus2/target3/lun4 device directory
+
Inside this directory, a number of device entries may be created,
depending on which SCSI device-type drivers were installed.
tape driver creates.
The SCSI CD-ROM driver creates:
+
cd
+
The SCSI generic driver creates:
+
generic
-IDE Devices <subsection>
------------
+
+IDE Devices
+
To uniquely identify any IDE device requires the following
information:
+
controller
bus (aka. primary/secondary)
target (aka. master/slave)
unit
-All IDE devices are placed under /dev/ide (assuming devfs is mounted
-on /dev), and uses a similar naming scheme to the SCSI subsystem.
+All IDE devices are placed under /dev/ide, and uses a similar
+naming scheme to the SCSI subsystem.
+
+XT Hard Discs
+
+All XT discs are placed under /dev/xd. The first XT disc has
+the directory /dev/xd/disc0.
-XT Hard Discs <subsection>
--------------
-All XT discs are placed under /dev/xd (assuming devfs is mounted on
-/dev). The first XT disc has the directory /dev/xd/disc0
+TTY devices
-TTY devices <subsection>
------------
The tty devices now appear as:
+
New name Old-name Device Type
-------- -------- -----------
/dev/tts/{0,1,...} /dev/ttyS{0,1,...} Serial ports
/dev/pty/m{0,1,...} /dev/ptyp?? PTY masters
/dev/pty/s{0,1,...} /dev/ttyp?? PTY slaves
-RAMDISCS <subsection>
---------
+
+RAMDISCS
+
The RAMDISCS are placed in their own directory, and are named thus:
+
/dev/rd/{0,1,2,...}
-Meta Devices <subsection>
-------------
+
+Meta Devices
+
The meta devices are placed in their own directory, and are named
thus:
+
/dev/md/{0,1,2,...}
-Floppy discs <subsection>
-------------
+
+Floppy discs
+
Floppy discs are placed in the /dev/floppy directory.
-Loop devices <subsection>
-------------
+Loop devices
+
Loop devices are placed in the /dev/loop directory.
-Sound devices <subsection>
--------------
-Sound devices are placed in the /dev/sound directory (audio,
-sequencer, ...).
+Sound devices
+
+Sound devices are placed in the /dev/sound directory
+(audio, sequencer, ...).
+
+
+Devfsd Naming Scheme
+
+Devfsd provides a naming scheme which is a convenient abbreviation of
+the kernel-supplied namespace. In some
+cases, the kernel-supplied naming scheme is quite convenient, so
+devfsd does not provide another naming scheme. The convenience names
+that devfsd creates are in fact the same names as the original devfs
+kernel patch created (before Linus mandated the Big Name Change).
+
+In order to configure devfsd to create these convenience names, the
+following lines should be placed in your /etc/devfsd.conf:
+
+REGISTER .* MKNEWCOMPAT
+UNREGISTER .* RMNEWCOMPAT
+
+This will cause devfsd to create (and destroy) symbolic links which
+point to the kernel-supplied names.
+
+SCSI Hard Discs
+
+All SCSI discs are placed under /dev/sd (assuming devfs is
+mounted on /dev). Hence, a SCSI disc with the following
+parameters: c=1,b=2,t=3,u=4 would appear as:
+
+ /dev/sd/c1b2t3u4 for the whole disc
+ /dev/sd/c1b2t3u4p5 for the 5th partition
+ /dev/sd/c1b2t3u4p5s6 for the 6th slice in the 5th partition
+
+
+SCSI Tapes
+All SCSI tapes are placed under /dev/st. A similar naming
+scheme is used as for SCSI discs. A SCSI tape with the
+parameters:c=1,b=2,t=3,u=4 would appear as:
-SCSI Host Probing Issues <section>
-========================
+ /dev/st/c1b2t3u4m0 for mode 0
+ /dev/st/c1b2t3u4m1 for mode 1
+ /dev/st/c1b2t3u4m2 for mode 2
+ /dev/st/c1b2t3u4m3 for mode 3
+ /dev/st/c1b2t3u4m0n for mode 0, no rewind
+ /dev/st/c1b2t3u4m1n for mode 1, no rewind
+ /dev/st/c1b2t3u4m2n for mode 2, no rewind
+ /dev/st/c1b2t3u4m3n for mode 3, no rewind
+
+
+SCSI CD-ROMs
+
+All SCSI CD-ROMs are placed under /dev/sr. A similar naming
+scheme is used as for SCSI discs. A SCSI CD-ROM with the
+parameters:c=1,b=2,t=3,u=4 would appear as:
+
+ /dev/sr/c1b2t3u4
+
+
+SCSI Generic Devices
+
+All SCSI CD-ROMs are placed under /dev/sg. A similar naming
+scheme is used as for SCSI discs. A SCSI generic device with the
+parameters:c=1,b=2,t=3,u=4 would appear as:
+
+ /dev/sg/c1b2t3u4
+
+
+IDE Hard Discs
+
+All IDE discs are placed under /dev/ide/hd, using a similar
+convention to SCSI discs. The following mappings exist between the new
+and the old names:
+
+ /dev/hda /dev/ide/hd/c0b0t0u0
+ /dev/hdb /dev/ide/hd/c0b0t1u0
+ /dev/hdc /dev/ide/hd/c0b1t0u0
+ /dev/hdd /dev/ide/hd/c0b1t1u0
+
+
+IDE Tapes
+
+A similar naming scheme is used as for IDE discs. The entries will
+appear in the /dev/ide/mt directory.
+
+IDE CD-ROM
+
+A similar naming scheme is used as for IDE discs. The entries will
+appear in the /dev/ide/cd directory.
+
+IDE Floppies
+
+A similar naming scheme is used as for IDE discs. The entries will
+appear in the /dev/ide/fd directory.
+
+XT Hard Discs
+
+All XT discs are placed under /dev/xd. The first XT disc
+would appear as /dev/xd/c0t0.
+
+
+SCSI Host Probing Issues
Devfs allows you to identify SCSI discs based in part on SCSI host
numbers. If you have only one SCSI host (card) in your computer, then
you to specify the probe order for different types of SCSI hosts. The
syntax of this parameter is:
-scsihosts=<name_1>:<name_2>:<name_3>:...:<name_n>
+scsihosts=:::...:
-where <name_1>,<name_2>,...,<name_n> are the names of drivers used in
+where ,,..., are the names of drivers used in
/proc filesystem. For example:
scsihosts=aha1542:ppa:aha1542::ncr53c7xx
+
means that devices connected to
+
- first aha1542 controller - will be c0b#t#u#
- first parallel port ZIP - will be c1b#t#u#
- second aha1542 controller - will be c2b#t#u#
not be used by any other device.
- c3b#t#u# names will never be used
+
You can use ',' instead of ':' as the separator character if you
-wish.
+wish. I have used the devfsd naming scheme
+here.
Note that this scheme does not address the SCSI host order if you have
multiple cards of the same type (such as NCR53c8xx). In this case you
need to use the driver-specific boot parameters to control this.
+-----------------------------------------------------------------------------
+
+
+Device drivers currently ported
+
+- All miscellaneous character devices support devfs (this is done
+ transparently through misc_register())
+
+- SCSI discs and generic hard discs
+
+- Character memory devices (null, zero, full and so on)
+ Thanks to C. Scott Ananian <cananian@alumni.princeton.edu>
+
+- Loop devices (/dev/loop?)
+
+- TTY devices (console, serial ports, terminals and pseudo-terminals)
+ Thanks to C. Scott Ananian <cananian@alumni.princeton.edu>
+
+- SCSI tapes (/dev/scsi and /dev/tapes)
+
+- SCSI CD-ROMs (/dev/scsi and /dev/cdroms)
+
+- SCSI generic devices (/dev/scsi)
+
+- RAMDISCS (/dev/ram?)
+
+- Meta Devices (/dev/md*)
+
+- Floppy discs (/dev/floppy)
+
+- Parallel port printers (/dev/printers)
+
+- Sound devices (/dev/sound)
+ Thanks to Eric Dumas <dumas@linux.eu.org> and
+ C. Scott Ananian <cananian@alumni.princeton.edu>
+
+- Joysticks (/dev/joysticks)
+
+- Sparc keyboard (/dev/kbd)
+
+- DSP56001 digital signal processor (/dev/dsp56k)
+
+- Apple Desktop Bus (/dev/adb)
+
+- Coda network file system (/dev/cfs*)
+
+- Virtual console capture devices (/dev/vcc)
+ Thanks to Dennis Hou <smilax@mindmeld.yi.org>
+
+- Frame buffer devices (/dev/fb)
+
+- Video capture devices (/dev/v4l)
+
-Allocation of Device Numbers <section>
-============================
+-----------------------------------------------------------------------------
+
+
+Allocation of Device Numbers
Devfs allows you to write a driver which doesn't need to allocate a
device number (major&minor numbers) for the internal operation of the
kernel. However, there are a number of userspace programmes that use
the device number as a unique handle for a device. An example is the
-<find> programme, which uses device numbers to determine whether an
-inode is on a different filesystem than another inode. The device
+find programme, which uses device numbers to determine whether
+an inode is on a different filesystem than another inode. The device
number used is the one for the block device which a filesystem is
using. To preserve compatibility with userspace programmes, block
devices using devfs need to have unique device numbers allocated to
Alternatively, you can have devfs choose unique device numbers for
you. When you register a character or block device using
-<devfs_register> you can provide the optional DEVFS_FL_AUTO_DEVNUM
-flag, which will then automatically allocate a unique device number
-(the allocation is separated for the character and block devices).
+devfs_register you can provide the optional
+DEVFS_FL_AUTO_DEVNUM flag, which will then automatically allocate a
+unique device number (the allocation is separated for the character
+and block devices).
+
This device number is a 16 bit number, so this leaves plenty of space
for large numbers of discs and partitions. This scheme can also be
used for character devices, in particular the tty devices, which are
A final note on this scheme: since it doesn't increase the size of
device numbers, there are no compatibility issues with userspace.
+
+-----------------------------------------------------------------------------
+
+
+Questions and Answers
+
+
+Making things work
+Alternatives to devfs
+
+
+
+Making things work
+
+Here are some common questions and answers.
+
+
+
+Devfsd is not managing all my permissions
+
+Make sure you are capturing the appropriate events. For example,
+device entries created by the kernel generate REGISTER events,
+but those created by devfsd generate CREATE events.
+
+
+Devfsd is not capturing all REGISTER events
+
+See the previous entry: you may need to capture CREATE events.
+
+
+X will not start
+
+Make sure you followed the steps
+outlined above.
+
+
+Why don't my network devices appear in devfs?
+
+This is not a bug. Network devices have their own, completely separate
+namespace. They are accessed via socket(2) and
+setsockopt(2) calls, and thus require no device nodes. I have
+raised the possibilty of moving network devices in the device
+namespace, but have had no response.
+
+
+
+
+
+Alternatives to devfs
+
+I've attempted to collate all the anti-devfs proposals and explain
+their limitations. Under construction.
+
+
+Why not just pass device create/remove events to a daemon?
+
+Here the suggestion is to develop an API in the kernel so that devices
+can register create and remove events, and a daemon listens for those
+events. The daemon would then populate/depopulate /dev (which
+resides on disc).
+
+This has several limitations:
+
+
+it only works for modules loaded and unloaded (or devices inserted
+and removed) after the kernel has finished booting. Without a database
+of events, there is no way the daemon could fully populate
+/dev
+
+
+if you add a database to this scheme, the question is then how to
+present that database to user-space. If you make it a list of strings
+with embedded event codes which are passed through a pipe to the
+daemon, then this is only of use to the daemon. I would argue that the
+natural way to present this data is via a filesystem (since many of
+the events will be of a hierarchical nature), such as devfs.
+Presenting the data as a filesystem makes it easy for the user to see
+what is available and also makes it easy to write scripts to scan the
+"database"
+
+
+the tight binding between device nodes and drivers is no longer
+possible (requiring the otherwise perfectly avoidable
+table lookups)
+
+
+you cannot catch inode lookup events on /dev which means
+that module autoloading requires device nodes to be created. This is a
+problem, particularly for drivers where only a few inodes are created
+from a potentially large set
+
+
+this technique can't be used when the root FS is mounted
+read-only
+
+
+
+
+Just implement a better scsidev
+
+This suggestion involves taking the scsidev programme and
+extending it to scan for all devices, not just SCSI devices. The
+scsidev programme works by scanning /proc/scsi
+
+Problems:
+
+
+the kernel does not currently provide a list of all devices
+available. Not all drivers register entries in /proc or
+generate kernel messages
+
+
+there is no uniform mechanism to register devices other than the
+devfs API
+
+
+implementing such an API is then the same as the
+proposal above
+
+
+
+
+Put /dev on a ramdisc
+
+This suggestion involves creating a ramdisc and populating it with
+device nodes and then mounting it over /dev.
+
+Problems:
+
+
+
+this doesn't help when mounting the root filesystem, since you
+still need a device node to do that
+
+
+if you want to use this technique for the root device node as
+well, you need to use initrd. This complicates the booting sequence
+and makes it significantly harder to administer and configure. The
+initrd is essentially opaque, robbing the system administrator of easy
+configuration
+
+
+insufficient information is available to correctly populate the
+ramdisc. So we come back to the
+proposal above to "solve" this
+
+
+a ramdisc-based solution would take more kernel memory, since the
+backing store would be (at best) normal VFS inodes and dentries, which
+take 284 bytes and 112 bytes, respectively, for each entry. Compare
+that to 49 or 93 bytes for devfs
+
+
+
+
+Do nothing: there's no problem
+
+Sometimes people can be heard to claim that the existing scheme is
+fine. This is what they're ignoring:
+
+
+device number size (8 bits each for major and minor) is a real
+limitation, and must be fixed somehow. Systems with large numbers of
+SCSI devices, for example, will continue to consume the remaining
+unallocated major numbers. USB will also need to push beyond the 8 bit
+minor limitation
+
+
+simplying increasing the device number size is insufficient. Apart
+from causing a lot of pain, it doesn't solve the management issues
+with a /dev with thousands or more device nodes
+
+
+ignoring the problem of a huge /dev will not make it go
+away, and dismisses the legitimacy of a large number of people who
+want a dynamic /dev
+
+
+the standard response then becomes: "write a device management
+daemon", which brings us back to the
+proposal above
+
+
+
+-----------------------------------------------------------------------------
+
+
+Other resources
+
+
+
+Douglas Gilbert has written a useful document at
+
+http://www.torque.net/sg/devfs_scsi.html which
+explores the SCSI subsystem and how it interacts with devfs.
+
+
+
+
+
Richard Gooch <rgooch@atnf.csiro.au>
- 14-DEC-1999
+ 30-APR-2000
-When either CONFIG_DEVFS_DEBUG or CONFIG_DEVFS_BOOT_OPTIONS are
-enabled, you can pass several boot options to the kernel to control
-devfs behaviour. The boot options are prefixed by "devfs=", and are
-separated by commas. Spaces are not allowed. The syntax looks like
-this:
+When CONFIG_DEVFS_DEBUG is enabled, you can pass several boot options
+to the kernel to debug devfs. The boot options are prefixed by
+"devfs=", and are separated by commas. Spaces are not allowed. The
+syntax looks like this:
devfs=<option1>,<option2>,<option3>
show show unregistered devices by default
+mount mount devfs onto /dev at boot time
+
nomount do not mount devfs onto /dev at boot time
only disable non-devfs device nodes for devfs-capable drivers
+++ /dev/null
-#! /bin/csh -f
-
-# WARNING: make sure /devfs is not a mounted devfs
-
-cd /devfs
-if (-e .devfsd) then
- echo "/devfs must not be a mounted devfs"
- exit 1
-endif
-if ( ! -e null ) then
- echo "Cannot find null device"
- exit 1
-endif
-
-
-# Make SCSI disc links.
-# WARNING: this assumes your SCSI discs are numbered ID=0, ID=1, ID=2 and so on
-set discs = (a b c d e f)
-if ( ! -d sd ) mkdir sd
-ln -sf /devfs/sd /dev
-
-@ scsi_id = 0
-while ($scsi_id < $#discs)
- @ discnum = $scsi_id + 1
- ls -lF sd${discs[$discnum]}
- rm /dev/sd${discs[$discnum]}
- ln -s /devfs/sd${discs[$discnum]} /dev
- ln -s ../sd${discs[$discnum]} sd/c0b0t${scsi_id}u0
- @ partition = 1
- while ($partition < 16)
- ls -lF sd${discs[$discnum]}${partition}
- rm /dev/sd${discs[$discnum]}${partition}
- ln -s /devfs/sd${discs[$discnum]}${partition} /dev
- ln -s ../sd${discs[$discnum]}${partition} sd/c0b0t${scsi_id}u0p$partition
- @ partition ++
- end
- @ scsi_id ++
-end
-
-
-# Make IDE disc links
-foreach i (hd*)
- rm /dev/$i
- ln -s /devfs/$i /dev
-end
-
-
-# Make miscellaneous character devices links (character, major=10)
-foreach i (`ls -l * | grep '^c' | fgrep '10,' | awk '{print $10}'`)
- rm /dev/$i
- ln -s /devfs/$i /dev
-end
-
-
-# Make memory devices links (character, major=1)
-foreach i (`ls -l * | grep '^c' | fgrep ' 1,' | awk '{print $10}'`)
- rm /dev/$i
- ln -s /devfs/$i /dev
-end
-
-
-# Make loop device links
-foreach i (loop*)
- rm /dev/$i
- ln -s /devfs/$i /dev
-end
-
-
-# Make various tty device links
-foreach i (tty* pty* cua* console)
- rm /dev/$i
- ln -s /devfs/$i /dev
-end
-
-
-# Make SCSI CD-ROM, tapes and generic links
-ln -s /devfs/sr /dev
-ln -s /devfs/st /dev
-ln -s /devfs/sg /dev
-foreach i (sr* st* nst* sg*)
- if ("$i" == "stderr") continue
- if ("$i" == "stdin") continue
- if ("$i" == "stdout") continue
- rm /dev/$i
- ln -s /devfs/$i /dev
-end
-
-
-# Make RAMDISC device links
-ln -s /devfs/rd /dev
-foreach i (ram*)
- rm /dev/$i
- ln -s /devfs/$i /dev
-end
-
-
-# Make floppy device links
-ln -s /devfs/floppy /dev
-foreach i (fd?*)
- rm /dev/$i
- ln -s /devfs/$i /dev
-end
-
-
-# Make line printer device links
-foreach i (lp*)
- rm /dev/$i
- ln -s /devfs/$i /dev
-end
-
-# Make sound devices links
-if ( ! -d sound ) mkdir sound
-ln -sf /devfs/sound /dev
-foreach i (mixer sequencer midi dsp audio sequencer2 mixer1 patmgr0 midi1\
- dsp1 audio1 patmgr1 midi2 midi3)
-
- if ( -f /dev/$i ) then
- rm /dev/$i
- ln -s /devfs/$i /dev
- endif
-end
-
-
alias /dev/inportbm msbusmouse
alias /dev/logibm busmouse
+# PPP devices
+alias /dev/ppp* ppp_generic
+
# Video capture devices
alias /dev/video* /dev/v4l
alias /dev/vbi* /dev/v4l
<mailto:rusty@rustcorp.com.au>
0xB0 all RATIO devices in development:
<mailto:vgo@ratio.de>
+0xB1 00-1F PPPoX <mailto:mostrows@styx.uwaterloo.ca>
0xCB 00-1F CBM serial IEC bus in development:
<mailto:michael.klein@puffin.lb.shuttle.de>
L: linux-ppp@vger.rutgers.edu
S: Maintained
+PPP OVER ETHERNET
+P: Michal Ostrowski
+M: mostrows@styx.uwaterloo.ca
+S: Maintained
+
PROMISE DC4030 CACHING DISK CONTROLLER DRIVER
P: Peter Denison
M: promise@pnd-pc.demon.co.uk
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_PCMCIA_XIRC2PS is not set
# CONFIG_ARCNET_COM20020_CS is not set
# CONFIG_PCMCIA_IBMTR is not set
-
-#
-# 3Com 3c575 moved to Ethernet 10/100 menu
-#
# CONFIG_PCMCIA_XIRTULIP is not set
CONFIG_NET_PCMCIA_RADIO=y
CONFIG_PCMCIA_RAYCS=y
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_PROC_FS is not set
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
outb(LATCH >> 8, 0x40); /* MSB */
printk("PIT: LATCH at 0x%x%x for %d HZ\n", LATCH >> 8, LATCH & 0xff, HZ);
#endif
-#ifdef __SMP__
+#ifdef CONFIG_SMP
init_smp_config();
#endif
screen_info = sn1_screen_info;
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
eret
END(except_vec0_r45k_bvahwbug)
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* TLB refill, EXL == 0, R4000 MP badvaddr hwbug version */
LEAF(except_vec0_r4k_mphwbug)
.set mips3
eret
END(except_vec0_r4k_250MHZhwbug)
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* TLB refill, EXL == 0, R4000 MP 250MHZ entrylo[01]+badvaddr bug version */
LEAF(except_vec0_r4k_MP250MHZhwbug)
.set mips3
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
* Copyright (C) 1994 - 2000 by Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics
*/
+#include <linux/config.h>
#include <asm/asm.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
FEXPORT(ret_from_sys_call)
FEXPORT(ret_from_irq)
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#error Barffff...
#else
la t1, softirq_state
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_HPFS_FS=m
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
real_irq_entry:
SAVE_ALL
-#ifdef __SMP__
+#ifdef CONFIG_SMP
.globl patchme_maybe_smp_msg
cmp %l7, 12
RESTORE_ALL
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* SMP per-cpu ticker interrupts are handled specially. */
smp4m_ticker:
bne real_irq_continue+4
/* FIXME */
1: b,a 1b
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
/* This routine handles illegal instructions and privileged
* instruction attempts from user code.
b C_LABEL(ret_sys_call)
ld [%sp + REGWIN_SZ + PT_I0], %o0
-#ifdef __SMP__
+#ifdef CONFIG_SMP
.globl C_LABEL(ret_from_smpfork)
C_LABEL(ret_from_smpfork):
wr %l0, PSR_ET, %psr
sethi %hi(0x10c6), %o1
call .umul
or %o1, %lo(0x10c6), %o1
-#ifndef __SMP__
+#ifndef CONFIG_SMP
sethi %hi(C_LABEL(loops_per_sec)), %o3
call .umul
ld [%o3 + %lo(C_LABEL(loops_per_sec))], %o1
_stext:
start:
C_LABEL(trapbase):
-#ifdef __SMP__
+#ifdef CONFIG_SMP
C_LABEL(trapbase_cpu0):
#endif
/* We get control passed to us here at t_zero. */
t_irq13:TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */
t_irq14:TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */
.globl t_nmi
-#ifndef __SMP__
+#ifndef CONFIG_SMP
t_nmi: NMI_TRAP /* Level 15 (NMI) */
#else
t_nmi: TRAP_ENTRY(0x1f, linux_trap_ipi15_sun4m)
.globl C_LABEL(end_traptable)
C_LABEL(end_traptable):
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Trap tables for the other cpus. */
.globl C_LABEL(trapbase_cpu1), C_LABEL(trapbase_cpu2), C_LABEL(trapbase_cpu3)
C_LABEL(trapbase_cpu1):
or %g5, %g3, %g5
st %g5, [%g4]
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Get our CPU id out of bootbus */
set SUN4D_BOOTBUS_CPUID, %g3
lduba [%g3] ASI_M_CTL, %g3
*/
set C_LABEL(init_task_union), %g6
set C_LABEL(current_set), %g2
-#ifdef __SMP__
+#ifdef CONFIG_SMP
sethi %hi(C_LABEL(boot_cpu_id4)), %g3
ldub [%g3 + %lo(C_LABEL(boot_cpu_id4))], %g3
st %g6, [%g2]
{
int i, len = 0;
struct irqaction * action;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int j;
#endif
if (!action)
continue;
len += sprintf(buf+len, "%3d: ", i);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
len += sprintf(buf+len, "%10u ", kstat_irqs(i));
#else
for (j = 0; j < smp_num_cpus; j++)
restore_flags(flags);
}
-#ifndef __SMP__
+#ifndef CONFIG_SMP
unsigned int local_bh_count;
unsigned int local_irq_count;
}
}
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
{
{
struct irqaction * action;
int cpu = smp_processor_id();
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern void smp4m_irq_rotate(int cpu);
#endif
irq_enter(cpu, irq);
disable_pil_irq(irq);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */
if(irq < 10)
smp4m_irq_rotate(cpu);
struct irqaction *action;
unsigned long flags;
unsigned int cpu_irq;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
struct tt_entry *trap_table;
extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3;
#endif
table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
INSTANTIATE(sparc_ttable)
-#ifdef __SMP__
+#ifdef CONFIG_SMP
trap_table = &trapbase_cpu1; INSTANTIATE(trap_table)
trap_table = &trapbase_cpu2; INSTANTIATE(trap_table)
trap_table = &trapbase_cpu3; INSTANTIATE(trap_table)
struct task_struct *last_task_used_math = NULL;
struct task_struct *current_set[NR_CPUS] = {&init_task, };
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define SUN4C_FAULT_HIGH 100
__show_backtrace(fp);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
void smp_show_backtrace_all_cpus(void)
{
xc0((smpfunc_t) show_backtrace);
*/
void exit_thread(void)
{
-#ifndef __SMP__
+#ifndef CONFIG_SMP
if(last_task_used_math == current) {
#else
if(current->flags & PF_USEDFPU) {
put_psr(get_psr() | PSR_EF);
fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr,
¤t->thread.fpqueue[0], ¤t->thread.fpqdepth);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
last_task_used_math = NULL;
#else
current->flags &= ~PF_USEDFPU;
/* No new signal delivery by default */
current->thread.new_signal = 0;
-#ifndef __SMP__
+#ifndef CONFIG_SMP
if(last_task_used_math == current) {
#else
if(current->flags & PF_USEDFPU) {
put_psr(get_psr() | PSR_EF);
fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr,
¤t->thread.fpqueue[0], ¤t->thread.fpqdepth);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
last_task_used_math = NULL;
#else
current->flags &= ~PF_USEDFPU;
* allocate the task_struct and kernel stack in
* do_fork().
*/
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern void ret_from_smpfork(void);
#else
extern void ret_from_syscall(void);
struct reg_window *new_stack;
unsigned long stack_offset;
-#ifndef __SMP__
+#ifndef CONFIG_SMP
if(last_task_used_math == current) {
#else
if(current->flags & PF_USEDFPU) {
put_psr(get_psr() | PSR_EF);
fpsave(&p->thread.float_regs[0], &p->thread.fsr,
&p->thread.fpqueue[0], &p->thread.fpqdepth);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
current->flags &= ~PF_USEDFPU;
#endif
}
copy_regwin(new_stack, (((struct reg_window *) regs) - 1));
p->thread.ksp = (unsigned long) new_stack;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
p->thread.kpc = (((unsigned long) ret_from_smpfork) - 0x8);
p->thread.kpsr = current->thread.fork_kpsr | PSR_PIL;
#else
fpregs->pr_q_entrysize = 8;
return 1;
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
if (current->flags & PF_USEDFPU) {
put_psr(get_psr() | PSR_EF);
fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr,
{
unsigned long prom_tbr, flags;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
global_irq_holder = NO_PROC_ID;
*((unsigned char *)&global_irq_lock) = 0;
*((unsigned char *)&global_bh_lock) = 0;
"type\t\t: %s\n"
"ncpus probed\t: %d\n"
"ncpus active\t: %d\n"
-#ifndef __SMP__
+#ifndef CONFIG_SMP
"BogoMips\t: %lu.%02lu\n"
#endif
,
romvec->pv_romvers, prom_rev, romvec->pv_printrev >> 16, (short)romvec->pv_printrev,
&cputypval,
linux_num_cpus, smp_num_cpus
-#ifndef __SMP__
+#ifndef CONFIG_SMP
, loops_per_sec/500000, (loops_per_sec/5000) % 100
#endif
);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
len += smp_bogo_info(buffer + len);
#endif
len += mmu_info(buffer + len);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
len += smp_info(buffer + len);
#endif
return len;
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/signal.h>
restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
{
int err;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
if (current->flags & PF_USEDFPU)
regs->psr &= ~PSR_EF;
#else
save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
{
int err = 0;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
if (current->flags & PF_USEDFPU) {
put_psr(get_psr() | PSR_EF);
fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr,
extern void dump_thread(struct pt_regs *, struct user *);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern spinlock_t kernel_flag;
#endif
EXPORT_SYMBOL_PRIVATE(_rw_read_exit);
EXPORT_SYMBOL_PRIVATE(_rw_write_enter);
#endif
-#ifdef __SMP__
+#ifdef CONFIG_SMP
EXPORT_SYMBOL(__global_save_flags);
EXPORT_SYMBOL(__global_restore_flags);
EXPORT_SYMBOL(__global_sti);
EXPORT_SYMBOL_PRIVATE(_clear_le_bit);
/* IRQ implementation. */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
EXPORT_SYMBOL(kernel_flag);
EXPORT_SYMBOL(global_irq_holder);
EXPORT_SYMBOL(global_irq_lock);
/* EXPORT_SYMBOL(iounit_map_dma_page); */
/* Btfixup stuff cannot have versions, it would be complicated too much */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(___xchg32));
#else
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(__smp_processor_id));
claim_ticker14(NULL, PROFILE_IRQ, 0);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
static void sun4c_nop(void) {}
#endif
BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
init_timers = sun4c_init_timers;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
BTFIXUPSET_CALL(set_irq_udt, sun4c_nop, BTFIXUPCALL_NOP);
* Heavily based on arch/sparc/kernel/irq.c.
*/
+#include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/linkage.h>
extern struct irqaction static_irqaction[MAX_STATIC_ALLOC];
extern int static_irq_count;
unsigned char cpu_leds[32];
-#ifdef __SMP__
+#ifdef CONFIG_SMP
unsigned char sbus_tid[32];
#endif
};
static int nsbi;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
spinlock_t sun4d_imsk_lock = SPIN_LOCK_UNLOCKED;
#endif
{
int i, j = 0, k = 0, len = 0, sbusl;
struct irqaction * action;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int x;
#endif
continue;
}
found_it: len += sprintf(buf+len, "%3d: ", i);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
len += sprintf(buf+len, "%10u ", kstat_irqs(i));
#else
for (x = 0; x < smp_num_cpus; x++)
static void sun4d_disable_irq(unsigned int irq)
{
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int tid = sbus_tid[(irq >> 5) - 1];
unsigned long flags;
#endif
if (irq < NR_IRQS) return;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
spin_lock_irqsave(&sun4d_imsk_lock, flags);
cc_set_imsk_other(tid, cc_get_imsk_other(tid) | (1 << sbus_to_pil[(irq >> 2) & 7]));
spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
static void sun4d_enable_irq(unsigned int irq)
{
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int tid = sbus_tid[(irq >> 5) - 1];
unsigned long flags;
#endif
if (irq < NR_IRQS) return;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
spin_lock_irqsave(&sun4d_imsk_lock, flags);
cc_set_imsk_other(tid, cc_get_imsk_other(tid) & ~(1 << sbus_to_pil[(irq >> 2) & 7]));
spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
#endif
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
static void sun4d_set_cpu_int(int cpu, int level)
{
sun4d_send_ipi(cpu, level);
/* Map the User Timer registers. */
memset(&r, 0, sizeof(r));
-#ifdef __SMP__
+#ifdef CONFIG_SMP
r.start = CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT;
#else
r.start = CSR_BASE(0)+BW_TIMER_LIMIT;
for(cpu = 0; cpu < linux_num_cpus; cpu++)
sun4d_load_profile_irq((linux_cpus[cpu].mid >> 3), 0);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
{
unsigned long flags;
extern unsigned long lvl14_save[4];
sbus_actions = (struct sbus_action *)kmalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action)));
for_each_sbus(sbus) {
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern unsigned char boot_cpu_id;
set_sbi_tid(sbus->devid, boot_cpu_id << 3);
BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(__irq_itoa, sun4d_irq_itoa, BTFIXUPCALL_NORM);
init_timers = sun4d_init_timers;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP);
BTFIXUPSET_CALL(set_irq_udt, sun4d_set_udt, BTFIXUPCALL_NOP);
* Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
*/
+#include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/linkage.h>
sun4m_interrupts->clear = cpu_pil_to_imask[pil];
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
static void sun4m_send_ipi(int cpu, int level)
{
unsigned long mask;
} else {
sun4m_timers->cpu_timers[0].l14_timer_limit = 0;
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
{
unsigned long flags;
extern unsigned long lvl14_save[4];
BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
init_timers = sun4m_init_timers;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM);
/* last time the cmos clock got updated */
static long last_rtc_update=0;
-#ifndef __SMP__
+#ifndef CONFIG_SMP
if(!user_mode(regs))
sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
#endif
* I hate traps on the sparc, grrr...
*/
+#include <linux/config.h>
#include <linux/sched.h> /* for jiffies */
#include <linux/kernel.h>
#include <linux/signal.h>
put_psr(get_psr() | PSR_EF); /* Allow FPU ops. */
regs->psr |= PSR_EF;
-#ifndef __SMP__
+#ifndef CONFIG_SMP
if(last_task_used_math == current)
goto out;
if(last_task_used_math) {
}
current->flags |= PF_USEDFPU;
#endif
-#ifndef __SMP__
+#ifndef CONFIG_SMP
out:
#endif
unlock_kernel();
siginfo_t info;
unsigned long fsr;
int ret = 0;
-#ifndef __SMP__
+#ifndef CONFIG_SMP
struct task_struct *fpt = last_task_used_math;
#else
struct task_struct *fpt = current;
* error into our fake static buffer and hope it don't
* happen again. Thank you crashme...
*/
-#ifndef __SMP__
+#ifndef CONFIG_SMP
if(!fpt) {
#else
if(!(fpt->flags & PF_USEDFPU)) {
}
/* nope, better SIGFPE the offending process... */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
fpt->flags &= ~PF_USEDFPU;
#endif
if(psr & PSR_PS) {
info.si_code = FPE_FLTRES;
}
send_sig_info(SIGFPE, &info, fpt);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
last_task_used_math = NULL;
#endif
regs->psr &= ~PSR_EF;
* Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
*/
+#include <linux/config.h>
#include <asm/cprefix.h>
#include <asm/ptrace.h>
#include <asm/psr.h>
.globl __atomic_begin
__atomic_begin:
-#ifndef __SMP__
+#ifndef CONFIG_SMP
.globl ___xchg32_sun4c
___xchg32_sun4c:
rd %psr, %g3
or %g3, PSR_PIL, %g7 ! Disable interrupts
wr %g7, 0x0, %psr ! Set %psr
nop; nop; nop; ! Let the bits set
-#ifdef __SMP__
+#ifdef CONFIG_SMP
1: ldstub [%g1 + 3], %g7 ! Spin on the byte lock for SMP.
orcc %g7, 0x0, %g0 ! Did we get it?
bne 1b ! Nope...
or %g3, PSR_PIL, %g7 ! Disable interrupts
wr %g7, 0x0, %psr ! Set %psr
nop; nop; nop; ! Let the bits set
-#ifdef __SMP__
+#ifdef CONFIG_SMP
1: ldstub [%g1 + 3], %g7 ! Spin on the byte lock for SMP.
orcc %g7, 0x0, %g0 ! Did we get it?
bne 1b ! Nope...
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/config.h>
#include <asm/cprefix.h>
#include <asm/ptrace.h>
#include <asm/psr.h>
or %g3, PSR_PIL, %g5
wr %g5, 0x0, %psr
nop; nop; nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
set C_LABEL(bitops_spinlock), %g5
2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
orcc %g7, 0x0, %g0 ! Did we get it?
ld [%g1], %g7
or %g7, %g2, %g5
and %g7, %g2, %g2
-#ifdef __SMP__
+#ifdef CONFIG_SMP
st %g5, [%g1]
set C_LABEL(bitops_spinlock), %g5
stb %g0, [%g5]
or %g3, PSR_PIL, %g5
wr %g5, 0x0, %psr
nop; nop; nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
set C_LABEL(bitops_spinlock), %g5
2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
orcc %g7, 0x0, %g0 ! Did we get it?
ld [%g1], %g7
andn %g7, %g2, %g5
and %g7, %g2, %g2
-#ifdef __SMP__
+#ifdef CONFIG_SMP
st %g5, [%g1]
set C_LABEL(bitops_spinlock), %g5
stb %g0, [%g5]
or %g3, PSR_PIL, %g5
wr %g5, 0x0, %psr
nop; nop; nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
set C_LABEL(bitops_spinlock), %g5
2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
orcc %g7, 0x0, %g0 ! Did we get it?
ld [%g1], %g7
xor %g7, %g2, %g5
and %g7, %g2, %g2
-#ifdef __SMP__
+#ifdef CONFIG_SMP
st %g5, [%g1]
set C_LABEL(bitops_spinlock), %g5
stb %g0, [%g5]
or %g3, PSR_PIL, %g5
wr %g5, 0x0, %psr
nop; nop; nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
set C_LABEL(bitops_spinlock), %g5
2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
orcc %g7, 0x0, %g0 ! Did we get it?
ldub [%g1], %g7
or %g7, %g2, %g5
and %g7, %g2, %g2
-#ifdef __SMP__
+#ifdef CONFIG_SMP
stb %g5, [%g1]
set C_LABEL(bitops_spinlock), %g5
stb %g0, [%g5]
or %g3, PSR_PIL, %g5
wr %g5, 0x0, %psr
nop; nop; nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
set C_LABEL(bitops_spinlock), %g5
2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP.
orcc %g7, 0x0, %g0 ! Did we get it?
ldub [%g1], %g7
andn %g7, %g2, %g5
and %g7, %g2, %g2
-#ifdef __SMP__
+#ifdef CONFIG_SMP
stb %g5, [%g1]
set C_LABEL(bitops_spinlock), %g5
stb %g0, [%g5]
* Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
*/
+#include <linux/config.h>
#include <asm/ptrace.h>
#include <asm/psr.h>
nop
nop
nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
1: ldstub [%g1 + 4], %g7
tst %g7
bne 1b
sethi %hi(0x01000000), %g2
nop
nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
1: ldstub [%g1 + 4], %g7
tst %g7
bne 1b
nop
nop
nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
1: ldstub [%g1 + 4], %g7
tst %g7
bne 1b
sethi %hi(0x01000000), %g2
nop
nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
1: ldstub [%g1 + 4], %g7
tst %g7
bne 1b
} else
p = q + count;
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
flush_cacheall = (void (*)(void))BTFIXUPVAL_CALL(local_flush_cache_all);
#else
flush_cacheall = (void (*)(void))BTFIXUPVAL_CALL(flush_cache_all);
#include <asm/asi.h>
#include <asm/page.h>
#include <asm/pgtsrmmu.h>
+#include <linux/config.h>
#include <linux/init.h>
#define WINDOW_FLUSH(tmp1, tmp2) \
/* We expand the window flush to get maximum performance. */
hypersparc_flush_cache_mm:
-#ifndef __SMP__
+#ifndef CONFIG_SMP
ld [%o0 + AOFF_mm_context], %g1
cmp %g1, -1
be hypersparc_flush_cache_mm_out
/* The things we do for performance... */
hypersparc_flush_cache_range:
-#ifndef __SMP__
+#ifndef CONFIG_SMP
ld [%o0 + AOFF_mm_context], %g1
cmp %g1, -1
be hypersparc_flush_cache_range_out
hypersparc_flush_cache_page:
ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */
ld [%o0 + AOFF_mm_context], %g2
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %g2, -1
be hypersparc_flush_cache_page_out
#endif
mov SRMMU_CTX_REG, %g1
ld [%o0 + AOFF_mm_context], %o1
lda [%g1] ASI_M_MMUREGS, %g5
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %o1, -1
be hypersparc_flush_tlb_mm_out
#endif
mov SRMMU_CTX_REG, %g1
ld [%o0 + AOFF_mm_context], %o3
lda [%g1] ASI_M_MMUREGS, %g5
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %o3, -1
be hypersparc_flush_tlb_range_out
#endif
mov SRMMU_CTX_REG, %g1
ld [%o0 + AOFF_mm_context], %o3
andn %o1, (PAGE_SIZE - 1), %o1
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %o3, -1
be hypersparc_flush_tlb_page_out
#endif
printk("%ld pages of RAM\n", totalram_pages);
printk("%d free pages\n", nr_free_pages());
printk("%ld pages in page table cache\n",pgtable_cache_size);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
if (sparc_cpu_model == sun4m || sparc_cpu_model == sun4d)
printk("%ld entries in page dir cache\n",pgd_cache_size);
#endif
extern unsigned long last_valid_pfn;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define FLUSH_BEGIN(mm)
#define FLUSH_END
#else
#define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page)
int flush_page_for_dma_global = 1;
#define flush_chunk(chunk) BTFIXUP_CALL(flush_chunk)(chunk)
-#ifdef __SMP__
+#ifdef CONFIG_SMP
BTFIXUPDEF_CALL(void, local_flush_page_for_dma, unsigned long)
#define local_flush_page_for_dma(page) BTFIXUP_CALL(local_flush_page_for_dma)(page)
static void srmmu_quick_kernel_fault(unsigned long address)
{
-#ifdef __SMP__
+#ifdef CONFIG_SMP
printk("CPU[%d]: Kernel faults at addr=0x%08lx\n",
smp_processor_id(), address);
while (1) ;
{
int nd, cache_lines;
char node_str[128];
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int cpu = 0;
unsigned long max_size = 0;
unsigned long min_line_size = 0x10000000;
vac_cache_size = cache_lines * vac_line_size;
vac_badbits = (vac_cache_size - 1) & PAGE_MASK;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
if(vac_cache_size > max_size)
max_size = vac_cache_size;
if(vac_line_size < min_line_size)
prom_printf("No CPU nodes found, halting.\n");
prom_halt();
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
vac_cache_size = max_size;
vac_line_size = min_line_size;
vac_badbits = (vac_cache_size - 1) & PAGE_MASK;
mreg &= ~(VIKING_ACENABLE);
srmmu_set_mmureg(mreg);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Avoid unnecessary cross calls. */
BTFIXUPCOPY_CALL(flush_cache_all, local_flush_cache_all);
BTFIXUPCOPY_CALL(flush_cache_mm, local_flush_cache_mm);
BTFIXUPSET_CALL(flush_cache_page, viking_flush_cache_page, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(flush_cache_range, viking_flush_cache_range, BTFIXUPCALL_NORM);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
if (sparc_cpu_model == sun4d) {
BTFIXUPSET_CALL(flush_tlb_all, sun4dsmp_flush_tlb_all, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(flush_tlb_mm, sun4dsmp_flush_tlb_mm, BTFIXUPCALL_NORM);
PATCH_BRANCH(sparc_ttable[SP_TRAP_DACC].inst_three, srmmu_fault);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Local cross-calls. */
static void smp_flush_page_for_dma(unsigned long page)
{
pg_iobits = SRMMU_VALID | SRMMU_WRITE | SRMMU_REF;
/* Functions */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4md, BTFIXUPCALL_SWAPG1G2);
#endif
BTFIXUPSET_CALL(get_pte_fast, srmmu_get_pte_fast, BTFIXUPCALL_RETINT(0));
get_srmmu_type();
patch_window_trap_handlers();
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* El switcheroo... */
BTFIXUPCOPY_CALL(local_flush_cache_all, flush_cache_all);
ld_mmu_iounit();
else
ld_mmu_iommu();
-#ifdef __SMP__
+#ifdef CONFIG_SMP
if (sparc_cpu_model == sun4d)
sun4d_init_smp();
else
_SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE;
/* Functions */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4c, BTFIXUPCALL_NORM);
#endif
BTFIXUPSET_CALL(get_pte_fast, sun4c_pte_get, BTFIXUPCALL_NORM);
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
*/
+#include <linux/config.h>
#include <asm/psr.h>
#include <asm/asi.h>
#include <asm/page.h>
.globl swift_flush_cache_mm
swift_flush_cache_mm:
-#ifndef __SMP__
+#ifndef CONFIG_SMP
ld [%o0 + AOFF_mm_context], %g2
cmp %g2, -1
be swift_flush_cache_mm_out
swift_flush_cache_page:
ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */
70:
-#ifndef __SMP__
+#ifndef CONFIG_SMP
ld [%o0 + AOFF_mm_context], %g2
cmp %g2, -1
be swift_flush_cache_page_out
.globl swift_flush_tlb_all
swift_flush_tlb_mm:
swift_flush_tlb_range:
-#ifndef __SMP__
+#ifndef CONFIG_SMP
ld [%o0 + AOFF_mm_context], %g2
cmp %g2, -1
be swift_flush_tlb_all_out
mov SRMMU_CTX_REG, %g1
ld [%o0 + AOFF_mm_context], %o3
andn %o1, (PAGE_SIZE - 1), %o1
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %o3, -1
be swift_flush_tlb_page_out
nop
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/config.h>
#include <asm/ptrace.h>
#include <asm/psr.h>
#include <asm/asi.h>
tsunami_flush_cache_mm:
tsunami_flush_cache_range:
ld [%o0 + AOFF_mm_context], %g2
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %g2, -1
be tsunami_flush_cache_out
#endif
/* More slick stuff... */
tsunami_flush_tlb_mm:
tsunami_flush_tlb_range:
-#ifndef __SMP__
+#ifndef CONFIG_SMP
ld [%o0 + AOFF_mm_context], %g2
cmp %g2, -1
be tsunami_flush_tlb_out
mov SRMMU_CTX_REG, %g1
ld [%o0 + AOFF_mm_context], %o3
andn %o1, (PAGE_SIZE - 1), %o1
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %o3, -1
be tsunami_flush_tlb_page_out
#endif
* Copyright (C) 1999 Pavel Semerad (semerad@ss1000.ms.mff.cuni.cz)
*/
+#include <linux/config.h>
#include <asm/ptrace.h>
#include <asm/psr.h>
#include <asm/asi.h>
#include <asm/cprefix.h>
#include <asm/btfixup.h>
-#ifdef __SMP__
+#ifdef CONFIG_SMP
.data
.align 4
sun4dsmp_flush_tlb_spin:
restore %g0, %g0, %g0;
viking_flush_cache_page:
-#ifndef __SMP__
+#ifndef CONFIG_SMP
ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */
#endif
viking_flush_cache_mm:
viking_flush_cache_range:
-#ifndef __SMP__
+#ifndef CONFIG_SMP
ld [%o0 + AOFF_mm_context], %g1
cmp %g1, -1
bne viking_flush_cache_all
mov SRMMU_CTX_REG, %g1
ld [%o0 + AOFF_mm_context], %o1
lda [%g1] ASI_M_MMUREGS, %g5
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %o1, -1
be 1f
#endif
sta %g0, [%g2] ASI_M_FLUSH_PROBE
retl
sta %g5, [%g1] ASI_M_MMUREGS
-#ifndef __SMP__
+#ifndef CONFIG_SMP
1: retl
nop
#endif
mov SRMMU_CTX_REG, %g1
ld [%o0 + AOFF_mm_context], %o3
lda [%g1] ASI_M_MMUREGS, %g5
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %o3, -1
be 2f
#endif
sta %g0, [%o1] ASI_M_FLUSH_PROBE
retl
sta %g5, [%g1] ASI_M_MMUREGS
-#ifndef __SMP__
+#ifndef CONFIG_SMP
2: retl
nop
#endif
mov SRMMU_CTX_REG, %g1
ld [%o0 + AOFF_mm_context], %o3
lda [%g1] ASI_M_MMUREGS, %g5
-#ifndef __SMP__
+#ifndef CONFIG_SMP
cmp %o3, -1
be 1f
#endif
sta %g0, [%o1] ASI_M_FLUSH_PROBE
retl
sta %g5, [%g1] ASI_M_MMUREGS
-#ifndef __SMP__
+#ifndef CONFIG_SMP
1: retl
nop
#endif
retl
nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
.globl sun4dsmp_flush_tlb_all, sun4dsmp_flush_tlb_mm
.globl sun4dsmp_flush_tlb_range, sun4dsmp_flush_tlb_page
sun4dsmp_flush_tlb_all:
dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
+ fi
fi
tristate ' SLIP (serial line) support' CONFIG_SLIP
if [ "$CONFIG_SLIP" != "n" ]; then
fi
endmenu
+mainmenu_option next_comment
+comment 'XFree86 DRI support'
+bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
+# dep_tristate ' Creator/Creator3D/Elite3D' CONFIG_DRM_FFB $CONFIG_DRM
+endmenu
+
source fs/Config.in
mainmenu_option next_comment
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PPP_DEFLATE is not set
# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
CONFIG_SLIP=m
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLIP_SMART=y
CONFIG_VIDEO_DEV=y
# CONFIG_VIDEO_BT848 is not set
+#
+# XFree86 DRI support
+#
+CONFIG_DRM=y
+
#
# File systems
#
CONFIG_HPFS_FS=m
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info))
-#ifdef __SMP__
+#ifdef CONFIG_SMP
char *sparc_cpu_type[64] = { "cpu-oops", "cpu-oops1", "cpu-oops2", "cpu-oops3" };
char *sparc_fpu_type[64] = { "fpu-oops", "fpu-oops1", "fpu-oops2", "fpu-oops3" };
#else
/* Setup Interrupt globals */
wrpr %o1, (PSTATE_IG|PSTATE_IE), %pstate
-#ifndef __SMP__
+#ifndef CONFIG_SMP
sethi %hi(__up_workvec), %g5
or %g5, %lo(__up_workvec), %g6
#else
-/* $Id: ioctl32.c,v 1.88 2000/04/14 10:10:34 davem Exp $
+/* $Id: ioctl32.c,v 1.89 2000/05/06 10:38:42 davem Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
#include <linux/fd.h>
#include <linux/ppp_defs.h>
#include <linux/if_ppp.h>
+#include <linux/if_pppox.h>
#include <linux/mtio.h>
#include <linux/cdrom.h>
#include <linux/loop.h>
COMPATIBLE_IOCTL(PPPIOCCONNECT)
COMPATIBLE_IOCTL(PPPIOCDISCONN)
COMPATIBLE_IOCTL(PPPIOCATTCHAN)
+/* PPPOX */
+COMPATIBLE_IOCTL(PPPOEIOCSFWD);
+COMPATIBLE_IOCTL(PPPOEIOCDFWD);
/* CDROM stuff */
COMPATIBLE_IOCTL(CDROMPAUSE)
COMPATIBLE_IOCTL(CDROMRESUME)
#define SA_IMAP_MASKED 0x100
#define SA_DMA_SYNC 0x200
-#ifdef __SMP__
+#ifdef CONFIG_SMP
static void distribute_irqs(void);
#endif
struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (64)));
-#ifndef __SMP__
+#ifndef CONFIG_SMP
unsigned int __up_workvec[16] __attribute__ ((aligned (64)));
#define irq_work(__cpu, __pil) &(__up_workvec[(void)(__cpu), (__pil)])
#else
{
int i, len = 0;
struct irqaction *action;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int j;
#endif
if(!(action = *(i + irq_action)))
continue;
len += sprintf(buf + len, "%3d: ", i);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
len += sprintf(buf + len, "%10u ", kstat_irqs(i));
#else
for (j = 0; j < smp_num_cpus; j++)
}
restore_flags(flags);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
distribute_irqs();
#endif
return 0;
/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it
* lives in the brlock table for cache reasons.
*/
-#ifndef __SMP__
+#ifndef CONFIG_SMP
unsigned int local_irq_count;
unsigned int local_bh_count;
#else
}
}
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
void catch_disabled_ivec(struct pt_regs *regs)
{
{
struct ino_bucket *bp, *nbp;
int cpu = smp_processor_id();
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern int this_is_starfire;
int should_forward = (this_is_starfire == 0 &&
irq < 10 &&
}
#endif
-#ifndef __SMP__
+#ifndef CONFIG_SMP
/*
* Check for TICK_INT on level 14 softint.
*/
kstat.irqs[cpu][irq]++;
/* Sliiiick... */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
bp = ((irq != 0) ?
__bucket(xchg32(irq_work(cpu, irq), 0)) :
&pil0_dummy_bucket);
}
/* Only the dummy bucket lacks IMAP/ICLR. */
if(bp->pil != 0) {
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Ok, here is what is going on:
* 1) Retargeting IRQs on Starfire is very
* expensive so just forget about it on them.
restore_flags(flags);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
distribute_irqs();
#endif
return 0;
unsigned long pstate;
extern unsigned long timer_tick_offset;
int node, err;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern void smp_tick_init(void);
#endif
node = linux_cpus[0].prom_node;
*clock = prom_getint(node, "clock-frequency");
timer_tick_offset = *clock / HZ;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
smp_tick_init();
#endif
sti();
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
static int retarget_one_irq(struct irqaction *p, int goal_cpu)
{
extern int this_is_starfire;
map_prom_timers();
kill_prom_timer();
memset(&ivector_table[0], 0, sizeof(ivector_table));
-#ifndef __SMP__
+#ifndef CONFIG_SMP
memset(&__up_workvec[0], 0, sizeof(__up_workvec));
#endif
}
/* #define VERBOSE_SHOWREGS */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
/*
* the idle loop on a Sparc... ;)
} while ((size -= sizeof(unsigned)));
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
static spinlock_t regdump_lock = SPIN_LOCK_UNLOCKED;
#endif
void __show_regs(struct pt_regs * regs)
{
-#ifdef __SMP__
+#ifdef CONFIG_SMP
unsigned long flags;
spin_lock_irqsave(®dump_lock, flags);
regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
regs->u_regs[15]);
show_regwindow(regs);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
spin_unlock_irqrestore(®dump_lock, flags);
#endif
}
extern long etrap, etraptl1;
#endif
__show_regs(regs);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
{
extern void smp_report_regs(void);
"type\t\t: sun4u\n"
"ncpus probed\t: %d\n"
"ncpus active\t: %d\n"
-#ifndef __SMP__
+#ifndef CONFIG_SMP
"BogoMips\t: %lu.%02lu\n"
#endif
,
sparc_fpu_type[cpuid],
prom_rev, prom_prev >> 16, (prom_prev >> 8) & 0xff, prom_prev & 0xff,
linux_num_cpus, smp_num_cpus
-#ifndef __SMP__
+#ifndef CONFIG_SMP
, loops_per_sec/500000, (loops_per_sec/5000) % 100
#endif
);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
len += smp_bogo(buffer + len);
#endif
len += mmu_info(buffer + len);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
len += smp_info(buffer + len);
#endif
#undef ZS_LOG
extern void dump_thread(struct pt_regs *, struct user *);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern spinlock_t kernel_flag;
extern int smp_num_cpus;
#ifdef SPIN_LOCK_DEBUG
{ (unsigned long) &__sparc_priv_ ## sym, "__" #sym }
/* used by various drivers */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#ifndef SPIN_LOCK_DEBUG
/* Out of line rw-locking implementation. */
EXPORT_SYMBOL_PRIVATE(read_lock);
-/* $Id: sys_sparc32.c,v 1.145 2000/04/13 07:30:34 jj Exp $
+/* $Id: sys_sparc32.c,v 1.146 2000/05/09 04:48:34 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
write_lock(&xtime_lock);
do {
-#ifndef __SMP__
+#ifndef CONFIG_SMP
if ((regs->tstate & TSTATE_PRIV) != 0)
sparc64_do_profile(regs->tpc, regs->u_regs[UREG_RETPC]);
#endif
write_unlock(&xtime_lock);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
void timer_tick_interrupt(struct pt_regs *regs)
{
write_lock(&xtime_lock);
instruction_dump ((unsigned int *) regs->tpc);
} else
user_instruction_dump ((unsigned int *) regs->tpc);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
smp_report_regs();
#endif
#ifdef CONFIG_EC_FLUSH_TRAP
void cache_flush_trap(struct pt_regs *regs)
{
-#ifndef __SMP__
+#ifndef CONFIG_SMP
unsigned node = linux_cpus[get_cpuid()].prom_node;
#else
#error cache_flush_trap not supported on sparc64/SMP yet
tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10)
tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12)
tl0_irq13: TRAP_IRQ(handler_irq, 13)
-#ifndef __SMP__
+#ifndef CONFIG_SMP
tl0_irq14: TRAP_IRQ(handler_irq, 14)
#else
tl0_irq14: TICK_SMP_IRQ
* Copyright (C) 1998 David S. Miller (davem@redhat.com)
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <asm/system.h>
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* To enable this code, just define SPIN_LOCK_DEBUG in asm/spinlock.h */
#ifdef SPIN_LOCK_DEBUG
}
#endif /* SPIN_LOCK_DEBUG */
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
if(pgtable_cache_size > high) {
do {
-#ifdef __SMP__
+#ifdef CONFIG_SMP
if(pgd_quicklist)
free_pgd_slow(get_pgd_fast()), freed++;
#endif
free_pte_slow(get_pte_fast(1)), freed++;
} while(pgtable_cache_size > low);
}
-#ifndef __SMP__
+#ifndef CONFIG_SMP
if (pgd_cache_size > high / 4) {
struct page *page, *page2;
for (page2 = NULL, page = (struct page *)pgd_quicklist; page;) {
printk("%ld pages of RAM\n", num_physpages);
printk("%d free pages\n", nr_free_pages());
printk("%d pages in page table cache\n",pgtable_cache_size);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
printk("%d entries in page dir cache\n",pgd_cache_size);
#endif
show_buffers();
mm->context = new_ctx;
}
-#ifndef __SMP__
+#ifndef CONFIG_SMP
struct pgtable_cache_struct pgt_quicklists;
#endif
initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin));
initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT;
-#ifndef __SMP__
+#ifndef CONFIG_SMP
{
/* Put empty_pg_dir on pgd_quicklist */
extern pgd_t empty_pg_dir[1024];
* Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com)
*/
+#include <linux/config.h>
#include <asm/asi.h>
#include <asm/pgtable.h>
#include <asm/page.h>
1: retl
nop
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* These are all called by the slaves of a cross call, at
* trap level 1, with interrupts fully disabled.
*
nop
flush %g6
retry
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
extern int serial_console;
#endif
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern void smp_capture(void);
extern void smp_release(void);
#endif
* So in order for everything to work reliably, even
* on SMP, we need to drop the IRQ locks we hold.
*/
-#ifdef __SMP__
+#ifdef CONFIG_SMP
irq_exit(smp_processor_id(), 0);
smp_capture();
#else
p1275_cmd ("enter", P1275_INOUT(0,0));
-#ifdef __SMP__
+#ifdef CONFIG_SMP
smp_release();
irq_enter(smp_processor_id(), 0);
spin_unlock_wait(&__br_write_locks[BR_GLOBALIRQ_LOCK].lock);
__restore_flags(flags);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern void smp_promstop_others(void);
#endif
void
prom_halt(void)
{
-#ifdef __SMP__
+#ifdef CONFIG_SMP
smp_promstop_others();
udelay(8000);
#endif
return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
void prom_startcpu(int cpunode, unsigned long pc, unsigned long o0)
{
p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, o0);
-/* $Id: fs.c,v 1.18 2000/04/08 02:11:54 davem Exp $
+/* $Id: fs.c,v 1.19 2000/05/09 04:48:35 davem Exp $
* fs.c: fs related syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/smp_lock.h>
case SOLARIS_CONFIG_PROF_TCK:
return prom_getintdefault(prom_cpu_nodes[smp_processor_id()],
"clock-frequency", 167000000);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
case SOLARIS_CONFIG_NPROC_CONF: return NR_CPUS;
case SOLARIS_CONFIG_NPROC_ONLN: return smp_num_cpus;
#else
echo
#
case $USMP in
- y* | Y* ) FSMP="-D__SMP__"
+ y* | Y* ) FSMP="-DCONFIG_SMP"
;;
*) FSMP=""
;;
/*
Local variables:
- compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c amiserial.c"
+ compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c amiserial.c"
End:
*/
A driver for PCMCIA serial devices
- serial_cs.c 1.117 1999/12/11 03:59:18
+ serial_cs.c 1.118 2000/05/04 01:29:47
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"serial_cs.c 1.117 1999/12/11 03:59:18 (David Hinds)";
+"serial_cs.c 1.118 2000/05/04 01:29:47 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
{
serial_info_t *info = link->priv;
dev_link_t **linkp;
- long flags;
int ret;
DEBUG(0, "serial_detach(0x%p)\n", link);
if (*linkp == NULL)
return;
- save_flags(flags);
- cli();
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- restore_flags(flags);
-
+ del_timer(&link->release);
if (link->state & DEV_CONFIG)
serial_release((u_long)link);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ if (link->state & DEV_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
#if (LINUX_VERSION_CODE > 0x20100)
serial_driver.driver_name = "serial";
#endif
-#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
+#ifdef CONFIG_DEVFS_FS
serial_driver.name = "tts/%d";
#else
serial_driver.name = "ttyS";
* major number and the subtype code.
*/
callout_driver = serial_driver;
-#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
+#ifdef CONFIG_DEVFS_FS
callout_driver.name = "cua/%d";
#else
callout_driver.name = "cua";
static void ide_detach(dev_link_t *link)
{
dev_link_t **linkp;
- long flags;
int ret;
DEBUG(0, "ide_detach(0x%p)\n", link);
if (*linkp == NULL)
return;
- save_flags(flags);
- cli();
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- restore_flags(flags);
-
+ del_timer(&link->release);
if (link->state & DEV_CONFIG)
ide_release((u_long)link);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ if (link->state & DEV_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
+ fi
fi
tristate 'SLIP (serial line) support' CONFIG_SLIP
# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
export-objs := 8390.o arlan.o aironet4500_core.o aironet4500_card.o ppp_async.o \
- ppp_generic.o slhc.o
+ ppp_generic.o slhc.o pppox.o
ifeq ($(CONFIG_PCMCIA),y)
SUB_DIRS += pcmcia
ifeq ($(CONFIG_PPP_BSDCOMP),m)
obj-m += bsd_comp.o
endif
+ obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
else
ifeq ($(CONFIG_PPP),m)
obj-m += ppp_generic.o slhc.o
obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
+ obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
ifeq ($(CONFIG_PPP_BSDCOMP),m)
obj-m += bsd_comp.o
endif
u_short media_status;
u_short fast_poll;
u_long last_irq;
- spinlock_t lock;
};
/* Set iff a MII transceiver on any interface requires mdio preamble.
static struct net_device_stats *el3_get_stats(struct net_device *dev);
static int el3_rx(struct net_device *dev, int worklimit);
static int el3_close(struct net_device *dev);
+static void el3_tx_timeout(struct net_device *dev);
static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void set_rx_mode(struct net_device *dev);
-static void el3_tx_timeout(struct net_device *dev);
static dev_info_t dev_info = "3c574_cs";
#endif
}
-/*
- We never need to do anything when a tc574 device is "initialized"
- by the net software, because we only register already-found cards.
-*/
-
-static int tc574_init(struct net_device *dev)
-{
- return 0;
-}
-
/*
tc574_attach() creates an "instance" of the driver, allocating
local data structures for one device. The device is registered
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
-
- lp->lock = SPIN_LOCK_UNLOCKED;
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
dev->do_ioctl = &el3_ioctl;
dev->set_multicast_list = &set_rx_mode;
ether_setup(dev);
- strcpy(dev->name, lp->node.dev_name);
- dev->init = &tc574_init;
dev->open = &el3_open;
dev->stop = &el3_close;
dev->tx_timeout = el3_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- netif_start_queue (dev);
-
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
{
struct el3_private *lp = link->priv;
dev_link_t **linkp;
- long flags;
DEBUG(0, "3c574_detach(0x%p)\n", link);
if (*linkp == NULL)
return;
- spin_lock_irqsave(&lp->lock, flags);
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- spin_unlock_irqrestore(&lp->lock, flags);
-
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
tc574_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
goto failed;
}
- link->state &= ~DEV_CONFIG_PENDING;
-
ioaddr = dev->base_addr;
+ strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node;
+ link->state &= ~DEV_CONFIG_PENDING;
/* The 3c574 normally uses an EEPROM for configuration info, including
the hardware address. The future products may include a modem chip
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ link->state &= ~DEV_CONFIG;
} /* tc574_release */
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(dev);
- link->release.expires = jiffies + HZ/20;
- add_timer(&link->release);
+ mod_timer(&link->release, jiffies + HZ/20);
}
break;
case CS_EVENT_CARD_INSERTION:
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
-
CardServices(ReleaseConfiguration, link->handle);
}
break;
link->open++;
MOD_INC_USE_COUNT;
- netif_start_queue (dev);
+ netif_start_queue(dev);
tc574_reset(dev);
lp->media.function = &media_check;
/* Issue TX_RESET and TX_START commands. */
wait_for_completion(dev, TxReset);
outw(TxEnable, ioaddr + EL3_CMD);
- netif_start_queue (dev);
+ netif_start_queue(dev);
}
static void pop_tx_status(struct net_device *dev)
/* TxFree appears only in Window 1, not offset 0x1c. */
if (inw(ioaddr + TxFree) <= 1536) {
- netif_stop_queue (dev);
+ netif_stop_queue(dev);
/* Interrupt us when the FIFO has room for max-sized packet.
The threshold is in units of dwords. */
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
}
-
+
dev_kfree_skb (skb);
pop_tx_status(dev);
ioaddr_t ioaddr, status;
int work_budget = max_interrupt_work;
- if (!netif_device_present(dev))
+ if (!netif_device_present(dev))
return;
-
- spin_lock (&lp->lock);
-
ioaddr = dev->base_addr;
DEBUG(3, "%s: interrupt, status %4.4x.\n",
while ((status = inw(ioaddr + EL3_STATUS)) &
(IntLatch | RxComplete | RxEarly | StatsFull)) {
-
- if (!netif_device_present(dev) || ((status & 0xe000) != 0x2000)) {
+ if (!netif_device_present(dev) ||
+ ((status & 0xe000) != 0x2000)) {
DEBUG(1, "%s: Interrupt from dead card\n", dev->name);
break;
}
DEBUG(3, " TX room bit was handled.\n");
/* There's room in the FIFO for a full-sized packet. */
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
- netif_wake_queue (dev);
+ netif_wake_queue(dev);
}
if (status & TxComplete)
DEBUG(3, "%s: exiting interrupt, status %4.4x.\n",
dev->name, inw(ioaddr + EL3_STATUS));
-
- spin_unlock (&lp->lock);
+ return;
}
/*
ioaddr_t ioaddr = dev->base_addr;
u_long flags;
u_short /* cable, */ media, partner;
-
- if (!netif_device_present(dev))
+
+ if (!netif_device_present(dev))
goto reschedule;
/* Check for pending interrupt with expired latency timer: with
{
struct el3_private *lp = (struct el3_private *)dev->priv;
ioaddr_t ioaddr = dev->base_addr;
- u8 upper_cnt;
+ u8 rx, tx, up;
DEBUG(2, "%s: updating the statistics.\n", dev->name);
lp->stats.tx_window_errors += inb(ioaddr + 4);
lp->stats.rx_fifo_errors += inb(ioaddr + 5);
lp->stats.tx_packets += inb(ioaddr + 6);
- upper_cnt = inb(ioaddr + 9);
- lp->stats.tx_packets += (upper_cnt&0x30) << 4;
- /* Rx packets */ inb(ioaddr + 7);
- /* Tx deferrals */ inb(ioaddr + 8);
- lp->stats.rx_bytes += inw(ioaddr + 10);
- lp->stats.tx_bytes += inw(ioaddr + 12);
-
- /* With Vortex and later we must also clear the BadSSD counter. */
+ up = inb(ioaddr + 9);
+ lp->stats.tx_packets += (up&0x30) << 4;
+ /* Rx packets */ inb(ioaddr + 7);
+ /* Tx deferrals */ inb(ioaddr + 8);
+ rx = inw(ioaddr + 10);
+ tx = inw(ioaddr + 12);
+
EL3WINDOW(4);
- inb(ioaddr + 12);
+ /* BadSSD */ inb(ioaddr + 12);
+ up = inb(ioaddr + 13);
- {
- u8 up = inb(ioaddr + 13);
- lp->stats.rx_bytes += (up & 0x0f) << 16;
- lp->stats.tx_bytes += (up & 0xf0) << 12;
- }
+ lp->stats.rx_bytes += rx + ((up & 0x0f) << 16);
+ lp->stats.tx_bytes += tx + ((up & 0xf0) << 12);
EL3WINDOW(1);
}
DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
- netif_stop_queue (dev);
-
if (DEV_OK(link)) {
/* Turn off statistics ASAP. We update lp->stats below. */
outw(StatsDisable, ioaddr + EL3_CMD);
}
link->open--;
+ netif_stop_queue(dev);
del_timer(&lp->media);
- if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
- 3c589_cs.c 1.145 2000/02/11 03:11:51
+ 3c589_cs.c 1.151 2000/05/08 22:03:18
The network driver code is based on Donald Becker's 3c589 code:
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"3c589_cs.c 1.145 2000/02/11 03:11:51 (David Hinds)";
+"3c589_cs.c 1.151 2000/05/08 22:03:18 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
static int el3_rx(struct net_device *dev);
static int el3_close(struct net_device *dev);
static void el3_tx_timeout(struct net_device *dev);
-
static void set_multicast_list(struct net_device *dev);
static dev_info_t dev_info = "3c589_cs";
CardServices(ReportError, handle, &err);
}
-/*======================================================================
-
- We never need to do anything when a tc589 device is "initialized"
- by the net software, because we only register already-found cards.
-
-======================================================================*/
-
-static int tc589_init(struct net_device *dev)
-{
- return 0;
-}
-
/*======================================================================
tc589_attach() creates an "instance" of the driver, allocating
dev->get_stats = &el3_get_stats;
dev->set_multicast_list = &set_multicast_list;
ether_setup(dev);
- strcpy(dev->name, lp->node.dev_name);
- dev->init = &tc589_init;
dev->open = &el3_open;
dev->stop = &el3_close;
dev->tx_timeout = el3_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- netif_start_queue (dev);
-
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
{
struct el3_private *lp = link->priv;
dev_link_t **linkp;
- long flags;
DEBUG(0, "3c589_detach(0x%p)\n", link);
if (*linkp == NULL)
return;
- save_flags(flags);
- cli();
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- restore_flags(flags);
-
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
tc589_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c589_cs: register_netdev() failed\n");
goto failed;
}
- link->state &= ~DEV_CONFIG_PENDING;
ioaddr = dev->base_addr;
EL3WINDOW(0);
goto failed;
}
}
-
+
+ strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node;
+ link->state &= ~DEV_CONFIG_PENDING;
/* The address and resource configuration register aren't loaded from
the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ link->state &= ~DEV_CONFIG;
} /* tc589_release */
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(dev);
- link->release.expires = jiffies + HZ/20;
- add_timer(&link->release);
+ mod_timer(&link->release, jiffies + HZ/20);
}
break;
case CS_EVENT_CARD_INSERTION:
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
-
CardServices(ReleaseConfiguration, link->handle);
}
break;
link->open++;
MOD_INC_USE_COUNT;
- netif_start_queue (dev);
+ netif_start_queue(dev);
tc589_reset(dev);
lp->media.function = &media_check;
/* Issue TX_RESET and TX_START commands. */
wait_for_completion(dev, TxReset);
outw(TxEnable, ioaddr + EL3_CMD);
- netif_start_queue (dev);
+ netif_start_queue(dev);
}
static void pop_tx_status(struct net_device *dev)
"status %4.4x.\n", dev->name, (long)skb->len,
inw(ioaddr + EL3_STATUS));
- netif_stop_queue (dev);
- {
- struct el3_private *lp = (struct el3_private *)dev->priv;
- lp->stats.tx_bytes += skb->len;
- }
+ ((struct el3_private *)dev->priv)->stats.tx_bytes += skb->len;
+
/* Put out the doubleword header... */
outw(skb->len, ioaddr + TX_FIFO);
outw(0x00, ioaddr + TX_FIFO);
outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
dev->trans_start = jiffies;
- if (inw(ioaddr + TX_FREE) > 1536) {
- netif_start_queue (dev);
- } else
+ if (inw(ioaddr + TX_FREE) <= 1536) {
+ netif_stop_queue(dev);
/* Interrupt us when the FIFO has room for max-sized packet. */
outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
+ }
dev_kfree_skb(skb);
pop_tx_status(dev);
while ((status = inw(ioaddr + EL3_STATUS)) &
(IntLatch | RxComplete | StatsFull)) {
- if (!netif_device_present(dev) || ((status & 0xe000) != 0x2000)) {
+ if (!netif_device_present(dev) ||
+ ((status & 0xe000) != 0x2000)) {
DEBUG(1, "%s: interrupt from dead card\n", dev->name);
break;
}
DEBUG(3, " TX room bit was handled.\n");
/* There's room in the FIFO for a full-sized packet. */
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
- netif_wake_queue (dev);
+ netif_wake_queue(dev);
}
if (status & TxComplete)
u_short media, errs;
u_long flags;
- if (!netif_device_present(dev))
- goto reschedule;
+ if (!netif_device_present(dev)) goto reschedule;
EL3WINDOW(1);
/* Check for pending interrupt with expired latency timer: with
ioaddr_t ioaddr = dev->base_addr;
DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
-
- netif_stop_queue (dev);
if (DEV_OK(link)) {
/* Turn off statistics ASAP. We update lp->stats below. */
}
link->open--;
+ netif_stop_queue(dev);
del_timer(&lp->media);
- if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
static void fmvj18x_release(u_long arg);
static int fmvj18x_event(event_t event, int priority,
event_callback_args_t *args);
-static int fmvj18x_init(struct net_device *dev);
static dev_link_t *fmvj18x_attach(void);
static void fmvj18x_detach(dev_link_t *);
static void fjn_reset(struct net_device *dev);
static struct net_device_stats *fjn_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
-static void fjn_tx_timeout (struct net_device *dev);
+static void fjn_tx_timeout(struct net_device *dev);
static dev_info_t dev_info = "fmvj18x_cs";
static dev_link_t *dev_list = NULL;
cardtype_t cardtype;
u_short sent;
u_char mc_filter[8];
- spinlock_t lock;
} local_info_t;
#define MC_FILTERBREAK 64
#define INTR_OFF 0x0d /* LAN controler ignores interrupts */
#define INTR_ON 0x1d /* LAN controler will catch interrupts */
-#define TX_TIMEOUT 10
+#define TX_TIMEOUT ((400*HZ)/1000)
/*======================================================================
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
-
- lp->lock = SPIN_LOCK_UNLOCKED;
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
dev->set_config = &fjn_config;
dev->get_stats = &fjn_get_stats;
dev->set_multicast_list = &set_rx_mode;
- strcpy(dev->name, lp->node.dev_name);
ether_setup(dev);
- dev->init = &fmvj18x_init;
dev->open = &fjn_open;
dev->stop = &fjn_close;
dev->tx_timeout = fjn_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- netif_start_queue (dev);
/* Register with Card Services */
link->next = dev_list;
{
local_info_t *lp = link->priv;
dev_link_t **linkp;
- long flags;
DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
if (*linkp == NULL)
return;
- save_flags(flags);
- cli();
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- restore_flags(flags);
-
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
fmvj18x_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
CS_CHECK(RequestConfiguration, link->handle, &link->conf);
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
goto failed;
break;
}
+ strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ link->state &= ~DEV_CONFIG;
} /* fmvj18x_release */
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(dev);
- link->release.expires = jiffies + HZ/20;
- add_timer(&link->release);
+ mod_timer(&link->release, jiffies + HZ/20);
}
break;
case CS_EVENT_CARD_INSERTION:
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
if (link->open)
- netif_device_detach(dev);
-
+ netif_device_detach(dev);
CardServices(ReleaseConfiguration, link->handle);
}
break;
return 0;
} /* fmvj18x_event */
-static int fmvj18x_init(struct net_device *dev)
-{
- return 0;
-} /* fmvj18x_init */
-
/*====================================================================*/
static int __init init_fmvj18x_cs(void)
"unknown device.\n", irq);
return;
}
-
- spin_lock (&lp->lock);
-
ioaddr = dev->base_addr;
/* avoid multiple interrupts */
lp->tx_queue = 0;
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
- netif_wake_queue (dev);
} else {
lp->tx_started = 0;
- netif_stop_queue (dev);
}
+ netif_wake_queue(dev);
}
DEBUG(4, "%s: exiting interrupt,\n", dev->name);
DEBUG(4, " tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
outb(D_TX_INTR, ioaddr + TX_INTR);
outb(D_RX_INTR, ioaddr + RX_INTR);
- spin_unlock (&lp->lock);
-
} /* fjn_interrupt */
/*====================================================================*/
-static void fjn_tx_timeout (struct net_device *dev)
+
+static void fjn_tx_timeout(struct net_device *dev)
{
- struct local_info_t *lp = (struct local_info_t *) dev->priv;
- ioaddr_t ioaddr = dev->base_addr;
- unsigned long flags;
-
- printk (KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
- dev->name, htons (inw (ioaddr + TX_STATUS)),
- inb (ioaddr + TX_STATUS) & F_TMT_RDY
- ? "IRQ conflict" : "network cable problem");
- printk (KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
- "%04x %04x %04x %04x %04x.\n",
- dev->name, htons (inw (ioaddr + 0)),
- htons (inw (ioaddr + 2)), htons (inw (ioaddr + 4)),
- htons (inw (ioaddr + 6)), htons (inw (ioaddr + 8)),
- htons (inw (ioaddr + 10)), htons (inw (ioaddr + 12)),
- htons (inw (ioaddr + 14)));
- lp->stats.tx_errors++;
-
- /* ToDo: We should try to restart the adaptor... */
- spin_lock_irqsave (&lp->lock, flags);
-
- fjn_reset (dev);
-
- lp->tx_started = 0;
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- lp->sent = 0;
- lp->open_time = jiffies;
- netif_start_queue (dev);
-
- spin_unlock_irqrestore (&lp->lock, flags);
-}
+ struct local_info_t *lp = (struct local_info_t *)dev->priv;
+ ioaddr_t ioaddr = dev->base_addr;
+
+ printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
+ dev->name, htons(inw(ioaddr + TX_STATUS)),
+ inb(ioaddr + TX_STATUS) & F_TMT_RDY
+ ? "IRQ conflict" : "network cable problem");
+ printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
+ "%04x %04x %04x %04x %04x.\n",
+ dev->name, htons(inw(ioaddr + 0)),
+ htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
+ htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
+ htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
+ htons(inw(ioaddr +14)));
+ lp->stats.tx_errors++;
+ /* ToDo: We should try to restart the adaptor... */
+ cli();
+
+ fjn_reset(dev);
+ lp->tx_started = 0;
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+ lp->sent = 0;
+ lp->open_time = jiffies;
+ sti();
+ netif_start_queue(dev);
+}
static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct local_info_t *lp = (struct local_info_t *)dev->priv;
ioaddr_t ioaddr = dev->base_addr;
- netif_stop_queue (dev);
- if (1) {
+ netif_stop_queue(dev);
+
+ {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
lp->tx_started = 1;
- netif_start_queue (dev);
+ netif_start_queue(dev);
} else {
if( sram_config == 0 ) {
if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
/* Yes, there is room for one more packet. */
- netif_start_queue (dev);
+ netif_start_queue(dev);
} else {
if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) &&
lp->tx_queue < 127 )
/* Yes, there is room for one more packet. */
- netif_start_queue (dev);
+ netif_start_queue(dev);
}
}
}
/* If any worth-while packets have been received, dev_rint()
- has done a mark_bh(NET_BH) for us and will work on them
+ has done a netif_wake_queue() for us and will work on them
when we get to the bottom-half routine. */
/*
if( lp->cardtype != TDK ) {
lp->tx_queue = 0;
lp->tx_queue_len = 0;
lp->open_time = jiffies;
- netif_start_queue (dev);
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
DEBUG(4, "fjn_close('%s').\n", dev->name);
lp->open_time = 0;
- netif_stop_queue (dev);
+ netif_stop_queue(dev);
/* Set configuration register 0 to disable Tx and Rx. */
if( sram_config == 0 )
outb(INTR_OFF, ioaddr + LAN_CTRL);
link->open--;
- if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
return 0;
Updated to version 2.2.7 to match the first version of the kernel
that the modification to ibmtr.c were incorporated into.
-
======================================================================*/
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
-#define PCMCIA_DEBUG 10
#ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
dev->init = &ibmtr_probe;
-#if 0
- dev->tbusy = 1;
-#endif
-
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
struct ibmtr_dev_t *info = link->priv;
dev_link_t **linkp;
struct net_device *dev;
- long flags;
-
DEBUG(0, "ibmtr_detach(0x%p)\n", link);
return;
dev = info->dev;
-
- save_flags(flags);
- cli();
{
struct tok_info *ti = (struct tok_info *)dev->priv;
- if (timer_pending(&ti->tr_timer)) del_timer(&ti->tr_timer);
+ del_timer(&(ti->tr_timer));
}
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- restore_flags(flags);
-
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
ibmtr_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
req.Base = mmiobase;
req.Size = 0x2000;
req.AccessSpeed = 250;
- link->win = (window_handle_t) link->handle;
+ link->win = (window_handle_t)link->handle;
CS_CHECK(RequestWindow, &link->win, &req);
+
mem.CardOffset = req.Base;
mem.Page = 0;
CS_CHECK(MapMemPage, link->win, &mem);
Adapters Technical Reference" SC30-3585 for this info. */
ibmtr_hw_setup(dev);
-#if 0
- dev->tbusy = 0;
-#endif
-
i = register_trdev(dev);
if (i != 0) {
dev_link_t *link = (dev_link_t *)arg;
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
- struct tok_info *ti=(struct tok_info *) dev->priv;
DEBUG(0, "ibmtr_release(0x%p)\n", link);
return;
}
- ti->open_status=CLOSED;
-
CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
CardServices(ReleaseWindow, info->sram_win_handle);
}
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ link->state &= ~DEV_CONFIG;
} /* ibmtr_release */
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
-#if 0
- dev->tbusy = 1; dev->start = 0;
-#endif
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
+ netif_device_detach(dev);
+ mod_timer(&link->release, jiffies + HZ/20);
}
break;
case CS_EVENT_CARD_INSERTION:
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
-#if 0
- if (link->open) {
- dev->tbusy = 1; dev->start = 0;
- }
-#endif
+ if (link->open)
+ netif_device_detach(dev);
CardServices(ReleaseConfiguration, link->handle);
}
break;
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
(dev->init)(dev);
-#if 0
- dev->tbusy = 0; dev->start = 1;
-#endif
+ netif_device_attach(dev);
}
}
break;
---------------------------------------------------------------------------- */
#define MULTI_TX 0
-#define TIMEOUT_TX 1
#define RESET_ON_TIMEOUT 1
#define TX_INTERRUPTABLE 1
#define RESET_XILINX 0
#define MACE_LADRF_LEN 8
/* 8 bytes in Logical Address Filter */
-/* Transmitter Busy Bit Index Defines */
-#define TBUSY_UNSPECIFIED 0
-#define TBUSY_PARTIAL_TX_FRAME 0
-#define TBUSY_NO_FREE_TX_FRAMES 1
-
/* Loop Control Defines */
#define MACE_MAX_IR_ITERATIONS 10
#define MACE_MAX_RX_ITERATIONS 12
#undef MACE_IMR_DEFAULT
#define MACE_IMR_DEFAULT 0x00 /* New statistics handling: grab everything */
-#define TX_TIMEOUT (5*HZ)
-
-
+#define TX_TIMEOUT ((400*HZ)/1000)
/* ----------------------------------------------------------------------------
Type Definitions
dev_link_t link;
struct net_device dev;
dev_node_t node;
- spinlock_t lock;
struct net_device_stats linux_stats; /* Linux statistics counters */
mace_statistics mace_stats; /* MACE chip statistics counters */
static int mace_open(struct net_device *dev);
static int mace_close(struct net_device *dev);
static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void mace_tx_timeout(struct net_device *dev);
static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static struct net_device_stats *mace_get_stats(struct net_device *dev);
static int mace_rx(struct net_device *dev, unsigned char RxCnt);
static void restore_multicast_list(struct net_device *dev);
-static void mace_tx_timeout (struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
CardServices(ReportError, handle, &err);
}
-/* ----------------------------------------------------------------------------
-nmclan_init
- We never need to do anything when a nmclan device is "initialized"
- by the net software, because we only register already-found cards.
----------------------------------------------------------------------------- */
-
-static int nmclan_init(struct net_device *dev)
-{
- return 0;
-}
-
/* ----------------------------------------------------------------------------
nmclan_attach
Creates an "instance" of the driver, allocating local data
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
-
- lp->lock = SPIN_LOCK_UNLOCKED;
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
dev->set_config = &mace_config;
dev->get_stats = &mace_get_stats;
dev->set_multicast_list = &set_multicast_list;
- strcpy(dev->name, lp->node.dev_name);
ether_setup(dev);
- dev->init = &nmclan_init;
dev->open = &mace_open;
dev->stop = &mace_close;
dev->tx_timeout = mace_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- netif_start_queue (dev);
-
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
if (*linkp == NULL)
return;
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
nmclan_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
CS_CHECK(RequestConfiguration, handle, &link->conf);
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- netif_start_queue (dev);
i = register_netdev(dev);
if (i != 0) {
printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
else
printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
+ strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ link->state &= ~DEV_CONFIG;
} /* nmclan_release */
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(dev);
- link->release.expires = jiffies + HZ/20;
- add_timer(&link->release);
+ mod_timer(&link->release, jiffies + HZ/20);
}
break;
case CS_EVENT_CARD_INSERTION:
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
-
CardServices(ReleaseConfiguration, link->handle);
}
break;
return 0;
} /* nmclan_event */
-/* ------------------------------------------------------------------------- */
-
/* ----------------------------------------------------------------------------
nmclan_reset
Reset and restore all of the Xilinx and MACE registers.
MACEBANK(0);
- netif_start_queue (dev);
+ netif_start_queue(dev);
nmclan_reset(dev);
return 0; /* Always succeed */
dev_link_t *link = &lp->link;
DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
-
- netif_stop_queue (dev);
/* Mask off all interrupts from the MACE chip. */
outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR);
link->open--;
- if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ netif_stop_queue(dev);
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
return 0;
} /* mace_close */
-
-static void mace_tx_timeout (struct net_device *dev)
-{
- mace_private *lp = (mace_private *)dev->priv;
- dev_link_t *link = &lp->link;
-
- printk (KERN_NOTICE "%s: transmit timed out -- ", dev->name);
-#if RESET_ON_TIMEOUT
- printk ("resetting card\n");
- CardServices (ResetCard, link->handle);
-#else /* #if RESET_ON_TIMEOUT */
- printk ("NOT resetting card\n");
-#endif /* #if RESET_ON_TIMEOUT */
- dev->trans_start = jiffies;
- netif_start_queue (dev);
-}
-
-
/* ----------------------------------------------------------------------------
mace_start_xmit
This routine begins the packet transmit function. When completed,
driver." If _start_xmit returns non-zero, the "transmission
failed, put skb back into a list."
---------------------------------------------------------------------------- */
+
+static void mace_tx_timeout(struct net_device *dev)
+{
+ mace_private *lp = (mace_private *)dev->priv;
+ dev_link_t *link = &lp->link;
+
+ printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
+#if RESET_ON_TIMEOUT
+ printk("resetting card\n");
+ CardServices(ResetCard, link->handle);
+#else /* #if RESET_ON_TIMEOUT */
+ printk("NOT resetting card\n");
+#endif /* #if RESET_ON_TIMEOUT */
+ dev->trans_start = jiffies;
+ netif_start_queue(dev);
+}
+
static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
mace_private *lp = (mace_private *)dev->priv;
ioaddr_t ioaddr = dev->base_addr;
+ netif_stop_queue(dev);
+
DEBUG(3, "%s: mace_start_xmit(length = %ld) called.\n",
dev->name, (long)skb->len);
- netif_stop_queue (dev);
-
#if (!TX_INTERRUPTABLE)
/* Disable MACE TX interrupts. */
outb(MACE_IMR_DEFAULT | MACE_IR_XMTINT,
{
/* This block must not be interrupted by another transmit request!
- dev->tbusy will take care of timer-based retransmissions from
+ mace_tx_timeout will take care of timer-based retransmissions from
the upper layers. The interrupt handler is guaranteed never to
service a transmit interrupt while we are in here.
*/
dev->trans_start = jiffies;
- if (lp->tx_free_frames > 0) {
#if MULTI_TX
- netif_start_queue (dev);
+ if (lp->tx_free_frames > 0)
+ netif_start_queue(dev);
#endif /* #if MULTI_TX */
- }
-
}
#if (!TX_INTERRUPTABLE)
irq);
return;
}
-
- spin_lock (&lp->lock);
if (lp->tx_irq_disabled) {
printk(
lp->linux_stats.tx_packets++;
lp->tx_free_frames++;
- netif_wake_queue (dev);
+ netif_wake_queue(dev);
} /* if (status & MACE_IR_XMTINT) */
if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) {
} while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt));
exception:
- spin_unlock (&lp->lock);
+ return;
} /* mace_interrupt */
/* ----------------------------------------------------------------------------
Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
- pcnet_cs.c 1.112 2000/02/11 01:24:44
+ pcnet_cs.c 1.117 2000/05/04 01:29:47
The network driver code is based on Donald Becker's NE2000 code:
======================================================================*/
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"pcnet_cs.c 1.112 2000/02/11 01:24:44 (David Hinds)";
+"pcnet_cs.c 1.117 2000/05/04 01:29:47 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
event_callback_args_t *args);
static int pcnet_open(struct net_device *dev);
static int pcnet_close(struct net_device *dev);
+static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
static void ei_watchdog(u_long arg);
static void pcnet_reset_8390(struct net_device *dev);
/*====================================================================*/
typedef struct hw_info_t {
- u_long offset;
+ u_int offset;
u_char a0, a1, a2;
- u_long flags;
+ u_int flags;
} hw_info_t;
#define DELAY_OUTPUT 0x01
#define HAS_MISC_REG 0x02
#define USE_BIG_BUF 0x04
#define HAS_IBM_MISC 0x08
-#define IS_DL10019A 0x10
+#define IS_DL10019 0x10
+#define IS_AX88190 0x20
#define USE_SHMEM 0x80 /* autodetected */
static hw_info_t hw_info[] = {
{ /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
{ /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
{ /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 },
- { /* PCMCIA Technology OEM */ 0x01c8, 0xa0, 0x0c, 0 }
+ { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }
};
#define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t))
static hw_info_t default_info =
{ /* Unknown NE2000 Clone */ 0x00, 0x00, 0x00, 0x00, 0 };
-static hw_info_t dl_fast_info =
-{ /* D-Link EtherFast */ 0x00, 0x00, 0x00, 0x00, IS_DL10019A };
+static hw_info_t dl10019_info =
+{ /* D-Link DL10019 chipset */ 0x00, 0x00, 0x00, 0x00, IS_DL10019 };
typedef struct pcnet_dev_t {
- struct net_device dev; /* so &dev == &pcnet_dev_t */
+ struct net_device dev; /* so &dev == &pcnet_dev_t */
dev_link_t link;
dev_node_t node;
- u_long flags;
+ u_int flags;
caddr_t base;
struct timer_list watchdog;
- int stale, state;
- u_short fast_poll;
+ int stale, fast_poll;
+ u_char link_status;
} pcnet_dev_t;
/*======================================================================
link->conf.IntType = INT_MEMORY_AND_IO;
ethdev_init(dev);
- strcpy(dev->name, info->node.dev_name);
dev->init = &pcnet_init;
dev->open = &pcnet_open;
dev->stop = &pcnet_close;
dev->set_config = &set_config;
- netif_stop_queue(dev);
-
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
{
pcnet_dev_t *info = link->priv;
dev_link_t **linkp;
- long flags;
DEBUG(0, "pcnet_detach(0x%p)\n", link);
if (*linkp == NULL)
return;
- save_flags(flags);
- cli();
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- restore_flags(flags);
-
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
pcnet_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
} /* pcnet_detach */
-/*======================================================================
-
- For the Linksys EtherFast 10/100 card
-
-======================================================================*/
-
-static hw_info_t *get_dl_fast(dev_link_t *link)
-{
- struct net_device *dev = link->priv;
- int i;
- u_char sum;
-
- for (sum = 0, i = 0x14; i < 0x1c; i++)
- sum += inb_p(dev->base_addr + i);
- if (sum != 0xff)
- return NULL;
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i);
- return &dl_fast_info;
-}
-
/*======================================================================
This probes for a card's hardware address, for card types that
static hw_info_t *get_prom(dev_link_t *link)
{
struct net_device *dev = link->priv;
- unsigned char prom[32];
- ioaddr_t ioaddr;
+ ioaddr_t ioaddr = dev->base_addr;
+ u_char prom[32];
int i, j;
/* This is lifted straight from drivers/net/ne.c */
struct {
- unsigned char value, offset;
+ u_char value, offset;
} program_seq[] = {
{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
{0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
{E8390_RREAD+E8390_START, E8390_CMD},
};
- ioaddr = dev->base_addr;
-
pcnet_reset_8390(dev);
udelay(10000);
return NULL;
} /* get_prom */
+/*======================================================================
+
+ For DL10019 based cards, like the Linksys EtherFast
+
+======================================================================*/
+
+static hw_info_t *get_dl10019(dev_link_t *link)
+{
+ struct net_device *dev = link->priv;
+ int i;
+ u_char sum;
+
+ for (sum = 0, i = 0x14; i < 0x1c; i++)
+ sum += inb_p(dev->base_addr + i);
+ if (sum != 0xff)
+ return NULL;
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i);
+ return &dl10019_info;
+}
+
+/*======================================================================
+
+ For Asix AX88190 based cards
+
+======================================================================*/
+
+static hw_info_t *get_ax88190(dev_link_t *link)
+{
+ struct net_device *dev = link->priv;
+ ioaddr_t ioaddr = dev->base_addr;
+ int i, j;
+
+ /* Not much of a test, but the alternatives are messy */
+ if (link->conf.ConfigBase != 0x03c0)
+ return NULL;
+
+ outb_p(0x01, EN0_DCFG); /* Set word-wide access. */
+ outb_p(0x00, EN0_RSARLO); /* DMA starting at 0x0400. */
+ outb_p(0x04, EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, E8390_CMD);
+
+ for (i = 0; i < 6; i += 2) {
+ j = inw(ioaddr + PCNET_DATAPORT);
+ dev->dev_addr[i] = j & 0xff;
+ dev->dev_addr[i+1] = j >> 8;
+ }
+ printk(KERN_INFO "pcnet_cs: sorry, the AX88190 chipset is not "
+ "supported.\n");
+ return NULL;
+}
+
/*======================================================================
This should be totally unnecessary... but when we can't figure
} else {
dev->if_port = 0;
}
- netif_start_queue(dev);
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
goto failed;
if (hw_info == NULL)
hw_info = get_prom(link);
if (hw_info == NULL)
- hw_info = get_dl_fast(link);
+ hw_info = get_dl10019(link);
+ if (hw_info == NULL)
+ hw_info = get_ax88190(link);
if (hw_info == NULL)
hw_info = get_hwired(link);
ei_status.word16 = 1;
ei_status.reset_8390 = &pcnet_reset_8390;
+ strcpy(info->node.dev_name, dev->name);
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
- printk(KERN_INFO "%s: NE2000 Compatible: io %#3lx, irq %d,",
- dev->name, dev->base_addr, dev->irq);
+ if (info->flags & IS_DL10019) {
+ dev->do_ioctl = &do_ioctl;
+ printk(KERN_INFO "%s: NE2000 (DL10019 rev %02x): ",
+ dev->name, inb(dev->base_addr + 0x1a));
+ } else if (info->flags & IS_AX88190) {
+ printk(KERN_INFO "%s: NE2000 (AX88190): ", dev->name);
+ } else
+ printk(KERN_INFO "%s: NE2000 Compatible: ", dev->name);
+ printk("io %#3lx, irq %d,", dev->base_addr, dev->irq);
if (info->flags & USE_SHMEM)
printk (" mem %#5lx,", dev->mem_start);
if (info->flags & HAS_MISC_REG)
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ link->state &= ~DEV_CONFIG;
} /* pcnet_release */
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(&info->dev);
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
+ mod_timer(&link->release, jiffies + HZ/20);
}
break;
case CS_EVENT_CARD_INSERTION:
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(&info->dev);
-
CardServices(ReleaseConfiguration, link->handle);
}
break;
request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev);
/* Start by assuming the link is bad */
- info->state = 1;
+ info->link_status = 1;
info->watchdog.function = &ei_watchdog;
info->watchdog.data = (u_long)info;
info->watchdog.expires = jiffies + HZ;
free_irq(dev->irq, dev);
link->open--;
+ netif_stop_queue(dev);
del_timer(&info->watchdog);
- if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
} /* pcnet_reset_8390 */
-/* ======================================================================= */
+/*====================================================================*/
static int set_config(struct net_device *dev, struct ifmap *map)
{
return 0;
}
-/* ======================================================================= */
+/*====================================================================*/
static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = &info->dev;
ioaddr_t nic_base = dev->base_addr;
- if (!netif_device_present(dev))
- goto reschedule;
+ if (!netif_device_present(dev)) goto reschedule;
/* Check for pending interrupt with expired latency timer: with
this, we can limp along even if the interrupt is blocked */
return;
}
- if (info->flags & IS_DL10019A) {
- int state = inb(dev->base_addr+0x1c) & 0x01;
- if (state != info->state) {
+ if (info->flags & IS_DL10019) {
+ u_char link = inb(dev->base_addr+0x1c) & 0x01;
+ if (link != info->link_status) {
printk(KERN_INFO "%s: %s link beat\n", dev->name,
- (state) ? "lost" : "found");
- if (!state)
+ (link) ? "lost" : "found");
+ if (!link)
NS8390_init(dev, 1);
- info->state = state;
+ info->link_status = link;
}
}
add_timer(&info->watchdog);
}
-/* ======================================================================= */
+/*======================================================================
+
+ MII interface support for DL10019 based cards
+
+ There are two types of DL10019 based cards. Some have the MII IO
+ direction bit as 0x10, others as 0x20; setting both bits seems to
+ work on all cards.
+
+======================================================================*/
+
+#define MDIO_SHIFT_CLK 0x80
+#define MDIO_DATA_OUT 0x40
+#define MDIO_DIR_WRITE 0x30
+#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT)
+#define MDIO_DATA_READ 0x10
+#define MDIO_MASK 0x0f
+
+static void mdio_sync(ioaddr_t addr)
+{
+ int bits, mask = inb(addr) & MDIO_MASK;
+ for (bits = 0; bits < 32; bits++) {
+ outb(mask | MDIO_DATA_WRITE1, addr);
+ outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
+ }
+}
+
+static int mdio_read(ioaddr_t addr, int phy_id, int loc)
+{
+ u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
+ int i, retval = 0, mask = inb(addr) & MDIO_MASK;
+
+ mdio_sync(addr);
+ for (i = 13; i >= 0; i--) {
+ int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+ outb(mask | dat, addr);
+ outb(mask | dat | MDIO_SHIFT_CLK, addr);
+ }
+ for (i = 19; i > 0; i--) {
+ outb(mask, addr);
+ retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
+ outb(mask | MDIO_SHIFT_CLK, addr);
+ }
+ return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value)
+{
+ u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+ int i, mask = inb(addr) & MDIO_MASK;
+
+ mdio_sync(addr);
+ for (i = 31; i >= 0; i--) {
+ int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+ outb(mask | dat, addr);
+ outb(mask | dat | MDIO_SHIFT_CLK, addr);
+ }
+ for (i = 1; i >= 0; i--) {
+ outb(mask, addr);
+ outb(mask | MDIO_SHIFT_CLK, addr);
+ }
+}
+
+static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ u16 *data = (u16 *)&rq->ifr_data;
+ ioaddr_t addr = dev->base_addr + 0x1c;
+ switch (cmd) {
+ case SIOCDEVPRIVATE:
+ data[0] = 0;
+ case SIOCDEVPRIVATE+1:
+ data[3] = mdio_read(addr, 0, data[1] & 0x1f);
+ return 0;
+ case SIOCDEVPRIVATE+2:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ mdio_write(addr, 0, data[1] & 0x1f, data[2]);
+ return 0;
+ }
+ return -EOPNOTSUPP;
+}
+
+/*====================================================================*/
static void dma_get_8390_hdr(struct net_device *dev,
struct e8390_pkt_hdr *hdr,
ei_status.dmaing &= ~0x01;
}
-/* ======================================================================= */
+/*====================================================================*/
static void dma_block_input(struct net_device *dev, int count,
struct sk_buff *skb, int ring_offset)
/*====================================================================*/
static void dma_block_output(struct net_device *dev, int count,
- const unsigned char *buf,
- const int start_page)
+ const u_char *buf, const int start_page)
{
ioaddr_t nic_base = dev->base_addr;
pcnet_dev_t *info = (pcnet_dev_t *)dev;
/*====================================================================*/
-static void copyin(unsigned char *dest, unsigned char *src, int c)
+static void copyin(u_char *dest, u_char *src, int c)
{
- unsigned short *d = (unsigned short *) dest;
- unsigned short *s = (unsigned short *) src;
+ u_short *d = (u_short *)dest, *s = (u_short *)src;
int odd;
if (c <= 0)
return;
- odd = (c & 01); c >>= 1;
+ odd = (c & 1); c >>= 1;
if (c) {
do { *d++ = __raw_readw(s++); } while (--c);
}
/* get last byte by fetching a word and masking */
if (odd)
- *((unsigned char *)d) = readw(s) & 0xff;
+ *((u_char *)d) = readw(s) & 0xff;
}
-static void copyout(unsigned char *dest, const unsigned char *src, int c)
+static void copyout(u_char *dest, const u_char *src, int c)
{
- volatile unsigned short *d = (unsigned short *) dest;
- unsigned short *s = (unsigned short *) src;
+ u_short *d = (u_short *)dest, *s = (u_short *)src;
int odd;
if (c <= 0)
return;
- odd = (c & 01); c >>= 1;
+ odd = (c & 1); c >>= 1;
if (c) {
do { __raw_writew(*s++, d++); } while (--c);
/*====================================================================*/
static void shmem_block_output(struct net_device *dev, int count,
- const unsigned char *buf,
- const int start_page)
+ const u_char *buf, const int start_page)
{
void *shmem = (void *)dev->mem_start + (start_page << 8);
shmem -= ei_status.tx_start_page << 8;
-
- if (ei_debug > 4)
- printk(KERN_DEBUG "[bo=%d @ %x]\n", count, start_page);
-
copyout(shmem, buf, count);
}
Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
- smc91c92_cs.c 1.85 2000/01/15 02:03:14
+ smc91c92_cs.c 1.96 2000/05/09 02:35:58
This driver contains code written by Donald Becker
(becker@cesdis.gsfc.nasa.gov), Rowan Hughes (x-csrdh@jcu.edu.au),
/* Operational parameter that usually are not changed. */
-/* Do you want to use 32 bit xfers? This should work on all chips,
- but could cause trouble with some PCMCIA controllers... */
-#define USE_32_BIT 1
-
/* Time in jiffies before concluding Tx hung */
#define TX_TIMEOUT ((400*HZ)/1000)
currently have room for another Tx packet. */
#define MEMORY_WAIT_TIME 8
-/* Values that should be specific lengths */
-typedef unsigned short uint16;
-
static dev_info_t dev_info = "smc91c92_cs";
static dev_link_t *dev_list = NULL;
u_short media_status;
u_short fast_poll;
u_long last_rx;
-
- spinlock_t lock;
};
/* Special definitions for Megahertz multifunction cards */
/* Symbolic constants for the SMC91c9* series chips, from Erik Stahlman. */
#define BANK_SELECT 14 /* Window select register. */
-#define SMC_SELECT_BANK(x) { outw( x, ioaddr + BANK_SELECT); }
+#define SMC_SELECT_BANK(x) { outw(x, ioaddr + BANK_SELECT); }
/* Bank 0 registers. */
#define TCR 0 /* transmit control register */
static int smc91c92_event(event_t event, int priority,
event_callback_args_t *args);
-static void smc91c92_tx_timeout (struct net_device *dev);
static int smc91c92_open(struct net_device *dev);
static int smc91c92_close(struct net_device *dev);
+static void smc_tx_timeout(struct net_device *dev);
static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void smc_rx(struct net_device *dev);
CardServices(ReportError, handle, &err);
}
-/*====================================================================*/
-
-static int smc91c92_init(struct net_device *dev)
-{
- DEBUG(0, "%s: smc91c92_init called!\n", dev->name);
- return 0;
-}
-
/*======================================================================
smc91c92_attach() creates an "instance" of the driver, allocating
dev->get_stats = &smc91c92_get_stats;
dev->set_config = &s9k_config;
dev->set_multicast_list = &set_rx_mode;
- strcpy(dev->name, smc->node.dev_name);
ether_setup(dev);
- dev->init = &smc91c92_init;
dev->open = &smc91c92_open;
dev->stop = &smc91c92_close;
- dev->tx_timeout = smc91c92_tx_timeout;
+ dev->tx_timeout = smc_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
dev->priv = link->priv = link->irq.Instance = smc;
- netif_start_queue (dev);
-
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
{
struct smc_private *smc = link->priv;
dev_link_t **linkp;
- long flags;
DEBUG(0, "smc91c92_detach(0x%p)\n", link);
if (*linkp == NULL)
return;
- save_flags(flags);
- cli();
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- restore_flags(flags);
-
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
smc91c92_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
/* Allocate a memory window, for accessing the ISR */
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
- req.Base = 0;
- req.Size = 0x1000;
+ req.Base = req.Size = 0;
req.AccessSpeed = 0;
link->win = (window_handle_t)link->handle;
i = CardServices(RequestWindow, &link->win, &req);
if (i != CS_SUCCESS)
return i;
- smc->base = ioremap(req.Base, 0x1000);
+ smc->base = ioremap(req.Base, req.Size);
mem.CardOffset = mem.Page = 0;
if (smc->manfid == MANFID_MOTOROLA)
mem.CardOffset = link->conf.ConfigBase;
struct net_device *dev = &smc->dev;
ioaddr_t ioaddr = dev->base_addr;
int i, wait=0, loop;
- unsigned int addr;
+ u_int addr;
/* Read Ethernet address from Serial EEPROM */
for (i = 0; i < 3; i++) {
- SMC_SELECT_BANK( 2 );
+ SMC_SELECT_BANK(2);
outw(MOT_EEPROM + i, ioaddr + POINTER);
- SMC_SELECT_BANK( 1 );
+ SMC_SELECT_BANK(1);
outw((CTL_RELOAD | CTL_EE_SELECT), ioaddr + CONTROL);
for (loop = 0; loop < 200; loop++) {
if (smc->manfid == MANFID_OSITECH) {
i = osi_config(link);
- } else if (smc->manfid == MANFID_MOTOROLA
- || ((smc->manfid == MANFID_MEGAHERTZ)
- && ((smc->cardid == PRODID_MEGAHERTZ_VARIOUS)
- || (smc->cardid == PRODID_MEGAHERTZ_EM3288)))) {
+ } else if ((smc->manfid == MANFID_MOTOROLA) ||
+ ((smc->manfid == MANFID_MEGAHERTZ) &&
+ ((smc->cardid == PRODID_MEGAHERTZ_VARIOUS) ||
+ (smc->cardid == PRODID_MEGAHERTZ_EM3288)))) {
i = mhz_mfc_config(link);
} else {
i = smc_config(link);
dev->if_port = if_port;
else
printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
- netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
goto config_undo;
}
+ strcpy(smc->node.dev_name, dev->name);
link->dev = &smc->node;
link->state &= ~DEV_CONFIG_PENDING;
case 5: name = "95"; break;
case 7: name = "100"; break;
case 8: name = "100-FD"; break;
+ case 9: name = "110"; break;
}
printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
"hw_addr ", dev->name, name, (rev & 0x0f), dev->base_addr,
CardServices(ReleaseWindow, link->win);
}
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ link->state &= ~DEV_CONFIG;
} /* smc91c92_release */
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(dev);
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
+ mod_timer(&link->release, jiffies + HZ/20);
}
break;
case CS_EVENT_CARD_INSERTION:
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
-
CardServices(ReleaseConfiguration, link->handle);
}
break;
}
link->open++;
MOD_INC_USE_COUNT;
-
- netif_start_queue (dev);
+
+ netif_start_queue(dev);
smc->saved_skb = 0;
smc->packets_waiting = 0;
DEBUG(0, "%s: smc91c92_close(), status %4.4x.\n",
dev->name, inw(ioaddr + BANK_SELECT));
-
- netif_stop_queue (dev);
-
+
+ netif_stop_queue(dev);
+
/* Shut off all interrupts, and turn off the Tx and Rx sections.
Don't bother to check for chip present. */
- SMC_SELECT_BANK( 2 ); /* Nominally paranoia, but do no assume... */
+ SMC_SELECT_BANK(2); /* Nominally paranoia, but do no assume... */
outw(0, ioaddr + INTERRUPT);
- SMC_SELECT_BANK( 0 );
+ SMC_SELECT_BANK(0);
mask_bits(0xff00, ioaddr + RCR);
mask_bits(0xff00, ioaddr + TCR);
/* Put the chip into power-down mode. */
- SMC_SELECT_BANK( 1 );
- outw(CTL_POWERDOWN, ioaddr + CONTROL );
+ SMC_SELECT_BANK(1);
+ outw(CTL_POWERDOWN, ioaddr + CONTROL );
link->open--;
del_timer(&smc->media);
- if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
======================================================================*/
-static void smc_hardware_send_packet( struct net_device * dev )
+static void smc_hardware_send_packet(struct net_device * dev)
{
struct smc_private *smc = dev->priv;
struct sk_buff *skb = smc->saved_skb;
ioaddr_t ioaddr = dev->base_addr;
- unsigned char packet_no;
+ u_char packet_no;
- if ( !skb ) {
+ if (!skb) {
printk(KERN_ERR "%s: In XMIT with no packet to send.\n", dev->name);
return;
}
/* There should be a packet slot waiting. */
packet_no = inw(ioaddr + PNR_ARR) >> 8;
- if ( packet_no & 0x80 ) {
+ if (packet_no & 0x80) {
/* If not, there is a hardware problem! Likely an ejected card. */
printk(KERN_WARNING "%s: 91c92 hardware Tx buffer allocation"
" failed, status %#2.2x.\n", dev->name, packet_no);
- dev_kfree_skb (skb);
+ dev_kfree_skb_irq(skb);
smc->saved_skb = NULL;
- netif_start_queue (dev);
+ netif_start_queue(dev);
return;
}
-
+
smc->stats.tx_bytes += skb->len;
/* The card should use the just-allocated buffer. */
- outw( packet_no, ioaddr + PNR_ARR );
+ outw(packet_no, ioaddr + PNR_ARR);
/* point to the beginning of the packet */
- outw( PTR_AUTOINC , ioaddr + POINTER );
+ outw(PTR_AUTOINC , ioaddr + POINTER);
- /* Send the packet length ( +6 for status, length and ctl byte )
- and the status word ( set to zeros ). */
+ /* Send the packet length (+6 for status, length and ctl byte)
+ and the status word (set to zeros). */
{
- unsigned char *buf = skb->data;
- int length = skb->len; /* The chip will pad to ethernet min length. */
+ u_char *buf = skb->data;
+ u_int length = skb->len; /* The chip will pad to ethernet min. */
DEBUG(2, "%s: Trying to xmit packet of length %d.\n",
dev->name, length);
-#ifdef USE_32_BIT
- outl((length+6) << 16, ioaddr + DATA_1);
- if (length & 0x2) {
- outsl(ioaddr + DATA_1, buf, length >> 2 );
- outw( *((uint16 *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
- } else
- outsl(ioaddr + DATA_1, buf, length >> 2 );
-#else
- /* send the packet length: +6 for status words, length, and ctl */
- outw( 0, ioaddr + DATA_1 );
- outw(length + 6, ioaddr + DATA_1 );
- outsw(ioaddr + DATA_1 , buf, length >> 1);
-#endif
+ /* send the packet length: +6 for status word, length, and ctl */
+ outw(0, ioaddr + DATA_1);
+ outw(length + 6, ioaddr + DATA_1);
+ outsw(ioaddr + DATA_1, buf, length >> 1);
/* The odd last byte, if there is one, goes in the control word. */
- outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1 );
+ outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1);
}
/* Enable the Tx interrupts, both Tx (TxErr) and TxEmpty. */
ioaddr + INTERRUPT);
/* The chip does the rest of the work. */
- outw( MC_ENQUEUE , ioaddr + MMU_CMD );
+ outw(MC_ENQUEUE , ioaddr + MMU_CMD);
smc->saved_skb = NULL;
- dev_kfree_skb (skb);
+ dev_kfree_skb_irq(skb);
dev->trans_start = jiffies;
- netif_start_queue (dev);
+ netif_start_queue(dev);
return;
}
/*====================================================================*/
-static void smc91c92_tx_timeout (struct net_device *dev)
+static void smc_tx_timeout(struct net_device *dev)
{
- struct smc_private *smc = dev->priv;
- ioaddr_t ioaddr = dev->base_addr;
+ struct smc_private *smc = dev->priv;
+ ioaddr_t ioaddr = dev->base_addr;
- printk (KERN_NOTICE "%s: SMC91c92 transmit timed out, "
- "Tx_status %2.2x status %4.4x.\n",
- dev->name, inw (ioaddr) & 0xff, inw (ioaddr + 2));
- smc->stats.tx_errors++;
- smc_reset (dev);
- dev->trans_start = jiffies;
- smc->saved_skb = NULL;
- netif_start_queue (dev);
+ printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
+ "Tx_status %2.2x status %4.4x.\n",
+ dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2));
+ smc->stats.tx_errors++;
+ smc_reset(dev);
+ dev->trans_start = jiffies;
+ smc->saved_skb = NULL;
+ netif_start_queue(dev);
}
-
-/*====================================================================*/
-
static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct smc_private *smc = dev->priv;
ioaddr_t ioaddr = dev->base_addr;
- unsigned short num_pages;
+ u_short num_pages;
short time_out, ir;
-
+
+ netif_stop_queue(dev);
+
DEBUG(2, "%s: smc91c92_start_xmit(length = %d) called,"
" status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));
- netif_stop_queue (dev);
-
- if ( smc->saved_skb) {
+ if (smc->saved_skb) {
/* THIS SHOULD NEVER HAPPEN. */
smc->stats.tx_aborted_errors++;
printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n",
/* A packet is now waiting. */
smc->packets_waiting++;
- SMC_SELECT_BANK( 2 ); /* Paranoia, we should always be in window 2 */
+ SMC_SELECT_BANK(2); /* Paranoia, we should always be in window 2 */
/* Allocate the memory; send the packet now if we win. */
- outw( MC_ALLOC | num_pages, ioaddr + MMU_CMD );
+ outw(MC_ALLOC | num_pages, ioaddr + MMU_CMD);
for (time_out = MEMORY_WAIT_TIME; time_out >= 0; time_out--) {
ir = inw(ioaddr+INTERRUPT);
if (ir & IM_ALLOC_INT) {
======================================================================*/
-static void smc_tx_err( struct net_device * dev )
+static void smc_tx_err(struct net_device * dev)
{
struct smc_private *smc = (struct smc_private *)dev->priv;
ioaddr_t ioaddr = dev->base_addr;
int tx_status;
/* select this as the packet to read from */
- outw( packet_no, ioaddr + PNR_ARR );
+ outw(packet_no, ioaddr + PNR_ARR);
/* read the first word from this packet */
- outw( PTR_AUTOINC | PTR_READ | 0, ioaddr + POINTER );
+ outw(PTR_AUTOINC | PTR_READ | 0, ioaddr + POINTER);
tx_status = inw(ioaddr + DATA_1);
smc->tx_err++;
}
- if ( tx_status & TS_SUCCESS ) {
+ if (tx_status & TS_SUCCESS) {
printk(KERN_NOTICE "%s: Successful packet caused error "
"interrupt?\n", dev->name);
}
/* re-enable transmit */
- SMC_SELECT_BANK( 0 );
- outw( inw(ioaddr + TCR) | TCR_ENABLE, ioaddr + TCR);
- SMC_SELECT_BANK( 2 );
+ SMC_SELECT_BANK(0);
+ outw(inw(ioaddr + TCR) | TCR_ENABLE, ioaddr + TCR);
+ SMC_SELECT_BANK(2);
- outw( MC_FREEPKT, ioaddr + MMU_CMD ); /* Free the packet memory. */
+ outw(MC_FREEPKT, ioaddr + MMU_CMD); /* Free the packet memory. */
/* one less packet waiting for me */
smc->packets_waiting--;
- outw( saved_packet, ioaddr + PNR_ARR );
+ outw(saved_packet, ioaddr + PNR_ARR);
return;
}
{
struct smc_private *smc = dev->priv;
ioaddr_t ioaddr = dev->base_addr;
- unsigned short card_stats, ephs;
+ u_short card_stats, ephs;
SMC_SELECT_BANK(0);
ephs = inw(ioaddr + EPH);
DEBUG(2, "%s: Ethernet protocol handler interrupt, status"
" %4.4x.\n", dev->name, ephs);
/* Could be a counter roll-over warning: update stats. */
- card_stats = inw( ioaddr + COUNTER );
+ card_stats = inw(ioaddr + COUNTER);
/* single collisions */
smc->stats.collisions += card_stats & 0xF;
card_stats >>= 4;
card_stats >>= 4; /* excess deferred */
#endif
/* If we had a transmit error we must re-enable the transmitter. */
- outw( inw(ioaddr + TCR) | TCR_ENABLE, ioaddr + TCR);
+ outw(inw(ioaddr + TCR) | TCR_ENABLE, ioaddr + TCR);
/* Clear a link error interrupt. */
SMC_SELECT_BANK(1);
u_short saved_bank, saved_pointer, mask, status;
char bogus_cnt = INTR_WORK; /* Work we are willing to do. */
- if ((smc == NULL) || !netif_device_present(dev))
+ if (!netif_device_present(dev))
return;
ioaddr = dev->base_addr;
- spin_lock (&smc->lock);
-
DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name,
irq, ioaddr);
if ((saved_bank & 0xff00) != 0x3300) {
/* The device does not exist -- the card could be off-line, or
maybe it has been ejected. */
-#ifdef PCMCIA_DEBUG
- if (dev->start)
- DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent"
- "/ejected device.\n", dev->name, irq);
-#endif
+ DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent"
+ "/ejected device.\n", dev->name, irq);
goto irq_done;
}
saved_pointer = inw(ioaddr + POINTER);
mask = inw(ioaddr + INTERRUPT) >> 8;
/* clear all interrupts */
- outw( 0, ioaddr + INTERRUPT );
+ outw(0, ioaddr + INTERRUPT);
do { /* read the status flag, and mask it */
status = inw(ioaddr + INTERRUPT) & 0xff;
smc_hardware_send_packet(dev);
/* enable xmit interrupts based on this */
- mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
+ mask |= (IM_TX_EMPTY_INT | IM_TX_INT);
/* and let the card send more packets to me */
- netif_wake_queue (dev);
+ netif_wake_queue(dev);
}
if (status & IM_RX_OVRN_INT) {
smc->stats.rx_errors++;
}
if (status & IM_EPH_INT)
smc_eph_irq(dev);
- } while ( --bogus_cnt);
+ } while (--bogus_cnt);
DEBUG(3, " Restoring saved registers mask %2.2x bank %4.4x"
" pointer %4.4x.\n", mask, saved_bank, saved_pointer);
/* restore state register */
outw((mask<<8), ioaddr + INTERRUPT);
outw(saved_pointer, ioaddr + POINTER);
- SMC_SELECT_BANK( saved_bank );
-
- spin_unlock (&smc->lock);
+ SMC_SELECT_BANK(saved_bank);
DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq);
}
/* Reset the read pointer, and read the status and packet length. */
- outw( PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER );
+ outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER);
rx_status = inw(ioaddr + DATA_1);
packet_length = inw(ioaddr + DATA_1) & 0x07ff;
DEBUG(2, "%s: Receive status %4.4x length %d.\n",
dev->name, rx_status, packet_length);
- if ( !(rx_status & RS_ERRORS )) {
+ if (!(rx_status & RS_ERRORS)) {
/* do stuff to make a new packet */
struct sk_buff *skb;
/* Note: packet_length adds 5 or 6 extra bytes here! */
skb = dev_alloc_skb(packet_length+2);
- if ( skb == NULL ) {
+ if (skb == NULL) {
DEBUG(1, "%s: Low memory, packet dropped.\n", dev->name);
smc->stats.rx_dropped++;
- outw( MC_RELEASE, ioaddr + MMU_CMD );
+ outw(MC_RELEASE, ioaddr + MMU_CMD);
return;
}
======================================================================*/
-static unsigned const ethernet_polynomial = 0x04c11db7U;
+static const u_int ethernet_polynomial = 0x04c11db7U;
-static unsigned ether_crc(int length, unsigned char *data)
+static u_int ether_crc(int length, u_char *data)
{
int crc = 0xffffffff; /* Initial value. */
while (--length >= 0) {
- unsigned char current_octet = *data++;
+ u_char current_octet = *data++;
int bit;
for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
crc = (crc << 1) ^
======================================================================*/
static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
- unsigned char *multicast_table)
+ u_char *multicast_table)
{
struct dev_mc_list *mc_addr;
for (mc_addr = addrs; mc_addr && --count > 0; mc_addr = mc_addr->next) {
- unsigned int position = ether_crc(6, mc_addr->dmi_addr);
+ u_int position = ether_crc(6, mc_addr->dmi_addr);
#ifndef final_version /* Verify multicast address. */
- if ( (mc_addr->dmi_addr[0] & 1) == 0)
+ if ((mc_addr->dmi_addr[0] & 1) == 0)
continue;
#endif
multicast_table[position >> 29] |= 1 << ((position >> 26) & 7);
static void set_rx_mode(struct net_device *dev)
{
ioaddr_t ioaddr = dev->base_addr;
- unsigned int multicast_table[ 2 ] = { 0, };
+ u_int multicast_table[ 2 ] = { 0, };
long flags;
- uint16 rx_cfg_setting;
+ u_short rx_cfg_setting;
if (dev->flags & IFF_PROMISC) {
printk(KERN_NOTICE "%s: setting Rx mode to promiscuous.\n", dev->name);
else {
if (dev->mc_count) {
fill_multicast_tbl(dev->mc_count, dev->mc_list,
- (unsigned char *)multicast_table);
+ (u_char *)multicast_table);
}
rx_cfg_setting = RxStripCRC | RxEnable;
}
/* Load MC table and Rx setting into the chip without interrupts. */
save_flags(flags);
cli();
- SMC_SELECT_BANK( 3 );
+ SMC_SELECT_BANK(3);
outl(multicast_table[0], ioaddr + MULTICAST0);
outl(multicast_table[1], ioaddr + MULTICAST4);
SMC_SELECT_BANK(0);
/* The first interaction must be a write to bring the chip out
of sleep mode. */
- SMC_SELECT_BANK( 0 );
+ SMC_SELECT_BANK(0);
/* Reset the chip. */
- outw( RCR_SOFTRESET, ioaddr + RCR );
+ outw(RCR_SOFTRESET, ioaddr + RCR);
udelay(10);
/* Clear the transmit and receive configuration registers. */
- outw( RCR_CLEAR, ioaddr + RCR );
- outw( TCR_CLEAR, ioaddr + TCR );
+ outw(RCR_CLEAR, ioaddr + RCR);
+ outw(TCR_CLEAR, ioaddr + TCR);
/* Set the Window 1 control, configuration and station addr registers.
No point in writing the I/O base register ;-> */
/* Reset the MMU */
SMC_SELECT_BANK(2);
- outw(MC_RESET, ioaddr + MMU_CMD );
- outw(0, ioaddr + INTERRUPT );
+ outw(MC_RESET, ioaddr + MMU_CMD);
+ outw(0, ioaddr + INTERRUPT);
/* Re-enable the chip. */
SMC_SELECT_BANK(0);
set_rx_mode(dev);
/* Enable interrupts. */
- SMC_SELECT_BANK( 2 );
- outw( (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT) << 8,
- ioaddr + INTERRUPT );
+ SMC_SELECT_BANK(2);
+ outw((IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT) << 8,
+ ioaddr + INTERRUPT);
}
/*======================================================================
int new_mii; /* has full 10baseT/100baseT MII */
int modem; /* is a multi function card (i.e with a modem) */
caddr_t dingo_ccr; /* only used for CEM56 cards */
- int suspended;
unsigned last_ptr_value; /* last packets transmitted value */
const char *manf_str;
- spinlock_t lock;
} local_info_t;
/****************
* Some more prototypes
*/
static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void do_tx_timeout(struct net_device *dev);
static struct enet_statistics *do_get_stats(struct net_device *dev);
static void set_addresses(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
-static int do_init(struct net_device *dev);
static int set_card_type(dev_link_t *link, const void *s);
static int do_config(struct net_device *dev, struct ifmap *map);
static int do_open(struct net_device *dev);
static int init_mii(struct net_device *dev);
static void do_powerdown(struct net_device *dev);
static int do_stop(struct net_device *dev);
-static void xirc_tx_timeout (struct net_device *dev);
/*=============== Helper functions =========================*/
static void
local = kmalloc(sizeof(*local), GFP_KERNEL);
if (!local) return NULL;
memset(local, 0, sizeof(*local));
-
- local->lock = SPIN_LOCK_UNLOCKED;
link = &local->link; dev = &local->dev;
link->priv = dev->priv = local;
dev->get_stats = &do_get_stats;
dev->do_ioctl = &do_ioctl;
dev->set_multicast_list = &set_multicast_list;
- strcpy(dev->name, local->node.dev_name);
ether_setup(dev);
- dev->init = &do_init;
dev->open = &do_open;
dev->stop = &do_stop;
- dev->tx_timeout = xirc_tx_timeout;
+ dev->tx_timeout = do_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- netif_start_queue(dev);
/* Register with Card Services */
link->next = dev_list;
{
local_info_t *local = link->priv;
dev_link_t **linkp;
- long flags;
DEBUG(0, "detach(0x%p)\n", link);
return;
}
- save_flags(flags);
- cli();
- if (link->state & DEV_RELEASE_PENDING) {
- del_timer(&link->release);
- link->state &= ~DEV_RELEASE_PENDING;
- }
- restore_flags(flags);
-
/*
* If the device is currently configured and active, we won't
* actually delete it yet. Instead, it is marked so that when
* the release() function is called, that will trigger a proper
* detach().
*/
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
DEBUG(0, "detach postponed, '%s' still locked\n",
link->dev->dev_name);
* memory and write direct to the CIS registers
*/
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
- req.Base = 0;
- req.Size = 0x1000; /* 4k window */
+ req.Base = req.Size = 0;
req.AccessSpeed = 0;
link->win = (window_handle_t)link->handle;
if ((err = CardServices(RequestWindow, &link->win, &req))) {
/* we can now register the device with the net subsystem */
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- netif_start_queue(dev);
if ((err=register_netdev(dev))) {
printk(KNOT_XIRC "register_netdev() failed\n");
goto config_error;
}
link->state &= ~DEV_CONFIG_PENDING;
+ strcpy(local->node.dev_name, dev->name);
link->dev = &local->node;
if (local->dingo)
CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
- link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
+ link->state &= ~DEV_CONFIG;
} /* xirc2ps_release */
DEBUG(0, "event(%d)\n", (int)event);
switch (event) {
- case CS_EVENT_REGISTRATION_COMPLETE:
- DEBUG(0, "registration complete\n");
- break;
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- netif_device_detach(dev);
- link->release.expires = jiffies + HZ / 20;
- add_timer(&link->release);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- xirc2ps_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG) {
- if (link->open) {
- netif_device_detach(dev);
- lp->suspended=1;
- do_powerdown(dev);
- }
- CardServices(ReleaseConfiguration, link->handle);
- }
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (link->state & DEV_CONFIG) {
- CardServices(RequestConfiguration, link->handle, &link->conf);
- if (link->open) {
- do_reset(dev,1);
- lp->suspended=0;
- netif_device_attach(dev);
- }
- }
- break;
+ case CS_EVENT_REGISTRATION_COMPLETE:
+ DEBUG(0, "registration complete\n");
+ break;
+ case CS_EVENT_CARD_REMOVAL:
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ netif_device_detach(dev);
+ mod_timer(&link->release, jiffies + HZ/20);
+ }
+ break;
+ case CS_EVENT_CARD_INSERTION:
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ xirc2ps_config(link);
+ break;
+ case CS_EVENT_PM_SUSPEND:
+ link->state |= DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_RESET_PHYSICAL:
+ if (link->state & DEV_CONFIG) {
+ if (link->open) {
+ netif_device_detach(dev);
+ do_powerdown(dev);
+ }
+ CardServices(ReleaseConfiguration, link->handle);
+ }
+ break;
+ case CS_EVENT_PM_RESUME:
+ link->state &= ~DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_CARD_RESET:
+ if (link->state & DEV_CONFIG) {
+ CardServices(RequestConfiguration, link->handle, &link->conf);
+ if (link->open) {
+ do_reset(dev,1);
+ netif_device_attach(dev);
+ }
+ }
+ break;
}
return 0;
} /* xirc2ps_event */
* -- on a laptop?
*/
- spin_lock (&lp->lock);
if (!netif_device_present(dev))
return;
goto loop_entry;
}
SelectPage(saved_page);
-
- spin_unlock (&lp->lock);
-
PutByte(XIRCREG_CR, EnableIntr); /* re-enable interrupts */
/* Instead of dropping packets during a receive, we could
* force an interrupt with this command:
/*====================================================================*/
-static void xirc_tx_timeout (struct net_device *dev)
+static void
+do_tx_timeout(struct net_device *dev)
{
- local_info_t *lp = dev->priv;
-
- if (lp->suspended) {
- dev->trans_start = jiffies;
- lp->stats.tx_dropped++;
- netif_start_queue(dev);
- return;
- }
-
- printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
- lp->stats.tx_errors++;
- /* reset the card */
- do_reset(dev,1);
- dev->trans_start = jiffies;
- netif_start_queue(dev);
+ local_info_t *lp = dev->priv;
+ printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
+ lp->stats.tx_errors++;
+ /* reset the card */
+ do_reset(dev,1);
+ dev->trans_start = jiffies;
+ netif_start_queue(dev);
}
-
static int
do_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
dev_kfree_skb (skb);
dev->trans_start = jiffies;
- netif_start_queue(dev);
lp->stats.tx_bytes += pktlen;
+ netif_start_queue(dev);
return 0;
}
SelectPage(0);
}
-/****************
- * We never need to do anything when a IIps device is "initialized"
- * by the net software, because we only register already-found cards.
- */
-static int
-do_init(struct net_device *dev)
-{
- DEBUG(0, "do_init(%p)\n", dev);
- return 0;
-}
-
static int
do_config(struct net_device *dev, struct ifmap *map)
{
MOD_INC_USE_COUNT;
netif_start_queue(dev);
- lp->suspended = 0;
do_reset(dev,1);
return 0;
SelectPage(0);
link->open--;
- if (link->state & DEV_STALE_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- link->state |= DEV_RELEASE_PENDING;
- add_timer(&link->release);
- }
+ if (link->state & DEV_STALE_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
MOD_DEC_USE_COUNT;
--- /dev/null
+/** -*- linux-c -*- ***********************************************************
+ * Linux PPP over Ethernet (PPPoX/PPPoE) Sockets
+ *
+ * PPPoX --- Generic PPP encapsulation socket family
+ * PPPoE --- PPP over Ethernet (RFC 2516)
+ *
+ *
+ * Version: 0.5.0
+ *
+ * Author: Michal Ostrowski <mostrows@styx.uwaterloo.ca>
+ *
+ * License:
+ * 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 Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+
+#include <asm/uaccess.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/if_pppox.h>
+#include <net/sock.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/if_pppvar.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/file.h>
+#include <linux/proc_fs.h>
+
+
+
+static int __attribute__((unused)) pppoe_debug = 7;
+#define PPPOE_HASH_SIZE 16
+
+int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
+
+struct proto_ops pppoe_ops;
+
+
+#if 0
+#define CHECKPTR(x,y) { if (!(x) && pppoe_debug &7 ){ printk(KERN_CRIT "PPPoE Invalid pointer : %s , %p\n",#x,(x)); error=-EINVAL; goto y; }}
+#define DEBUG(s,args...) if( pppoe_debug & (s) ) printk(KERN_CRIT args );
+#else
+#define CHECKPTR(x,y) do {} while (0);
+#define DEBUG(s,args...) do { } while (0);
+#endif
+
+
+
+static rwlock_t pppoe_hash_lock = RW_LOCK_UNLOCKED;
+
+
+static inline int cmp_2_addr(struct pppoe_addr *a, struct pppoe_addr *b)
+{
+ return (a->sid == b->sid &&
+ (memcmp(a->remote, b->remote, ETH_ALEN) == 0));
+}
+
+static inline int cmp_addr(struct pppoe_addr *a, unsigned long sid, char *addr)
+{
+ return (a->sid == sid &&
+ (memcmp(a->remote,addr,ETH_ALEN) == 0));
+}
+
+static int hash_item(unsigned long sid, unsigned char *addr)
+{
+ int i = 0;
+ union {
+ char c[sizeof(unsigned long)];
+ unsigned long i;
+ } hash;
+
+ hash.i = sid;
+
+ for (i = 0; i < ETH_ALEN; ++i)
+ hash.c[0] = hash.c[0] ^ addr[i];
+
+ for (i = 1; i < sizeof(int); ++i)
+ hash.c[0] = hash.c[0] ^ hash.c[i];
+
+ i = (int) (hash.c[0] & (PPPOE_HASH_SIZE - 1));
+
+ return i;
+}
+
+static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE] = { 0, };
+
+/**********************************************************************
+ *
+ * Set/get/delete/rehash items (internal versions)
+ *
+ **********************************************************************/
+static struct pppox_opt *__get_item(unsigned long sid, unsigned char *addr)
+{
+ int hash = hash_item(sid, addr);
+ struct pppox_opt *ret;
+
+ ret = item_hash_table[hash];
+
+ while (ret && !cmp_addr(&ret->pppoe_pa, sid, addr))
+ ret = ret->next;
+
+ return ret;
+}
+
+static int __set_item(struct pppox_opt *po)
+{
+ int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
+ struct pppox_opt *ret;
+
+ ret = item_hash_table[hash];
+ while (ret) {
+ if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa))
+ return -EALREADY;
+
+ ret = ret->next;
+ }
+
+ if (!ret) {
+ po->next = item_hash_table[hash];
+ item_hash_table[hash] = po;
+ }
+
+ return 0;
+}
+
+static struct pppox_opt *__delete_item(unsigned long sid, char *addr)
+{
+ int hash = hash_item(sid, addr);
+ struct pppox_opt *ret, **src;
+
+ ret = item_hash_table[hash];
+ src = &item_hash_table[hash];
+
+ while (ret) {
+ if (cmp_addr(&ret->pppoe_pa, sid, addr)) {
+ *src = ret->next;
+ break;
+ }
+
+ src = &ret->next;
+ ret = ret->next;
+ }
+
+ return ret;
+}
+
+static struct pppox_opt *__find_on_dev(struct net_device *dev,
+ struct pppox_opt *start)
+{
+ struct pppox_opt *po;
+ int hash;
+
+ if (start != NULL) {
+ hash = hash_item(start->pppoe_pa.sid, start->pppoe_pa.remote);
+ po = start;
+ } else {
+ hash = 0;
+ po = NULL;
+
+ while (!po && ++hash < PPPOE_HASH_SIZE)
+ po = item_hash_table[hash];
+ }
+
+ while (po && (po->pppoe_dev != dev)){
+ if (po->next) {
+ po = po->next;
+ } else {
+ po = NULL;
+ while (!po && ++hash < PPPOE_HASH_SIZE)
+ po = item_hash_table[hash];
+ }
+ }
+
+ return po;
+}
+
+/**********************************************************************
+ *
+ * Set/get/delete/rehash items
+ *
+ **********************************************************************/
+static inline struct pppox_opt *get_item(unsigned long sid,
+ unsigned char *addr)
+{
+ struct pppox_opt *po;
+
+ read_lock_bh(&pppoe_hash_lock);
+ po = __get_item(sid, addr);
+ read_unlock_bh(&pppoe_hash_lock);
+
+ return po;
+}
+
+static inline struct pppox_opt *get_item_by_addr(struct sockaddr_pppox *sp)
+{
+ return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote);
+}
+
+static inline int set_item(struct pppox_opt *po)
+{
+ int i;
+
+ if (!po)
+ return -EINVAL;
+
+ write_lock_bh(&pppoe_hash_lock);
+ i = __set_item(po);
+ write_unlock_bh(&pppoe_hash_lock);
+
+ return i;
+}
+
+static inline struct pppox_opt *delete_item(unsigned long sid, char *addr)
+{
+ struct pppox_opt *ret;
+
+ write_lock_bh(&pppoe_hash_lock);
+ ret = __delete_item(sid, addr);
+ write_unlock_bh(&pppoe_hash_lock);
+
+ return ret;
+}
+
+static struct pppox_opt *find_on_dev(struct net_device *dev,
+ struct pppox_opt *start)
+{
+ struct pppox_opt *po;
+ read_lock_bh(&pppoe_hash_lock);
+ po = __find_on_dev(dev,start);
+ read_unlock_bh(&pppoe_hash_lock);
+ return po;
+}
+
+/***************************************************************************
+ *
+ * Handler for device events
+ * Certain device events require that sockets be unconnected
+ *
+ **************************************************************************/
+static int pppoe_device_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ int error = NOTIFY_DONE;
+ struct net_device *dev = (struct net_device *) ptr;
+ struct pppox_opt *po = NULL;
+
+ /* Only look at sockets that are using this specific device. */
+ switch (event) {
+ case NETDEV_CHANGEMTU:
+ /* A change in mtu is a bad thing, requiring
+ * LCP re-negotiation.
+ */
+ case NETDEV_GOING_DOWN:
+ case NETDEV_DOWN:
+ do {
+ po = find_on_dev(dev, po);
+ if(!po)
+ break;
+
+ if (po->sk->state & PPPOX_CONNECTED)
+ pppox_unbind_sock(po->sk);
+
+ if (po->sk->state & PPPOX_CONNECTED) {
+ lock_sock(po->sk);
+ po->sk->shutdown = RCV_SHUTDOWN&SEND_SHUTDOWN;
+
+ po->sk->state = PPPOX_DEAD;
+ po->pppoe_dev = NULL;
+
+ wake_up(po->sk->sleep);
+ release_sock(po->sk);
+ }
+ } while (1);
+
+ break;
+ default:
+ break;
+ };
+
+ return error;
+}
+
+
+static struct notifier_block pppoe_notifier = {
+ pppoe_device_event,
+ NULL,
+ 0
+};
+
+
+
+
+/************************************************************************
+ *
+ * Receive a PPPoE Session frame.
+ *
+ ***********************************************************************/
+static int pppoe_rcv(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt)
+
+{
+ struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw;
+ struct pppox_opt *po;
+ struct sock *sk ;
+
+ po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source);
+
+ if(!po)
+ goto abort;
+
+ sk = po->sk;
+
+ if (!sk || !(sk->state & PPPOX_CONNECTED))
+ goto abort;
+
+ if (sk->state & PPPOX_BOUND) {
+ skb_pull(skb, sizeof(struct pppoe_hdr));
+
+ ppp_input(&po->chan, skb);
+ } else {
+ sock_queue_rcv_skb(sk, skb);
+ }
+
+ return 1;
+
+abort:
+ kfree_skb(skb);
+ return 0;
+}
+
+/************************************************************************
+ *
+ * Receive a PPPoE Discovery frame.
+ * -- This is solely for detection of PADT frames
+ *
+ ***********************************************************************/
+static int pppoe_disc_rcv(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt)
+
+{
+ struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw;
+ struct pppox_opt *po;
+ struct sock *sk ;
+
+ if (ph->code != PADT_CODE)
+ goto abort;
+
+ po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source);
+
+ if (!po)
+ goto abort;
+
+ sk = po->sk;
+
+ pppox_unbind_sock(sk);
+
+abort:
+ kfree_skb(skb);
+ return 0;
+}
+
+
+
+
+struct packet_type pppoes_ptype = {
+ __constant_htons(ETH_P_PPP_SES),
+ NULL,
+ pppoe_rcv,
+ NULL,
+ NULL
+};
+
+struct packet_type pppoed_ptype = {
+ __constant_htons(ETH_P_PPP_DISC),
+ NULL,
+ pppoe_disc_rcv,
+ NULL,
+ NULL
+};
+
+/**********************************************************************
+ *
+ * The destruct hook --- this can be trashed if there is no need for
+ * the sock to clear its receive queue?
+ *
+ *********************************************************************/
+void sock_pppoe_destruct(struct sock *sk)
+{
+ if (sk->protinfo.destruct_hook)
+ kfree(sk->protinfo.destruct_hook);
+
+ while (skb_queue_len(&sk->receive_queue) > 0) {
+ struct sk_buff *skb = skb_dequeue(&sk->receive_queue);
+ if (skb)
+ kfree_skb(skb);
+ }
+}
+
+int pppoe_backlog_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ /* Never seen this called, don't expect it to be called,
+ though I've curious whether or not it ever will be. */
+ DEBUG(KERN_CRIT "Backlog rcv called: %p\n", sk);
+
+ kfree_skb(skb);
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Initialize a new struct sock.
+ *
+ **********************************************************************/
+static int pppoe_create(struct socket *sock)
+{
+ int error = 0;
+ struct sock *sk;
+
+ MOD_INC_USE_COUNT;
+
+ sk = sk_alloc(PF_PPPOX, GFP_KERNEL, 1);
+ if (!sk)
+ return -ENOMEM;
+
+ sock_init_data(sock, sk);
+
+ sock->state = SS_UNCONNECTED;
+ sock->ops = &pppoe_ops;
+
+ sk->protocol = PX_PROTO_OE;
+ sk->family = PF_PPPOX;
+
+ sk->backlog_rcv = pppoe_backlog_rcv;
+ sk->next = NULL;
+ sk->pprev = NULL;
+ sk->state = PPPOX_NONE;
+ sk->type = SOCK_STREAM;
+
+ sk->protinfo.pppox = kmalloc(sizeof(struct pppox_opt), GFP_KERNEL);
+ if (!sk->protinfo.pppox) {
+ error = -ENOMEM;
+ goto free_sk;
+ }
+
+ memset((void *) sk->protinfo.pppox, 0, sizeof(struct pppox_opt));
+ sk->protinfo.pppox->sk = sk;
+
+ /* Delete the protinfo when it is time to do so. */
+ sk->protinfo.destruct_hook = sk->protinfo.pppox;
+ sock->sk = sk;
+
+ return 0;
+
+free_sk:
+ sk_free(sk);
+ MOD_DEC_USE_COUNT;
+ return error;
+}
+
+int pppoe_release(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ struct pppox_opt *po;
+ int error = 0;
+
+ if (!sk)
+ return 0;
+
+ if (sk->dead != 0)
+ return -EBADF;
+
+ pppox_unbind_sock(sk);
+
+ sock_orphan(sk);
+
+ /* Signal the death of the socket. */
+ sk->state = PPPOX_DEAD;
+
+ po = sk->protinfo.pppox;
+ if (po->pppoe_pa.sid)
+ delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
+
+ kfree(po);
+
+
+ /* Should also do a queue purge here */
+
+ sk->protinfo.pppox = NULL;
+ sock->sk = NULL;
+
+ skb_queue_purge(&sk->receive_queue);
+
+ sock_put(sk);
+ MOD_DEC_USE_COUNT;
+
+ return error;
+}
+
+
+int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
+ int sockaddr_len, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct net_device *dev = NULL;
+ struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+ struct pppox_opt *po=sk->protinfo.pppox;
+ int error;
+
+ lock_sock(sk);
+
+ error = -EINVAL;
+ if (sp->sa_protocol != PX_PROTO_OE)
+ goto end;
+
+ error = -EBUSY;
+ if (sk->state & PPPOX_CONNECTED)
+ goto end;
+
+ dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
+
+ error = -ENODEV;
+ if (!dev)
+ goto end;
+
+ error = 0;
+ if (po->pppoe_pa.sid) {
+ pppox_unbind_sock(sk);
+
+ /* Delete the old binding */
+ delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote);
+
+ memset(po, 0, sizeof(struct pppox_opt));
+ po->sk = sk;
+
+ sk->state = PPPOX_NONE;
+ }
+
+ /* Don't re-bind if sid==0 */
+ if (sp->sa_addr.pppoe.sid != 0) {
+ memcpy(&po->pppoe_pa,
+ &sp->sa_addr.pppoe,
+ sizeof(struct pppoe_addr));
+
+ error = set_item(po);
+ if (error < 0)
+ goto end;
+
+ po->pppoe_dev = dev;
+
+ po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
+ dev->hard_header_len);
+
+ po->chan.private = sk;
+ po->chan.ops = &pppoe_chan_ops;
+
+ error = ppp_register_channel(&po->chan);
+
+ sk->state = PPPOX_CONNECTED;
+ }
+
+ sk->num = sp->sa_addr.pppoe.sid;
+
+ end:
+ release_sock(sk);
+ return error;
+}
+
+
+int pppoe_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *usockaddr_len, int peer)
+{
+ int len = sizeof(struct sockaddr_pppox);
+ struct sockaddr_pppox sp;
+
+ sp.sa_family = AF_PPPOX;
+ sp.sa_protocol = PX_PROTO_OE;
+ memcpy(&sp.sa_addr.pppoe, &sock->sk->protinfo.pppox->pppoe_pa,
+ sizeof(struct pppoe_addr));
+
+ memcpy(uaddr, &sp, len);
+
+ *usockaddr_len = len;
+
+ return 0;
+}
+
+
+int pppoe_ioctl(struct socket *sock, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sock *sk = sock->sk;
+ struct pppox_opt *po;
+ int val = 0;
+ int err = 0;
+
+ po = sk->protinfo.pppox;
+ switch (cmd) {
+ case PPPIOCGMRU:
+ err = -ENXIO;
+
+ if (!(sk->state & PPPOX_CONNECTED))
+ break;
+
+ err = -EFAULT;
+ if (put_user(po->pppoe_dev->mtu -
+ sizeof(struct pppoe_hdr) -
+ PPP_HDRLEN,
+ (int *) arg))
+ break;
+ err = 0;
+ break;
+
+ case PPPIOCSMRU:
+ err = -ENXIO;
+ if (!(sk->state & PPPOX_CONNECTED))
+ break;
+
+ err = -EFAULT;
+ if (get_user(val,(int *) arg))
+ break;
+
+ if (val < (po->pppoe_dev->mtu
+ - sizeof(struct pppoe_hdr)
+ - PPP_HDRLEN))
+ err = 0;
+ else
+ err = -EINVAL;
+ break;
+
+ case PPPIOCSFLAGS:
+ err = -EFAULT;
+ if (get_user(val, (int *) arg))
+ break;
+ err = 0;
+ break;
+
+ case PPPOEIOCSFWD:
+ {
+ struct pppox_opt *relay_po;
+
+ err = -EBUSY;
+ if (sk->state & PPPOX_BOUND)
+ break;
+
+ err = -ENOTCONN;
+ if (!(sk->state & PPPOX_CONNECTED))
+ break;
+
+ /* PPPoE address from the user specifies an outbound
+ PPPoE address to which frames are forwarded to */
+ err = -EFAULT;
+ if( copy_from_user(&po->pppoe_relay,
+ (void*)arg,
+ sizeof(struct sockaddr_pppox)))
+ break;
+
+ err = -EINVAL;
+ if (po->pppoe_relay.sa_family != AF_PPPOX ||
+ po->pppoe_relay.sa_protocol!= PX_PROTO_OE)
+ break;
+
+ /* Check that the socket referenced by the address
+ actually exists. */
+ relay_po = get_item_by_addr(&po->pppoe_relay);
+
+ if (!relay_po)
+ break;
+
+ sk->state |= PPPOX_RELAY;
+ err = 0;
+ break;
+ }
+
+ case PPPOEIOCDFWD:
+ err = -EALREADY;
+ if (!(sk->state & PPPOX_RELAY))
+ break;
+
+ sk->state &= ~PPPOX_RELAY;
+ err = 0;
+ break;
+
+ default:
+ };
+
+ return err;
+}
+
+
+int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
+ int total_len, struct scm_cookie *scm)
+{
+ struct sk_buff *skb = NULL;
+ struct sock *sk = sock->sk;
+ int error = 0;
+ struct pppoe_hdr hdr;
+ struct pppoe_hdr *ph;
+ struct net_device *dev;
+ char *start;
+ int copied = 0;
+
+ if (sk->dead || !(sk->state & PPPOX_CONNECTED)) {
+ error = -ENOTCONN;
+ goto end;
+ }
+
+ hdr.ver = 1;
+ hdr.type = 1;
+ hdr.code = 0;
+ hdr.sid = sk->num;
+
+ dev = sk->protinfo.pppox->pppoe_dev;
+
+ skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32,
+ 0, GFP_KERNEL);
+ if (!skb) {
+ error = -ENOMEM;
+ goto end;
+ }
+
+ /* Reserve space for headers. */
+ skb_reserve(skb, dev->hard_header_len);
+ skb->nh.raw = skb->data;
+ skb->dev = dev;
+ skb->priority = sk->priority;
+ skb->protocol = __constant_htons(ETH_P_PPP_SES);
+
+ ph = (struct pppoe_hdr *) skb_put(skb, total_len + sizeof(struct pppoe_hdr));
+ start = (char *) &ph->tag[0];
+
+ copied = memcpy_fromiovec( start, m->msg_iov, m->msg_iovlen);
+
+ dev->hard_header(skb, dev, ETH_P_PPP_SES,
+ sk->protinfo.pppox->pppoe_pa.remote,
+ NULL, copied);
+
+ memcpy(ph, &hdr, sizeof(struct pppoe_hdr));
+
+ ph->length = htons(copied);
+
+ dev_queue_xmit(skb);
+ return copied;
+
+end:
+ return error;
+}
+
+/************************************************************************
+ *
+ * xmit function called by generic PPP driver
+ * sends PPP frame over PPPoE socket
+ *
+ ***********************************************************************/
+int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+ struct sock *sk = (struct sock *) chan->private;
+ struct net_device *dev = sk->protinfo.pppox->pppoe_dev;
+ struct pppoe_hdr hdr;
+ struct pppoe_hdr *ph;
+ int headroom = skb_headroom(skb);
+ int data_len = skb->len;
+
+ if (sk->dead || !(sk->state & PPPOX_CONNECTED)) {
+ goto abort;
+ }
+
+ hdr.ver = 1;
+ hdr.type = 1;
+ hdr.code = 0;
+ hdr.sid = sk->num;
+ hdr.length = htons(skb->len);
+
+ if (!dev) {
+ goto abort;
+ }
+
+ /* Copy the skb if there is no space for the header. */
+ if (headroom < (sizeof(struct pppoe_hdr) + dev->hard_header_len)) {
+ struct sk_buff *skb2;
+
+ skb2 = dev_alloc_skb(32+skb->len +
+ sizeof(struct pppoe_hdr) +
+ dev->hard_header_len);
+
+ if (skb2 == NULL)
+ goto abort;
+
+ skb_reserve(skb2, dev->hard_header_len + sizeof(struct pppoe_hdr));
+ memcpy(skb_put(skb2, skb->len), skb->data, skb->len);
+
+ skb_unlink(skb);
+ kfree_skb(skb);
+ skb = skb2;
+ }
+
+ ph = (struct pppoe_hdr *) skb_push(skb, sizeof(struct pppoe_hdr));
+ memcpy(ph, &hdr, sizeof(struct pppoe_hdr));
+ skb->protocol = __constant_htons(ETH_P_PPP_SES);
+
+ skb->nh.raw = skb->data;
+ skb->dev = dev;
+
+ dev->hard_header(skb, dev, ETH_P_PPP_SES,
+ sk->protinfo.pppox->pppoe_pa.remote,
+ NULL, data_len);
+
+ if (dev_queue_xmit(skb) < 0)
+ goto abort;
+
+ return 1;
+ abort:
+ return 0;
+}
+
+struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL };
+
+int pppoe_rcvmsg(struct socket *sock, struct msghdr *m, int total_len, int flags, struct scm_cookie *scm)
+{
+ struct sock *sk = sock->sk;
+ struct sk_buff *skb = NULL;
+ int error = 0;
+ int len;
+ struct pppoe_hdr *ph = NULL;
+
+ if (sk->state & PPPOX_BOUND) {
+ error = -EIO;
+ goto end;
+ }
+
+ skb = skb_recv_datagram(sk, flags, 0, &error);
+
+ if (error < 0) {
+ goto end;
+ }
+
+ m->msg_namelen = 0;
+
+ if (skb) {
+ error = 0;
+ ph = (struct pppoe_hdr *) skb->nh.raw;
+ len = ntohs(ph->length);
+
+ error = memcpy_toiovec(m->msg_iov, (unsigned char *) &ph->tag[0], len);
+ if (error < 0)
+ goto do_skb_free;
+ error = len;
+ }
+
+do_skb_free:
+ if (skb)
+ kfree_skb(skb);
+end:
+ return error;
+}
+
+int pppoe_proc_info(char *buffer, char **start, off_t offset, int length)
+{
+ struct pppox_opt *po;
+ int len = 0;
+ off_t pos = 0;
+ off_t begin = 0;
+ int size;
+ int i;
+
+ len += sprintf(buffer,
+ "Id Address Device\n");
+ pos = len;
+
+ write_lock_bh(&pppoe_hash_lock);
+
+ for (i = 0; i < PPPOE_HASH_SIZE; i++) {
+ po = item_hash_table[i];
+ while (po) {
+ char *dev = po->pppoe_pa.dev;
+
+ size = sprintf(buffer + len,
+ "%08X %02X:%02X:%02X:%02X:%02X:%02X %8s\n",
+ po->pppoe_pa.sid,
+ po->pppoe_pa.remote[0],
+ po->pppoe_pa.remote[1],
+ po->pppoe_pa.remote[2],
+ po->pppoe_pa.remote[3],
+ po->pppoe_pa.remote[4],
+ po->pppoe_pa.remote[5],
+ dev);
+ len += size;
+ pos += size;
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+
+ if (pos > offset + length)
+ break;
+
+ po = po->next;
+ }
+
+ if (po)
+ break;
+ }
+ write_unlock_bh(&pppoe_hash_lock);
+
+ *start = buffer + (offset - begin);
+ len -= (offset - begin);
+ if (len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
+
+struct proto_ops pppoe_ops = {
+ family: AF_PPPOX,
+ release: pppoe_release,
+ bind: sock_no_bind,
+ connect: pppoe_connect,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: pppoe_getname,
+ poll: datagram_poll,
+ ioctl: pppoe_ioctl,
+ listen: sock_no_listen,
+ shutdown: sock_no_shutdown,
+ setsockopt: sock_no_setsockopt,
+ getsockopt: sock_no_getsockopt,
+ sendmsg: pppoe_sendmsg,
+ recvmsg: pppoe_rcvmsg,
+ mmap: sock_no_mmap
+};
+
+struct pppox_proto pppoe_proto = {
+ create: pppoe_create,
+ ioctl: pppoe_ioctl
+};
+
+
+int __init pppoe_init(void)
+{
+ int err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
+
+ if (err == 0) {
+ printk(KERN_INFO "Registered PPPoE v0.5\n");
+
+ dev_add_pack(&pppoes_ptype);
+ register_netdevice_notifier(&pppoe_notifier);
+ proc_net_create("pppoe", 0, pppoe_proc_info);
+ }
+ return err;
+}
+
+
+#ifdef MODULE
+MODULE_PARM(debug, "i");
+int init_module(void)
+{
+ return pppoe_init();
+}
+
+void cleanup_module(void)
+{
+ unregister_pppox_proto(PX_PROTO_OE);
+ dev_remove_pack(&pppoes_ptype);
+ unregister_netdevice_notifier(&pppoe_notifier);
+ proc_net_remove("pppoe");
+}
+
+#else
+
+int pppoe_proto_init(struct net_proto *np)
+{
+ return pppoe_init();
+}
+
+#endif
--- /dev/null
+/** -*- linux-c -*- ***********************************************************
+ * Linux PPP over X/Ethernet (PPPoX/PPPoE) Sockets
+ *
+ * PPPoX --- Generic PPP encapsulation socket family
+ * PPPoE --- PPP over Ethernet (RFC 2516)
+ *
+ *
+ * Version: 0.5.0
+ *
+ * Author: Michal Ostrowski <mostrows@styx.uwaterloo.ca>
+ *
+ * License:
+ * 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 Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+
+#include <asm/uaccess.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/init.h>
+#include <linux/if_pppox.h>
+#include <net/sock.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/ppp_channel.h>
+
+static struct pppox_proto *proto[PX_MAX_PROTO+1] = { NULL, };
+
+int register_pppox_proto(int proto_num, struct pppox_proto *pp)
+{
+ if (proto_num < 0 || proto_num > PX_MAX_PROTO) {
+ return -EINVAL;
+ }
+
+ if (proto[proto_num])
+ return -EALREADY;
+
+ MOD_INC_USE_COUNT;
+
+ proto[proto_num] = pp;
+ return 0;
+}
+
+void unregister_pppox_proto(int proto_num)
+{
+ if (proto_num >= 0 && proto_num <= PX_MAX_PROTO) {
+ proto[proto_num] = NULL;
+ MOD_DEC_USE_COUNT;
+ }
+}
+
+void pppox_unbind_sock(struct sock *sk)
+{
+ /* Clear connection to ppp device, if attached. */
+
+ if (sk->state & PPPOX_BOUND) {
+ ppp_unregister_channel(&sk->protinfo.pppox->chan);
+ sk->state &= ~PPPOX_BOUND;
+ }
+}
+
+EXPORT_SYMBOL(register_pppox_proto);
+EXPORT_SYMBOL(unregister_pppox_proto);
+EXPORT_SYMBOL(pppox_unbind_sock);
+
+int pppox_ioctl(struct socket* sock, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sock *sk = sock->sk;
+ struct pppox_opt *po;
+ int err = 0;
+
+ po = sk->protinfo.pppox;
+
+ lock_sock(sk);
+
+ switch (cmd) {
+ case PPPIOCGCHAN:{
+ int index;
+ err = -ENOTCONN;
+ if (!(sk->state & PPPOX_CONNECTED))
+ break;
+
+ err = -EINVAL;
+ index = ppp_channel_index(&po->chan);
+ if (put_user(index , (int *) arg))
+ break;
+
+ err = 0;
+ sk->state |= PPPOX_BOUND;
+ break;
+ }
+ default:
+ if (proto[sk->protocol]->ioctl)
+ err = (*proto[sk->protocol]->ioctl)(sock, cmd, arg);
+
+ break;
+ };
+
+ release_sock(sk);
+ return err;
+}
+
+
+int pppox_create(struct socket *sock, int protocol)
+{
+ int err = 0;
+
+ if (protocol < 0 || protocol > PX_MAX_PROTO)
+ return -EPROTOTYPE;
+
+ if (proto[protocol] == NULL)
+ return -EPROTONOSUPPORT;
+
+ err = (*proto[protocol]->create)(sock);
+
+ if (err == 0) {
+ /* We get to set the ioctl handler. */
+ /* For everything else, pppox is just a shell. */
+ sock->ops->ioctl = pppox_ioctl;
+ }
+
+ return err;
+}
+
+struct net_proto_family pppox_proto_family = {
+ PF_PPPOX,
+ pppox_create
+};
+
+#ifdef MODULE
+int init_module(void)
+#else
+void __init pppox_proto_init(struct net_proto *pro)
+#endif
+{
+ int err = 0;
+
+ err = sock_register(&pppox_proto_family);
+
+ if (err == 0)
+ printk(KERN_INFO "Registered PPPoX v0.5\n");
+
+#ifdef CONFIG_PPPOE
+ pppoe_init();
+#endif
+
+ return err;
+}
+
+#ifdef MODULE
+
+MODULE_PARM(debug, "i");
+
+void cleanup_module(void)
+{
+ sock_unregister(PF_PPPOX);
+}
+
+#endif
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
-#include <linux/compile.h>
+#include <linux/pm.h>
#include <linux/pci.h>
#include <asm/system.h>
#include <asm/irq.h>
#include "cs_internal.h"
#include "rsrc_mgr.h"
-#include <linux/pm.h>
-static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data);
-
#ifdef PCMCIA_DEBUG
int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define CB_OPT ""
#endif
#ifdef CONFIG_PM
-#define APM_OPT " [pm]"
+#define PM_OPT " [pm]"
#else
-#define APM_OPT ""
+#define PM_OPT ""
#endif
#if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && !defined(CONFIG_PM)
#define OPTIONS " none"
#else
-#define OPTIONS PCI_OPT CB_OPT APM_OPT
+#define OPTIONS PCI_OPT CB_OPT PM_OPT
#endif
static const char *release = "Linux PCMCIA Card Services " CS_RELEASE;
-#ifdef MODULE
-static const char *kernel = "kernel build: " UTS_RELEASE " " UTS_VERSION;
-#endif
static const char *options = "options: " OPTIONS;
MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
/* Parameters that can be set with 'insmod' */
-static int setup_delay = HZ/20; /* ticks */
-static int resume_delay = HZ/5; /* ticks */
-static int shutdown_delay = HZ/40; /* ticks */
-static int vcc_settle = HZ*4/10; /* ticks */
-static int reset_time = 10; /* usecs */
-static int unreset_delay = HZ/10; /* ticks */
-static int unreset_check = HZ/10; /* ticks */
-static int unreset_limit = 30; /* unreset_check's */
+#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
+
+INT_MODULE_PARM(setup_delay, HZ/20); /* ticks */
+INT_MODULE_PARM(resume_delay, HZ/5); /* ticks */
+INT_MODULE_PARM(shutdown_delay, HZ/40); /* ticks */
+INT_MODULE_PARM(vcc_settle, HZ*4/10); /* ticks */
+INT_MODULE_PARM(reset_time, 10); /* usecs */
+INT_MODULE_PARM(unreset_delay, HZ/10); /* ticks */
+INT_MODULE_PARM(unreset_check, HZ/10); /* ticks */
+INT_MODULE_PARM(unreset_limit, 30); /* unreset_check's */
/* Access speed for attribute memory windows */
-static int cis_speed = 300; /* ns */
+INT_MODULE_PARM(cis_speed, 300); /* ns */
/* Access speed for IO windows */
-static int io_speed = 0; /* ns */
+INT_MODULE_PARM(io_speed, 0); /* ns */
/* Optional features */
#ifdef CONFIG_PM
-static int do_apm = 1;
-MODULE_PARM(do_apm, "i");
+INT_MODULE_PARM(do_apm, 1);
#else
-static int do_apm = 0;
+INT_MODULE_PARM(do_apm, 0);
#endif
-MODULE_PARM(setup_delay, "i");
-MODULE_PARM(resume_delay, "i");
-MODULE_PARM(shutdown_delay, "i");
-MODULE_PARM(vcc_settle, "i");
-MODULE_PARM(reset_time, "i");
-MODULE_PARM(unreset_delay, "i");
-MODULE_PARM(unreset_check, "i");
-MODULE_PARM(unreset_limit, "i");
-MODULE_PARM(cis_speed, "i");
-MODULE_PARM(io_speed, "i");
-
/*====================================================================*/
socket_state_t dead_socket = {
s->sock = ns;
s->setup.data = sockets;
s->setup.function = &setup_socket;
- s->setup_timeout = 0;
s->shutdown.data = sockets;
s->shutdown.function = &shutdown_socket;
/* base address = 0, map = 0 */
char name[3];
sprintf(name, "%02d", i);
s->proc = proc_mkdir(name, proc_pccard);
+ if (s->proc)
+ ss_entry->proc_setup(ns, s->proc);
#ifdef PCMCIA_DEBUG
- create_proc_read_entry("clients",0,s->proc,proc_read_clients,s);
+ if (s->proc)
+ create_proc_read_entry("clients", 0, s->proc,
+ proc_read_clients, s);
#endif
- ss_entry->proc_setup(ns, s->proc);
}
#endif
}
#ifdef PCMCIA_DEBUG
remove_proc_entry("clients", s->proc);
#endif
+ remove_proc_entry(name, proc_pccard);
}
}
#endif
}
s->state |= SOCKET_SETUP_PENDING;
s->setup.function = &setup_socket;
+ s->setup_timeout = 0;
if (s->state & SOCKET_SUSPEND)
s->setup.expires = jiffies + resume_delay;
else
static int __init init_pcmcia_cs(void)
{
printk(KERN_INFO "%s\n", release);
-#ifdef MODULE
- printk(KERN_INFO " %s\n", kernel);
-#endif
printk(KERN_INFO " %s\n", options);
DEBUG(0, "%s\n", version);
if (do_apm)
-/* $Id: sab82532.c,v 1.44 2000/04/26 09:36:32 davem Exp $
+/* $Id: sab82532.c,v 1.45 2000/05/08 22:23:08 ecd Exp $
* sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
free_fifo++;
}
+ if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
+ count = readb(&info->regs->r.rbcl) & (info->recv_fifo_size - 1);
+ free_fifo++;
+ }
+
/* Issue a FIFO read command in case we where idle. */
if (stat->sreg.isr0 & SAB82532_ISR0_TIME) {
sab82532_cec_wait(info);
sab82532_cec_wait(info);
}
- if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
- count = readb(&info->regs->r.rbcl) & (info->recv_fifo_size - 1);
- if (count == 0)
- count = info->recv_fifo_size;
- free_fifo++;
- }
-
if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
#if 1
printk("sab82532: receive_chars: RFO");
SAB82532_IMR0_PLLA;
writeb(info->interrupt_mask0, &info->regs->w.imr0);
info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_XOFF |
- SAB82532_IMR1_TIN | SAB82532_IMR1_XON |
- SAB82532_IMR1_XPR;
+ SAB82532_IMR1_TIN | SAB82532_IMR1_CSC |
+ SAB82532_IMR1_XON | SAB82532_IMR1_XPR;
writeb(info->interrupt_mask1, &info->regs->w.imr1);
if (info->tty)
writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);
writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FCTS), &info->regs->rw.mode);
+ info->interrupt_mask1 &= ~(SAB82532_IMR1_CSC);
+ writeb(info->interrupt_mask1, &info->regs->w.imr1);
} else {
writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);
writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FCTS, &info->regs->rw.mode);
+ info->interrupt_mask1 |= SAB82532_IMR1_CSC;
+ writeb(info->interrupt_mask1, &info->regs->w.imr1);
}
writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RAC, &info->regs->rw.mode);
restore_flags(flags);
static inline void __init show_serial_version(void)
{
- char *revision = "$Revision: 1.44 $";
+ char *revision = "$Revision: 1.45 $";
char *version, *p;
version = strchr(revision, ' ');
This driver supports the Adaptec AHA-1460, the New Media Bus
Toaster, and the New Media Toast & Jam.
- aha152x_cs.c 1.52 2000/01/11 01:04:31
+ aha152x_cs.c 1.53 2000/05/04 01:30:00
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"aha152x_cs.c 1.52 2000/01/11 01:04:31 (David Hinds)";
+"aha152x_cs.c 1.53 2000/05/04 01:30:00 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
if (*linkp == NULL)
return;
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
aha152x_release_cs((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- add_timer(&link->release);
- }
+ if (link->state & DEV_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
A driver for Future Domain-compatible PCMCIA SCSI cards
- fdomain_cs.c 1.41 1999/11/15 06:05:48
+ fdomain_cs.c 1.42 2000/05/04 01:30:00
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"fdomain_cs.c 1.41 1999/11/15 06:05:48 (David Hinds)";
+"fdomain_cs.c 1.42 2000/05/04 01:30:00 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
if (*linkp == NULL)
return;
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
fdomain_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- add_timer(&link->release);
- }
+ if (link->state & DEV_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
A driver for the Qlogic SCSI card
- qlogic_cs.c 1.77 2000/02/01 19:08:09
+ qlogic_cs.c 1.78 2000/05/04 01:30:00
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"qlogic_cs.c 1.77 2000/02/01 19:08:09 (David Hinds)";
+"qlogic_cs.c 1.78 2000/05/04 01:30:00 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
if (*linkp == NULL)
return;
+ del_timer(&link->release);
if (link->state & DEV_CONFIG) {
qlogic_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- link->release.expires = jiffies + HZ/20;
- add_timer(&link->release);
- }
+ if (link->state & DEV_CONFIG)
+ mod_timer(&link->release, jiffies + HZ/20);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
bool '/proc file system support' CONFIG_PROC_FS
dep_bool '/dev file system support (EXPERIMENTAL)' CONFIG_DEVFS_FS $CONFIG_EXPERIMENTAL
+dep_bool ' Automatically mount at boot' CONFIG_DEVFS_MOUNT $CONFIG_DEVFS_FS
dep_bool ' Debug devfs' CONFIG_DEVFS_DEBUG $CONFIG_DEVFS_FS
# It compiles as a module for testing only. It should not be used
Don't kill existing block ops in <devfs_read_inode>.
Work sponsored by SGI.
v0.94
+ 20000424 Richard Gooch <rgooch@atnf.csiro.au>
+ Don't create missing directories in <devfs_find_handle>.
+ Work sponsored by SGI.
+ v0.95
+ 20000430 Richard Gooch <rgooch@atnf.csiro.au>
+ Added CONFIG_DEVFS_MOUNT.
+ Work sponsored by SGI.
+ v0.96
*/
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/bitops.h>
#include <asm/atomic.h>
-#define DEVFS_VERSION "0.94 (20000415)"
+#define DEVFS_VERSION "0.96 (20000430)"
#ifndef DEVFS_NAME
# define DEVFS_NAME "devfs"
# endif
#endif
-/* by default, we do not mount devfs on bootup */
+#ifdef CONFIG_DEVFS_MOUNT
+static unsigned int boot_options = OPTION_NONE;
+#else
static unsigned int boot_options = OPTION_NOMOUNT;
+#endif
/* Forward function declarations */
static struct devfs_entry *search_for_entry (struct devfs_entry *dir,
++name;
--namelen;
}
- entry = search_for_entry (dir, name, namelen, TRUE, FALSE, NULL,
+ entry = search_for_entry (dir, name, namelen, FALSE, FALSE, NULL,
traverse_symlink);
if (entry != NULL) return entry;
}
#ifndef _ALPHA_ATOMIC_H
#define _ALPHA_ATOMIC_H
+#include <linux/config.h>
+
/*
* Atomic operations that C can't guarantee us. Useful for
* resource counting etc...
* than regular operations.
*/
-#ifdef __SMP__
+#ifdef CONFIG_SMP
typedef struct { volatile int counter; } atomic_t;
#else
typedef struct { int counter; } atomic_t;
#ifndef __ALPHA_DELAY_H
#define __ALPHA_DELAY_H
+#include <linux/config.h>
#include <asm/smp.h>
/*
__delay((long)usecs >> 32);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define udelay(u) __udelay((u), cpu_data[smp_processor_id()].loops_per_sec)
#else
#define udelay(u) __udelay((u), loops_per_sec)
/* Initially just a straight copy of the i386 code. */
+#include <linux/config.h>
#include <linux/threads.h>
-#ifndef __SMP__
+#ifndef CONFIG_SMP
extern int __local_irq_count;
#define local_irq_count(cpu) ((void)(cpu), __local_irq_count)
extern unsigned long __irq_attempt[];
#define in_irq() (local_irq_count(smp_processor_id()) != 0)
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0)
#define hardirq_endlock(cpu) ((void) 0)
extern void synchronize_irq(void);
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
#endif /* _ALPHA_HARDIRQ_H */
* +-------------+----------------+--------------+
*/
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#include <asm/smp.h>
#define cpu_last_asn(cpuid) (cpu_data[cpuid].last_asn)
#else
extern unsigned long last_asn;
#define cpu_last_asn(cpuid) last_asn
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
#define WIDTH_HARDWARE_ASN 8
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define WIDTH_THIS_PROCESSOR 5
#else
#define WIDTH_THIS_PROCESSOR 0
icache flushing. While functional, it is _way_ overkill. The
icache is tagged with ASNs and it suffices to allocate a new ASN
for the process. */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define flush_icache_range(start, end) imb()
#else
#define flush_icache_range(start, end) smp_imb()
that icache entries are tagged with the ASN and load a new mm context. */
/* ??? Ought to use this in arch/alpha/kernel/signal.c too. */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
static inline void
flush_icache_page(struct vm_area_struct *vma, struct page *page)
{
{
}
-#ifndef __SMP__
+#ifndef CONFIG_SMP
/*
* Flush everything (kernel mapping may also have
* changed due to vmalloc/vfree)
flush_tlb_mm(mm);
}
-#else /* __SMP__ */
+#else /* CONFIG_SMP */
extern void flush_tlb_all(void);
extern void flush_tlb_mm(struct mm_struct *);
extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
extern void flush_tlb_range(struct mm_struct *, unsigned long, unsigned long);
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
/*
* Allocate and free page tables. The xxx_kernel() versions are
* used to allocate a kernel page table - this turns on ASN bits
* if any.
*/
-#ifndef __SMP__
+#ifndef CONFIG_SMP
extern struct pgtable_cache_struct {
unsigned long *pgd_cache;
unsigned long *pte_cache;
#ifndef __ASM_SMP_H
#define __ASM_SMP_H
+#include <linux/config.h>
#include <asm/pal.h>
/* HACK: Cabrio WHAMI return value is bogus if more than 8 bits used.. :-( */
return __r0;
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#include <linux/threads.h>
#include <asm/irq.h>
extern unsigned long cpu_present_mask;
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
#define NO_PROC_ID (-1)
#ifndef _ALPHA_SOFTIRQ_H
#define _ALPHA_SOFTIRQ_H
+#include <linux/config.h>
#include <linux/stddef.h>
#include <asm/atomic.h>
#include <asm/hardirq.h>
-#ifndef __SMP__
+#ifndef CONFIG_SMP
extern int __local_bh_count;
#define local_bh_count(cpu) ((void)(cpu), __local_bh_count)
#else
#define local_irq_disable() __cli()
#define local_irq_enable() __sti()
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern int global_irq_holder;
#define save_flags(flags) ((flags) = __global_save_flags())
#define restore_flags(flags) __global_restore_flags(flags)
-#else /* __SMP__ */
+#else /* CONFIG_SMP */
#define cli() __cli()
#define sti() __sti()
#define save_and_cli(flags) __save_and_cli(flags)
#define restore_flags(flags) __restore_flags(flags)
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
/*
* TB routines..
#include <linux/config.h>
-#ifdef __SMP__
+#ifdef CONFIG_SMP
typedef struct { volatile int counter; } atomic_t;
#else
typedef struct { int counter; } atomic_t;
#ifndef _ASM_DELAY_H
#define _ASM_DELAY_H
+#include <linux/config.h>
+
extern __inline__ void
__delay(unsigned long loops)
{
__delay(usecs);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define __udelay_val cpu_data[smp_processor_id()].udelay_val
#else
#define __udelay_val loops_per_sec
#ifndef _ASM_HARDIRQ_H
#define _ASM_HARDIRQ_H
+#include <linux/config.h>
#include <linux/threads.h>
extern unsigned int local_irq_count[NR_CPUS];
(local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
#define in_irq() (local_irq_count[smp_processor_id()] != 0)
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0)
#define hardirq_endlock(cpu) do { } while (0)
#error No habla MIPS SMP
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
#endif /* _ASM_HARDIRQ_H */
#ifndef _ASM_PGALLOC_H
#define _ASM_PGALLOC_H
+#include <linux/config.h>
+
/* TLB flushing:
*
* - flush_tlb_all() flushes all processes TLB entries
{
struct task_struct * p;
pgd_t *pgd;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int i;
#endif
*pgd_offset(p->mm,address) = entry;
}
read_unlock(&tasklist_lock);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
pgd[address >> PGDIR_SHIFT] = entry;
#else
#include <asm/isadep.h>
+#include <linux/config.h>
+
/*
* Default implementation of macro that returns current
* instruction pointer ("program counter").
extern struct mips_cpuinfo boot_cpu_data;
extern unsigned int vced_count, vcei_count;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern struct mips_cpuinfo cpu_data[];
#define current_cpu_data cpu_data[smp_processor_id()]
#else
#ifndef _ASM_ATOMIC_H
#define _ASM_ATOMIC_H
+#include <linux/config.h>
#include <asm/sgidefs.h>
-#ifdef __SMP__
+#ifdef CONFIG_SMP
typedef struct { volatile int counter; } atomic_t;
#else
typedef struct { int counter; } atomic_t;
#ifndef _ASM_DELAY_H
#define _ASM_DELAY_H
+#include <linux/config.h>
+
extern __inline__ void
__delay(unsigned long loops)
{
__delay(usecs);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define __udelay_val cpu_data[smp_processor_id()].udelay_val
#else
#define __udelay_val loops_per_sec
#ifndef _ASM_HARDIRQ_H
#define _ASM_HARDIRQ_H
+#include <linux/config.h>
#include <linux/threads.h>
extern unsigned int local_irq_count[NR_CPUS];
(local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
#define in_irq() (local_irq_count[smp_processor_id()] != 0)
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0)
#define hardirq_endlock(cpu) do { } while (0)
#error No habla MIPS SMP
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
#endif /* _ASM_HARDIRQ_H */
#ifndef _ASM_PGALLOC_H
#define _ASM_PGALLOC_H
+#include <linux/config.h>
+
/* TLB flushing:
*
* - flush_tlb_all() flushes all processes TLB entries
{
struct task_struct * p;
pgd_t *pgd;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int i;
#endif
*pgd_offset(p->mm, address) = entry;
}
read_unlock(&tasklist_lock);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
pgd[address >> PGDIR_SHIFT] = entry;
#else
*/
#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+#include <linux/config.h>
#if !defined (_LANGUAGE_ASSEMBLY)
#include <asm/cachectl.h>
#include <asm/mipsregs.h>
extern struct mips_cpuinfo boot_cpu_data;
extern unsigned int vced_count, vcei_count;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern struct mips_cpuinfo cpu_data[];
#define current_cpu_data cpu_data[smp_processor_id()]
#else
#define ASIZ_task_parent_exec_id 0x00000004
#define AOFF_task_self_exec_id 0x000005fc
#define ASIZ_task_self_exec_id 0x00000004
-#define AOFF_task_exit_sem 0x00000600
-#define ASIZ_task_exit_sem 0x00000020
+#define AOFF_task_alloc_lock 0x00000600
+#define ASIZ_task_alloc_lock 0x00000004
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000004
#define AOFF_mm_mmap_avl 0x00000004
#define ASIZ_task_parent_exec_id 0x00000004
#define AOFF_task_self_exec_id 0x00000700
#define ASIZ_task_self_exec_id 0x00000004
-#define AOFF_task_exit_sem 0x00000704
-#define ASIZ_task_exit_sem 0x00000024
+#define AOFF_task_alloc_lock 0x00000704
+#define ASIZ_task_alloc_lock 0x00000008
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000004
#define AOFF_mm_mmap_avl 0x00000004
#ifndef __ARCH_SPARC_ATOMIC__
#define __ARCH_SPARC_ATOMIC__
-#ifdef __SMP__
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
/* This is a temporary measure. -DaveM */
typedef struct { volatile int counter; } atomic_t;
#define ATOMIC_INIT(i) { (i << 8) }
#include <asm/system.h>
#include <asm/psr.h>
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define atomic_read(v) ((v)->counter)
#define atomic_set(v, i) (((v)->counter) = i)
#ifndef _SPARC_ATOPS_H
#define _SPARC_ATOPS_H
-#ifdef __SMP__
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
extern __inline__ __volatile__ unsigned char ldstub(volatile unsigned char *lock)
{
#ifndef _SPARC_BITOPS_H
#define _SPARC_BITOPS_H
+#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/byteorder.h>
#include <asm/system.h>
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define __SMPVOL volatile
#else
#define __SMPVOL
#ifndef __SPARC_HARDIRQ_H
#define __SPARC_HARDIRQ_H
+#include <linux/config.h>
#include <linux/threads.h>
-#ifndef __SMP__
+#ifndef CONFIG_SMP
extern unsigned int local_irq_count;
/*
extern void synchronize_irq(void);
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
#endif /* __SPARC_HARDIRQ_H */
#ifndef _SPARC_IRQ_H
#define _SPARC_IRQ_H
+#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/threads.h> /* For NR_CPUS */
#define NR_IRQS 15
/* IRQ handler dispatch entry and exit. */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern unsigned int local_irq_count[NR_CPUS];
#define irq_enter(cpu, irq) \
do { hardirq_enter(cpu); \
int irq,
unsigned int timeout);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
BTFIXUPDEF_CALL(void, set_cpu_int, int, int)
BTFIXUPDEF_CALL(void, clear_cpu_int, int, int)
BTFIXUPDEF_CALL(void, set_irq_udt, int)
#ifndef _SPARC_PGALLOC_H
#define _SPARC_PGALLOC_H
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/btfixup.h>
/* Fine grained cache/tlb flushing. */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
BTFIXUPDEF_CALL(void, local_flush_cache_all, void)
BTFIXUPDEF_CALL(void, local_flush_cache_mm, struct mm_struct *)
BTFIXUPDEF_CALL(void, local_flush_cache_range, struct mm_struct *, unsigned long, unsigned long)
#ifndef _SPARC_SEMAPHORE_HELPER_H
#define _SPARC_SEMAPHORE_HELPER_H
+#include <linux/config.h>
+
/*
* (barely) SMP- and interrupt-safe semaphore helper functions, sparc version.
*
{
int ret;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int tmp;
__asm__ __volatile__("
{
int ret;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int tmp;
__asm__ __volatile__("
{
int ret;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
int tmp;
__asm__ __volatile__("
#ifndef _SFP_MACHINE_H
#define _SFP_MACHINE_H
+
+#include <linux/config.h>
#define _FP_W_TYPE_SIZE 32
#define _FP_W_TYPE unsigned long
"3" ((USItype)(x0)) \
: "cc")
-#ifndef __SMP__
+#ifndef CONFIG_SMP
extern struct task_struct *last_task_used_math;
#endif
/* Obtain the current rounding mode. */
#ifndef FP_ROUNDMODE
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define FP_ROUNDMODE ((current->thread.fsr >> 30) & 0x3)
#else
#define FP_ROUNDMODE ((last_task_used_math->thread.fsr >> 30) & 0x3)
#define FP_HANDLE_EXCEPTIONS return _fex
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define FP_INHIBIT_RESULTS ((current->thread.fsr >> 23) & _fex)
#else
#define FP_INHIBIT_RESULTS ((last_task_used_math->thread.fsr >> 23) & _fex)
#ifndef _SPARC_SMP_H
#define _SPARC_SMP_H
+#include <linux/config.h>
#include <linux/threads.h>
#include <asm/head.h>
#include <asm/btfixup.h>
#endif /* !(__ASSEMBLY__) */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#ifndef __ASSEMBLY__
#define PROC_CHANGE_PENALTY 15
-#endif /* !(__SMP__) */
+#endif /* !(CONFIG_SMP) */
#define NO_PROC_ID 0xFF
#ifndef __SPARC_SOFTIRQ_H
#define __SPARC_SOFTIRQ_H
+#include <linux/config.h>
#include <linux/threads.h> /* For NR_CPUS */
#include <asm/atomic.h>
#include <asm/hardirq.h>
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern unsigned int local_bh_count[NR_CPUS];
#define local_bh_disable() (local_bh_count[smp_processor_id()]++)
extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
void *fpqueue, unsigned long *fpqdepth);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define SWITCH_ENTER \
if(prev->flags & PF_USEDFPU) { \
put_psr(get_psr() | PSR_EF); \
#define local_irq_save(flags) __save_and_cli(flags)
#define local_irq_restore(flags) __restore_flags(flags)
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern unsigned char global_irq_holder;
#define nop() __asm__ __volatile__ ("nop");
/* This has special calling conventions */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
BTFIXUPDEF_CALL(void, ___xchg32, void)
#endif
extern __inline__ unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
{
-#ifdef __SMP__
+#ifdef CONFIG_SMP
__asm__ __volatile__("swap [%2], %0"
: "=&r" (val)
: "0" (val), "r" (m));
#ifndef _SPARC_WINMACRO_H
#define _SPARC_WINMACRO_H
+#include <linux/config.h>
#include <asm/ptrace.h>
#include <asm/psr.h>
add %scratch, 1, %scratch; \
st %scratch, [%cur_reg + AOFF_task_thread + AOFF_thread_w_saved];
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define LOAD_CURRENT4M(dest_reg, idreg) \
rd %tbr, %idreg; \
sethi %hi(C_LABEL(current_set)), %dest_reg; \
#define ASIZ_task_parent_exec_id 0x00000004
#define AOFF_task_self_exec_id 0x00000834
#define ASIZ_task_self_exec_id 0x00000004
-#define AOFF_task_exit_sem 0x00000838
-#define ASIZ_task_exit_sem 0x00000038
-#define ASIZ_task 0x00000870
+#define AOFF_task_alloc_lock 0x00000838
+#define ASIZ_task_alloc_lock 0x00000004
+#define ASIZ_task 0x00000840
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000008
#define AOFF_mm_mmap_avl 0x00000008
#define ASIZ_task_parent_exec_id 0x00000004
#define AOFF_task_self_exec_id 0x00000a24
#define ASIZ_task_self_exec_id 0x00000004
-#define AOFF_task_exit_sem 0x00000a28
-#define ASIZ_task_exit_sem 0x00000038
-#define ASIZ_task 0x00000a60
+#define AOFF_task_alloc_lock 0x00000a28
+#define ASIZ_task_alloc_lock 0x00000001
+#define ASIZ_task 0x00000a30
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000008
#define AOFF_mm_mmap_avl 0x00000008
#define ASIZ_task_parent_exec_id 0x00000004
#define AOFF_task_self_exec_id 0x00000a3c
#define ASIZ_task_self_exec_id 0x00000004
-#define AOFF_task_exit_sem 0x00000a40
-#define ASIZ_task_exit_sem 0x00000040
-#define ASIZ_task 0x00000a80
+#define AOFF_task_alloc_lock 0x00000a40
+#define ASIZ_task_alloc_lock 0x0000000c
+#define ASIZ_task 0x00000a50
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000008
#define AOFF_mm_mmap_avl 0x00000008
#ifndef __SPARC64_DELAY_H
#define __SPARC64_DELAY_H
-#ifdef __SMP__
+#include <linux/config.h>
+#ifdef CONFIG_SMP
#include <linux/sched.h>
#include <asm/smp.h>
#endif
__delay(usecs);
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define __udelay_val cpu_data[smp_processor_id()].udelay_val
#else
#define __udelay_val loops_per_sec
#ifndef __SPARC64_HARDIRQ_H
#define __SPARC64_HARDIRQ_H
+#include <linux/config.h>
#include <linux/threads.h>
#include <linux/brlock.h>
#include <linux/spinlock.h>
-#ifndef __SMP__
+#ifndef CONFIG_SMP
extern unsigned int local_irq_count;
#define irq_enter(cpu, irq) (local_irq_count++)
#define irq_exit(cpu, irq) (local_irq_count--)
/* This tests only the local processors hw IRQ context disposition. */
#define in_irq() (local_irq_count != 0)
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define hardirq_trylock(cpu) ((void)(cpu), local_irq_count == 0)
#define hardirq_endlock(cpu) do { (void)(cpu); } while(0)
#define synchronize_irq() barrier()
-#else /* (__SMP__) */
+#else /* (CONFIG_SMP) */
static __inline__ int irqs_running(void)
{
extern void synchronize_irq(void);
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
#endif /* !(__SPARC64_HARDIRQ_H) */
#ifndef _SPARC64_IRQ_H
#define _SPARC64_IRQ_H
+#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/kernel.h>
extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
extern unsigned int psycho_build_irq(void *psycho, int imap_off, int ino, int need_dma_sync);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern void set_cpu_int(int, int);
extern void clear_cpu_int(int, int);
extern void set_irq_udt(int);
#ifndef __SPARC64_OPLIB_H
#define __SPARC64_OPLIB_H
+#include <linux/config.h>
#include <asm/openprom.h>
/* Enumeration to describe the prom major version we have detected. */
extern enum prom_output_device prom_query_output_device(void);
/* Multiprocessor operations... */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Start the CPU with the given device tree node, context table, and context
* at the passed program counter.
*/
#ifndef _SPARC64_PGALLOC_H
#define _SPARC64_PGALLOC_H
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
unsigned long pgsz, unsigned long size);
extern void __flush_tlb_page(unsigned long context, unsigned long page, unsigned long r);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define flush_cache_all() __flush_cache_all()
#define flush_tlb_all() __flush_tlb_all()
SECONDARY_CONTEXT); \
} while(0)
-#else /* __SMP__ */
+#else /* CONFIG_SMP */
extern void smp_flush_cache_all(void);
extern void smp_flush_tlb_all(void);
#define flush_tlb_page(vma, page) \
smp_flush_tlb_page((vma)->vm_mm, page)
-#endif /* ! __SMP__ */
+#endif /* ! CONFIG_SMP */
/* This will change for Cheetah and later chips. */
#define VPTE_BASE 0xfffffffe00000000
}
/* Page table allocation/freeing. */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Sliiiicck */
#define pgt_quicklists cpu_data[smp_processor_id()]
#else
#define pgtable_cache_size (pgt_quicklists.pgcache_size)
#define pgd_cache_size (pgt_quicklists.pgdcache_size)
-#ifndef __SMP__
+#ifndef CONFIG_SMP
extern __inline__ void free_pgd_fast(pgd_t *pgd)
{
return (pgd_t *)ret;
}
-#else /* __SMP__ */
+#else /* CONFIG_SMP */
extern __inline__ void free_pgd_fast(pgd_t *pgd)
{
free_page((unsigned long)pgd);
}
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address_premasked);
-/* $Id: pgtable.h,v 1.125 2000/04/12 08:10:26 davem Exp $
+/* $Id: pgtable.h,v 1.126 2000/05/05 21:57:03 davem Exp $
* pgtable.h: SpitFire page table operations.
*
* Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
* Undefined behaviour if not..
*/
#define pte_read(pte) (pte_val(pte) & _PAGE_READ)
+#define pte_exec(pte) pte_read(pte)
#define pte_write(pte) (pte_val(pte) & _PAGE_WRITE)
#define pte_dirty(pte) (pte_val(pte) & _PAGE_MODIFIED)
#define pte_young(pte) (pte_val(pte) & _PAGE_ACCESSED)
*/
#define current_text_addr() ({ void *pc; __asm__("rd %%pc, %0" : "=r" (pc)); pc; })
+#include <linux/config.h>
#include <asm/asi.h>
#include <asm/a.out.h>
#include <asm/pstate.h>
}
/* On Uniprocessor, even in RMO processes see TSO semantics */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#define TSTATE_INITIAL_MM TSTATE_TSO
#else
#define TSTATE_INITIAL_MM TSTATE_RMO
#ifndef _SPARC64_SMP_H
#define _SPARC64_SMP_H
+#include <linux/config.h>
#include <linux/threads.h>
#include <asm/asi.h>
#endif /* !(__ASSEMBLY__) */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
#ifndef __ASSEMBLY__
#define PROC_CHANGE_PENALTY 20
-#endif /* !(__SMP__) */
+#endif /* !(CONFIG_SMP) */
#define NO_PROC_ID 0xFF
#ifndef __SPARC64_SOFTIRQ_H
#define __SPARC64_SOFTIRQ_H
+#include <linux/config.h>
#include <asm/atomic.h>
#include <asm/hardirq.h>
#include <asm/system.h> /* for membar() */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
extern unsigned int local_bh_count;
#else
#define local_bh_count (cpu_data[smp_processor_id()].bh_count)
#ifndef __SPARC64_SYSTEM_H
#define __SPARC64_SYSTEM_H
+#include <linux/config.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/asm_offsets.h>
#define local_irq_save(flags) __save_and_cli(flags)
#define local_irq_restore(flags) __restore_flags(flags)
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define cli() __cli()
#define sti() __sti()
#define save_flags(x) __save_flags(x)
* and also profiling if enabled.
*/
+#include <linux/config.h>
+
/* Two timers, traditionally steered to PIL's 10 and 14 respectively.
* But since INO packets are used on sun5, we could use any PIL level
* we like, however for now we use the normal ones.
*/
#define SUN5_HZ_TO_LIMIT(__hz) (1000000/(__hz))
-#ifdef __SMP__
+#ifdef CONFIG_SMP
extern unsigned long timer_tick_offset;
extern void timer_tick_interrupt(struct pt_regs *);
#endif
#ifdef __KERNEL__
-#include <linux/string.h>
#include <asm/semaphore.h>
#include <asm/byteorder.h>
#define ETH_P_AARP 0x80F3 /* Appletalk AARP */
#define ETH_P_IPX 0x8137 /* IPX over DIX */
#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
+#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */
+#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */
/*
* Non DIX types. Won't clash for 1500 types.
--- /dev/null
+/***************************************************************************
+ * Linux PPP over X - Generic PPP transport layer sockets
+ * Linux PPP over Ethernet (PPPoE) Socket Implementation (RFC 2516)
+ *
+ * This file supplies definitions required by the PPP over Ethernet driver
+ * (pppox.c). All version information wrt this file is located in pppox.c
+ *
+ * License:
+ * 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 Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __LINUX_IF_PPPOX_H
+#define __LINUX_IF_PPPOX_H
+
+#include <linux/if_ether.h>
+#include <linux/if.h>
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#ifdef __KERNEL__
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <asm/semaphore.h>
+#include <linux/ppp_channel.h>
+#endif /* __KERNEL__ */
+
+/* For user-space programs to pick up these definitions
+ * which they wouldn't get otherwise without defining __KERNEL__
+ */
+#ifndef AF_PPPOX
+#define AF_PPPOX 24
+#define PF_PPPOX AF_PPPOX
+#endif /* !(AF_PPPOX) */
+
+/************************************************************************
+ * PPPoE addressing definition
+ */
+typedef __u16 sid_t;
+struct pppoe_addr{
+ sid_t sid; /* Session identifier */
+ unsigned char remote[ETH_ALEN]; /* Remote address */
+ char dev[IFNAMSIZ]; /* Local device to use */
+};
+
+/************************************************************************
+ * Protocols supported by AF_PPPOX
+ */
+#define PX_PROTO_OE 0 /* Currently just PPPoE */
+#define PX_MAX_PROTO 1
+
+struct sockaddr_pppox {
+ sa_family_t sa_family; /* address family, AF_PPPOX */
+ unsigned int sa_protocol; /* protocol identifier */
+ union{
+ struct pppoe_addr pppoe;
+ }sa_addr;
+}__attribute__ ((packed));
+
+
+/*********************************************************************
+ *
+ * ioctl interface for defining forwarding of connections
+ *
+ ********************************************************************/
+
+#define PPPOEIOCSFWD _IOW(0xB1 ,0, sizeof(struct sockaddr_pppox))
+#define PPPOEIOCDFWD _IO(0xB1 ,1)
+/*#define PPPOEIOCGFWD _IOWR(0xB1,2, sizeof(struct sockaddr_pppox))*/
+
+/* Codes to identify message types */
+#define PADI_CODE 0x09
+#define PADO_CODE 0x07
+#define PADR_CODE 0x19
+#define PADS_CODE 0x65
+#define PADT_CODE 0xa7
+struct pppoe_tag {
+ __u16 tag_type;
+ __u16 tag_len;
+ char tag_data[0];
+} __attribute ((packed));
+
+/* Tag identifiers */
+#define PTT_EOL __constant_htons(0x0000)
+#define PTT_SRV_NAME __constant_htons(0x0101)
+#define PTT_AC_NAME __constant_htons(0x0102)
+#define PTT_HOST_UNIQ __constant_htons(0x0103)
+#define PTT_AC_COOKIE __constant_htons(0x0104)
+#define PTT_VENDOR __constant_htons(0x0105)
+#define PTT_RELAY_SID __constant_htons(0x0110)
+#define PTT_SRV_ERR __constant_htons(0x0201)
+#define PTT_SYS_ERR __constant_htons(0x0202)
+#define PTT_GEN_ERR __constant_htons(0x0203)
+
+struct pppoe_hdr {
+ __u8 ver : 4;
+ __u8 type : 4;
+ __u8 code;
+ __u16 sid;
+ __u16 length;
+ struct pppoe_tag tag[0];
+} __attribute__ ((packed));
+
+#ifdef __KERNEL__
+
+struct pppox_proto {
+ int (*create)(struct socket *sock);
+ int (*ioctl)(struct socket *sock, unsigned int cmd,
+ unsigned long arg);
+};
+
+extern int register_pppox_proto(int proto_num, struct pppox_proto *pp);
+extern void unregister_pppox_proto(int proto_num);
+extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
+extern int pppox_channel_ioctl(struct ppp_channel *pc, unsigned int cmd,
+ unsigned long arg);
+
+/* PPPoE socket states */
+enum {
+ PPPOX_NONE = 0, /* initial state */
+ PPPOX_CONNECTED = 1, /* connection established ==TCP_ESTABLISHED */
+ PPPOX_BOUND = 2, /* bound to ppp device */
+ PPPOX_RELAY = 4, /* forwarding is enabled */
+ PPPOX_DEAD = 8
+};
+
+extern struct ppp_channel_ops pppoe_chan_ops;
+
+extern void pppox_proto_init(struct net_proto *np);
+
+#endif /* __KERNEL__ */
+
+#endif /* !(__LINUX_IF_PPPOX_H) */
#ifndef _LINUX_NET_H
#define _LINUX_NET_H
+#include <linux/config.h>
#include <linux/socket.h>
#include <linux/wait.h>
extern unsigned long net_random(void);
extern void net_srandom(unsigned long);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
#define SOCKOPS_WRAPPED(name) name
#define SOCKOPS_WRAP(name, fam)
#else
#include <linux/list.h>
#include <linux/skbuff.h>
#include <linux/poll.h>
+#include <asm/atomic.h>
struct ppp_channel;
int (*start_xmit)(struct ppp_channel *, struct sk_buff *);
/* Handle an ioctl call that has come in via /dev/ppp. */
int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long);
+
};
struct ppp_channel {
#define AF_ATMSVC 20 /* ATM SVCs */
#define AF_SNA 22 /* Linux SNA Project (nutters!) */
#define AF_IRDA 23 /* IRDA sockets */
+#define AF_PPPOX 24 /* PPPoX sockets */
#define AF_MAX 32 /* For now.. */
/* Protocol families, same as address families. */
#define PF_ATMSVC AF_ATMSVC
#define PF_SNA AF_SNA
#define PF_IRDA AF_IRDA
-
+#define PF_PPPOX AF_PPPOX
#define PF_MAX AF_MAX
/* Maximum queue length specifiable by listen. */
#endif
#endif
+#if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE)
+#include <linux/if_pppox.h>
+#include <linux/ppp_channel.h> /* struct ppp_channel */
+#endif
+
#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
#if defined(CONFIG_SPX) || defined(CONFIG_SPX_MODULE)
#include <net/spx.h>
};
#endif
+#if defined(CONFIG_PPPOE) || defined (CONFIG_PPPOE_MODULE)
+struct pppoe_opt
+{
+ struct net_device *dev; /* device associated with socket*/
+ struct pppoe_addr pa; /* what this socket is bound to*/
+ struct sockaddr_pppox relay; /* what socket data will be
+ relayed to (PPPoE relaying) */
+};
+
+struct pppox_opt
+{
+ struct ppp_channel chan;
+ struct sock *sk;
+ struct pppox_opt *next; /* for hash table */
+ union {
+ struct pppoe_opt pppoe;
+ } proto;
+};
+#define pppoe_dev proto.pppoe.dev
+#define pppoe_pa proto.pppoe.pa
+#define pppoe_relay proto.pppoe.relay
+#endif
/* This defines a selective acknowledgement block. */
struct tcp_sack_block {
#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
rose_cb *rose;
#endif
+#if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE)
+ struct pppox_opt *pppox;
+#endif
#ifdef CONFIG_NETLINK
struct netlink_opt *af_netlink;
#endif
EXPORT_SYMBOL(follow_down);
EXPORT_SYMBOL(path_init);
EXPORT_SYMBOL(path_walk);
+EXPORT_SYMBOL(path_release);
EXPORT_SYMBOL(__user_walk);
EXPORT_SYMBOL(lookup_one);
EXPORT_SYMBOL(lookup_hash);
EXPORT_SYMBOL(vfs_rmdir);
EXPORT_SYMBOL(vfs_unlink);
EXPORT_SYMBOL(vfs_rename);
+EXPORT_SYMBOL(vfs_statfs);
EXPORT_SYMBOL(generic_read_dir);
EXPORT_SYMBOL(__pollwait);
EXPORT_SYMBOL(ROOT_DEV);
EXPORT_SYMBOL(autoirq_report);
#endif
-#ifdef __SMP__
+#ifdef CONFIG_SMP
EXPORT_SYMBOL(del_timer_sync);
#endif
EXPORT_SYMBOL(mod_timer);
EXPORT_SYMBOL(timer_active);
EXPORT_SYMBOL(timer_table);
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Various random spinlocks we want to export */
EXPORT_SYMBOL(tqueue_lock);
* 1997-11-02 Modified for POSIX.1b signals by Richard Henderson
*/
+#include <linux/config.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/unistd.h>
sigaddset(&t->signal, sig);
if (!sigismember(&t->blocked, sig)) {
t->sigpending = 1;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/*
* If the task is running on a different CPU
* force a reschedule on the other CPU - note that
if (t->has_cpu && t->processor != smp_processor_id())
smp_send_reschedule(t->processor);
spin_unlock(&runqueue_lock);
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
}
out:
struct list_head * page_lru, * dispose;
struct page * page = NULL;
- count = (nr_lru_pages << 1) >> (priority >> 1);
+ count = nr_lru_pages / (priority + 1);
/* we need pagemap_lru_lock for list_del() ... subtle code below */
spin_lock(&pagemap_lru_lock);
page = list_entry(page_lru, struct page, lru);
list_del(page_lru);
+ dispose = &lru_cache;
+ if (PageTestandClearReferenced(page))
+ goto dispose_continue;
+
count--;
+ dispose = &old;
/*
- * Any page we can't touch (because it is
- * locked or shared or something), gets
- * put on the old list (maybe we can touch
- * it next time).
- *
- * We leave the Reference bit untouched,
- * so that it can stay "young" despite being
- * moved to the back of the queue.
- *
* Avoid unscalable SMP locking for pages we can
* immediate tell are untouchable..
*/
- dispose = &old;
if (!page->buffers && page_count(page) > 1)
goto dispose_continue;
/*
* Is it a buffer page? Try to clean it up regardless
- * of zone and Reference bits..
+ * of zone - it's old.
*/
if (page->buffers) {
if (!try_to_free_buffers(page))
}
}
- /*
- * Page is from a zone we don't care about.
- * Put it on the old list, but leave the reference
- * bit untouched - which may end up keeping
- * it young (so that the LRU for that zone is
- * not destroyed completely).
- */
- if (page->zone->free_pages > page->zone->pages_high)
- goto unlock_continue;
-
- /*
- * The page is in use, or was used very recently, put it in
- * back at the top (it's young).. We may touch it after a
- * second pass if we haven't found anything else.
- */
- dispose = &lru_cache;
- if (PageTestandClearReferenced(page))
- goto unlock_continue;
-
/* Take the pagecache_lock spinlock held to avoid
other tasks to notice the page while we are looking at its
page count. If it's a pagecache-page we'll free it
in one atomic transaction after checking its page count. */
spin_lock(&pagecache_lock);
- dispose = &old;
/*
* We can't free pages unless there's just one user
* (count == 2 because we added one ourselves above).
goto made_inode_progress;
}
+ /*
+ * Page is from a zone we don't care about.
+ * Don't drop page cache entries in vain.
+ */
+ if (page->zone->free_pages > page->zone->pages_high)
+ goto cache_unlock_continue;
+
/* is it a page-cache page? */
if (page->mapping) {
if (!PageDirty(page) && !pgcache_under_min()) {
spin_lock(&pagemap_lru_lock);
UnlockPage(page);
put_page(page);
- list_add(page_lru, dispose);
- continue;
-
- /* we're holding pagemap_lru_lock, so we can just loop again */
dispose_continue:
list_add(page_lru, dispose);
}
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_if.c,v 1.2 2000/02/21 15:51:34 davem Exp $
+ * $Id: br_if.c,v 1.3 2000/05/05 02:17:17 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_private.h,v 1.2 2000/03/21 21:08:47 davem Exp $
+ * $Id: br_private.h,v 1.3 2000/05/05 02:17:17 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_stp.c,v 1.2 2000/02/21 15:51:34 davem Exp $
+ * $Id: br_stp.c,v 1.3 2000/05/05 02:17:17 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_stp_if.c,v 1.2 2000/02/21 15:51:34 davem Exp $
+ * $Id: br_stp_if.c,v 1.3 2000/05/05 02:17:17 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br_stp_timer.c,v 1.2 2000/02/21 15:51:35 davem Exp $
+ * $Id: br_stp_timer.c,v 1.3 2000/05/05 02:17:17 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
/*=======================================================================
- Receiver rotutines
+ Receiver routines
=======================================================================*/
int netdev_max_backlog = 300;
/*
* Linux NET3: IP/IP protocol decoder.
*
- * Version: $Id: ipip.c,v 1.32 2000/03/21 06:13:54 davem Exp $
+ * Version: $Id: ipip.c,v 1.33 2000/05/05 02:17:17 davem Exp $
*
* Authors:
* Sam Lantinga (slouken@cs.ucdavis.edu) 02/01/95
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Version: $Id: ipmr.c,v 1.52 2000/05/02 01:47:02 davem Exp $
+ * Version: $Id: ipmr.c,v 1.53 2000/05/05 02:17:17 davem Exp $
*
* Fixes:
* Michael Chastain : Incorrect size of copying.
#include <net/p8022call.h>
#endif
+
+#ifdef CONFIG_PPPOE
+#include <linux/if_pppox.h>
+#endif
+
/*
* Protocol Table
*/
#ifdef CONFIG_IRDA
{ "IrDA", irda_proto_init }, /* IrDA protocols */
#endif
-
+#ifdef CONFIG_PPPOE
+ { "PPPoX", pppox_proto_init }, /* PPP over Ethernet */
+#endif
{ NULL, NULL } /* End marker */
};
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Version: $Id: af_unix.c,v 1.94 2000/04/25 04:13:35 davem Exp $
+ * Version: $Id: af_unix.c,v 1.95 2000/05/09 04:48:37 davem Exp $
*
* Fixes:
* Linus Torvalds : Assorted bug cures.