diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/CREDITS linux.ac/CREDITS
--- linux.vanilla/CREDITS Tue Feb 23 14:21:32 1999
+++ linux.ac/CREDITS Fri Feb 26 01:47:18 1999
@@ -1061,6 +1061,14 @@
S: L3R 8B2
S: Canada
+N: Russell Kroll
+E: rkroll@exploits.org
+W: http://www.exploits.org/
+D: V4L Aztech radio card driver, mods to Aimslab driver
+S: Post Office Box 49458
+S: Colorado Springs, Colorado 80949-9458
+S: USA
+
N: Gero Kuhlmann
E: gero@gkminix.han.de
D: mounting root via NFS
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/Changes linux.ac/Documentation/Changes
--- linux.vanilla/Documentation/Changes Sun Jan 24 19:55:29 1999
+++ linux.ac/Documentation/Changes Tue Feb 16 17:11:41 1999
@@ -250,6 +250,11 @@
The ISDN code in the stock 2.0 kernel may not work for you. If it
doesn't, look in ftp://ftp.suse.com/pub/isdn4linux for updated versions.
+ In 2.0.x the kernel could be configured to drop source routed IP
+packets via a compile time configuration option. In 2.2.x, this has
+been replaced by a sysctl. See Documentation/networking/ip-sysctl.txt
+for more information.
+
Memory
======
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/Configure.help linux.ac/Documentation/Configure.help
--- linux.vanilla/Documentation/Configure.help Tue Feb 23 14:21:32 1999
+++ linux.ac/Documentation/Configure.help Fri Feb 26 01:59:54 1999
@@ -85,13 +85,13 @@
a system with only one CPU, like most personal computers, say N. If
you have a system with more than one CPU, say Y.
- If you say N here, the kernel will run on single and multiprocessor
- machines, but will use only one CPU of a multiprocessor machine. If
+ If you say N here, the kernel will run on single and multi-processor
+ machines, but will use only one CPU of a multi-processor machine. If
you say Y here, the kernel will run on many, but not all,
- singleprocessor machines. On a singleprocessor machine, the kernel
+ single-processor machines. On a single-processor machine, the kernel
will run faster if you say N here.
- Note that if you say Y here and choose architecture "586" or
+ Note that if you say Y here and choose architectures "586" or
"Pentium" under "Processor family", the kernel will not work on 486
architectures. Similarly, multiprocessor kernels for the "PPro"
architecture may not work on all Pentium based boards.
@@ -1089,25 +1089,6 @@
recommended to read the NET-3-HOWTO, available via FTP (user:
anonymous) from ftp://metalab.unc.edu/pub/Linux/docs/HOWTO.
-Network aliasing
-CONFIG_NET_ALIAS
- If you say Y here, you will be able to set multiple network
- addresses on the same low-level network device driver. This is
- typically used for services that act differently based on the
- address they listen on (e.g. "multihosting" or "virtual domains" or
- "virtual hosting services" on the web server apache and the ftp
- server wuftpd -- read the Virtual-Services-HOWTO, available via FTP
- (user: anonymous) from ftp://metalab.unc.edu/pub/Linux/docs/HOWTO)
- or for connecting to different logical networks through the same
- physical interface (most commonly an Ethernet networking card). See
- Documentation/networking/alias.txt for more info.
-
- This is the generic part, later when configuring network protocol
- options you will be asked for protocol-specific aliasing support,
- and you will have to say Y to at least one of them, most likely to
- "IP: aliasing support". If you need this feature (for any protocol,
- like IP) say Y; if unsure, say N.
-
Socket filtering
CONFIG_FILTER
The Linux Socket Filter is derived from the Berkeley Packet Filter.
@@ -1762,6 +1743,18 @@
except that your Apollo won't be able to boot from it (because the
code in the ROM will be for a PC).
+Apollo support
+CONFIG_APOLLO
+ Say Y here if you want to run Linux on an MC680x0-based Apollo
+ Domain workstation such as the DN3500.
+
+Apollo 3c505 support
+CONFIG_APOLLO_ELPLUS
+ Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
+ If you don't have one made for Apollos, you can use one from a PC,
+ except that your Apollo won't be able to boot from it (because the
+ code in the ROM will be for a PC).
+
Atari native chipset support
CONFIG_FB_ATARI
This is the frame buffer device driver for the builtin graphics
@@ -2099,7 +2092,7 @@
CONFIG_PNP_PARPORT
Some IEEE-1284 conforming parallel-port devices can identify
themselves when requested. Say Y to enable this feature, or M to
- compile it as a module (parport_ieee1284.o). If in doubt, say N.
+ compile it as a module (parport_probe.o). If in doubt, say N.
Enable loadable module support
CONFIG_MODULES
@@ -2735,20 +2728,6 @@
enabled. Those programs that would benefit from disabling this
facility can do it on a per connection basis themselves.
-IP: Drop source routed frames
-CONFIG_IP_NOSR
- Usually, the originator of an IP frame (packet) specifies only the
- destination, and the hosts along the way do the routing, i.e. they
- decide how to forward the frame. However, there is a feature of the
- IP protocol that allows to specify the full route for a given frame
- already at its origin. A frame with such a fully specified route is
- called "source routed". The question now is whether we should honour
- these route requests when such frames arrive, or if we should drop
- all those frames instead. Honouring them can introduce security
- problems (and is rarely a useful feature), and hence it is
- recommended that you say Y here unless you really know what you're
- doing.
-
IP: Allow large windows (not recommended if <16 MB of memory)
CONFIG_SKB_LARGE
On high speed, long distance networks the performance limit on
@@ -3712,34 +3691,49 @@
say M here and read Documentation/modules.txt. The module will be
called aic7xxx.o.
-Override driver defaults for commands per LUN
-CONFIG_OVERRIDE_CMDS
- Say Y here if you want to override the default maximum number of
- commands that a single device on the aic7xxx controller is allowed
- to have active at one time. This option only affects tagged queueing
- capable devices. The driver uses a value of 24 by default.
- If you say Y here, you can adjust the number of commands per LUN
- with the following configuration option.
-
- If unsure, say N.
+Enable or Disable Tagged Command Queueing by default
+CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+ This option causes the aic7xxx driver to attempt to use tagged command
+ queueing on any devices that claim to support it. If this is set to yes,
+ you can still turn off TCQ on troublesome devices with the use of the
+ tag_info boot parameter. See /usr/src/linux/drivers/scsi/README.aic7xxx
+ for more information on that and other aic7xxx setup commands. If this
+ option is turned off, you may still enable TCQ on known good devices by
+ use of the tag_info boot parameter.
+
+ If you are unsure about your devices then it is safest to say N here.
+
+ However, TCQ can increase performance on some hard drives by as much
+ as 50% or more, so I would recommend that if you say N here, that you
+ at least read the README.aic7xxx file so you will know how to enable
+ this option manually should your drives prove to be safe in regards
+ to TCQ.
+
+ Conversely, certain drives are known to lock up or cause bus resets when
+ TCQ is enabled on them. If you have a Western Digital Enterprise SCSI
+ drive for instance, then don't even bother to enable TCQ on it as the
+ drive will become unreliable, and it will actually reduce performance.
+
+Default number of TCQ commands per device
+CONFIG_AIC7XXX_CMDS_PER_DEVICE
+ Specify the number of commands you would like to allocate per SCSI
+ device when Tagged Command Queueing (TCQ) is enabled on that device.
-Maximum number of commands per LUN
-CONFIG_AIC7XXX_CMDS_PER_LUN
- Specify the maximum number of commands you would like to allocate
- per LUN (a LUN is a Logical Unit Number -- some physical SCSI
- devices, e.g. CD jukeboxes, act logically as several separate units,
- each of which gets its own number).
-
- Reasonable figures are in the range of 14 to 32 commands per device,
+ Reasonable figures are in the range of 8 to 24 commands per device,
but depending on hardware could be increased or decreased from that
figure. If the number is too high for any particular device, the
driver will automatically compensate usually after only 10 minutes
- of uptime and will issue a message to alert you to the fact that the
- number of commands for that device has been reduced. It will not
- hinder performance if some of your devices eventually have their
- commands per LUN reduced, but is a waste of memory if all of your
- devices end up reducing this number down to a more reasonable
- figure. Default: 24
+ of uptime. It will not hinder performance if some of your devices
+ eventually have their command depth reduced, but is a waste of memory
+ if all of your devices end up reducing this number down to a more
+ reasonable figure.
+
+ NOTE: Certain very broken drives are known to lock up when given more
+ commands than they like to deal with. Quantum Fireball drives are the
+ most common in this category. For the Quantum Fireball drives I would
+ suggest no more than 8 commands per device.
+
+ Default: 8
Collect statistics to report in /proc
CONFIG_AIC7XXX_PROC_STATS
@@ -4203,6 +4197,17 @@
say M here and read Documentation/modules.txt. The module will be
called initio.o
+Initio 91XXU(W) SCSI support
+CONFIG_SCSI_INITIO
+ This is support for the Initio 91XXU(W) SCSI host adapter.
+ Please read the SCSI-HOWTO, available via FTP (user: anonymous) at
+ ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read Documentation/modules.txt. The module will be
+ called initio.o
+
PAS16 SCSI support
CONFIG_SCSI_PAS16
This is support for a SCSI host adapter. It is explained in section
@@ -4216,6 +4221,17 @@
The module will be called pas16.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
+Initio INI-A100U2W SCSI support
+CONFIG_SCSI_INIA100
+ This is support for the Initio INI-A100U2W SCSI host adapter.
+ Please read the SCSI-HOWTO, available via FTP (user: anonymous) at
+ ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read Documentation/modules.txt. The module will be
+ called a100u2w.o
+
PCI2000 support
CONFIG_SCSI_PCI2000
This is support for the PCI2000I EIDE interface card which acts as a
@@ -4408,6 +4424,23 @@
say M here and read Documentation/modules.txt. The module will be
called NCR53c406.o.
+Symbios Logic sym53c416 support
+CONFIG_SCSI_SYM53C416
+ This is support for the sym53c416 SCSI host adapter. This is the
+ SCSI adapter that comes with some hp scanners. This driver requires that
+ the sym53c416 is configured first using some sort of pnp configuration
+ program (e.g. isapnp) or by a PnP aware BIOS. If you are using isapnp then
+ you need to compile it as a module and then load it using insmod after
+ isapnp has run. The parameters of the configured card(s) should be passed
+ to the driver. The format is:
+
+ insmod sym53c416 sym53c416=, [sym53c416_1=,]
+
+ There is support for up to four adapters. If you want to compile this
+ driver as a module ( = code which can be inserted in and removed from
+ the running kernel whenever you want), say M here and read
+ Documentation/modules.txt.
+
Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support
CONFIG_SCSI_DC390T
This driver supports PCI SCSI host adapters based on the Am53C974A
@@ -8924,6 +8957,20 @@
here (the module will be called sound.o) if you haven't found a
driver for your sound card above, then pick your driver from the
list below.
+
+Persistent DMA buffers
+CONFIG_SOUND_DMAP
+ Linux can often have problems allocating DMA buffers for ISA cards on
+ machines with more than 16MB of RAM. This is because ISA DMA buffers
+ must exist below the 16MB boundry and it is quite possible that we
+ can't find a large enough free block in this region after the machine
+ has been running for any amount of time. If you say Y here the DMA
+ buffers (64Kb) will be allocated at boot time and kept until the
+ shutdown. This option is only usefull if you say Y to OSS sound
+ modules. If you say M to OSS sound modules then you can just pass to
+ the sound.o module a "dmabuf=1" command-line argument.
+
+ Say Y unless you have 16MB or less RAM or a PCI sound card.
Support for Aztech Sound Galaxy (non-PnP) cards
CONFIG_SOUND_SGALAXY
@@ -9463,6 +9510,11 @@
ISDN subsystem
CONFIG_ISDN
+ CAUTION: the ISDN driver shipped with this kernel distribution
+ is outdated and might not work without problems. An updated driver
+ is available for download. Please read http://www.isdn4linux.de
+ on the WWW for a list of servers.
+
ISDN ("Integrated Services Digital Networks", called RNIS in France)
is a special type of fully digital telephone service; it's mostly
used to connect to your Internet service provider (with SLIP or
@@ -10503,6 +10555,44 @@
CONFIG_RADIO_SF16FMI_PORT
Enter the I/O port of your SF16FMI radio card.
+Typhoon Radio
+CONFIG_RADIO_TYPHOON
+ Choose Y here if you have one of these FM radio cards, and then fill
+ in the port address and the frequency used for muting below.
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video for Linux API. Information on
+ this API and pointers to "v4l" programs may be found on the WWW at
+ http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
+ you need to have access to a machine on the Internet that has a
+ program like lynx or netscape.
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read Documentation/modules.txt. The module will be
+ called radio-typhoon.o
+
+Support for /proc/radio-typhoon
+CONFIG_RADIO_TYPHOON_PROC_FS
+ Say Y here if you want the typhoon radio card driver to write
+ status information (frequency, volume, muted, mute frequency,
+ base address) to /proc/radio-typhoon. The file can be viewed with
+ your favorite pager (i.e. use "more /proc/radio-typhoon" or "less
+ /proc/radio-typhoon" or simply "cat /proc/radio-typhoon").
+
+Typhoon I/O port (0x316 or 0x336)
+CONFIG_RADIO_TYPHOON_PORT
+ Enter the I/O port of your Typhoon or EcoRadio radio card.
+
+Typhoon frequency set when muting the device (kHz)
+CONFIG_RADIO_TYPHOON_MUTEFREQ
+ Enter the frequency used for muting the radio. The device is never
+ completely silent. If the volume is just turned down, you can still
+ hear silent voices and music. For that reason, the frequency of the
+ radio device is set to the frequency you can enter here whenever
+ the device is muted. There should be no local radio station at that
+ frequency.
+
Zoltrix Radio
CONFIG_RADIO_ZOLTRIX
Choose Y here if you have one of these FM radio cards, and then fill
@@ -10748,24 +10838,10 @@
Documentation/modules.txt. IrLAN emulates an Ethernet and makes it
possible to put up a wireless LAN using infrared beams.
-IrLAN Client Protocol
-CONFIG_IRLAN_CLIENT
- Say Y here if you want to build support for the IrLAN client
- protocol. If you want to compile it as a module, say M here and read
- Documentation/modules.txt. The IrLAN client protocol can be used to
- talk with infrared access points like the HP NetbeamIR, or the ESI
- JetEye NET. You can also connect to another Linux machine running
- the IrLAN server protocol for ad-hoc networking!
-
-IrLAN Server Protocol
-CONFIG_IRLAN_SERVER
- Say Y here if you want to build support for infrared LAN access. If
- you want to compile it as a module, say M here and read
- Documentation/modules.txt. The IrLAN server protocol makes it
- possible to set up a wireless LAN with a machine running the IrLAN
- client protocol. Notice that the IrLAN server protocol currently
- only emulates an access point and does not implement the ad-hoc
- specification of IrLAN, but this will not be noticeable by the user.
+ The IrLAN protocol can be used to talk with infrared access points
+ like the HP NetbeamIR, or the ESI JetEye NET. You can also connect
+ to another Linux machine running the IrLAN protocol for ac-hoc
+ networking!
IrOBEX Protocol
CONFIG_IROBEX
@@ -10877,6 +10953,15 @@
the normal 9-pin serial port connector, and can currently only be
used by IrTTY. To activate support for Tekram dongles you will have
to insert "irattach -d tekram" in the /etc/irda/drivers script.
+
+Greenwich GIrBIL dongle
+CONFIG_GIRBIL_DONGLE
+ Say Y here if you want to build support for the Greenwich GIrBIL
+ dongle. If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. The Greenwich dongle attaches to the
+ normal 9-pin serial port connector, and can currently only be used
+ by IrTTY. To activate support for Greenwich dongles you will have to
+ insert "irattach -d girbil" in the /etc/irda/drivers script.
VME (Motorola and BVM) support
CONFIG_VME
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/filesystems/dcache.txt linux.ac/Documentation/filesystems/dcache.txt
--- linux.vanilla/Documentation/filesystems/dcache.txt Thu Jan 1 01:00:00 1970
+++ linux.ac/Documentation/filesystems/dcache.txt Thu Jan 14 04:02:58 1999
@@ -0,0 +1,173 @@
+Some dcache details
+
+A traditional Unix system has inodes (`index nodes') as in-core
+descriptors of files. An inode refers to the actual file, not
+to a directory entry naming it. Linux v2.1.43 introduced dentries
+(`directory entries') as in-core descriptors of file names.
+
+The entire purpose of dentries is to make the map
+filename -> inode fast. An interesting side effect
+is that the kernel knows what name was used to open a file
+and that a system call getcwd() is possible.
+
+Thus, the central part of the dcache code are the lines
+ dentry = reserved_lookup(base, &this);
+ if (!dentry) {
+ dentry = cached_lookup(base, &this);
+ if (!dentry)
+ dentry = real_lookup(base, &this);
+ }
+in namei.c. The reserved_lookup() takes care of . and ..;
+the cached_lookup() is what we have the dcache for,
+and the real_lookup() goes to the filesystem.
+
+The cached_lookup() returns the value of d_lookup(),
+but does a d_revalidate() before returning, and if that fails
+and the dentry has no children, it returns NULL.
+ [This is a rather obscure part. The d_revalidate()
+ is allowed to fail for any reason - for example,
+ autofs uses a timeout to make d_revalidate fail -
+ which means that the final dentry we come up with
+ need not be the dentry that d_lookup() found.
+ This causes bugs in the vfat filesystem.
+ Moreover, if d_revalidate(D) fails but D still has
+ children, then D is used anyway.
+ This also causes bugs in the vfat filesystem.
+ I think also nfs has problems.]
+
+
+
+
+A struct dentry has five members of type struct list_head:
+ struct list_head d_hash; /* lookup hash list */
+ struct list_head d_lru; /* d_count = 0 LRU list */
+ struct list_head d_child; /* child of parent list */
+ struct list_head d_subdirs; /* our children */
+ struct list_head d_alias; /* inode alias list */
+
+ [Some of these names were very badly chosen, and lead
+ to confusion all the time. We should do a global replace
+ changing d_subdirs into d_children and d_child into d_sister.]
+
+
+
+1. d_hash
+
+The d_hash field of a dentry links the dentry into
+the list of dentries for filenames with a given hash value
+with list head dentry_hashtable[hashvalue] defined in dcache.c.
+This list is used in d_lookup() to find a dentry with given name
+and parent. It is used in d_validate() to find a dentry with
+known hash and parent.
+ [The present code takes the parent into account when
+ computing a hash. Not doing this would make the code
+ simpler and faster, possibly at the expense of a few
+ more collisions. Has anyone investigated this?]
+The d_hash field is an empty list when the file is a mount point
+(cf. d_validate) or has been deleted, or when the dentry was
+dropped for some other reason.
+
+
+d_add(D,I) will put D into its hash chain and provide it
+with the inode I. It is called by all filesystem lookup routines.
+
+d_drop(D) will remove D from its hash chain. A dentry is called
+`unhashed' when its d_hash field is an empty list.
+Sometimes dentries are dropped temporarily to make sure
+no lookup will find them. The general routine vfs_rmdir(I,D)
+will drop D if d_count=2, so that all filesystem rmdir()
+routines can return -EBUSY when D still occurs in the hash list.
+The filesystem routines for unlink and rmdir call d_delete()
+which again calls d_drop().
+
+[The d_hash field is referred to in many places that should
+not know about its existence, in the phrase
+ if (list_empty(&dentry->d_hash)) ...
+No doubt there should be a line
+ #define unhashed(d) (list_empty(&(d)->d_hash))
+in dcache.h, together with a comment describing the semantics
+of being unhashed. Then all these occurrences of d_hash can
+be removed. Next, d_drop() should be renamed d_unhash().]
+
+The dentry for the root of a mounted filesystem is returned by
+d_alloc_root() and is unhashed.
+
+
+
+2. d_lru
+The simplest list is the one joining the d_lru fields of
+dentries that had d_count = 0 at some point in time.
+The list head is the variable dentry_unused defined in dcache.c.
+The number of elements in this list is dentry_stat.nr_unused.
+There are no references to the d_lru field outside dcache.[ch].
+
+Note that d_count is incremented by dget(), invoked by d_lookup(),
+without removing the dentry from the LRU list. Thus, anyone hoping
+to find unused dentries on this list must first check d_count.
+If a dentry is not on the LRU list, its d_lru field is an
+empty list (initialized by d_alloc()).
+
+dput(D) tries to get rid of D altogether when d_count = 0, but
+puts D at the head of the LRU list if it is still on the hash list.
+Thus, every D with d_count = 0 will be on the LRU list.
+
+select_dcache(ict,pct) removes D with d_count > 0 from the
+LRU list, and moves D that are ready to be sacrificed for memory
+to the end of the list. (If ict and/or pct is given, then we are
+satisfied when the selected D's involve ict inodes or pct pages.)
+
+prune_dcache(ct) removes D with d_count > 0 from the LRU list,
+and frees unused D, stopping when ct of them have been freed.
+
+shrink_dcache_sb(sb) removes all unused D with given superblock
+from the LRU list.
+
+select_parent(D) move all unused descendants of D to the end
+of the LRU list.
+
+
+
+3. d_child and d_subdirs
+As already noted, the names are terrible. The d_child field
+does not refer to a child but to a sibling, and the d_subdirs
+field does not refer to a subdirectory but to a child, directory
+or not. These two fields form a threaded tree: the d_subdirs field
+points to the first child, and the d_child field is member of the
+circularly linked list of all children of one parent.
+
+To be more precise: this circularly linked list of all children
+of one parent P passes through the d_child fields of all children
+and through the d_subdirs field of the parent P.
+
+
+
+4. d_alias
+Somewhat similar to the above, where we had a circularly linked list
+with one special element, we here have a circularly linked list
+passing through the d_alias field of all dentries that are aliases
+of one inode, and through the i_dentry field of the inode.
+
+The dentry is added to this list by d_instantiate().
+It is removed again by dentry_iput() which is called by dput()
+and d_delete().
+
+
+
+
+So far about the lists in the dentry structure.
+Some of the routines in dcache.c have been mentioned already.
+Let me describe one of the more obscure ones.
+
+d_move(D,T) is the routine called by the filesystem code
+just before finishing the rename(D,T) call. Since both
+dentries D and T may be busy we cannot just throw one away.
+Instead they are partially interchanged:
+D and T interchange names, and D is put into T's hash queue,
+and T is unhashed; D and T interchange parents, and are put
+on the list of children of their new parent.
+The result is that the file D that got renamed is now in perfect
+shape again - it has been renamed. T, if it existed, lost its
+name string, if it was short, but perhaps this is harmless -
+let us hope no-one will ever ask for T's name anymore.
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sound/CMI8330 linux.ac/Documentation/sound/CMI8330
--- linux.vanilla/Documentation/sound/CMI8330 Thu Jan 1 01:00:00 1970
+++ linux.ac/Documentation/sound/CMI8330 Fri Feb 26 16:42:54 1999
@@ -0,0 +1,85 @@
+How to enable CMI 8330 soundchip on Linux
+------------------------------------------
+Stefan Laudat
+
+Hello folks,
+
+ The CMI8330 soundchip is a very small chip found on many recent
+ motherboards. In order to use it you just have to use a proper
+ isapnp.conf and a little bit of patience.
+
+ Of course you will have to compile kernel sound support as module,
+ as shown below:
+
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_SB=m
+CONFIG_SOUND_ADLIB=m
+CONFIG_SOUND_MPU401=m
+# Just for fun :)
+CONFIG_SOUND_MSS=m
+
+ The /etc/isapnp.conf file will be:
+
+
+
+(READPORT 0x0203)
+(ISOLATE PRESERVE)
+(IDENTIFY *)
+(VERBOSITY 2)
+(CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
+(VERIFYLD N)
+# WSS
+
+(CONFIGURE CMI0001/16777472 (LD 0
+(IO 0 (SIZE 8) (BASE 0x0530))
+(IO 1 (SIZE 8) (BASE 0x0388))
+(INT 0 (IRQ 5 (MODE +E)))
+(DMA 0 (CHANNEL 0))
+(NAME "CMI0001/16777472[0]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+# Control device ?
+
+(CONFIGURE CMI0001/16777472 (LD 1
+(IO 0 (SIZE 2) (BASE 0x0330))
+(INT 0 (IRQ 11 (MODE +E)))
+(NAME "CMI0001/16777472[1]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+# Joystick
+
+(CONFIGURE CMI0001/16777472 (LD 2
+(IO 0 (SIZE 8) (BASE 0x0200))
+(NAME "CMI0001/16777472[2]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+# SB...
+(CONFIGURE CMI0001/16777472 (LD 3
+(IO 0 (SIZE 16) (BASE 0x0220))
+(INT 0 (IRQ 7 (MODE +E)))
+(DMA 0 (CHANNEL 1))
+(DMA 1 (CHANNEL 5))
+(NAME "CMI0001/16777472[3]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+
+(WAITFORKEY)
+
+
+
+ The module sequence is trivial:
+
+/sbin/modprobe sound
+/sbin/insmod uart401
+/sbin/insmod sb io=0x220 irq=5 dma=1 dma16=-1
+/sbin/insmod mpu401 io=0x330
+/sbin/insmod opl3 io=0x388
+# In case you want:
+/sbin/insmod ad1848
+
+ The soundchip is now fully initialized. Enjoy it.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/MAINTAINERS linux.ac/MAINTAINERS
--- linux.vanilla/MAINTAINERS Tue Feb 23 14:21:32 1999
+++ linux.ac/MAINTAINERS Wed Feb 24 17:09:00 1999
@@ -324,7 +324,7 @@
M: arobinso@nyx.net
L: linux-kernel@vger.rutgers.edu
W: http://www.nyx.net/~arobinso
-S: Maintainted
+S: Maintained
HFS FILESYSTEM
P: Adrian Sun
@@ -678,9 +678,18 @@
S: Supported
SPARC:
+P: David S. Miller
+M: davem@dm.cobaltmicro.com
P: Eddie C. Dost
M: ecd@skynet.be
+P: Jakub Jelinek
+M: jj@sunsite.ms.mff.cuni.cz
+P: Anton Blanchard
+M: anton@jubilex.progsoc.uts.edu.au
L: sparclinux@vger.rutgers.edu
+L: ultralinux@vger.rutgers.edu
+W: http://ultra.linux.cz
+W: http://www.geog.ubc.ca/s_linux.html
S: Maintained
SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Makefile linux.ac/Makefile
--- linux.vanilla/Makefile Tue Feb 23 14:21:32 1999
+++ linux.ac/Makefile Fri Feb 26 14:17:45 1999
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 2
-EXTRAVERSION =
+EXTRAVERSION = -ac5
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -343,7 +343,8 @@
clean: archclean
rm -f kernel/ksyms.lst include/linux/compile.h
- rm -f core `find . -name '*.[oas]' ! -regex '.*lxdialog/.*' -print`
+ rm -f core `find . -name '*.[oas]' ! \( -regex '.*lxdialog/.*' \
+ -o -regex '.*ksymoops/.*' \) -print`
rm -f core `find . -type f -name 'core' -print`
rm -f core `find . -name '.*.flags' -print`
rm -f vmlinux System.map
@@ -367,6 +368,7 @@
rm -f .version .config* config.in config.old
rm -f scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp
rm -f scripts/lxdialog/*.o scripts/lxdialog/lxdialog
+ rm -f scripts/ksymoops/*.o scripts/ksymoops/ksymoops
rm -f .menuconfig.log
rm -f include/asm
rm -rf include/config
@@ -379,8 +381,8 @@
distclean: mrproper
rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
- -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
- -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS
+ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
+ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS
backup: mrproper
cd .. && tar cf - linux/ | gzip -9 > backup.gz
@@ -389,7 +391,7 @@
sums:
find . -type f -print | sort | xargs sum > .SUMS
-dep-files: scripts/mkdep archdep include/linux/version.h
+dep-files: scripts/mkdep archdep include/linux/version.h new-genksyms
scripts/mkdep init/*.c > .depend
scripts/mkdep `find $(FINDHPATH) -follow -name \*.h ! -name modversions.h -print` > .hdepend
# set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep ;done
@@ -399,7 +401,19 @@
MODVERFILE :=
ifdef CONFIG_MODVERSIONS
+
MODVERFILE := $(TOPDIR)/include/linux/modversions.h
+
+new-genksyms:
+ @$(GENKSYMS) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) /dev/null || ( echo -e "\nYou need a new version of the genksyms\
+ program, which is part of\nthe modutils package. Please read the file\
+ Documentation/Changes\nfor more information.\n"; exit 1 )
+
+else
+
+new-genksyms:
+
endif
depend dep: dep-files $(MODVERFILE)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/defconfig linux.ac/arch/alpha/defconfig
--- linux.vanilla/arch/alpha/defconfig Mon Dec 28 23:09:39 1998
+++ linux.ac/arch/alpha/defconfig Fri Feb 26 01:59:54 1999
@@ -91,7 +91,6 @@
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -108,7 +107,6 @@
# (it is safe to leave these untouched)
#
# CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
#
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/process.c linux.ac/arch/alpha/kernel/process.c
--- linux.vanilla/arch/alpha/kernel/process.c Sun Jan 24 19:55:29 1999
+++ linux.ac/arch/alpha/kernel/process.c Sun Jan 24 20:20:25 1999
@@ -55,7 +55,6 @@
unsigned long init_user_stack[1024] = { STACK_MAGIC, };
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/time.c linux.ac/arch/alpha/kernel/time.c
--- linux.vanilla/arch/alpha/kernel/time.c Sun Jan 24 19:55:29 1999
+++ linux.ac/arch/alpha/kernel/time.c Wed Feb 24 16:35:19 1999
@@ -95,14 +95,17 @@
/*
* Calculate how many ticks have passed since the last update,
* including any previous partial leftover. Save any resulting
- * fraction for the next pass.
+ * fraction for the next pass. Don't change anything unless
+ * at least one tick has passed.
*/
now = rpcc();
delta = now - state.last_time;
- state.last_time = now;
delta = delta * state.scaled_ticks_per_cycle + state.partial_tick;
- state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1);
nticks = delta >> FIX_SHIFT;
+ if (nticks) {
+ state.last_time = now;
+ state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1);
+ }
while (nticks > 0) {
do_timer(regs);
@@ -316,12 +319,14 @@
{
unsigned long flags, now, delta_cycles, delta_usec;
unsigned long sec, usec;
+ unsigned long partial_tick;
- now = rpcc();
save_and_cli(flags);
+ now = rpcc();
sec = xtime.tv_sec;
usec = xtime.tv_usec;
delta_cycles = now - state.last_time;
+ partial_tick = state.partial_tick;
restore_flags(flags);
/*
@@ -337,7 +342,8 @@
* with no clear gain.
*/
- delta_usec = delta_cycles * state.scaled_ticks_per_cycle * 15625;
+ delta_usec = delta_cycles * state.scaled_ticks_per_cycle + partial_tick;
+ delta_usec *= 15625;
delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
usec += delta_usec;
@@ -353,8 +359,24 @@
void
do_settimeofday(struct timeval *tv)
{
+ unsigned long delta_usec;
+
+ /*
+ * The offset that is added into time in do_gettimeofday above must
+ * be subtracted here to keep a coherent view of the time. Without
+ * this, a full-tick error is possible.
+ */
cli();
+ delta_usec = (rpcc() - state.last_time) * state.scaled_ticks_per_cycle +
+ state.partial_tick;
+ delta_usec *= 15625;
+ delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
xtime = *tv;
+ xtime.tv_usec -= delta_usec;
+ if (xtime.tv_usec < 0) {
+ xtime.tv_usec += 1000000;
+ xtime.tv_sec--;
+ }
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_state = TIME_ERROR; /* p. 24, (a) */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/Makefile linux.ac/arch/arm/Makefile
--- linux.vanilla/arch/arm/Makefile Tue Dec 22 23:19:25 1998
+++ linux.ac/arch/arm/Makefile Sun Jan 24 21:11:30 1999
@@ -15,9 +15,8 @@
CFLAGS_PROC :=
ASFLAGS_PROC :=
-# All processors get `-mshort-load-bytes' for now, to work around alignment
-# problems. This is more of a hack that just happens to work than a real fix
-# but it will do for now.
+# GCC 2.7 uses different options to later compilers; sort out which we have
+CONFIG_BINUTILS_NEW := $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then echo n; else echo y; fi)
ifeq ($(CONFIG_CPU_26),y)
PROCESSOR = armo
@@ -103,7 +102,7 @@
ZRELADDR = 0x00008000
endif
-ifeq ($(CONFIG_ARCH_EBSA285),y)
+ifeq ($(CONFIG_HOST_FOOTBRIDGE),y)
MACHINE = ebsa285
ARCHDIR = ebsa285
ZTEXTADDR = 0x00008000
@@ -119,19 +118,6 @@
COMPRESSED_HEAD = head-nexuspci.o
endif
-ifeq ($(CONFIG_ARCH_VNC),y)
-TEXTADDR = 0xC000C000
-MACHINE = vnc
-ARCHDIR = vnc
-endif
-
-ifeq ($(CONFIG_ARCH_TBOX),y)
-MACHINE = tbox
-ARCHDIR = tbox
-ZTEXTADDR = 0x80008000
-ZRELDIR = 0x80008000
-endif
-
PERL = perl
ifeq ($(CONFIG_BINUTILS_NEW),y)
LD = $(CROSS_COMPILE)ld -m elf32arm
@@ -143,7 +129,6 @@
CPP = $(CC) -E
ARCHCC := $(word 1,$(CC))
GCCLIB := `$(CC) $(CFLAGS_PROC) --print-libgcc-file-name`
-#GCCARCH := -B/usr/bin/arm-linuxelf-
HOSTCFLAGS := $(CFLAGS:-fomit-frame-pointer=)
ifeq ($(CONFIG_FRAME_POINTER),y)
CFLAGS := $(CFLAGS:-fomit-frame-pointer=)
@@ -153,6 +138,15 @@
LINKFLAGS = -T $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds -e stext -Ttext $(TEXTADDR)
ZLINKFLAGS = -Ttext $(ZTEXTADDR)
+# If we're intending to debug the kernel, make sure it has line number
+# information. This gets stripped out when building (z)Image so it doesn't
+# add anything to the footprint of the running kernel.
+# Only do this on new binutils - old binutils run out of memory on the
+# final link
+ifeq ($(CONFIG_DEBUG_INFO),y)
+CFLAGS += -g
+endif
+
SUBDIRS := $(SUBDIRS:drivers=arch/arm/drivers) arch/arm/lib arch/arm/kernel arch/arm/mm
HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o
CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
@@ -161,10 +155,10 @@
BLOCK_DRIVERS := drivers/block/block.a
CDROM_DRIVERS := drivers/cdrom/cdrom.a
ifeq ($(CONFIG_FB),y)
-CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a
+CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a
else
ifeq ($(CONFIG_VGA_CONSOLE),y)
-CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a
+CHAR_DRIVERS := arch/arm/drivers/char1/char1.a drivers/char/char.a
else
CHAR_DRIVERS := arch/arm/drivers/char/char.a
endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/config.in linux.ac/arch/arm/config.in
--- linux.vanilla/arch/arm/config.in Tue Jan 19 02:57:23 1999
+++ linux.ac/arch/arm/config.in Sun Jan 24 21:11:30 1999
@@ -14,18 +14,22 @@
A5000 CONFIG_ARCH_A5K \
RiscPC CONFIG_ARCH_RPC \
EBSA-110 CONFIG_ARCH_EBSA110 \
- EBSA-285 CONFIG_ARCH_EBSA285 \
- NexusPCI CONFIG_ARCH_NEXUSPCI \
- Corel-VNC CONFIG_ARCH_VNC \
- Tbox CONFIG_ARCH_TBOX" RiscPC
+ DC21285-based-machines CONFIG_FOOTBRIDGE" RiscPC
-if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then
- bool ' Include support for CATS boards' CONFIG_CATS
+if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
+ choice 'DC21285 FootBridge mode' \
+ "HostBridge CONFIG_HOST_FOOTBRIDGE \
+ Add-in CONFIG_ADDIN_FOOTBRIDGE" HostBridge
+fi
+
+if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then
+ bool ' Include support for Intel EBSA285' CONFIG_ARCH_EBSA285
+ bool ' Include support for Chalice CATS boards' CONFIG_CATS
+ bool ' Include support for Corel NetWinder' CONFIG_ARCH_NETWINDER
fi
# Select various configuration options depending on the machine type
# Easy check for Acorn-style architectures
-
if [ "$CONFIG_ARCH_ARC" = "y" -o \
"$CONFIG_ARCH_A5K" = "y" -o \
"$CONFIG_ARCH_RPC" = "y" ]; then
@@ -39,18 +43,14 @@
fi
# These machines always have PCI
-
if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \
- "$CONFIG_ARCH_VNC" = "y" ]; then
+ "$CONFIG_FOOTBRIDGE" = "y" ]; then
define_bool CONFIG_PCI y
fi
-if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then
- bool "PCI support" CONFIG_PCI
-fi
# These machines have ISA-DMA
if [ "$CONFIG_CATS" = "y" -o \
- "$CONFIG_ARCH_VNC" = "y" ]; then
+ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
define_bool CONFIG_ISA_DMA y
else
define_bool CONFIG_ISA_DMA n
@@ -59,7 +59,6 @@
# Figure out whether this system uses 26-bit or 32-bit CPUs. Nobody has
# ever built a machine that can take both, and now that ARM3 is obsolete
# nobody is likely to either.
-
if [ "$CONFIG_ARCH_ARC" = "y" -o \
"$CONFIG_ARCH_A5K" = "y" ]; then
define_bool CONFIG_CPU_32 n
@@ -71,7 +70,6 @@
# Now allow the user to choose a more precise CPU. This is only used to set
# the flags we pass to GCC, not in any code.
-
choice 'Optimise for CPU' \
"ARM2 CONFIG_CPU_ARM2 \
ARM3 CONFIG_CPU_ARM3 \
@@ -80,10 +78,8 @@
SA110 CONFIG_CPU_SA110" ARM6
if [ "$CONFIG_CPU_26" = "y" ]; then
-
# For 26-bit CPUs, the page size changes with the amount of physical RAM!
# The default is 4MB but if the user has less they have to own up to it here.
-
choice 'Physical memory size' \
"4MB+ CONFIG_PAGESIZE_32 \
2MB CONFIG_PAGESIZE_16 \
@@ -94,8 +90,10 @@
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
-bool 'Use new compilation options (for GCC 2.8)' CONFIG_BINUTILS_NEW
-bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER
+if [ "$CONFIG_CPU_32" = "y" ]; then
+ bool 'Enable kernel-mode alignment trap handler (EXPERIMENTAL)' CONFIG_ALIGNMENT_TRAP
+fi
+bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS
endmenu
mainmenu_option next_comment
@@ -119,7 +117,9 @@
tristate 'Parallel port support' CONFIG_PARPORT
if [ "$CONFIG_PARPORT" != "n" ]; then
- dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
+ if [ "$CONFIG_ARCH_ARC" = "y" ]; then
+ dep_tristate ' Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
+ fi
dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
# If exactly one hardware type is selected then parport will optimise away
# support for loading any others. Defeat this if the user is keen.
@@ -129,11 +129,22 @@
fi
fi
fi
-if [ "$CONFIG_ARCH_EBSA285" = "y" -o \
- "$CONFIG_ARCH_EBSA110" = "y" -o \
- "$CONFIG_ARCH_VNC" = "y" ]; then
+if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
+ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
string 'Initial kernel command string' CONFIG_CMDLINE
fi
+if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
+ "$CONFIG_ARCH_EBSA110" = "y" -o \
+ "$CONFIG_ARCH_EBSA285" = "y" ]; then
+ bool 'Timer and CPU usage LEDs' CONFIG_LEDS
+ if [ "$CONFIG_LEDS" = "y" ]; then
+ if [ "$CONFIG_ARCH_NETWINDER" = "y" -o \
+ "$CONFIG_ARCH_EBSA285" = "y" ]; then
+ bool 'Timer LED' CONFIG_LEDS_TIMER
+ bool 'CPU usage LED' CONFIG_LEDS_CPU
+ fi
+ fi
+fi
endmenu
source drivers/pnp/Config.in
@@ -150,7 +161,13 @@
source drivers/char/Config.in
fi
if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
- source drivers/acorn/char/Config.in
+ if [ "$CONFIG_MOUSE" = "y" ]; then
+ if [ "$CONFIG_ARCH_RPC" != "y" ]; then
+ define_bool CONFIG_KBDMOUSE y
+ else
+ define_bool CONFIG_RPCMOUSE y
+ fi
+ fi
fi
if [ "$CONFIG_VT" = "y" ]; then
@@ -166,9 +183,11 @@
if [ "$CONFIG_NET" = "y" ]; then
source net/Config.in
-fi
-if [ "$CONFIG_NET" = "y" ]; then
+ source net/ax25/Config.in
+
+ source net/irda/Config.in
+
mainmenu_option next_comment
comment 'Network device support'
@@ -179,6 +198,15 @@
endmenu
fi
+# mainmenu_option next_comment
+# comment 'ISDN subsystem'
+#
+# tristate 'ISDN support' CONFIG_ISDN
+# if [ "$CONFIG_ISDN" != "n" ]; then
+# source drivers/isdn/Config.in
+# fi
+# endmenu
+
mainmenu_option next_comment
comment 'SCSI support'
@@ -200,21 +228,21 @@
endmenu
fi
-# mainmenu_option next_comment
-# comment 'ISDN subsystem'
-#
-# tristate 'ISDN support' CONFIG_ISDN
-# if [ "$CONFIG_ISDN" != "n" ]; then
-# source drivers/isdn/Config.in
-# fi
-# endmenu
-
source fs/Config.in
mainmenu_option next_comment
comment 'Kernel hacking'
-bool 'Debug kernel errors' CONFIG_DEBUG_ERRORS
+bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER
+bool 'Verbose kernel error messages' CONFIG_DEBUG_ERRORS
+bool 'Verbose user fault messages' CONFIG_DEBUG_USER
+bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+if [ "$CONFIG_CPU_26" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool 'Disable pgtable cache (EXPERIMENTAL)' CONFIG_NO_PGT_CACHE
+fi
+if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CPU_32" = "y" ]; then
+ tristate 'RISC OS personality' CONFIG_ARTHUR
+fi
endmenu
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/defconfig linux.ac/arch/arm/defconfig
--- linux.vanilla/arch/arm/defconfig Sun Nov 8 15:08:43 1998
+++ linux.ac/arch/arm/defconfig Fri Feb 26 01:59:54 1999
@@ -4,47 +4,72 @@
CONFIG_ARM=y
#
+# System and processor type
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_FOOTBRIDGE=y
+CONFIG_HOST_FOOTBRIDGE=y
+# CONFIG_ADDIN_FOOTBRIDGE is not set
+CONFIG_ARCH_EBSA285=y
+# CONFIG_CATS is not set
+CONFIG_ARCH_NETWINDER=y
+# CONFIG_ARCH_ACORN is not set
+CONFIG_PCI=y
+CONFIG_ISA_DMA=y
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM2 is not set
+# CONFIG_CPU_ARM3 is not set
+# CONFIG_CPU_ARM6 is not set
+# CONFIG_CPU_ARM7 is not set
+CONFIG_CPU_SA110=y
+# CONFIG_PAGESIZE_32 is not set
+# CONFIG_PAGESIZE_16 is not set
+# CONFIG_PAGESIZE_8 is not set
+
+#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_ALIGNMENT_TRAP is not set
+# CONFIG_TEXT_SECTIONS is not set
#
# Loadable module support
#
CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
+# CONFIG_MODVERSIONS is not set
CONFIG_KMOD=y
#
# General setup
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-CONFIG_ARCH_RPC=y
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_NEXUSPCI is not set
-CONFIG_ARCH_ACORN=y
-# CONFIG_PCI is not set
-# CONFIG_CPU_ARM2 is not set
-# CONFIG_CPU_ARM3 is not set
-# CONFIG_CPU_ARM6 is not set
-CONFIG_CPU_SA110=y
-CONFIG_FRAME_POINTER=y
-# CONFIG_BINUTILS_NEW is not set
-CONFIG_DEBUG_ERRORS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=m
-# CONFIG_BINFMT_JAVA is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
+CONFIG_CMDLINE="root=/dev/hda2 ro mem=32M parport=0x378,23 ide0=autotune"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+# CONFIG_LEDS_CPU is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
#
-# Floppy, IDE, and other block devices
+# Block devices
#
-CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_IDE=y
#
@@ -52,47 +77,186 @@
#
# CONFIG_BLK_DEV_HD_IDE is not set
CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_IDE_PCMCIA is not set
-CONFIG_BLK_DEV_IDE_CARDS=y
-CONFIG_BLK_DEV_IDE_ICSIDE=y
-# CONFIG_BLK_DEV_IDE_RAPIDE is not set
-# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_BLK_DEV_OFFBOARD=y
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_VIA82C586 is not set
+# CONFIG_BLK_DEV_CMD646 is not set
+CONFIG_BLK_DEV_SL82C105=y
+# CONFIG_IDE_CHIPSETS is not set
#
# Additional Block Devices
#
CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_STRIPED=m
+CONFIG_MD_MIRRORING=m
+CONFIG_MD_RAID5=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_XD is not set
CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-CONFIG_BLK_DEV_PART=y
+CONFIG_PARIDE=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
# CONFIG_BLK_DEV_HD is not set
#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_PRINTER=m
+CONFIG_PRINTER_READBACK=y
+CONFIG_MOUSE=y
+
+#
+# Mice
+#
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+CONFIG_DS1620=y
+# CONFIG_QIC02_TAPE is not set
+CONFIG_WATCHDOG=y
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WDT is not set
+CONFIG_SOFT_WATCHDOG=y
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_ACQUIRE_WDT is not set
+CONFIG_DS1620=y
+# CONFIG_NVRAM is not set
+CONFIG_NWBUTTON=y
+CONFIG_NWBUTTON_REBOOT=y
+CONFIG_RTC=y
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_FT_NORMAL_DEBUG is not set
+# CONFIG_FT_FULL_DEBUG is not set
+# CONFIG_FT_NO_TRACE is not set
+# CONFIG_FT_NO_TRACE_AT_ALL is not set
+# CONFIG_FT_STD_FDC is not set
+# CONFIG_FT_MACH2 is not set
+# CONFIG_FT_PROBE_FC10 is not set
+# CONFIG_FT_ALT_FDC is not set
+
+#
+# Console drivers
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_CYBER2000=y
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+# CONFIG_FBCON_CFB32 is not set
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+CONFIG_FBCON_VGA=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
# Networking options
#
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
+CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_IP_ACCT is not set
-# CONFIG_IP_MASQUERADE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+CONFIG_IP_ALIAS=y
# CONFIG_SYN_COOKIES is not set
#
@@ -100,7 +264,7 @@
#
# CONFIG_INET_RARP is not set
CONFIG_IP_NOSR=y
-# CONFIG_SKB_LARGE is not set
+CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
#
@@ -112,155 +276,228 @@
# CONFIG_LAPB is not set
# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set
# CONFIG_CPU_IS_SLOW is not set
+
+#
+# QoS and/or fair queueing
+#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_PROFILE is not set
#
-# SCSI support
+# Amateur Radio support
#
-CONFIG_SCSI=y
+# CONFIG_HAMRADIO is not set
#
-# SCSI support type (disk, tape, CD-ROM)
+# IrDA subsystem support
#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-# CONFIG_CHR_DEV_SG is not set
+# CONFIG_IRDA is not set
#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+# Network device support
#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
+CONFIG_NETDEVICES=y
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_EL3 is not set
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=y
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_EISA=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DE4X5 is not set
+CONFIG_DEC_ELCP=m
+# CONFIG_DGRS is not set
+# CONFIG_EEXPRESS_PRO100 is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NE3210 is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_ES3210 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_ZNET is not set
+# CONFIG_NET_POCKET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_DLCI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
#
-# SCSI low-level drivers
+# CCP compressors for PPP are only built as modules.
#
-CONFIG_SCSI_ACORNSCSI_3=m
-CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y
-CONFIG_SCSI_ACORNSCSI_SYNC=y
-CONFIG_SCSI_CUMANA_2=m
-CONFIG_SCSI_POWERTECSCSI=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
+# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
#
-# The following drives are not fully supported
+# SCSI support
#
-CONFIG_SCSI_CUMANA_1=m
-CONFIG_SCSI_OAK1=m
-CONFIG_SCSI_PPA=m
-CONFIG_SCSI_PPA_HAVE_PEDANTIC=2
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_G_NCR5380_PORT is not set
+# CONFIG_SCSI_G_NCR5380_MEM is not set
#
-# Network device support
+# Sound
#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_PPP=m
+CONFIG_SOUND=m
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=m
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_SB is not set
+CONFIG_SOUND_ADLIB=m
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_CS4232 is not set
+CONFIG_SOUND_OPL3SA2=m
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_VIDC is not set
+CONFIG_SOUND_WAVEARTIST=m
+CONFIG_WAVEARTIST_BASE=250
+CONFIG_WAVEARTIST_IRQ=28
+CONFIG_WAVEARTIST_DMA=5
+CONFIG_WAVEARTIST_DMA2=9
#
-# CCP compressors for PPP are only built as modules.
+# Additional low level sound drivers
#
-# CONFIG_SLIP is not set
-CONFIG_ETHER1=m
-CONFIG_ETHER3=m
-CONFIG_ETHERH=m
+# CONFIG_LOWLEVEL_SOUND is not set
#
# Filesystems
#
# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
-CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFSD=y
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_ADFS_FS=y
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-CONFIG_ADFS_FS=y
-CONFIG_ADFS_FS=y
-# CONFIG_MAC_PARTITION is not set
-CONFIG_NLS=y
#
-# Native Language Support
+# Network File Systems
#
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_KOI8_R is not set
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+# CONFIG_NFSD_SUN is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
#
-# Character devices
+# Partition Types
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_SERIAL_EXTENDED is not set
-CONFIG_ATOMWIDE_SERIAL=y
-CONFIG_DUALSP_SERIAL=y
-CONFIG_MOUSE=y
-CONFIG_PRINTER=m
-CONFIG_PRINTER_READBACK=y
-# CONFIG_UMISC is not set
-# CONFIG_WATCHDOG is not set
-CONFIG_RPCMOUSE=y
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_ADFS=y
+# CONFIG_ACORN_PARTITION_ICS is not set
+# CONFIG_ACORN_PARTITION_POWERTEC is not set
+# CONFIG_ACORN_PARTITION_RISCIX is not set
+CONFIG_NLS=y
#
-# Sound
+# Native Language Support
#
-CONFIG_SOUND=m
-CONFIG_VIDC=y
-CONFIG_AUDIO=y
-DSP_BUFFSIZE=65536
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_ISO8859_9=m
+# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_KOI8_R=m
#
# Kernel hacking
#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_USER is not set
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_ARTHUR is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/Makefile linux.ac/arch/arm/kernel/Makefile
--- linux.vanilla/arch/arm/kernel/Makefile Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/Makefile Sun Jan 24 21:11:30 1999
@@ -9,31 +9,39 @@
ENTRY_OBJ = entry-$(PROCESSOR).o
O_TARGET := kernel.o
-O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o setup.o \
+O_OBJS := $(ENTRY_OBJ) irq.o process.o ptrace.o setup.o \
signal.o sys_arm.o time.o traps.o
-DMA_OBJS_arc = dma-arc.o
-DMA_OBJS_a5k = dma-a5k.o
-DMA_OBJS_rpc = dma-rpc.o
-DMA_OBJS_ebsa110 = dma-dummy.o
-DMA_OBJS_ebsa285 = dma-ebsa285.o
-DMA_OBJS_nexuspci =
-DMA_OBJS_vnc = dma-vnc.o
-
-O_OBJS_arc = ecard.o iic.o fiq.o oldlatches.o
-O_OBJS_a5k = ecard.o iic.o fiq.o
-O_OBJS_rpc = ecard.o iic.o fiq.o
-O_OBJS_ebsa110 = leds-ebsa110.o
-O_OBJS_ebsa285 = leds-ebsa285.o hw-ebsa285.o
-O_OBJS_nexuspci =
-O_OBJS_vnc = leds-ebsa285.o hw-vnc.o
+ifeq ($(CONFIG_ISA_DMA),y)
+ ISA_DMA_OBJS += dma-isa.o
+endif
+
+O_OBJS_arc = dma-arc.o iic.o fiq.o oldlatches.o
+O_OBJS_a5k = dma-a5k.o iic.o fiq.o
+O_OBJS_rpc = dma-rpc.o iic.o fiq.o
+O_OBJS_ebsa110 = dma-dummy.o
+O_OBJS_ebsa285 = dma-ebsa285.o $(ISA_DMA_OBJS)
+O_OBJS_nexuspci = dma-dummy.o
+O_OBJS_co285 = dma-ebsa285.o $(ISA_DMA_OBJS)
+
+OX_OBJS_arc = dma.o
+OX_OBJS_a5k = dma.o
+OX_OBJS_rpc = dma.o
+OX_OBJS_ebsa110 =
+OX_OBJS_ebsa285 = dma.o hw-ebsa285.o
+OX_OBJS_nexuspci =
+OX_OBJS_co285 = dma.o
all: lib kernel.o $(HEAD_OBJ) init_task.o
+O_OBJS += $(O_OBJS_$(MACHINE))
+
ifeq ($(CONFIG_MODULES),y)
OX_OBJS = armksyms.o
-else
- O_OBJS += armksyms.o
+endif
+
+ifeq ($(CONFIG_ARCH_ACORN),y)
+ OX_OBJS += ecard.o
endif
ifeq ($(MACHINE),nexuspci)
@@ -46,17 +54,23 @@
endif
endif
-ifneq ($(DMA_OBJS_$(MACHINE)),)
- OX_OBJS += dma.o
- O_OBJS += $(DMA_OBJS_$(MACHINE))
- ifeq ($(CONFIG_ISA_DMA),y)
- O_OBJS += dma-isa.o
- endif
+ifdef CONFIG_LEDS
+ O_OBJS += leds-$(MACHINE).o
+endif
+
+ifeq ($(CONFIG_MODULES),y)
+ OX_OBJS += $(OX_OBJS_$(MACHINE))
else
- O_OBJS += dma-dummy.o
+ O_OBJS += $(OX_OBJS_$(MACHINE))
endif
-O_OBJS += $(O_OBJS_$(MACHINE))
+ifeq ($(CONFIG_ARTHUR),y)
+ O_OBJS += arthur.o
+else
+ ifeq ($(CONFIG_ARTHUR),m)
+ M_OBJS += arthur.o
+ endif
+endif
$(HEAD_OBJ): $(HEAD_OBJ:.o=.S)
$(CC) -D__ASSEMBLY__ -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/armksyms.c linux.ac/arch/arm/kernel/armksyms.c
--- linux.vanilla/arch/arm/kernel/armksyms.c Sun Nov 8 15:08:43 1998
+++ linux.ac/arch/arm/kernel/armksyms.c Sun Jan 24 21:11:30 1999
@@ -7,11 +7,11 @@
#include
#include
-#include
#include
#include
#include
#include
+#include
#include
#include
@@ -20,6 +20,19 @@
extern void inswb(unsigned int port, void *to, int len);
extern void outswb(unsigned int port, const void *to, int len);
+extern unsigned int local_bh_count[NR_CPUS];
+extern unsigned int local_irq_count[NR_CPUS];
+
+/*
+ * syscalls
+ */
+extern int sys_write(int, const char *, int);
+extern int sys_read(int, char *, int);
+extern int sys_lseek(int, off_t, int);
+extern int sys_open(const char *, int, int);
+extern int sys_exit(int);
+extern int sys_wait4(int, int *, int, struct rusage *);
+
/*
* libgcc functions - functions that are used internally by the
* compiler... (prototypes are not correct though, but that
@@ -62,14 +75,8 @@
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(udelay);
EXPORT_SYMBOL(xchg_str);
-
- /* expansion card support */
-#ifdef CONFIG_ARCH_ACORN
-EXPORT_SYMBOL(ecard_startfind);
-EXPORT_SYMBOL(ecard_find);
-EXPORT_SYMBOL(ecard_readchunk);
-EXPORT_SYMBOL(ecard_address);
-#endif
+EXPORT_SYMBOL(local_bh_count);
+EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
@@ -167,3 +174,17 @@
EXPORT_SYMBOL(armidlist);
EXPORT_SYMBOL(armidindex);
EXPORT_SYMBOL(elf_platform);
+
+ /* syscalls */
+EXPORT_SYMBOL(sys_write);
+EXPORT_SYMBOL(sys_read);
+EXPORT_SYMBOL(sys_lseek);
+EXPORT_SYMBOL(sys_open);
+EXPORT_SYMBOL(sys_exit);
+EXPORT_SYMBOL(sys_wait4);
+
+ /* semaphores */
+EXPORT_SYMBOL_NOVERS(__down_failed);
+EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
+EXPORT_SYMBOL_NOVERS(__up_wakeup);
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/arthur.c linux.ac/arch/arm/kernel/arthur.c
--- linux.vanilla/arch/arm/kernel/arthur.c Thu Jan 1 01:00:00 1970
+++ linux.ac/arch/arm/kernel/arthur.c Sun Jan 24 21:11:30 1999
@@ -0,0 +1,88 @@
+/*
+ * Arthur personality
+ * Copyright (C) 1998 Philip Blundell
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+/* RISC OS doesn't have many signals, and a lot of those that it does
+ have don't map easily to any Linux equivalent. Never mind. */
+
+#define RISCOS_SIGABRT 1
+#define RISCOS_SIGFPE 2
+#define RISCOS_SIGILL 3
+#define RISCOS_SIGINT 4
+#define RISCOS_SIGSEGV 5
+#define RISCOS_SIGTERM 6
+#define RISCOS_SIGSTAK 7
+#define RISCOS_SIGUSR1 8
+#define RISCOS_SIGUSR2 9
+#define RISCOS_SIGOSERROR 10
+
+static unsigned long riscos_to_linux_signals[32] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31
+};
+
+static unsigned long linux_to_riscos_signals[32] = {
+ 0, -1, RISCOS_SIGINT, -1,
+ RISCOS_SIGILL, 5, RISCOS_SIGABRT, 7,
+ RISCOS_SIGFPE, 9, RISCOS_SIGUSR1, RISCOS_SIGSEGV,
+ RISCOS_SIGUSR2, 13, 14, RISCOS_SIGTERM,
+ 16, 17, 18, 19,
+ 20, 21, 22, 23,
+ 24, 25, 26, 27,
+ 28, 29, 30, 31
+};
+
+static void arthur_lcall7(int nr, struct pt_regs *regs)
+{
+ struct siginfo info;
+ info.si_signo = SIGSWI;
+ info.si_code = nr;
+ /* Bounce it to the emulator */
+ send_sig_info(SIGSWI, &info, current);
+}
+
+static struct exec_domain riscos_exec_domain = {
+ "Arthur", /* name */
+ (lcall7_func)arthur_lcall7,
+ PER_RISCOS, PER_RISCOS,
+ riscos_to_linux_signals,
+ linux_to_riscos_signals,
+#ifdef MODULE
+ &__this_module, /* No usage counter. */
+#else
+ NULL,
+#endif
+ NULL /* Nothing after this in the list. */
+};
+
+/*
+ * We could do with some locking to stop Arthur being removed while
+ * processes are using it.
+ */
+
+#ifdef MODULE
+int init_module(void)
+#else
+int initialise_arthur(void)
+#endif
+{
+ return register_exec_domain(&riscos_exec_domain);
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+ unregister_exec_domain(&riscos_exec_domain);
+}
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/calls.S linux.ac/arch/arm/kernel/calls.S
--- linux.vanilla/arch/arm/kernel/calls.S Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/calls.S Sun Jan 24 21:11:30 1999
@@ -110,7 +110,7 @@
.long SYMBOL_NAME(sys_ni_syscall) /* was sys_profil */
.long SYMBOL_NAME(sys_statfs)
/* 100 */ .long SYMBOL_NAME(sys_fstatfs)
- .long SYMBOL_NAME(sys_ni_syscall) /* .long _sys_ioperm */
+ .long SYMBOL_NAME(sys_ni_syscall)
.long SYMBOL_NAME(sys_socketcall)
.long SYMBOL_NAME(sys_syslog)
.long SYMBOL_NAME(sys_setitimer)
@@ -119,7 +119,7 @@
.long SYMBOL_NAME(sys_newlstat)
.long SYMBOL_NAME(sys_newfstat)
.long SYMBOL_NAME(sys_uname)
-/* 110 */ .long SYMBOL_NAME(sys_iopl)
+/* 110 */ .long SYMBOL_NAME(sys_ni_syscall)
.long SYMBOL_NAME(sys_vhangup)
.long SYMBOL_NAME(sys_idle)
.long SYMBOL_NAME(sys_syscall) /* call a syscall */
@@ -196,6 +196,10 @@
.long SYMBOL_NAME(sys_capget)
/* 185 */ .long SYMBOL_NAME(sys_capset)
.long SYMBOL_NAME(sys_sigaltstack_wrapper)
+ .long SYMBOL_NAME(sys_sendfile)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
+/* 190 */ .long SYMBOL_NAME(sys_vfork_wrapper)
.rept NR_syscalls-186
.long SYMBOL_NAME(sys_ni_syscall)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dec21285.c linux.ac/arch/arm/kernel/dec21285.c
--- linux.vanilla/arch/arm/kernel/dec21285.c Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/dec21285.c Sun Jan 24 21:11:30 1999
@@ -17,8 +17,6 @@
extern void pcibios_fixup_ebsa285(struct pci_dev *dev);
extern void pcibios_init_ebsa285(void);
-extern void pcibios_fixup_vnc(struct pci_dev *dev);
-extern void pcibios_init_vnc(void);
int
pcibios_present(void)
@@ -151,10 +149,7 @@
struct pci_dev *dev;
for (dev = pci_devices; dev; dev = dev->next) {
- if (machine_is_ebsa285() || machine_is_cats())
- pcibios_fixup_ebsa285(dev);
- if (machine_is_netwinder())
- pcibios_fixup_vnc(dev);
+ pcibios_fixup_ebsa285(dev);
pcibios_write_config_byte(dev->bus->number, dev->devfn,
PCI_INTERRUPT_LINE, dev->irq);
@@ -164,18 +159,18 @@
dev->bus->number, dev->devfn,
dev->vendor, dev->device, dev->irq);
}
+ /*
+ * this ought to have a better home
+ */
if (machine_is_netwinder())
hw_init();
}
__initfunc(void pcibios_init(void))
{
- if (machine_is_ebsa285() || machine_is_cats())
- pcibios_init_ebsa285();
- if (machine_is_netwinder())
- pcibios_init_vnc();
+ pcibios_init_ebsa285();
- printk("DEC21285 PCI revision %02X\n", *(unsigned char *)0xfe000008);
+ printk(KERN_DEBUG "PCI: DEC21285 revision %02X\n", *(unsigned char *)0xfe000008);
}
__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-arc.c linux.ac/arch/arm/kernel/dma-arc.c
--- linux.vanilla/arch/arm/kernel/dma-arc.c Sun Nov 8 15:08:43 1998
+++ linux.ac/arch/arm/kernel/dma-arc.c Sun Jan 24 21:11:31 1999
@@ -14,7 +14,7 @@
#include "dma.h"
-int arch_request_dma(dmach_t channel, dma_t *dma)
+int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id)
{
if (channel == DMA_VIRTUAL_FLOPPY0 ||
channel == DMA_VIRTUAL_FLOPPY1)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-ebsa285.c linux.ac/arch/arm/kernel/dma-ebsa285.c
--- linux.vanilla/arch/arm/kernel/dma-ebsa285.c Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/dma-ebsa285.c Sun Jan 24 21:11:31 1999
@@ -30,10 +30,11 @@
case 0:
case 1: /* 21285 internal channels */
return 0;
-
+#ifdef CONFIG_ISA_DMA
case 2 ... 9:
- if (machine_is_cats())
+ if (machine_is_cats() || machine_is_netwinder())
return isa_request_dma(channel - 2, dma, dev_name);
+#endif
}
return -EINVAL;
@@ -52,10 +53,9 @@
case 0:
case 1:
break;
-#ifdef CONFIG_CATS
+#ifdef CONFIG_ISA_DMA
case 2 ... 9:
- if (machine_is_cats())
- residue = isa_get_dma_residue(channel - 2);
+ residue = isa_get_dma_residue(channel - 2, dma);
#endif
}
return residue;
@@ -70,10 +70,9 @@
* Not yet implemented
*/
break;
-#ifdef CONFIG_CATS
+#ifdef CONFIG_ISA_DMA
case 2 ... 9:
- if (machine_is_cats())
- isa_enable_dma(channel - 2, dma);
+ isa_enable_dma(channel - 2, dma);
#endif
}
}
@@ -87,15 +86,17 @@
* Not yet implemented
*/
break;
-#ifdef CONFIG_CATS
+#ifdef CONFIG_ISA_DMA
case 2 ... 9:
- if (machine_is_cats())
- isa_disable_dma(channel - 2, dma);
+ isa_disable_dma(channel - 2, dma);
#endif
}
}
__initfunc(void arch_dma_init(dma_t *dma))
{
- /* Nothing to do */
+#ifdef CONFIG_ISA_DMA
+ if (machine_is_cats() || machine_is_netwinder())
+ isa_init_dma();
+#endif
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-isa.c linux.ac/arch/arm/kernel/dma-isa.c
--- linux.vanilla/arch/arm/kernel/dma-isa.c Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/dma-isa.c Sun Jan 24 21:11:31 1999
@@ -11,6 +11,7 @@
* Copyright (C) 1998 Phil Blundell
*/
#include
+#include
#include
#include
@@ -18,6 +19,10 @@
#include "dma.h"
#include "dma-isa.h"
+#define ISA_DMA_MODE_READ 0x44
+#define ISA_DMA_MODE_WRITE 0x48
+#define ISA_DMA_AUTOINIT 0x10
+
#define ISA_DMA_MASK 0
#define ISA_DMA_MODE 1
#define ISA_DMA_CLRFF 2
@@ -56,25 +61,27 @@
unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT];
int count;
- count = 1 + inb(io_port) + (inb(io_port) << 8);
+ count = 1 + inb(io_port);
+ count |= inb(io_port) << 8;
return channel < 4 ? count : (count << 1);
}
void isa_enable_dma(int channel, dma_t *dma)
{
- unsigned long address, length;
-
if (dma->invalid) {
+ unsigned long address, length;
+ unsigned int mode;
+
address = dma->buf.address;
length = dma->buf.length - 1;
- outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]);
outb(address >> 16, isa_dma_port[channel][ISA_DMA_PGLO]);
+ outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]);
if (channel >= 4) {
address >>= 1;
- length = (length >> 1) & 0xfe; /* why &0xfe? */
+ length >>= 1;
}
outb(0, isa_dma_port[channel][ISA_DMA_CLRFF]);
@@ -85,17 +92,27 @@
outb(length, isa_dma_port[channel][ISA_DMA_COUNT]);
outb(length >> 8, isa_dma_port[channel][ISA_DMA_COUNT]);
- outb(dma->dma_mode | (channel & 3), isa_dma_port[channel][ISA_DMA_MODE]);
+ mode = channel & 3;
- switch (dma->dma_mode) {
+ switch (dma->dma_mode & DMA_MODE_MASK) {
case DMA_MODE_READ:
+ mode |= ISA_DMA_MODE_READ;
dma_cache_inv(__bus_to_virt(dma->buf.address), dma->buf.length);
break;
case DMA_MODE_WRITE:
+ mode |= ISA_DMA_MODE_WRITE;
dma_cache_wback(__bus_to_virt(dma->buf.address), dma->buf.length);
break;
+
+ default:
+ break;
}
+
+ if (dma->dma_mode & DMA_AUTOINIT)
+ mode |= ISA_DMA_AUTOINIT;
+
+ outb(mode, isa_dma_port[channel][ISA_DMA_MODE]);
dma->invalid = 0;
}
outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]);
@@ -104,4 +121,39 @@
void isa_disable_dma(int channel, dma_t *dma)
{
outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]);
+}
+
+__initfunc(void isa_init_dma(void))
+{
+ int channel;
+
+ outb(0xff, 0x0d);
+ outb(0xff, 0xda);
+
+ for (channel = 0; channel < 8; channel++)
+ isa_disable_dma(channel, NULL);
+
+ outb(0x40, 0x0b);
+ outb(0x41, 0x0b);
+ outb(0x42, 0x0b);
+ outb(0x43, 0x0b);
+
+ outb(0xc0, 0xd6);
+ outb(0x41, 0xd6);
+ outb(0x42, 0xd6);
+ outb(0x43, 0xd6);
+
+ outb(0, 0xd4);
+
+ outb(0x10, 0x08);
+ outb(0x10, 0xd0);
+
+ outb(0x30, 0x40b);
+ outb(0x31, 0x40b);
+ outb(0x32, 0x40b);
+ outb(0x33, 0x40b);
+
+ outb(0x31, 0x4d6);
+ outb(0x32, 0x4d6);
+ outb(0x33, 0x4d6);
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-isa.h linux.ac/arch/arm/kernel/dma-isa.h
--- linux.vanilla/arch/arm/kernel/dma-isa.h Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/dma-isa.h Sun Jan 24 21:11:31 1999
@@ -23,3 +23,7 @@
*/
void isa_disable_dma(int channel, dma_t *dma);
+/*
+ * Initialise DMA
+ */
+void isa_init_dma(void);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-rpc.c linux.ac/arch/arm/kernel/dma-rpc.c
--- linux.vanilla/arch/arm/kernel/dma-rpc.c Sun Nov 8 15:08:43 1998
+++ linux.ac/arch/arm/kernel/dma-rpc.c Sun Jan 24 21:11:31 1999
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#include
#include
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/dma-vnc.c linux.ac/arch/arm/kernel/dma-vnc.c
--- linux.vanilla/arch/arm/kernel/dma-vnc.c Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/dma-vnc.c Thu Jan 1 01:00:00 1970
@@ -1,51 +0,0 @@
-/*
- * arch/arm/kernel/dma-vnc.c
- *
- * Copyright (C) 1998 Russell King
- */
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#include "dma.h"
-#include "dma-isa.h"
-
-int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
-{
- if (channel < 8)
- return isa_request_dma(channel, dma, dev_name);
- return -EINVAL;
-}
-
-void arch_free_dma(dmach_t channel, dma_t *dma)
-{
- isa_free_dma(channel, dma);
-}
-
-int arch_get_dma_residue(dmach_t channel, dma_t *dma)
-{
- return isa_get_dma_residue(channel, dma);
-}
-
-void arch_enable_dma(dmach_t channel, dma_t *dma)
-{
- isa_enable_dma(channel, dma);
-}
-
-void arch_disable_dma(dmach_t channel, dma_t *dma)
-{
- isa_disable_dma(channel, dma);
-}
-
-__initfunc(void arch_dma_init(dma_t *dma))
-{
- /* Nothing to do */
-}
-
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/ecard.c linux.ac/arch/arm/kernel/ecard.c
--- linux.vanilla/arch/arm/kernel/ecard.c Mon Dec 28 23:09:40 1998
+++ linux.ac/arch/arm/kernel/ecard.c Sun Jan 24 21:11:31 1999
@@ -7,32 +7,41 @@
*
* Created from information from Acorns RiscOS3 PRMs
*
- * 08-Dec-1996 RMK Added code for the 9'th expansion card - the ether podule slot.
+ * 08-Dec-1996 RMK Added code for the 9'th expansion card - the ether
+ * podule slot.
* 06-May-1997 RMK Added blacklist for cards whose loader doesn't work.
- * 12-Sep-1997 RMK Created new handling of interrupt enables/disables - cards can
- * now register their own routine to control interrupts (recommended).
- * 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled on reset from
- * Linux. (Caused cards not to respond under RiscOS without hard reset).
+ * 12-Sep-1997 RMK Created new handling of interrupt enables/disables
+ * - cards can now register their own routine to control
+ * interrupts (recommended).
+ * 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled
+ * on reset from Linux. (Caused cards not to respond
+ * under RiscOS without hard reset).
* 15-Feb-1998 RMK Added DMA support
* 12-Sep-1998 RMK Added EASI support
+ * 10-Jan-1999 RMK Run loaders in a simulated RISC OS environment.
*/
#define ECARD_C
+#define __KERNEL_SYSCALLS__
#include
+#include
#include
#include
#include
#include
#include
#include
+#include
+#include
#include
-#include
-#include
+#include
#include
+#include
+#include
#include
-#include
+#include
#ifdef CONFIG_ARCH_ARC
#include
@@ -40,45 +49,418 @@
#define oldlatch_init()
#endif
-#define BLACKLIST_NAME(m,p,s) { m, p, NULL, s }
-#define BLACKLIST_LOADER(m,p,l) { m, p, l, NULL }
-#define BLACKLIST_NOLOADER(m,p) { m, p, noloader, blacklisted_str }
-#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
+enum req {
+ req_readbytes,
+ req_reset
+};
-extern unsigned long atomwide_serial_loader[], oak_scsi_loader[], noloader[];
-static const char blacklisted_str[] = "*loader s/w is not 32-bit compliant*";
+struct ecard_request {
+ enum req req;
+ ecard_t *ec;
+ unsigned int address;
+ unsigned int length;
+ unsigned int use_loader;
+ void *buffer;
+};
-static const struct expcard_blacklist {
+struct expcard_blacklist {
unsigned short manufacturer;
unsigned short product;
- const loader_t loader;
const char *type;
-} blacklist[] = {
-/* Cards without names */
- BLACKLIST_NAME(MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1"),
-
-/* Cards with corrected loader */
- BLACKLIST_LOADER(MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, atomwide_serial_loader),
- BLACKLIST_LOADER(MANU_OAK, PROD_OAK_SCSI, oak_scsi_loader),
+};
-/* Supported cards with broken loader */
- { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI, noloader, "AlSystems PowerTec SCSI" },
+static pid_t ecard_pid;
+static struct wait_queue *ecard_wait;
+static struct wait_queue *ecard_done;
+static struct ecard_request *ecard_req;
+static struct task_struct *ecard_tsk;
+static ecard_t *cards;
+static ecard_t *slot_to_expcard[MAX_ECARDS];
+#ifdef HAS_EXPMASK
+static unsigned int have_expmask;
+#endif
-/* Unsupported cards with no loader */
- BLACKLIST_NOLOADER(MANU_MCS, PROD_MCS_CONNECT32)
+/* List of descriptions of cards which don't have an extended
+ * identification, or chunk directories containing a description.
+ */
+static const struct expcard_blacklist blacklist[] = {
+ { MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1" }
};
+asmlinkage extern int ecard_loader_reset(volatile unsigned char *pa,
+ loader_t loader);
+asmlinkage extern int ecard_loader_read(int off, volatile unsigned char *pa,
+ loader_t loader);
extern int setup_arm_irq(int, struct irqaction *);
+extern void do_ecard_IRQ(int, struct pt_regs *);
+
+
+static void
+ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs);
+
+static struct irqaction irqexpansioncard = {
+ ecard_irq_noexpmask, SA_INTERRUPT, 0, "expansion cards", NULL, NULL
+};
+
+static inline unsigned short
+ecard_getu16(unsigned char *v)
+{
+ return v[0] | v[1] << 8;
+}
+
+static inline signed long
+ecard_gets24(unsigned char *v)
+{
+ return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
+}
+
+static inline ecard_t *
+slot_to_ecard(unsigned int slot)
+{
+ return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL;
+}
+/* ===================== Expansion card daemon ======================== */
/*
- * from linux/arch/arm/kernel/irq.c
+ * Since the loader programs on the expansion cards need to be run
+ * in a specific environment, create a separate task with this
+ * environment up, and pass requests to this task as and when we
+ * need to.
+ *
+ * This should allow 99% of loaders to be called from Linux.
+ *
+ * From a security standpoint, we trust the card vendors. This
+ * may be a misplaced trust.
*/
-extern void do_ecard_IRQ(int irq, struct pt_regs *);
+#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
+#define POD_INT_ADDR(x) ((volatile unsigned char *)\
+ ((BUS_ADDR((x)) - IO_BASE) + IO_START))
-static ecard_t expcard[MAX_ECARDS];
-static signed char irqno_to_expcard[16];
-static unsigned int ecard_numcards, ecard_numirqcards;
-static unsigned int have_expmask;
+static void
+ecard_task_reset(struct ecard_request *req)
+{
+ if (req->ec == NULL) {
+ ecard_t *ec;
+
+ for (ec = cards; ec; ec = ec->next) {
+ printk(KERN_DEBUG "Resetting card %d\n",
+ ec->slot_no);
+
+ if (ec->loader)
+ ecard_loader_reset(POD_INT_ADDR(ec->podaddr),
+ ec->loader);
+ }
+ printk(KERN_DEBUG "All cards reset\n");
+ } else if (req->ec->loader)
+ ecard_loader_reset(POD_INT_ADDR(req->ec->podaddr),
+ req->ec->loader);
+}
+
+static void
+ecard_task_readbytes(struct ecard_request *req)
+{
+ unsigned char *buf = (unsigned char *)req->buffer;
+ volatile unsigned char *base_addr =
+ (volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr);
+ unsigned int len = req->length;
+
+ if (req->ec->slot_no == 8) {
+ /*
+ * The card maintains an index which
+ * increments the address into a 4096-byte
+ * page on each access. We need to keep
+ * track of the counter.
+ */
+ static unsigned int index;
+ unsigned int offset, page;
+ unsigned char byte = 0; /* keep gcc quiet */
+
+ offset = req->address & 4095;
+ page = req->address >> 12;
+
+ if (page > 256)
+ return;
+
+ page *= 4;
+
+ if (offset == 0 || index > offset) {
+ /*
+ * We need to reset the index counter.
+ */
+ *base_addr = 0;
+ index = 0;
+ }
+
+ while (index <= offset) {
+ byte = base_addr[page];
+ index += 1;
+ }
+
+ while (len--) {
+ *buf++ = byte;
+ if (len) {
+ byte = base_addr[page];
+ index += 1;
+ }
+ }
+ } else {
+ unsigned int off = req->address;
+
+ if (!req->use_loader || !req->ec->loader) {
+ off *= 4;
+ while (len--) {
+ *buf++ = base_addr[off];
+ off += 4;
+ }
+ } else {
+ while(len--) {
+ /*
+ * The following is required by some
+ * expansion card loader programs.
+ */
+ *(unsigned long *)0x108 = 0;
+ *buf++ = ecard_loader_read(off++, base_addr,
+ req->ec->loader);
+ }
+ }
+ }
+
+}
+
+#ifdef CONFIG_CPU_32
+/*
+ * Set up the expansion card daemon's environment.
+ */
+static void
+ecard_init_task(void)
+{
+ /* We want to set up the page tables for the following mapping:
+ * Virtual Physical
+ * 0x03000000 0x03000000
+ * 0x03010000 unmapped
+ * 0x03210000 0x03210000
+ * 0x03400000 unmapped
+ * 0x08000000 0x08000000
+ * 0x10000000 unmapped
+ *
+ * FIXME: we don't follow this 100% yet.
+ */
+ pgd_t *src_pgd, *dst_pgd;
+ unsigned int dst_addr = IO_START;
+
+ src_pgd = pgd_offset(current->mm, IO_BASE);
+ dst_pgd = pgd_offset(current->mm, dst_addr);
+
+ while (dst_addr < IO_START + IO_SIZE) {
+ *dst_pgd++ = *src_pgd++;
+ dst_addr += PGDIR_SIZE;
+ }
+
+ flush_tlb_range(current->mm, IO_START, IO_START + IO_SIZE);
+
+ dst_addr = EASI_START;
+ src_pgd = pgd_offset(current->mm, EASI_BASE);
+ dst_pgd = pgd_offset(current->mm, dst_addr);
+
+ while (dst_addr < EASI_START + EASI_SIZE) {
+ *dst_pgd++ = *src_pgd++;
+ dst_addr += PGDIR_SIZE;
+ }
+
+ flush_tlb_range(current->mm, EASI_START, EASI_START + EASI_SIZE);
+}
+
+static int
+ecard_task(void * unused)
+{
+ ecard_tsk = current;
+
+ current->session = 1;
+ current->pgrp = 1;
+
+ /*
+ * We don't want /any/ signals, not even SIGKILL
+ */
+ sigfillset(¤t->blocked);
+ sigemptyset(¤t->signal);
+
+ strcpy(current->comm, "kecardd");
+
+ /*
+ * Set up the environment
+ */
+ ecard_init_task();
+
+ while (1) {
+ struct ecard_request *req;
+
+ do {
+ req = xchg(&ecard_req, NULL);
+
+ if (req == NULL) {
+ sigemptyset(¤t->signal);
+ interruptible_sleep_on(&ecard_wait);
+ }
+ } while (req == NULL);
+
+ switch (req->req) {
+ case req_readbytes:
+ ecard_task_readbytes(req);
+ break;
+
+ case req_reset:
+ ecard_task_reset(req);
+ break;
+ }
+ wake_up(&ecard_done);
+ }
+}
+
+/*
+ * Wake the expansion card daemon to action our request.
+ *
+ * FIXME: The test here is not sufficient to detect if the
+ * kcardd is running.
+ */
+static inline void
+ecard_call(struct ecard_request *req)
+{
+ /*
+ * If we're called from task 0, or from an
+ * interrupt (will be keyboard interrupt),
+ * we forcefully set up the memory map, and
+ * call the loader. We can't schedule, or
+ * sleep for this call.
+ */
+ if ((current == task[0] || in_interrupt()) &&
+ req->req == req_reset && req->ec == NULL) {
+ ecard_init_task();
+ ecard_task_reset(req);
+ } else {
+ if (ecard_pid <= 0)
+ ecard_pid = kernel_thread(ecard_task, NULL, 0);
+
+ ecard_req = req;
+
+ wake_up(&ecard_wait);
+
+ sleep_on(&ecard_done);
+ }
+}
+#else
+/*
+ * On 26-bit processors, we don't need the kcardd thread to access the
+ * expansion card loaders. We do it directly.
+ */
+static inline void
+ecard_call(struct ecard_request *req)
+{
+ if (req->req == req_reset)
+ ecard_task_reset(req);
+ else
+ ecard_task_readbytes(req);
+}
+#endif
+
+/* ======================= Mid-level card control ===================== */
+/*
+ * This is called to reset the loaders for each expansion card on reboot.
+ *
+ * This is required to make sure that the card is in the correct state
+ * that RiscOS expects it to be.
+ */
+void
+ecard_reset(int slot)
+{
+ struct ecard_request req;
+
+ req.req = req_reset;
+
+ if (slot < 0)
+ req.ec = NULL;
+ else
+ req.ec = slot_to_ecard(slot);
+
+ ecard_call(&req);
+
+#ifdef HAS_EXPMASK
+ if (have_expmask && slot < 0) {
+ have_expmask |= ~0;
+ EXPMASK_ENABLE = have_expmask;
+ }
+#endif
+}
+
+static void
+ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
+{
+ struct ecard_request req;
+
+ req.req = req_readbytes;
+ req.ec = ec;
+ req.address = off;
+ req.length = len;
+ req.use_loader = useld;
+ req.buffer = addr;
+
+ ecard_call(&req);
+}
+
+int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
+{
+ struct ex_chunk_dir excd;
+ int index = 16;
+ int useld = 0;
+
+ if (!ec->cid.cd)
+ return 0;
+
+ while(1) {
+ ecard_readbytes(&excd, ec, index, 8, useld);
+ index += 8;
+ if (c_id(&excd) == 0) {
+ if (!useld && ec->loader) {
+ useld = 1;
+ index = 0;
+ continue;
+ }
+ return 0;
+ }
+ if (c_id(&excd) == 0xf0) { /* link */
+ index = c_start(&excd);
+ continue;
+ }
+ if (c_id(&excd) == 0x80) { /* loader */
+ if (!ec->loader) {
+ ec->loader = (loader_t)kmalloc(c_len(&excd),
+ GFP_KERNEL);
+ ecard_readbytes(ec->loader, ec,
+ (int)c_start(&excd),
+ c_len(&excd), useld);
+ }
+ continue;
+ }
+ if (c_id(&excd) == id && num-- == 0)
+ break;
+ }
+
+ if (c_id(&excd) & 0x80) {
+ switch (c_id(&excd) & 0x70) {
+ case 0x70:
+ ecard_readbytes((unsigned char *)excd.d.string, ec,
+ (int)c_start(&excd), c_len(&excd),
+ useld);
+ break;
+ case 0x00:
+ break;
+ }
+ }
+ cd->start_offset = c_start(&excd);
+ memcpy(cd->d.string, excd.d.string, 256);
+ return 1;
+}
+
+/* ======================= Interrupt control ============================ */
static void ecard_def_irq_enable(ecard_t *ec, int irqnr)
{
@@ -100,6 +482,11 @@
#endif
}
+static int ecard_def_irq_pending(ecard_t *ec)
+{
+ return !ec->irqmask || ec->irqaddr[0] & ec->irqmask;
+}
+
static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr)
{
panic("ecard_def_fiq_enable called - impossible");
@@ -110,11 +497,18 @@
panic("ecard_def_fiq_disable called - impossible");
}
+static int ecard_def_fiq_pending(ecard_t *ec)
+{
+ return !ec->fiqmask || ec->fiqaddr[0] & ec->fiqmask;
+}
+
static expansioncard_ops_t ecard_default_ops = {
ecard_def_irq_enable,
ecard_def_irq_disable,
+ ecard_def_irq_pending,
ecard_def_fiq_enable,
- ecard_def_fiq_disable
+ ecard_def_fiq_disable,
+ ecard_def_fiq_pending
};
/*
@@ -125,10 +519,9 @@
*/
void ecard_enableirq(unsigned int irqnr)
{
- irqnr &= 7;
- if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) {
- ecard_t *ec = expcard + irqno_to_expcard[irqnr];
+ ecard_t *ec = slot_to_ecard(irqnr);
+ if (ec) {
if (!ec->ops)
ec->ops = &ecard_default_ops;
@@ -142,10 +535,9 @@
void ecard_disableirq(unsigned int irqnr)
{
- irqnr &= 7;
- if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) {
- ecard_t *ec = expcard + irqno_to_expcard[irqnr];
+ ecard_t *ec = slot_to_ecard(irqnr);
+ if (ec) {
if (!ec->ops)
ec->ops = &ecard_default_ops;
@@ -156,10 +548,9 @@
void ecard_enablefiq(unsigned int fiqnr)
{
- fiqnr &= 7;
- if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) {
- ecard_t *ec = expcard + irqno_to_expcard[fiqnr];
+ ecard_t *ec = slot_to_ecard(fiqnr);
+ if (ec) {
if (!ec->ops)
ec->ops = &ecard_default_ops;
@@ -173,10 +564,9 @@
void ecard_disablefiq(unsigned int fiqnr)
{
- fiqnr &= 7;
- if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) {
- ecard_t *ec = expcard + irqno_to_expcard[fiqnr];
+ ecard_t *ec = slot_to_ecard(fiqnr);
+ if (ec) {
if (!ec->ops)
ec->ops = &ecard_default_ops;
@@ -185,41 +575,89 @@
}
}
-static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs)
+static void
+ecard_dump_irq_state(ecard_t *ec)
{
- const int num_cards = ecard_numirqcards;
- int i, called = 0;
+ printk(" %d: %sclaimed, ",
+ ec->slot_no,
+ ec->claimed ? "" : "not ");
+
+ if (ec->ops && ec->ops->irqpending &&
+ ec->ops != &ecard_default_ops)
+ printk("irq %spending\n",
+ ec->ops->irqpending(ec) ? "" : "not ");
+ else
+ printk("irqaddr %p, mask = %02X, status = %02X\n",
+ ec->irqaddr, ec->irqmask, *ec->irqaddr);
+}
- for (i = 0; i < num_cards; i++) {
- if (expcard[i].claimed && expcard[i].irq &&
- (!expcard[i].irqmask ||
- expcard[i].irqaddr[0] & expcard[i].irqmask)) {
- do_ecard_IRQ(expcard[i].irq, regs);
- called ++;
+static void
+ecard_check_lockup(void)
+{
+ static int last, lockup;
+ ecard_t *ec;
+
+ /*
+ * If the timer interrupt has not run since the last million
+ * unrecognised expansion card interrupts, then there is
+ * something seriously wrong. Disable the expansion card
+ * interrupts so at least we can continue.
+ *
+ * Maybe we ought to start a timer to re-enable them some time
+ * later?
+ */
+ if (last == jiffies) {
+ lockup += 1;
+ if (lockup > 1000000) {
+ printk(KERN_ERR "\nInterrupt lockup detected - "
+ "disabling all expansion card interrupts\n");
+
+ disable_irq(IRQ_EXPANSIONCARD);
+
+ printk("Expansion card IRQ state:\n");
+
+ for (ec = cards; ec; ec = ec->next)
+ ecard_dump_irq_state(ec);
}
+ } else
+ lockup = 0;
+
+ /*
+ * If we did not recognise the source of this interrupt,
+ * warn the user, but don't flood the user with these messages.
+ */
+ if (!last || time_after(jiffies, last + 5*HZ)) {
+ last = jiffies;
+ printk(KERN_WARNING "Unrecognised interrupt from backplane\n");
}
- cli();
- if (called == 0) {
- static int last, lockup;
+}
- if (last == jiffies) {
- lockup += 1;
- if (lockup > 1000000) {
- printk(KERN_ERR "\nInterrupt lockup detected - disabling expansion card IRQs\n");
- disable_irq(intr_no);
- printk("Expansion card IRQ state:\n");
- for (i = 0; i < num_cards; i++)
- printk(" %d: %sclaimed, irqaddr = %p, irqmask = %X, status=%X\n", expcard[i].irq - 32,
- expcard[i].claimed ? "" : "not", expcard[i].irqaddr, expcard[i].irqmask, *expcard[i].irqaddr);
- }
- } else
- lockup = 0;
+static void
+ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs)
+{
+ ecard_t *ec;
+ int called = 0;
+
+ for (ec = cards; ec; ec = ec->next) {
+ int pending;
+
+ if (!ec->claimed || ec->irq == NO_IRQ || ec->slot_no == 8)
+ continue;
- if (!last || time_after(jiffies, last + 5*HZ)) {
- last = jiffies;
- printk(KERN_ERR "\nUnrecognised interrupt from backplane\n");
+ if (ec->ops && ec->ops->irqpending)
+ pending = ec->ops->irqpending(ec);
+ else
+ pending = ecard_default_ops.irqpending(ec);
+
+ if (pending) {
+ do_ecard_IRQ(ec->irq, regs);
+ called ++;
}
}
+ cli();
+
+ if (called == 0)
+ ecard_check_lockup();
}
#ifdef HAS_EXPMASK
@@ -234,31 +672,35 @@
0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00
};
-static void ecard_irq_expmask(int intr_no, void *dev_id, struct pt_regs *regs)
+static void
+ecard_irq_expmask(int intr_no, void *dev_id, struct pt_regs *regs)
{
const unsigned int statusmask = 15;
unsigned int status;
status = EXPMASK_STATUS & statusmask;
if (status) {
- unsigned int irqno;
+ unsigned int slot;
ecard_t *ec;
again:
- irqno = first_set[status];
- ec = expcard + irqno_to_expcard[irqno];
+ slot = first_set[status];
+ ec = slot_to_ecard(slot);
if (ec->claimed) {
unsigned int oldexpmask;
/*
- * this ugly code is so that we can operate a prioritorising system.
+ * this ugly code is so that we can operate a
+ * prioritorising system:
+ *
* Card 0 highest priority
* Card 1
* Card 2
* Card 3 lowest priority
+ *
* Serial cards should go in 0/1, ethernet/scsi in 2/3
* otherwise you will lose serial data at high speeds!
*/
oldexpmask = have_expmask;
- EXPMASK_ENABLE = (have_expmask &= priority_masks[irqno]);
+ EXPMASK_ENABLE = (have_expmask &= priority_masks[slot]);
sti();
do_ecard_IRQ(ec->irq, regs);
cli();
@@ -267,15 +709,18 @@
if (status)
goto again;
} else {
- printk(KERN_WARNING "card%d: interrupt from unclaimed card???\n", irqno);
- EXPMASK_ENABLE = (have_expmask &= ~(1 << irqno));
+ printk(KERN_WARNING "card%d: interrupt from unclaimed "
+ "card???\n", slot);
+ EXPMASK_ENABLE = (have_expmask &= ~(1 << slot));
}
} else
printk(KERN_WARNING "Wild interrupt from backplane (masks)\n");
}
-static int ecard_checkirqhw(void)
+static void
+ecard_probeirqhw(void)
{
+ ecard_t *ec;
int found;
EXPMASK_ENABLE = 0x00;
@@ -283,62 +728,75 @@
found = ((EXPMASK_STATUS & 15) == 0);
EXPMASK_ENABLE = 0xff;
- return found;
+ if (!found)
+ return;
+
+ printk(KERN_DEBUG "Expansion card interrupt "
+ "management hardware found\n");
+
+ irqexpansioncard.handler = ecard_irq_expmask;
+
+ /* for each card present, set a bit to '1' */
+ have_expmask = 0x80000000;
+
+ for (ec = cards; ec; ec = ec->next)
+ have_expmask |= 1 << ec->slot_no;
+
+ EXPMASK_ENABLE = have_expmask;
}
+#else
+#define ecard_probeirqhw()
#endif
-static void ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
+unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
{
- extern int ecard_loader_read(int off, volatile unsigned int pa, loader_t loader);
- unsigned char *a = (unsigned char *)addr;
-
- if (ec->slot_no == 8) {
- static unsigned int lowaddress;
- unsigned int laddr, haddr;
- unsigned char byte = 0; /* keep gcc quiet */
-
- laddr = off & 4095; /* number of bytes to read from offset + base addr */
- haddr = off >> 12; /* offset into card from base addr */
+ switch (ec->slot_no) {
+ case 0 ... 3:
+ switch (type) {
+ case ECARD_MEMC:
+ return IO_EC_MEMC_BASE + (ec->slot_no << 12);
- if (haddr > 256)
- return;
+ case ECARD_IOC:
+ return IO_EC_IOC_BASE + (speed << 17) +
+ (ec->slot_no << 12);
- /*
- * If we require a low address or address 0, then reset, and start again...
- */
- if (!off || lowaddress > laddr) {
- outb(0, ec->podaddr);
- lowaddress = 0;
- }
- while (lowaddress <= laddr) {
- byte = inb(ec->podaddr + haddr);
- lowaddress += 1;
- }
- while (len--) {
- *a++ = byte;
- if (len) {
- byte = inb(ec->podaddr + haddr);
- lowaddress += 1;
- }
+#ifdef IO_EC_EASI_BASE
+ case ECARD_EASI:
+ return IO_EC_EASI_BASE + (ec->slot_no << 22);
+#endif
}
- } else {
- if (!useld || !ec->loader) {
- while(len--)
- *a++ = inb(ec->podaddr + (off++));
- } else {
- while(len--) {
- *(unsigned long *)0x108 = 0; /* hack for some loaders!!! */
- *a++ = ecard_loader_read(off++, BUS_ADDR(ec->podaddr), ec->loader);
- }
+ break;
+
+ case 4 ... 7:
+ switch (type) {
+#ifdef IO_EC_IOC4_BASE
+ case ECARD_IOC:
+ return IO_EC_IOC4_BASE + (speed << 17) +
+ ((ec->slot_no - 4) << 12);
+#endif
+#ifdef IO_EC_EASI_BASE
+ case ECARD_EASI:
+ return IO_EC_EASI_BASE + (ec->slot_no << 22);
+#endif
+ default:
+ break;
}
+ break;
+
+#ifdef IO_EC_MEMC8_BASE
+ case 8:
+ return IO_EC_MEMC8_BASE;
+#endif
}
+ return 0;
}
static int ecard_prints(char *buffer, ecard_t *ec)
{
char *start = buffer;
- buffer += sprintf(buffer, "\n %d: ", ec->slot_no);
+ buffer += sprintf(buffer, " %d: %s ", ec->slot_no,
+ ec->type == ECARD_EASI ? "EASI" : " ");
if (ec->cid.id == 0) {
struct in_chunk_dir incd;
@@ -346,63 +804,59 @@
buffer += sprintf(buffer, "[%04X:%04X] ",
ec->cid.manufacturer, ec->cid.product);
- if (!ec->card_desc && ec->cid.is && ec->cid.cd &&
+ if (!ec->card_desc && ec->cid.cd &&
ecard_readchunk(&incd, ec, 0xf5, 0))
ec->card_desc = incd.d.string;
if (!ec->card_desc)
ec->card_desc = "*unknown*";
- buffer += sprintf(buffer, "%s", ec->card_desc);
+ buffer += sprintf(buffer, "%s\n", ec->card_desc);
} else
- buffer += sprintf(buffer, "Simple card %d", ec->cid.id);
+ buffer += sprintf(buffer, "Simple card %d\n", ec->cid.id);
return buffer - start;
}
-static inline unsigned short ecard_getu16(unsigned char *v)
-{
- return v[0] | v[1] << 8;
-}
-
-static inline signed long ecard_gets24(unsigned char *v)
-{
- return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
-}
-
/*
* Probe for an expansion card.
*
* If bit 1 of the first byte of the card is set, then the
* card does not exist.
*/
-__initfunc(static int ecard_probe(int card, int freeslot, card_type_t type))
+__initfunc(static int
+ecard_probe(int slot, card_type_t type))
{
- ecard_t *ec = expcard + freeslot;
+ ecard_t **ecp;
+ ecard_t *ec;
struct ex_ecid cid;
char buffer[200];
- int i;
+ int i, rc = -ENOMEM;
+
+ ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
- irqno_to_expcard[card] = -1;
+ if (!ec)
+ goto nodev;
- ec->slot_no = card;
+ memset(ec, 0, sizeof(ecard_t));
+
+ ec->slot_no = slot;
+ ec->type = type;
ec->irq = NO_IRQ;
ec->fiq = NO_IRQ;
ec->dma = NO_DMA;
ec->card_desc = NULL;
ec->ops = &ecard_default_ops;
+ rc = -ENODEV;
if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
- return 0;
+ goto nodev;
cid.r_zero = 1;
ecard_readbytes(&cid, ec, 0, 16, 0);
if (cid.r_zero)
- return 0;
-
- irqno_to_expcard[card] = freeslot;
+ goto nodev;
- ec->type = type;
ec->cid.id = cid.r_id;
ec->cid.cd = cid.r_cd;
ec->cid.is = cid.r_is;
@@ -415,9 +869,9 @@
ec->cid.fiqmask = cid.r_fiqmask;
ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff);
ec->fiqaddr =
- ec->irqaddr = (unsigned char *)BUS_ADDR(ec->podaddr);
+ ec->irqaddr = (unsigned char *)ioaddr(ec->podaddr);
- if (ec->cid.cd && ec->cid.is) {
+ if (ec->cid.is) {
ec->irqmask = ec->cid.irqmask;
ec->irqaddr += ec->cid.irqoff;
ec->fiqmask = ec->cid.fiqmask;
@@ -430,88 +884,69 @@
for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
if (blacklist[i].manufacturer == ec->cid.manufacturer &&
blacklist[i].product == ec->cid.product) {
- ec->loader = blacklist[i].loader;
ec->card_desc = blacklist[i].type;
break;
}
- ecard_prints(buffer, ec);
- printk("%s", buffer);
-
- ec->irq = 32 + card;
+ ec->irq = 32 + slot;
#ifdef IO_EC_MEMC8_BASE
- if (card == 8)
+ if (slot == 8)
ec->irq = 11;
#endif
#ifdef CONFIG_ARCH_RPC
/* On RiscPC, only first two slots have DMA capability */
- if (card < 2)
- ec->dma = 2 + card;
+ if (slot < 2)
+ ec->dma = 2 + slot;
#endif
#if 0 /* We don't support FIQs on expansion cards at the moment */
- ec->fiq = 96 + card;
+ ec->fiq = 96 + slot;
#endif
- return 1;
-}
+ rc = 0;
-/*
- * This is called to reset the loaders for each expansion card on reboot.
- *
- * This is required to make sure that the card is in the correct state
- * that RiscOS expects it to be.
- */
-void ecard_reset(int card)
-{
- extern int ecard_loader_reset(volatile unsigned int pa, loader_t loader);
+ for (ecp = &cards; *ecp; ecp = &(*ecp)->next);
- if (card >= ecard_numcards)
- return;
-
- if (card < 0) {
- for (card = 0; card < ecard_numcards; card++)
- if (expcard[card].loader)
- ecard_loader_reset(BUS_ADDR(expcard[card].podaddr),
- expcard[card].loader);
- } else
- if (expcard[card].loader)
- ecard_loader_reset(BUS_ADDR(expcard[card].podaddr),
- expcard[card].loader);
+ *ecp = ec;
-#ifdef HAS_EXPMASK
- if (have_expmask) {
- have_expmask |= ~0;
- EXPMASK_ENABLE = have_expmask;
+nodev:
+ if (rc && ec)
+ kfree(ec);
+ else {
+ slot_to_expcard[slot] = ec;
+
+ ecard_prints(buffer, ec);
+ printk("%s", buffer);
}
-#endif
+ return rc;
}
-static unsigned int ecard_startcard;
+static ecard_t *finding_pos;
void ecard_startfind(void)
{
- ecard_startcard = 0;
+ finding_pos = NULL;
}
ecard_t *ecard_find(int cid, const card_ids *cids)
{
- int card;
+ if (!finding_pos)
+ finding_pos = cards;
+ else
+ finding_pos = finding_pos->next;
+
+ for (; finding_pos; finding_pos = finding_pos->next) {
+ if (finding_pos->claimed)
+ continue;
- if (!cids) {
- for (card = ecard_startcard; card < ecard_numcards; card++)
- if (!expcard[card].claimed &&
- (expcard[card].cid.id ^ cid) == 0)
+ if (!cids) {
+ if ((finding_pos->cid.id ^ cid) == 0)
break;
- } else {
- for (card = ecard_startcard; card < ecard_numcards; card++) {
+ } else {
unsigned int manufacturer, product;
int i;
- if (expcard[card].claimed)
- continue;
-
- manufacturer = expcard[card].cid.manufacturer;
- product = expcard[card].cid.product;
+ manufacturer = finding_pos->cid.manufacturer;
+ product = finding_pos->cid.product;
for (i = 0; cids[i].manufacturer != 65535; i++)
if (manufacturer == cids[i].manufacturer &&
@@ -523,111 +958,24 @@
}
}
- ecard_startcard = card + 1;
-
- return card < ecard_numcards ? &expcard[card] : NULL;
+ return finding_pos;
}
-int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
+__initfunc(static void ecard_free_all(void))
{
- struct ex_chunk_dir excd;
- int index = 16;
- int useld = 0;
+ ecard_t *ec, *ecn;
- if (!ec->cid.is || !ec->cid.cd)
- return 0;
-
- while(1) {
- ecard_readbytes(&excd, ec, index, 8, useld);
- index += 8;
- if (c_id(&excd) == 0) {
- if (!useld && ec->loader) {
- useld = 1;
- index = 0;
- continue;
- }
- return 0;
- }
- if (c_id(&excd) == 0xf0) { /* link */
- index = c_start(&excd);
- continue;
- }
- if (c_id(&excd) == 0x80) { /* loader */
- if (!ec->loader) {
- ec->loader = (loader_t)kmalloc(c_len(&excd), GFP_KERNEL);
- ecard_readbytes(ec->loader, ec, (int)c_start(&excd), c_len(&excd), useld);
- }
- continue;
- }
- if (c_id(&excd) == id && num-- == 0)
- break;
- }
+ for (ec = cards; ec; ec = ecn) {
+ ecn = ec->next;
- if (c_id(&excd) & 0x80) {
- switch (c_id(&excd) & 0x70) {
- case 0x70:
- ecard_readbytes((unsigned char *)excd.d.string, ec,
- (int)c_start(&excd), c_len(&excd), useld);
- break;
- case 0x00:
- break;
- }
+ kfree(ec);
}
- cd->start_offset = c_start(&excd);
- memcpy(cd->d.string, excd.d.string, 256);
- return 1;
-}
-
-unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
-{
- switch (ec->slot_no) {
- case 0 ... 3:
- switch (type) {
- case ECARD_MEMC:
- return IO_EC_MEMC_BASE + (ec->slot_no << 12);
- case ECARD_IOC:
- return IO_EC_IOC_BASE + (speed << 17) + (ec->slot_no << 12);
-
-#ifdef IO_EC_EASI_BASE
- case ECARD_EASI:
- return IO_EC_EASI_BASE + (ec->slot_no << 22);
-#endif
- }
- break;
-
- case 4 ... 7:
- switch (type) {
-#ifdef IO_EC_IOC4_BASE
- case ECARD_IOC:
- return IO_EC_IOC4_BASE + (speed << 17) + ((ec->slot_no - 4) << 12);
-#endif
-#ifdef IO_EC_EASI_BASE
- case ECARD_EASI:
- return IO_EC_EASI_BASE + (ec->slot_no << 22);
-#endif
- default:
- break;
- }
- break;
+ cards = NULL;
-#ifdef IO_EC_MEMC8_BASE
- case 8:
- return IO_EC_MEMC8_BASE;
-#endif
- }
- return 0;
+ memset(slot_to_expcard, 0, sizeof(slot_to_expcard));
}
-static struct irqaction irqexpansioncard = {
- ecard_irq_noexpmask,
- SA_INTERRUPT,
- 0,
- "expansion cards",
- NULL,
- NULL
-};
-
/*
* Initialise the expansion card system.
* Locate all hardware - interrupt management and
@@ -635,51 +983,31 @@
*/
__initfunc(void ecard_init(void))
{
- int i, nc = 0;
-
- memset(expcard, 0, sizeof(expcard));
-
-#ifdef HAS_EXPMASK
- if (ecard_checkirqhw()) {
- printk(KERN_DEBUG "Expansion card interrupt management hardware found\n");
- irqexpansioncard.handler = ecard_irq_expmask;
- irqexpansioncard.flags |= SA_IRQNOMASK;
- have_expmask = -1;
- }
-#endif
+ int slot;
- printk("Installed expansion cards:");
+ oldlatch_init();
- /*
- * First of all, probe all cards on the expansion card interrupt line
- */
- for (i = 0; i < 8; i++)
- if (ecard_probe(i, nc, ECARD_IOC) || ecard_probe(i, nc, ECARD_EASI))
- nc += 1;
- else
- have_expmask &= ~(1<
+
.equ ioc_base_high, IOC_BASE & 0xff000000
.equ ioc_base_low, IOC_BASE & 0x00ff0000
.macro disable_fiq
@@ -187,20 +191,79 @@
.endm
#elif defined(CONFIG_ARCH_EBSA285)
+#include
.macro disable_fiq
.endm
+ .equ irq_mask_pci_err_high, IRQ_MASK_PCI_ERR & 0xff000000
+ .equ irq_mask_pci_err_low, IRQ_MASK_PCI_ERR & 0x00ff0000
+
.macro get_irqnr_and_base, irqnr, irqstat, base
mov r4, #0xfe000000
ldr \irqstat, [r4, #0x180] @ get interrupts
- mov \irqnr, #0
-1001: tst \irqstat, #1
- addeq \irqnr, \irqnr, #1
- moveq \irqstat, \irqstat, lsr #1
- tsteq \irqnr, #32
- beq 1001b
- teq \irqnr, #32
+
+ tst \irqstat, #IRQ_MASK_SDRAMPARITY
+ movne \irqnr, #IRQ_SDRAMPARITY
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_UART_RX
+ movne \irqnr, #IRQ_CONRX
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_DMA1
+ movne \irqnr, #IRQ_DMA1
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_DMA2
+ movne \irqnr, #IRQ_DMA2
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_IN0
+ movne \irqnr, #IRQ_IN0
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_IN1
+ movne \irqnr, #IRQ_IN1
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_IN2
+ movne \irqnr, #IRQ_IN2
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_IN3
+ movne \irqnr, #IRQ_IN3
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_PCI
+ movne \irqnr, #IRQ_PCI
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_I2OINPOST
+ movne \irqnr, #IRQ_I2OINPOST
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_TIMER1
+ movne \irqnr, #IRQ_TIMER1
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_TIMER2
+ movne \irqnr, #IRQ_TIMER2
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_TIMER3
+ movne \irqnr, #IRQ_TIMER3
+ bne 1001f
+
+ tst \irqstat, #IRQ_MASK_UART_TX
+ movne \irqnr, #IRQ_CONTX
+ bne 1001f
+
+ tst \irqstat, #irq_mask_pci_err_high
+ tsteq \irqstat, #irq_mask_pci_err_low
+ movne \irqnr, #IRQ_PCI_ERR
+ bne 1001f
+1001:
.endm
.macro irq_prio_table
@@ -227,15 +290,18 @@
.endm
#elif defined(CONFIG_ARCH_VNC)
+#include
.macro disable_fiq
.endm
.equ pci_iack_high, PCI_IACK & 0xff000000
.equ pci_iack_low, PCI_IACK & 0x00ff0000
+ .equ irq_mask_pci_err_high, IRQ_MASK_PCI_ERR & 0xff000000
+ .equ irq_mask_pci_err_low, IRQ_MASK_PCI_ERR & 0x00ff0000
.macro get_irqnr_and_base, irqnr, irqstat, base
- mov r4, #IO_BASE_ARM_CSR
+ mov r4, #ARMCSR_BASE
ldr \irqstat, [r4, #CSR_IRQ_STATUS] @ just show us the unmasked ones
@ run through hard priorities
@@ -269,7 +335,8 @@
b 1001f
1002: @ PCI errors
- tst \irqstat, #IRQ_MASK_PCI_ERR
+ tst \irqstat, #irq_mask_pci_err_high
+ tsteq \irqstat, #irq_mask_pci_err_low
movne \irqnr, #IRQ_PCI_ERR
bne 1001f
@@ -348,25 +415,6 @@
msr cpsr, \temp
.endm
- .macro initialise_traps_extra
- mrs r0, cpsr
- bic r0, r0, #31
- orr r0, r0, #0xd3
- msr cpsr, r0
- .endm
-
-
-#ifndef __ARM_ARCH_4__
-.Larm700bug: str lr, [r8]
- ldr r0, [sp, #S_PSR] @ Get calling cpsr
- msr spsr, r0
- ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
- mov r0, r0
- add sp, sp, #S_PC
- ldr lr, [sp], #S_FRAME_SIZE - S_PC @ Get PC and jump over PC, PSR, OLD_R0
- movs pc, lr
-#endif
-
.macro get_current_task, rd
mov \rd, sp, lsr #13
mov \rd, \rd, lsl #13
@@ -379,231 +427,89 @@
adr\cond \reg, \label
.endm
-/*=============================================================================
- * Address exception handler
- *-----------------------------------------------------------------------------
- * These aren't too critical.
- * (they're not supposed to happen, and won't happen in 32-bit mode).
- */
-
-vector_addrexcptn:
- b vector_addrexcptn
-
-/*=============================================================================
- * Undefined FIQs
- *-----------------------------------------------------------------------------
- * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
- * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg.
- * Basically to switch modes, we *HAVE* to clobber one register... brain
- * damage alert! I don't think that we can execute any code in here in any
- * other mode than FIQ... Ok you can switch to another mode, but you can't
- * get out of that mode without clobbering one register.
- */
-_unexp_fiq: disable_fiq
- subs pc, lr, #4
-
-/*=============================================================================
- * Interrupt entry dispatcher
- *-----------------------------------------------------------------------------
- * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
- */
-vector_IRQ: @
- @ save mode specific registers
- @
- ldr r13, .LCirq
- sub lr, lr, #4
- str lr, [r13] @ save lr_IRQ
- mrs lr, spsr
- str lr, [r13, #4] @ save spsr_IRQ
- @
- @ now branch to the relevent MODE handling routine
- @
- mrs sp, cpsr @ switch to SVC mode
- bic sp, sp, #31
- orr sp, sp, #0x13
- msr spsr, sp
- and lr, lr, #15
- cmp lr, #4
- addlts pc, pc, lr, lsl #2 @ Changes mode and branches
- b __irq_invalid @ 4 - 15
- b __irq_usr @ 0 (USR_26 / USR_32)
- b __irq_invalid @ 1 (FIQ_26 / FIQ_32)
- b __irq_invalid @ 2 (IRQ_26 / IRQ_32)
- b __irq_svc @ 3 (SVC_26 / SVC_32)
-/*
- *------------------------------------------------------------------------------------------------
- * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode
- *------------------------------------------------------------------------------------------------
- * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
- */
-.LCirq: .word __temp_irq
-.LCund: .word __temp_und
-.LCabt: .word __temp_abt
-
-vector_undefinstr:
- @
- @ save mode specific registers
- @
- ldr r13, [pc, #.LCund - . - 8]
- str lr, [r13]
- mrs lr, spsr
- str lr, [r13, #4]
- @
- @ now branch to the relevent MODE handling routine
- @
- mrs sp, cpsr
- bic sp, sp, #31
- orr sp, sp, #0x13
- msr spsr, sp
- and lr, lr, #15
- cmp lr, #4
- addlts pc, pc, lr, lsl #2 @ Changes mode and branches
- b __und_invalid @ 4 - 15
- b __und_usr @ 0 (USR_26 / USR_32)
- b __und_invalid @ 1 (FIQ_26 / FIQ_32)
- b __und_invalid @ 2 (IRQ_26 / IRQ_32)
- b __und_svc @ 3 (SVC_26 / SVC_32)
-/*
- *------------------------------------------------------------------------------------------------
- * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode
- *------------------------------------------------------------------------------------------------
- * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
- */
-vector_prefetch:
- @
- @ save mode specific registers
- @
- sub lr, lr, #4
- ldr r13, .LCabt
- str lr, [r13]
- mrs lr, spsr
- str lr, [r13, #4]
- @
- @ now branch to the relevent MODE handling routine
- @
- mrs sp, cpsr
- bic sp, sp, #31
- orr sp, sp, #0x13
- msr spsr, sp
- and lr, lr, #15
- adds pc, pc, lr, lsl #2 @ Changes mode and branches
- b __pabt_invalid @ 4 - 15
- b __pabt_usr @ 0 (USR_26 / USR_32)
- b __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
- b __pabt_invalid @ 2 (IRQ_26 / IRQ_32)
- b __pabt_invalid @ 3 (SVC_26 / SVC_32)
/*
- *------------------------------------------------------------------------------------------------
- * Data abort dispatcher - dispatches it to the correct handler for the processor mode
- *------------------------------------------------------------------------------------------------
- * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
+ * Invalid mode handlers
*/
-vector_data: @
- @ save mode specific registers
- @
- sub lr, lr, #8
- ldr r13, .LCabt
- str lr, [r13]
- mrs lr, spsr
- str lr, [r13, #4]
- @
- @ now branch to the relevent MODE handling routine
- @
- mrs sp, cpsr
- bic sp, sp, #31
- orr sp, sp, #0x13
- msr spsr, sp
- and lr, lr, #15
- cmp lr, #4
- addlts pc, pc, lr, lsl #2 @ Changes mode & branches
- b __dabt_invalid @ 4 - 15
- b __dabt_usr @ 0 (USR_26 / USR_32)
- b __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
- b __dabt_invalid @ 2 (IRQ_26 / IRQ_32)
- b __dabt_svc @ 3 (SVC_26 / SVC_32)
+__pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
+ stmia sp, {r0 - lr} @ Save XXX r0 - lr
+ ldr r4, .LCabt
+ mov r1, #BAD_PREFETCH
+ b 1f
-/*=============================================================================
- * Prefetch abort handler
- *-----------------------------------------------------------------------------
- */
-pabtmsg: .ascii "Pabt: %08lX\n\0"
- .align
-__pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
- stmia sp, {r0 - r12} @ Save r0 - r12
- add r8, sp, #S_PC
- stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr
+__dabt_invalid: sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact]
ldr r4, .LCabt
- ldmia r4, {r5 - r7} @ Get USR pc, cpsr
- stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
+ mov r1, #BAD_DATA
+ b 1f
- mrs r7, cpsr @ Enable interrupts if they were
- bic r7, r7, #I_BIT @ previously
- msr cpsr, r7
- mov r0, r5 @ address (pc)
- mov r1, sp @ regs
- bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler
- teq r0, #0 @ Does this still apply???
- bne ret_from_exception @ Return from exception
-#ifdef DEBUG_UNDEF
- adr r0, t
- bl SYMBOL_NAME(printk)
-#endif
- mov r0, r5
- mov r1, sp
- and r2, r6, #31
- bl SYMBOL_NAME(do_undefinstr)
- ldr lr, [sp, #S_PSR] @ Get USR cpsr
- msr spsr, lr
- ldmia sp, {r0 - pc}^ @ Restore USR registers
+__irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame
+ stmfd sp, {r0 - lr} @ Save r0 - lr
+ ldr r4, .LCirq
+ mov r1, #BAD_IRQ
+ b 1f
-__pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
- stmia sp, {r0 - lr} @ Save XXX r0 - lr
- mov r7, r0 @ OLD R0
- ldr r4, .LCabt
- ldmia r4, {r5 - r7} @ Get XXX pc, cpsr
+__und_invalid: sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - lr}
+ ldr r4, .LCund
+ mov r1, #BAD_UNDEFINSTR @ int reason
+
+1: mov fp, #0
+ ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0
add r4, sp, #S_PC
stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0
- mov r0, sp @ Prefetch aborts are definitely *not*
- mov r1, #BAD_PREFETCH @ allowed in non-user modes. We cant
- and r2, r6, #31 @ recover from this problem.
+ mov r0, sp
+ and r2, r6, #31 @ int mode
b SYMBOL_NAME(bad_mode)
-#ifdef DEBUG_UNDEF
-t: .ascii "*** undef ***\r\n\0"
- .align
-#endif
-/*=============================================================================
- * Data abort handler code
- *-----------------------------------------------------------------------------
- */
-.LCprocfns: .word SYMBOL_NAME(processor)
+wfs_mask_data: .word 0x0e200110 @ WFS/RFS
+ .word 0x0fef0fff
+ .word 0x0d0d0100 @ LDF [sp]/STF [sp]
+ .word 0x0d0b0100 @ LDF [fp]/STF [fp]
+ .word 0x0f0f0f00
-__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
- stmia sp, {r0 - r12} @ save r0 - r12
- add r3, sp, #S_PC
- stmdb r3, {sp, lr}^
- ldr r0, .LCabt
- ldmia r0, {r0 - r2} @ Get USR pc, cpsr
- stmia r3, {r0 - r2} @ Save USR pc, cpsr, old_r0
- mov fp, #0
- mrs r2, cpsr @ Enable interrupts if they were
- bic r2, r2, #I_BIT @ previously
- msr cpsr, r2
- ldr r2, .LCprocfns
- mov lr, pc
- ldr pc, [r2, #8] @ call processor specific code
- mov r3, sp
- bl SYMBOL_NAME(do_DataAbort)
- b ret_from_sys_call
+/* We get here if an undefined instruction happens and the floating
+ * point emulator is not present. If the offending instruction was
+ * a WFS, we just perform a normal return as if we had emulated the
+ * operation. This is a hack to allow some basic userland binaries
+ * to run so that the emulator module proper can be loaded. --philb
+ */
+fpe_not_present:
+ adr r10, wfs_mask_data
+ ldmia r10, {r4, r5, r6, r7, r8}
+ ldr r10, [sp, #S_PC] @ Load PC
+ sub r10, r10, #-4
+ mask_pc r10, r10
+ ldrt r10, [r10] @ get instruction
+ and r5, r10, r5
+ teq r5, r4 @ Is it WFS?
+ moveq pc, r9
+ and r5, r10, r8
+ teq r5, r6 @ Is it LDF/STF on sp or fp?
+ teqne r5, r7
+ movne pc, lr
+ tst r10, #0x00200000 @ Does it have WB
+ moveq pc, r9
+ and r4, r10, #255 @ get offset
+ and r6, r10, #0x000f0000
+ tst r10, #0x00800000 @ +/-
+ rsbeq r4, r4, #0
+ ldr r5, [sp, r6, lsr #14] @ Load reg
+ add r5, r5, r4, lsl #2
+ str r5, [sp, r6, lsr #14] @ Save reg
+ mov pc, r9
+/*
+ * SVC mode handlers
+ */
+ .align 5
__dabt_svc: sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ save r0 - r12
ldr r2, .LCabt
add r0, sp, #S_FRAME_SIZE
+ ldmia r2, {r2 - r4} @ get pc, cpsr
add r5, sp, #S_SP
mov r1, lr
- ldmia r2, {r2 - r4} @ get pc, cpsr
stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
tst r3, #I_BIT
mrseq r0, cpsr @ Enable interrupts if they were
@@ -619,29 +525,15 @@
msr spsr, r0
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
-__dabt_invalid: sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact]
- mov r7, r0
- ldr r4, .LCabt
- ldmia r4, {r5, r6} @ Get SVC pc, cpsr
- add r4, sp, #S_PC
- stmia r4, {r5, r6, r7} @ Save SVC pc, cpsr, old_r0
- mov r0, sp
- mov r1, #BAD_DATA
- and r2, r6, #31
- b SYMBOL_NAME(bad_mode)
-
-/*=============================================================================
- * Interrupt (IRQ) handler
- *-----------------------------------------------------------------------------
- */
-__irq_usr: sub sp, sp, #S_FRAME_SIZE
+ .align 5
+__irq_svc: sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ save r0 - r12
- add r8, sp, #S_PC
- stmdb r8, {sp, lr}^
- ldr r4, .LCirq
- ldmia r4, {r5 - r7} @ get saved PC, SPSR
- stmia r8, {r5 - r7} @ save pc, psr, old_r0
+ ldr r7, .LCirq
+ add r5, sp, #S_FRAME_SIZE
+ ldmia r7, {r7 - r9}
+ add r4, sp, #S_SP
+ mov r6, lr
+ stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
1: get_irqnr_and_base r0, r6, r5
movne r1, sp
@
@@ -649,48 +541,97 @@
@
adrsvc ne, lr, 1b
bne do_IRQ
- b ret_with_reschedule
-
- irq_prio_table
+ ldr r0, [sp, #S_PSR]
+ msr spsr, r0
+ ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
-__irq_svc: sub sp, sp, #S_FRAME_SIZE
+ .align 5
+__und_svc: sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ save r0 - r12
mov r6, lr
- ldr r7, .LCirq
+ ldr r7, .LCund
ldmia r7, {r7 - r9}
add r5, sp, #S_FRAME_SIZE
add r4, sp, #S_SP
- stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
+ stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
+
+ adrsvc al, r9, 1f @ r9 = normal FP return
+ bl call_fpe @ lr = undefined instr return
+
+ mov r0, r5 @ unsigned long pc
+ mov r1, sp @ struct pt_regs *regs
+ bl SYMBOL_NAME(do_undefinstr)
+
+1: ldr lr, [sp, #S_PSR] @ Get SVC cpsr
+ msr spsr, lr
+ ldmia sp, {r0 - pc}^ @ Restore SVC registers
+
+ .align 5
+.LCirq: .word __temp_irq
+.LCund: .word __temp_und
+.LCabt: .word __temp_abt
+.LCprocfns: .word SYMBOL_NAME(processor)
+.LCfp: .word SYMBOL_NAME(fp_enter)
+
+ irq_prio_table
+
+/*
+ * User mode handlers
+ */
+#ifdef DEBUG_UNDEF
+t: .ascii "Prefetch -> undefined instruction\n\0"
+ .align
+#endif
+ .align 5
+__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
+ stmia sp, {r0 - r12} @ save r0 - r12
+ add r3, sp, #S_PC
+ stmdb r3, {sp, lr}^
+ ldr r4, .LCabt
+ ldmia r4, {r0 - r2} @ Get USR pc, cpsr
+ stmia r3, {r0 - r2} @ Save USR pc, cpsr, old_r0
+
+#ifdef CONFIG_ALIGNMENT_TRAP
+ ldr r7, [r4, #OFF_CR_ALIGNMENT(__temp_abt)]
+ mcr p15, 0, r7, c1, c0
+#endif
+
+ mov fp, #0
+ mrs r2, cpsr @ Enable interrupts if they were
+ bic r2, r2, #I_BIT @ previously
+ msr cpsr, r2
+ ldr r2, .LCprocfns
+ mov lr, pc
+ ldr pc, [r2, #8] @ call processor specific code
+ mov r3, sp
+ adrsvc al, lr, ret_from_sys_call
+ b SYMBOL_NAME(do_DataAbort)
+
+ .align 5
+__irq_usr: sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - r12} @ save r0 - r12
+ add r8, sp, #S_PC
+ stmdb r8, {sp, lr}^
+ ldr r4, .LCirq
+ ldmia r4, {r5 - r7} @ get saved PC, SPSR
+ stmia r8, {r5 - r7} @ save pc, psr, old_r0
+
+#ifdef CONFIG_ALIGNMENT_TRAP
+ ldr r7, [r4, #OFF_CR_ALIGNMENT(__temp_irq)]
+ mcr p15, 0, r7, c1, c0
+#endif
+
1: get_irqnr_and_base r0, r6, r5
movne r1, sp
+ adrsvc ne, lr, 1b
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
- adrsvc ne, lr, 1b
bne do_IRQ
- ldr r0, [sp, #S_PSR]
- msr spsr, r0
- ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
-
-__irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame
- stmfd sp, {r0 - lr} @ Save r0 - lr
- mov r7, #-1
- ldr r4, .LCirq
- ldmia r4, {r5, r6} @ get saved pc, psr
- add r4, sp, #S_PC
- stmia r4, {r5, r6, r7}
- mov fp, #0
- mov r0, sp
- mov r1, #BAD_IRQ
- b SYMBOL_NAME(bad_mode)
-
-/*=============================================================================
- * Undefined instruction handler
- *-----------------------------------------------------------------------------
- * Handles floating point instructions
- */
-.LC2: .word SYMBOL_NAME(fp_enter)
+ mov r4, #0
+ b ret_with_reschedule
+ .align 5
__und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia sp, {r0 - r12} @ Save r0 - r12
add r8, sp, #S_PC
@@ -698,99 +639,311 @@
ldr r4, .LCund
ldmia r4, {r5 - r7}
stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
+
+#ifdef CONFIG_ALIGNMENT_TRAP
+ ldr r7, [r4, #OFF_CR_ALIGNMENT(__temp_und)]
+ mcr p15, 0, r7, c1, c0
+#endif
+
mov fp, #0
- adrsvc al, r9, ret_from_exception @ r9 = normal FP return
+ adrsvc al, r9, ret_from_sys_call @ r9 = normal FP return
adrsvc al, lr, fpundefinstr @ lr = undefined instr return
-1: get_current_task r10
+call_fpe: get_current_task r10
mov r8, #1
strb r8, [r10, #TSK_USED_MATH] @ set current->used_math
add r10, r10, #TSS_FPESAVE @ r10 = workspace
- ldr r4, .LC2
+ ldr r4, .LCfp
ldr pc, [r4] @ Call FP module USR entry point
-__und_svc: sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - r12} @ save r0 - r12
- mov r6, lr
- ldr r7, .LCund
- ldmia r7, {r7 - r9}
- add r5, sp, #S_FRAME_SIZE
- add r4, sp, #S_SP
- stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
-
- adrsvc al, r9, 3f @ r9 = normal FP return
- bl 1b @ lr = undefined instr return
-
- mov r0, r5 @ unsigned long pc
- mov r1, sp @ struct pt_regs *regs
- bl SYMBOL_NAME(do_undefinstr)
-
-3: ldr lr, [sp, #S_PSR] @ Get SVC cpsr
- msr spsr, lr
- ldmia sp, {r0 - pc}^ @ Restore SVC registers
-
fpundefinstr: mov r0, lr
mov r1, sp
mrs r4, cpsr @ Enable interrupts
bic r4, r4, #I_BIT
msr cpsr, r4
- adrsvc al, lr, ret_from_exception
+ adrsvc al, lr, ret_from_sys_call
b SYMBOL_NAME(do_undefinstr)
-__und_invalid: sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - lr}
- mov r7, r0
- ldr r4, .LCund
- ldmia r4, {r5, r6} @ Get UND/IRQ/FIQ/ABT pc, cpsr
- add r4, sp, #S_PC
- stmia r4, {r5, r6, r7} @ Save UND/IRQ/FIQ/ABT pc, cpsr, old_r0
- mov r0, sp @ struct pt_regs *regs
- mov r1, #BAD_UNDEFINSTR @ int reason
- and r2, r6, #31 @ int mode
- b SYMBOL_NAME(bad_mode) @ Does not ever return...
+ .align 5
+__pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
+ stmia sp, {r0 - r12} @ Save r0 - r12
+ add r8, sp, #S_PC
+ stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr
+ ldr r4, .LCabt
+ ldmia r4, {r5 - r7} @ Get USR pc, cpsr
+ stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
-/* We get here if an undefined instruction happens and the floating
- * point emulator is not present. If the offending instruction was
- * a WFS, we just perform a normal return as if we had emulated the
- * operation. This is a hack to allow some basic userland binaries
- * to run so that the emulator module proper can be loaded. --philb
- */
-fpe_not_present:
- adr r10, wfs_mask_data
- ldmia r10, {r4, r5, r6, r7, r8}
- ldr r10, [sp, #S_PC] @ Load PC
- sub r10, r10, #4
- mask_pc r10, r10
- ldrt r10, [r10] @ get instruction
- and r5, r10, r5
- teq r5, r4 @ Is it WFS?
- moveq pc, r9
- and r5, r10, r8
- teq r5, r6 @ Is it LDF/STF on sp or fp?
- teqne r5, r7
- movne pc, lr
- tst r10, #0x00200000 @ Does it have WB
- moveq pc, r9
- and r4, r10, #255 @ get offset
- and r6, r10, #0x000f0000
- tst r10, #0x00800000 @ +/-
- rsbeq r4, r4, #0
- ldr r5, [sp, r6, lsr #14] @ Load reg
- add r5, r5, r4, lsl #2
- str r5, [sp, r6, lsr #14] @ Save reg
- mov pc, r9
+#ifdef CONFIG_ALIGNMENT_TRAP
+ ldr r7, [r4, #OFF_CR_ALIGNMENT(__temp_abt)]
+ mcr p15, 0, r7, c1, c0
+#endif
-wfs_mask_data: .word 0x0e200110 @ WFS
- .word 0x0fff0fff
- .word 0x0d0d0100 @ LDF [sp]/STF [sp]
- .word 0x0d0b0100 @ LDF [fp]/STF [fp]
- .word 0x0f0f0f00
+ mrs r7, cpsr @ Enable interrupts if they were
+ bic r7, r7, #I_BIT @ previously
+ msr cpsr, r7
+ mov r0, r5 @ address (pc)
+ mov r1, sp @ regs
+ bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler
+ teq r0, #0 @ Does this still apply???
+ bne ret_from_sys_call @ Return from exception
+#ifdef DEBUG_UNDEF
+ adr r0, t
+ bl SYMBOL_NAME(printk)
+#endif
+ mov r0, r5
+ mov r1, sp
+ and r2, r6, #31
+ bl SYMBOL_NAME(do_undefinstr)
+ ldr lr, [sp, #S_PSR] @ Get USR cpsr
+ msr spsr, lr
+ ldmia sp, {r0 - pc}^ @ Restore USR registers
#include "entry-common.S"
+ .text
+
+#ifndef __ARM_ARCH_4__
+.Larm700bug: str lr, [r8]
+ ldr r0, [sp, #S_PSR] @ Get calling cpsr
+ msr spsr, r0
+ ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
+ mov r0, r0
+ add sp, sp, #S_PC
+ ldr lr, [sp], #S_FRAME_SIZE - S_PC @ Get PC and jump over PC, PSR, OLD_R0
+ movs pc, lr
+#endif
+
+ .section ".text.init",#alloc,#execinstr
+/*
+ * Vector stubs. NOTE that we only align 'vector_IRQ' to a cache line boundary,
+ * and we rely on each stub being exactly 48 (1.5 cache lines) in size. This
+ * means that we only ever load two cache lines for this code, or one if we're
+ * lucky. We also copy this code to 0x200 so that we can use branches in the
+ * vectors, rather than ldr's.
+ */
+ .align 5
+__stubs_start:
+/*
+ * Interrupt dispatcher
+ * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
+ */
+vector_IRQ: @
+ @ save mode specific registers
+ @
+ ldr r13, .LCsirq
+ sub lr, lr, #4
+ str lr, [r13] @ save lr_IRQ
+ mrs lr, spsr
+ str lr, [r13, #4] @ save spsr_IRQ
+ @
+ @ now branch to the relevent MODE handling routine
+ @
+ bic r13, lr, #63
+ orr r13, r13, #0x93
+ msr spsr, r13 @ switch to SVC_32 mode
+
+ and lr, lr, #15
+ adr r13, .LCtab_irq
+ ldr lr, [r13, lr, lsl #2]
+ movs pc, lr @ Changes mode and branches
+/*
+ * Data abort dispatcher - dispatches it to the correct handler for the processor mode
+ * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
+ */
+vector_data: @
+ @ save mode specific registers
+ @
+ sub lr, lr, #8
+ ldr r13, .LCsabt
+ str lr, [r13]
+ mrs lr, spsr
+ str lr, [r13, #4]
+ @
+ @ now branch to the relevent MODE handling routine
+ @
+ bic r13, lr, #63
+ orr r13, r13, #0x93
+ msr spsr, r13 @ switch to SVC_32 mode
+
+ and lr, lr, #15
+ adr r13, .LCtab_dabt
+ ldr lr, [r13, lr, lsl #2]
+ movs pc, lr @ Changes mode and branches
+
+/*
+ * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode
+ * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
+ */
+vector_prefetch:
+ @
+ @ save mode specific registers
+ @
+ sub lr, lr, #4
+ ldr r13, .LCsabt
+ str lr, [r13] @ save lr_ABT
+ mrs lr, spsr
+ str lr, [r13, #4] @ save spsr_ABT
+ @
+ @ now branch to the relevent MODE handling routine
+ @
+ bic r13, lr, #63
+ orr r13, r13, #0x93
+ msr spsr, r13 @ switch to SVC_32 mode
+
+ ands lr, lr, #15
+ ldreq lr, .LCtab_pabt
+ ldrne lr, .LCtab_pabt + 4
+ movs pc, lr
+
+/*
+ * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode
+ * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
+ */
+vector_undefinstr:
+ @
+ @ save mode specific registers
+ @
+ ldr r13, .LCsund
+ str lr, [r13] @ save lr_UND
+ mrs lr, spsr
+ str lr, [r13, #4] @ save spsr_UND
+ @
+ @ now branch to the relevent MODE handling routine
+ @
+ bic r13, lr, #63
+ orr r13, r13, #0x93
+ msr spsr, r13 @ switch to SVC_32 mode
+
+ and lr, lr, #15
+ adr r13, .LCtab_und
+ ldr lr, [r13, lr, lsl #2]
+ movs pc, lr @ Changes mode and branches
+
+/*=============================================================================
+ * Undefined FIQs
+ *-----------------------------------------------------------------------------
+ * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
+ * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg.
+ * Basically to switch modes, we *HAVE* to clobber one register... brain
+ * damage alert! I don't think that we can execute any code in here in any
+ * other mode than FIQ... Ok you can switch to another mode, but you can't
+ * get out of that mode without clobbering one register.
+ */
+vector_FIQ: disable_fiq
+ subs pc, lr, #4
+
+/*=============================================================================
+ * Address exception handler
+ *-----------------------------------------------------------------------------
+ * These aren't too critical.
+ * (they're not supposed to happen, and won't happen in 32-bit data mode).
+ */
+
+vector_addrexcptn:
+ b vector_addrexcptn
+
+/*
+ * We group all the following data together to optimise
+ * for CPUs with separate I & D caches.
+ */
+ .align 5
+
+.LCtab_irq: .word __irq_usr @ 0 (USR_26 / USR_32)
+ .word __irq_invalid @ 1 (FIQ_26 / FIQ_32)
+ .word __irq_invalid @ 2 (IRQ_26 / IRQ_32)
+ .word __irq_svc @ 3 (SVC_26 / SVC_32)
+ .word __irq_invalid @ 4
+ .word __irq_invalid @ 5
+ .word __irq_invalid @ 6
+ .word __irq_invalid @ 7
+ .word __irq_invalid @ 8
+ .word __irq_invalid @ 9
+ .word __irq_invalid @ a
+ .word __irq_invalid @ b
+ .word __irq_invalid @ c
+ .word __irq_invalid @ d
+ .word __irq_invalid @ e
+ .word __irq_invalid @ f
+
+.LCtab_und: .word __und_usr @ 0 (USR_26 / USR_32)
+ .word __und_invalid @ 1 (FIQ_26 / FIQ_32)
+ .word __und_invalid @ 2 (IRQ_26 / IRQ_32)
+ .word __und_svc @ 3 (SVC_26 / SVC_32)
+ .word __und_invalid @ 4
+ .word __und_invalid @ 5
+ .word __und_invalid @ 6
+ .word __und_invalid @ 7
+ .word __und_invalid @ 8
+ .word __und_invalid @ 9
+ .word __und_invalid @ a
+ .word __und_invalid @ b
+ .word __und_invalid @ c
+ .word __und_invalid @ d
+ .word __und_invalid @ e
+ .word __und_invalid @ f
+
+.LCtab_dabt: .word __dabt_usr @ 0 (USR_26 / USR_32)
+ .word __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
+ .word __dabt_invalid @ 2 (IRQ_26 / IRQ_32)
+ .word __dabt_svc @ 3 (SVC_26 / SVC_32)
+ .word __dabt_invalid @ 4
+ .word __dabt_invalid @ 5
+ .word __dabt_invalid @ 6
+ .word __dabt_invalid @ 7
+ .word __dabt_invalid @ 8
+ .word __dabt_invalid @ 9
+ .word __dabt_invalid @ a
+ .word __dabt_invalid @ b
+ .word __dabt_invalid @ c
+ .word __dabt_invalid @ d
+ .word __dabt_invalid @ e
+ .word __dabt_invalid @ f
+
+.LCtab_pabt: .word __pabt_usr
+ .word __pabt_invalid
+
+.LCvswi: .word vector_swi
+
+.LCsirq: .word __temp_irq
+.LCsund: .word __temp_und
+.LCsabt: .word __temp_abt
+
+__stubs_end:
+
+ .equ __real_stubs_start, .LCvectors + 0x200
+
+.LCvectors: swi SYS_ERROR0
+ b __real_stubs_start + (vector_undefinstr - __stubs_start)
+ ldr pc, __real_stubs_start + (.LCvswi - __stubs_start)
+ b __real_stubs_start + (vector_prefetch - __stubs_start)
+ b __real_stubs_start + (vector_data - __stubs_start)
+ b __real_stubs_start + (vector_addrexcptn - __stubs_start)
+ b __real_stubs_start + (vector_IRQ - __stubs_start)
+ b __real_stubs_start + (vector_FIQ - __stubs_start)
+
+ENTRY(trap_init)
+ stmfd sp!, {r4 - r6, lr}
+ adr r0, __stubs_start @ copy stubs to 0x200
+ adr r1, __stubs_end
+ mov r2, #0x200
+1: ldr r3, [r0], #4
+ str r3, [r2], #4
+ cmp r0, r1
+ blt 1b
+
+ adr r1, .LCvectors @ set up the vectors
+ mov r0, #0
+ ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr}
+ stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr}
+ LOADREGS(fd, sp!, {r4 - r6, pc})
+
.data
+/*
+ * Do not reorder these, and do not insert extra data between...
+ */
+
__temp_irq: .word 0 @ saved lr_irq
.word 0 @ saved spsr_irq
.word -1 @ old_r0
@@ -800,3 +953,10 @@
__temp_abt: .word 0 @ Saved lr_abt
.word 0 @ Saved spsr_abt
.word -1 @ old_r0
+
+ .globl SYMBOL_NAME(cr_alignment)
+ .globl SYMBOL_NAME(cr_no_alignment)
+SYMBOL_NAME(cr_alignment):
+ .space 4
+SYMBOL_NAME(cr_no_alignment):
+ .space 4
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/entry-common.S linux.ac/arch/arm/kernel/entry-common.S
--- linux.vanilla/arch/arm/kernel/entry-common.S Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/entry-common.S Sun Jan 24 21:11:31 1999
@@ -1,51 +1,55 @@
+#include
+
/*============================================================================
* All exits to user mode from the kernel go through this code.
*/
-
-#include
-
.globl ret_from_sys_call
-ret_from_exception:
- adr r0, 1f
- ldmia r0, {r0, r1}
+ .align 5
+fast_syscall_return:
+ str r0, [sp, #S_R0 + 4] @ returned r0
+slow_syscall_return:
+ add sp, sp, #4
+ret_from_sys_call:
+ adr r0, bh_data
+ ldmia r0, {r0, r4}
ldr r0, [r0]
- ldr r1, [r1]
+ ldr r1, [r4]
tst r0, r1
blne SYMBOL_NAME(do_bottom_half)
-ret_from_intr: ldr r0, [sp, #S_PSR]
- tst r0, #3
- beq ret_with_reschedule
- b ret_from_all
+ret_with_reschedule:
+ get_current_task r1 @ check for scheduling
+ ldr r0, [r1, #TSK_NEED_RESCHED]
+ teq r0, #0
+ bne ret_reschedule
+ ldr r1, [r1, #TSK_SIGPENDING]
+ teq r1, #0 @ check for signals
+ bne ret_signal
+
+ret_from_all: restore_user_regs
ret_signal: mov r1, sp
adrsvc al, lr, ret_from_all
+ mov r2, r4
b SYMBOL_NAME(do_signal)
-2: bl SYMBOL_NAME(schedule)
+ret_reschedule: adrsvc al, lr, ret_with_reschedule
+ b SYMBOL_NAME(schedule)
-ret_from_sys_call:
- adr r0, 1f
+ret_from_exception:
+ adr r0, bh_data
ldmia r0, {r0, r1}
ldr r0, [r0]
ldr r1, [r1]
tst r0, r1
- adrsvc ne, lr, ret_from_intr
- bne SYMBOL_NAME(do_bottom_half)
-
-ret_with_reschedule:
- get_current_task r1
- ldr r0, [r1, #TSK_NEED_RESCHED]
- teq r0, #0
- bne 2b
- ldr r1, [r1, #TSK_SIGPENDING]
- teq r1, #0
- bne ret_signal
-
-ret_from_all: restore_user_regs
+ mov r4, #0
+ blne SYMBOL_NAME(do_bottom_half)
+ ldr r0, [sp, #S_PSR]
+ tst r0, #3 @ returning to user mode?
+ beq ret_with_reschedule
+ b ret_from_all
-1: .word SYMBOL_NAME(bh_mask)
- .word SYMBOL_NAME(bh_active)
+#include "calls.S"
/*=============================================================================
* SWI handler
@@ -57,140 +61,67 @@
* too worried.
*/
-#include "calls.S"
-
+ .align 5
vector_swi: save_user_regs
- mov fp, #0
mask_pc lr, lr
- ldr r6, [lr, #-4]! @ get SWI instruction
+ mov fp, #0
+ ldr r6, [lr, #-4] @ get SWI instruction
arm700_bug_check r6, r7
enable_irqs r7
-
+
+ str r4, [sp, #-4]! @ new style: (r0 = arg1, r4 = arg5)
+ adrsvc al, lr, fast_syscall_return
+
bic r6, r6, #0xff000000 @ mask off SWI op-code
eor r6, r6, #OS_NUMBER<<20 @ check OS number
cmp r6, #NR_syscalls @ check upper syscall limit
bcs 2f
- get_current_task r5
- ldr ip, [r5, #TSK_FLAGS] @ check for syscall tracing
- tst ip, #PF_TRACESYS
- bne 1f
+ adr r5, SYMBOL_NAME(sys_call_table)
- adr ip, SYMBOL_NAME(sys_call_table)
- str r4, [sp, #-4]! @ new style: (r0 = arg1, r5 = arg5)
- mov lr, pc
- ldr pc, [ip, r6, lsl #2] @ call sys routine
- add sp, sp, #4
- str r0, [sp, #S_R0] @ returned r0
- b ret_from_sys_call
+ get_current_task r7
+ ldr ip, [r7, #TSK_FLAGS] @ check for syscall tracing
+ tst ip, #PF_TRACESYS
+ ldreq pc, [r5, r6, lsl #2] @ call sys routine
-1: ldr r7, [sp, #S_IP] @ save old IP
+ ldr r7, [sp, #S_IP + 4] @ save old IP
mov r0, #0
- str r0, [sp, #S_IP] @ trace entry [IP = 0]
+ str r0, [sp, #S_IP + 4] @ trace entry [IP = 0]
bl SYMBOL_NAME(syscall_trace)
- str r7, [sp, #S_IP]
- ldmia sp, {r0 - r3} @ have to reload r0 - r3
- adr ip, SYMBOL_NAME(sys_call_table)
- str r4, [sp, #-4]! @ new style: (r0 = arg1, r5 = arg5)
+ str r7, [sp, #S_IP + 4]
+
+ ldmib sp, {r0 - r3} @ have to reload r0 - r3
mov lr, pc
- ldr pc, [ip, r6, lsl #2] @ call sys routine
- add sp, sp, #4
- str r0, [sp, #S_R0] @ returned r0
+ ldr pc, [r5, r6, lsl #2] @ call sys routine
+ str r0, [sp, #S_R0 + 4] @ returned r0
+
mov r0, #1
- str r0, [sp, #S_IP] @ trace exit [IP = 1]
+ str r0, [sp, #S_IP + 4] @ trace exit [IP = 1]
bl SYMBOL_NAME(syscall_trace)
- str r7, [sp, #S_IP]
- b ret_from_sys_call
+ str r7, [sp, #S_IP + 4]
+ b slow_syscall_return
-2: tst r6, #0x00f00000 @ is it a Unix SWI?
+2: add r1, sp, #4
+ tst r6, #0x00f00000 @ is it a Unix SWI?
bne 3f
- cmp r6, #(KSWI_SYS_BASE - KSWI_BASE)
- bcc 4f @ not private func
- bic r0, r6, #0x000f0000
- mov r1, sp
- bl SYMBOL_NAME(arm_syscall)
- b ret_from_sys_call
-
-3: eor r0, r6, #OS_NUMBER<<20 @ Put OS number back
- mov r1, sp
- bl SYMBOL_NAME(deferred)
- ldmfd sp, {r0 - r3}
- b ret_from_sys_call
-
-4: bl SYMBOL_NAME(sys_ni_syscall)
- str r0, [sp, #0] @ returned r0
- b ret_from_sys_call
+ subs r0, r6, #(KSWI_SYS_BASE - KSWI_BASE)
+ bcs SYMBOL_NAME(arm_syscall)
+ b SYMBOL_NAME(sys_ni_syscall) @ not private func
+
+3: add sp, sp, #4
+ eor r0, r6, #OS_NUMBER <<20 @ Put OS number back
+ adrsvc al, lr, slow_syscall_return
+ b SYMBOL_NAME(deferred)
-@ r0 = syscall number
-@ r1 = syscall r0
-@ r5 = syscall r4
-@ ip = syscall table
-SYMBOL_NAME(sys_syscall):
- mov r6, r0
- eor r6, r6, #OS_NUMBER << 20
- cmp r6, #NR_syscalls @ check range
- movgt r0, #-ENOSYS
- movgt pc, lr
- add sp, sp, #4 @ take of the save of our r4
- ldmib sp, {r0 - r4} @ get our args
- str r4, [sp, #-4]! @ Put our arg on the stack
- ldr pc, [ip, r6, lsl #2]
+ .align 5
+
+bh_data: .word SYMBOL_NAME(bh_mask)
+ .word SYMBOL_NAME(bh_active)
ENTRY(sys_call_table)
#include "calls.S"
-/*============================================================================
- * Special system call wrappers
- */
-sys_fork_wrapper:
- add r0, sp, #4
- b SYMBOL_NAME(sys_fork)
-
-sys_execve_wrapper:
- add r3, sp, #4
- b SYMBOL_NAME(sys_execve)
-
-sys_mount_wrapper:
- mov r6, lr
- add r5, sp, #4
- str r5, [sp]
- str r4, [sp, #-4]!
- bl SYMBOL_NAME(sys_compat_mount)
- add sp, sp, #4
- RETINSTR(mov,pc,r6)
-
-sys_clone_wapper:
- add r2, sp, #4
- b SYMBOL_NAME(sys_clone)
-
-sys_llseek_wrapper:
- mov r6, lr
- add r5, sp, #4
- str r5, [sp]
- str r4, [sp, #-4]!
- bl SYMBOL_NAME(sys_compat_llseek)
- add sp, sp, #4
- RETINSTR(mov,pc,r6)
-
-sys_sigsuspend_wrapper:
- add r3, sp, #4
- b SYMBOL_NAME(sys_sigsuspend)
-
-sys_rt_sigsuspend_wrapper:
- add r2, sp, #4
- b SYMBOL_NAME(sys_rt_sigsuspend)
-
-sys_sigreturn_wrapper:
- add r0, sp, #4
- b SYMBOL_NAME(sys_sigreturn)
-
-sys_rt_sigreturn_wrapper:
- add r0, sp, #4
- b SYMBOL_NAME(sys_rt_sigreturn)
-
-sys_sigaltstack_wrapper:
- ldr r2, [sp, #4 + S_SP]
- b do_sigaltstack
+#if defined(CONFIG_CPU_26)
/*
*=============================================================================
@@ -211,45 +142,6 @@
.section ".text.init",#alloc,#execinstr
-#if defined(CONFIG_CPU_32)
-/*
- * these go into 0x00
- */
-.Lbranches: swi SYS_ERROR0
- ldr pc, .Lbranches + 0xe4
- ldr pc, .Lbranches + 0xe8
- ldr pc, .Lbranches + 0xec
- ldr pc, .Lbranches + 0xf0
- ldr pc, .Lbranches + 0xf4
- ldr pc, .Lbranches + 0xf8
- ldr pc, .Lbranches + 0xfc
-/*
- * this is put into 0xe4 and above
- */
-.Ljump_addresses:
- .word vector_undefinstr @ 0xe4
- .word vector_swi @ 0xe8
- .word vector_prefetch @ 0xec
- .word vector_data @ 0xf0
- .word vector_addrexcptn @ 0xf4
- .word vector_IRQ @ 0xf8
- .word _unexp_fiq @ 0xfc
-/*
- * initialise the trap system
- */
-ENTRY(trap_init)
- stmfd sp!, {r4 - r7, lr}
- initialise_traps_extra
- mov r0, #0xe4
- adr r1, .Ljump_addresses
- ldmia r1, {r1 - r7}
- stmia r0, {r1 - r7}
- mov r0, #0
- adr r1, .Lbranches
- ldmia r1, {r1 - r7}
- stmia r0, {r1 - r7}
- LOADREGS(fd, sp!, {r4 - r7, pc})
-#elif defined(CONFIG_CPU_26)
.Ljump_addresses:
swi SYS_ERROR0
.word vector_undefinstr - 12
@@ -279,11 +171,75 @@
ldmfd sp!, {r4 - r7, pc}^
#endif
- .previous
+ .text
/*============================================================================
- * FP support
+ * Special system call wrappers
*/
+@ r0 = syscall number
+@ r5 = syscall table
+SYMBOL_NAME(sys_syscall):
+ eor r6, r0, #OS_NUMBER << 20
+ cmp r6, #NR_syscalls @ check range
+ ldmleib sp, {r0 - r4} @ get our args
+ strle r4, [sp] @ Put our arg on the stack
+ ldrle pc, [r5, r6, lsl #2]
+ mov r0, #-ENOSYS
+ mov pc, lr
+
+sys_fork_wrapper:
+ add r0, sp, #4
+ b SYMBOL_NAME(sys_fork)
+
+sys_vfork_wrapper:
+ add r0, sp, #4
+ b SYMBOL_NAME(sys_vfork)
+
+sys_execve_wrapper:
+ add r3, sp, #4
+ b SYMBOL_NAME(sys_execve)
+
+sys_mount_wrapper:
+ mov r6, lr
+ add r5, sp, #4
+ str r5, [sp]
+ str r4, [sp, #-4]!
+ bl SYMBOL_NAME(sys_compat_mount)
+ add sp, sp, #4
+ RETINSTR(mov,pc,r6)
+
+sys_clone_wapper:
+ add r2, sp, #4
+ b SYMBOL_NAME(sys_clone)
+
+sys_llseek_wrapper:
+ mov r6, lr
+ add r5, sp, #4
+ str r5, [sp]
+ str r4, [sp, #-4]!
+ bl SYMBOL_NAME(sys_compat_llseek)
+ add sp, sp, #4
+ RETINSTR(mov,pc,r6)
+
+sys_sigsuspend_wrapper:
+ add r3, sp, #4
+ b SYMBOL_NAME(sys_sigsuspend)
+
+sys_rt_sigsuspend_wrapper:
+ add r2, sp, #4
+ b SYMBOL_NAME(sys_rt_sigsuspend)
+
+sys_sigreturn_wrapper:
+ add r0, sp, #4
+ b SYMBOL_NAME(sys_sigreturn)
+
+sys_rt_sigreturn_wrapper:
+ add r0, sp, #4
+ b SYMBOL_NAME(sys_rt_sigreturn)
+
+sys_sigaltstack_wrapper:
+ ldr r2, [sp, #4 + S_SP]
+ b do_sigaltstack
.data
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/fiq.c linux.ac/arch/arm/kernel/fiq.c
--- linux.vanilla/arch/arm/kernel/fiq.c Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/fiq.c Sun Jan 24 21:11:31 1999
@@ -113,21 +113,68 @@
void set_fiq_regs(struct pt_regs *regs)
{
- /* not yet -
- * this is temporary to get the floppy working
- * again on RiscPC. It *will* become more
- * generic.
- */
-#ifdef CONFIG_ARCH_ACORN
- extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
- unsigned long port);
- floppy_fiqsetup(regs->ARM_r9, regs->ARM_r10, regs->ARM_fp);
+ register unsigned long tmp, tmp2;
+ __asm__ volatile (
+#ifdef CONFIG_CPU_26
+ "mov %0, pc
+ bic %1, %0, #0x0c000003
+ orr %1, %1, #1
+ teqp %1, #0 @ select FIQ mode
+ mov r0, r0
+ ldmia %2, {r8 - r14}
+ teqp %0, #0 @ return to SVC mode
+ mov r0, r0"
#endif
+#ifdef CONFIG_CPU_32
+ "mrs %0, cpsr
+ bic %1, %0, #0xf
+ orr %1, %1, #1
+ msr cpsr, %1 @ select FIQ mode
+ mov r0, r0
+ ldmia %2, {r8 - r14}
+ msr cpsr, %0 @ return to SVC mode
+ mov r0, r0"
+#endif
+ : "=r" (tmp), "=r" (tmp2)
+ : "r" (®s->ARM_r8)
+ /* These registers aren't modified by the above code in a way
+ visible to the compiler, but we mark them as clobbers anyway
+ so that GCC won't put any of the input or output operands in
+ them. */
+ : "r8", "r9", "r10", "r11", "r12", "r13", "r14");
}
void get_fiq_regs(struct pt_regs *regs)
{
- /* not yet */
+ register unsigned long tmp, tmp2;
+ __asm__ volatile (
+#ifdef CONFIG_CPU_26
+ "mov %0, pc
+ bic %1, %0, #0x0c000003
+ orr %1, %1, #1
+ teqp %1, #0 @ select FIQ mode
+ mov r0, r0
+ stmia %2, {r8 - r14}
+ teqp %0, #0 @ return to SVC mode
+ mov r0, r0"
+#endif
+#ifdef CONFIG_CPU_32
+ "mrs %0, cpsr
+ bic %1, %0, #0xf
+ orr %1, %1, #1
+ msr cpsr, %1 @ select FIQ mode
+ mov r0, r0
+ stmia %2, {r8 - r14}
+ msr cpsr, %0 @ return to SVC mode
+ mov r0, r0"
+#endif
+ : "=r" (tmp), "=r" (tmp2)
+ : "r" (®s->ARM_r8)
+ /* These registers aren't modified by the above code in a way
+ visible to the compiler, but we mark them as clobbers anyway
+ so that GCC won't put any of the input or output operands in
+ them. */
+ : "r8", "r9", "r10", "r11", "r12", "r13", "r14");
}
int claim_fiq(struct fiq_handler *f)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/head-armv.S linux.ac/arch/arm/kernel/head-armv.S
--- linux.vanilla/arch/arm/kernel/head-armv.S Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/head-armv.S Sun Jan 24 21:11:31 1999
@@ -8,12 +8,20 @@
#include
#include
-#ifndef CONFIG_ARCH_VNC
+#define DEBUG
+
+ .globl SYMBOL_NAME(swapper_pg_dir)
+ .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000
+
+ .section ".text.init",#alloc,#execinstr
+ENTRY(stext)
+ENTRY(_stext)
+
#if (TEXTADDR & 0xffff) != 0x8000
#error TEXTADDR must start at 0xXXXX8000
#endif
-#else
- .text
+
+#if defined(CONFIG_ARCH_VNC) || defined(CONFIG_ARCH_NETWINDER)
mov r0, r0
mov r0, r0
mov r0, r0
@@ -22,16 +30,34 @@
mov r0, r0
mov r0, r0
mov r0, r0
+
+ adr r2, 1f
+ ldmdb r2, {r7, r8}
+ and r3, r2, #0x0000c000
+ teq r3, #0x00008000
+ beq __entry
+ bic r3, r2, #0xc000
+ orr r3, r3, #0x8000
+ mov r0, r3
+ mov r4, #32
+ sub r5, r8, r7
+ b 1f
+
+ .word _stext
+ .word _end
+
+1: ldmia r2!, {r6, r7, r8, r9}
+ stmia r3!, {r6, r7, r8, r9}
+ subs r4, r4, #16
+ bcs 1b
+ movs r4, r5
+ mov r5, #0
+ movne pc, r0
+
mov r0, #0
mov r1, #5
#endif
-#define DEBUG
-
- .globl SYMBOL_NAME(swapper_pg_dir)
- .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000
-
- .text
/*
* Entry point and restart point. Entry *must* be called with r0 == 0,
* MMU off. Note! These should be unique!!! Please read Documentation/ARM-README
@@ -45,16 +71,15 @@
* r1 = 5 -> Corel Netwinder
* r1 = 6 -> CATS
* r1 = 7 -> tbox
+ * r1 = 8 -> SA110/21285 as co-processor
*/
-ENTRY(stext)
-ENTRY(_stext)
__entry: teq r0, #0 @ check for illegal entry...
bne .Lerror @ loop indefinitely
cmp r1, #8 @ Unknown machine architecture
bge .Lerror
-/* First thing to do is to get the page tables set up so that we can call the kernel
- * in the correct place. This is relocatable code...
+/* First thing to do is to get the page tables set up so that we can call
+ * the kernel in the correct place. This is relocatable code...
* - Read processor ID register (CP#15, CR0).
*/
mrc p15, 0, r9, c0, c0 @ get Processor ID
@@ -111,7 +136,11 @@
add r3, r3, #1 << 20
teq r0, r2
bne 1b
-#ifdef CONFIG_ARCH_VNC
+#ifdef CONFIG_ARCH_NETWINDER
+ teq r1, #5
+ bne 1f
+#endif
+#if defined(CONFIG_ARCH_VNC) || defined(CONFIG_ARCH_NETWINDER)
add r0, r4, #0x3f00
add r0, r0, #0x00f8
mov r3, #0x7c000000
@@ -120,6 +149,7 @@
add r3, r3, #1 << 20
str r3, [r0], #4
#endif
+1:
#endif
#ifdef CONFIG_ARCH_RPC
/* Map in screen at 0x02000000 & SCREEN2_BASE
@@ -250,7 +280,11 @@
mcr p15, 0, r4, c2, c0 @ load page table pointer
mov r0, #0x1f @ Domains 0, 1 = client
mcr p15, 0, r0, c3, c0 @ load domain access register
+#ifdef CONFIG_ALIGNMENT_TRAP
+ mov r0, #0x3f @ ....S..DPWCAM
+#else
mov r0, #0x3d @ ....S..DPWC.M
+#endif
orr r0, r0, #0x100
mov pc, lr
@@ -261,7 +295,11 @@
mcr p15, 0, r4, c2, c0 @ load page table pointer
mov r0, #0x1f @ Domains 0, 1 = client
mcr p15, 0, r0, c3, c0 @ load domain access register
+#ifdef CONFIG_ALIGNMENT_TRAP
+ mov r0, #0x7f @ ....S.LDPWCAM
+#else
mov r0, #0x7d @ ....S.LDPWC.M
+#endif
orr r0, r0, #0x100
mov pc, lr
@@ -276,12 +314,14 @@
mrc p15, 0, r0, c1, c0 @ get control register v4
bic r0, r0, #0x0e00
bic r0, r0, #0x0002
+#ifdef CONFIG_ALIGNMENT_TRAP
+ orr r0, r0, #0x003f @ I...S..DPWCAM
+#else
orr r0, r0, #0x003d @ I...S..DPWC.M
+#endif
orr r0, r0, #0x1100 @ v4 supports separate I cache
mov pc, lr
- .section ".text.init",#alloc,#execinstr
-
.Lsa_fastclock: mcr p15, 0, r4, c15, c1, 2 @ Enable clock switching
mov pc, lr
@@ -290,18 +330,22 @@
.long SYMBOL_NAME(__bss_start)
.long SYMBOL_NAME(processor_id)
.long SYMBOL_NAME(_end)
+ .long SYMBOL_NAME(cr_alignment)
.long SYMBOL_NAME(init_task_union)+8192
.align
.Lalready_done_mmap:
adr r4, .LC0
- ldmia r4, {r3, r4, r5, r6, r8, sp} @ Setup stack
+ ldmia r4, {r3, r4, r5, r6, r7, r8, sp} @ Setup stack
add r10, r10, r3 @ Add base back in
mov fp, #0
-1: cmp r5, r8 @ Clear BSS
+1: cmp r5, r7 @ Clear BSS
strcc fp, [r5],#4
bcc 1b
+ bic r2, r0, #2 @ Clear 'A' bit
+ stmia r8, {r0, r2} @ Save control register values
+
str r1, [r4] @ Save machine type
str r9, [r6] @ Save processor ID
mov lr, pc
@@ -363,6 +407,7 @@
.endm
#elif defined(CONFIG_ARCH_EBSA285)
+#if 1
.macro addruart,rx
mov \rx, #0xfe000000
.endm
@@ -379,7 +424,30 @@
.macro waituart,rd,rx
.endm
+#else
+ .macro addruart,rx
+ mov \rx, #0xff000000
+ orr \rx, \rx, #0x00e00000
+ orr \rx, \rx, #0x000003f8
+ .endm
+ .macro senduart,rd,rx
+ strb \rd, [\rx]
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldrb \rd, [\rx, #0x5]
+ and \rd, \rd, #0x60
+ teq \rd, #0x60
+ bne 1002b
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldrb \rd, [\rx, #0x6]
+ tst \rd, #0x10
+ beq 1001b
+ .endm
+#endif
#elif defined(CONFIG_ARCH_NEXUSPCI)
.macro addruart,rx
ldr \rx, =0xfff00000
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/hw-ebsa285.c linux.ac/arch/arm/kernel/hw-ebsa285.c
--- linux.vanilla/arch/arm/kernel/hw-ebsa285.c Mon Dec 28 23:09:40 1998
+++ linux.ac/arch/arm/kernel/hw-ebsa285.c Sun Jan 24 21:11:31 1999
@@ -3,27 +3,37 @@
*
* EBSA285 hardware specific functions
*
- * Copyright (C) 1998 Russell King, Phil Blundel
+ * Copyright (C) 1998 Russell King, Phil Blundell
*/
+#include
+#include
#include
#include
#include
#include
#include
#include
+#include
+#include
#include
+#include
+#include
#include
+#include
#include
-extern int setup_arm_irq(int, struct irqaction *);
+#define ETHER10_IO_BASE 0x301
+#define DEC21143_IO_BASE 0x401
+#define DEC21143_MEM_BASE 0x00800000
+#define CYBER2000_MEM_BASE 0x01000000
+extern int setup_arm_irq(int, struct irqaction *);
extern void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set);
extern void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr);
extern void pci_set_irq_line(struct pci_dev *dev, unsigned int irq);
-static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 };
-static int irqmap_cats[] __initdata = { 18, 8, 9, 11 };
+static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
__initfunc(static int ebsa_irqval(struct pci_dev *dev))
{
@@ -37,6 +47,9 @@
return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3];
}
+#ifdef CONFIG_CATS
+static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
+
__initfunc(static int cats_irqval(struct pci_dev *dev))
{
if (dev->irq >= 128)
@@ -56,77 +69,179 @@
dev->bus->number, dev->devfn, dev->irq);
return 0;
}
+#endif
__initfunc(void pcibios_fixup_ebsa285(struct pci_dev *dev))
{
- char cmd;
+ /* Latency timer of 32 */
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32);
+ /* 32-byte cache line size */
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
+ /* Set SysErr enable, Parity enable */
+ pci_set_cmd(dev, PCI_COMMAND_FAST_BACK, PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
/* sort out the irq mapping for this device */
switch (machine_type) {
case MACH_TYPE_EBSA285:
dev->irq = ebsa_irqval(dev);
+ /* Turn on bus mastering - boot loader doesn't
+ * - perhaps it should! - dag
+ */
+ pci_set_cmd(dev, 0, PCI_COMMAND_MASTER);
break;
+
+#ifdef CONFIG_CATS
case MACH_TYPE_CATS:
dev->irq = cats_irqval(dev);
+ /* Turn on bus mastering - boot loader doesn't
+ * - perhaps it should! - dag
+ */
+ pci_set_cmd(dev, 0, PCI_COMMAND_MASTER);
break;
+#endif
+#ifdef CONFIG_ARCH_NETWINDER
+ case MACH_TYPE_NETWINDER:
+ /* disable ROM */
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+
+#define DEV(v,d) ((v)<<16|(d))
+ switch (DEV(dev->vendor, dev->device)) {
+ /* Ether 100 */
+ case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142):
+ pci_set_base_addr(dev, 0, DEC21143_IO_BASE);
+ pci_set_base_addr(dev, 1, DEC21143_MEM_BASE);
+ pci_set_cmd(dev, 0, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
+ dev->irq = IRQ_NETWINDER_ETHER100;
+ break;
+
+ /* Ether 10 */
+ case DEV(PCI_VENDOR_ID_WINBOND2,0x5a5a):
+ pci_set_base_addr(dev, 0, ETHER10_IO_BASE);
+ pci_set_cmd(dev, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, PCI_COMMAND_IO);
+ dev->irq = IRQ_NETWINDER_ETHER10;
+ break;
+
+ /* ISA bridge */
+ case DEV(PCI_VENDOR_ID_WINBOND,PCI_DEVICE_ID_WINBOND_83C553):
+ pci_set_base_addr(dev, 0, 0);
+ pci_set_cmd(dev, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, PCI_COMMAND_IO);
+ /*
+ * Enable all memory requests from ISA to be channeled to PCI
+ */
+ pci_write_config_byte(dev, 0x48, 255);
+ /*
+ * Disable ping-pong (as per errata)
+ */
+ pci_write_config_byte(dev, 0x42, 0);
+ /*
+ * Enable PCI packet retry
+ */
+ pci_write_config_byte(dev, 0x40, 0x22);
+ /*
+ * Do not use PCI CPU park enable, park on
+ * last master, disable GAT bit
+ */
+ pci_write_config_byte(dev, 0x83, 0x02);
+ /*
+ * Default rotating priorities
+ */
+ pci_write_config_byte(dev, 0x80, 0xe0);
+ /*
+ * Rotate bank 4
+ */
+ pci_write_config_byte(dev, 0x81, 0x01);
+ break;
+
+ /* IDE */
+ case DEV(PCI_VENDOR_ID_WINBOND,PCI_DEVICE_ID_WINBOND_82C105):
+ pci_set_base_addr(dev, 0, 0x1f1);
+ pci_set_base_addr(dev, 1, 0x3f5);
+ pci_set_base_addr(dev, 2, 0x171);
+ pci_set_base_addr(dev, 3, 0x375);
+ pci_set_base_addr(dev, 4, 0xe801);
+ pci_set_cmd(dev, PCI_COMMAND_MEMORY, PCI_COMMAND_MASTER | PCI_COMMAND_IO);
+ dev->irq = IRQ_NETWINDER_IDE;
+ break;
+
+ /* VGA */
+ case DEV(PCI_VENDOR_ID_INTERG,0x2000):
+ pci_set_base_addr(dev, 0, CYBER2000_MEM_BASE);
+ pci_set_cmd(dev, PCI_COMMAND_MASTER, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ dev->irq = IRQ_NETWINDER_VGA;
+ break;
+ }
+#endif
}
-
- /* Turn on bus mastering - boot loader doesn't
- * - perhaps it should! - dag
- */
- pci_read_config_byte(dev, PCI_COMMAND, &cmd);
- pci_write_config_byte(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
}
-static void irq_pci_err(int irq, void *dev_id, struct pt_regs *regs)
+static void
+irq_pci_err(int irq, void *dev_id, struct pt_regs *regs)
{
- const char *err = "unknown";
- unsigned long cmd = *(unsigned long *)0xfe000004 & 0xffff;
- unsigned long ctrl = *(unsigned long *)0xfe00013c & 0xffffde07;
- static unsigned long next_warn[7];
- int idx = 6;
-
- switch(irq) {
- case IRQ_PCIPARITY:
- *(unsigned long *)0xfe000004 = cmd | 1 << 31;
- idx = 0;
- err = "parity";
- break;
+ static unsigned long next_warn;
+ unsigned long cmd = *CSR_PCICMD & 0x0000ffff;
+ unsigned long ctrl = (*CSR_SA110_CNTL) & 0xffffde07;
+ unsigned long irqstatus = *CSR_IRQ_RAWSTATUS;
+ struct pci_dev *dev;
+ int warn = time_after_eq(jiffies, next_warn);
+
+ if (warn) {
+ next_warn = jiffies + 3 * HZ / 100;
+ printk(KERN_DEBUG "PCI: ");
+ }
- case IRQ_PCITARGETABORT:
- *(unsigned long *)0xfe000004 = cmd | 1 << 28;
- idx = 1;
- err = "target abort";
- break;
+ if (irqstatus & (1 << 31)) {
+ if (warn)
+ printk("parity error ");
+ cmd |= 1 << 31;
+ }
- case IRQ_PCIMASTERABORT:
- *(unsigned long *)0xfe000004 = cmd | 1 << 29;
- idx = 2;
- err = "master abort";
- break;
+ if (irqstatus & (1 << 30)) {
+ if (warn)
+ printk("target abort ");
+ cmd |= 1 << 28;
+ }
- case IRQ_PCIDATAPARITY:
- *(unsigned long *)0xfe000004 = cmd | 1 << 24;
- idx = 3;
- err = "data parity";
- break;
+ if (irqstatus & (1 << 29)) {
+ if (warn)
+ printk("master abort ");
+ cmd |= 1 << 29;
+ }
- case IRQ_DISCARDTIMER:
- *(unsigned long *)0xfe00013c = ctrl | 1 << 8;
- idx = 4;
- err = "discard timer";
- break;
+ if (irqstatus & (1 << 28)) {
+ if (warn)
+ printk("data parity error ");
+ cmd |= 1 << 24;
+ }
- case IRQ_SERR:
- *(unsigned long *)0xfe00013c = ctrl | 1 << 3;
- idx = 5;
- err = "system";
- break;
+ if (irqstatus & (1 << 27)) {
+ if (warn)
+ printk("discard timer expired ");
+ ctrl |= 1 << 8;
}
- if (time_after_eq(jiffies, next_warn[idx])) {
- next_warn[idx] = jiffies + 3 * HZ / 100;
- printk(KERN_ERR "PCI %s error detected\n", err);
+
+ if (irqstatus & (1 << 23)) {
+ if (warn)
+ printk("system error ");
+ ctrl |= 1 << 3;
+ }
+
+ if (warn)
+ printk("pc=%08lX\n", instruction_pointer(regs));
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ unsigned short status;
+
+ pci_read_config_word(dev, PCI_STATUS, &status);
+ if (status & 0xf900) {
+ printk("PCI: [%04X:%04X] status = %X\n",
+ dev->vendor, dev->device, status);
+
+ pci_write_config_word(dev, PCI_STATUS, status & 0xf900);
+ }
}
+
+ *CSR_PCICMD = cmd;
+ *CSR_SA110_CNTL = ctrl;
}
static struct irqaction irq_pci_error = {
@@ -135,12 +250,9 @@
__initfunc(void pcibios_init_ebsa285(void))
{
- setup_arm_irq(IRQ_PCIPARITY, &irq_pci_error);
- setup_arm_irq(IRQ_PCITARGETABORT, &irq_pci_error);
- setup_arm_irq(IRQ_PCIMASTERABORT, &irq_pci_error);
- setup_arm_irq(IRQ_PCIDATAPARITY, &irq_pci_error);
- setup_arm_irq(IRQ_DISCARDTIMER, &irq_pci_error);
- setup_arm_irq(IRQ_SERR, &irq_pci_error);
+ unsigned int mem_size = (int)high_memory - PAGE_OFFSET;
+
+ setup_arm_irq(IRQ_PCI_ERR, &irq_pci_error);
/*
* Map our SDRAM at a known address in PCI space, just in case
@@ -150,12 +262,374 @@
*
* We should really only do this if the central function is enabled.
*/
- *(unsigned long *)0xfe000010 = 0;
- *(unsigned long *)0xfe000018 = 0xe0000000;
- *(unsigned long *)0xfe0000f8 = 0;
- *(unsigned long *)0xfe0000fc = 0;
- *(unsigned long *)0xfe000100 = 0x01fc0000;
- *(unsigned long *)0xfe000104 = 0;
- *(unsigned long *)0xfe000108 = 0x80000000;
- *(unsigned long *)0xfe000004 = 0x17;
+ *CSR_CSRBASEMASK = 0;
+ *CSR_CSRBASEOFFSET = 0;
+ *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000;
+ *CSR_SDRAMBASEOFFSET = 0;
+ *CSR_ROMBASEMASK = 0x80000000;
+ *CSR_PCICACHELINESIZE = 0x00002008;
+ *CSR_PCICSRBASE = 0;
+ *CSR_PCICSRIOBASE = 0;
+ *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET);
+ *CSR_PCIROMBASE = 0;
+ *CSR_PCICMD = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+ PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY;
+ *CSR_PCIADDR_EXTN = 0;
+}
+
+/*
+ * Netwinder stuff
+ */
+#ifdef CONFIG_ARCH_NETWINDER
+/*
+ * This is a lock for accessing ports 0x338 and 0x33a
+ */
+spinlock_t __netwinder_data gpio_lock = SPIN_LOCK_UNLOCKED;
+
+static unsigned int __netwinder_data current_gpio_op = 0;
+static unsigned int __netwinder_data current_gpio_io = 0;
+static unsigned int __netwinder_data current_cpld = 0;
+
+void __netwinder_text gpio_modify_op(int mask, int set)
+{
+ unsigned int new_gpio, changed;
+unsigned long flags; save_flags_cli(flags);
+if ((flags & 128) == 0) {printk("gpio_modify_op called with IRQs enabled from %p\n", __builtin_return_address(0)); __backtrace(); }
+
+ new_gpio = (current_gpio_op & ~mask) | set;
+ changed = new_gpio ^ current_gpio_op;
+ current_gpio_op = new_gpio;
+
+ if (changed & 0xff)
+ outb(new_gpio, 0x338);
+ if (changed & 0xff00)
+ outb(new_gpio >> 8, 0x33a);
+restore_flags(flags);
+}
+
+static inline void __gpio_modify_io(int mask, int in)
+{
+ unsigned int new_gpio, changed;
+ int port;
+
+ new_gpio = (current_gpio_io & ~mask) | in;
+ changed = new_gpio ^ current_gpio_io;
+ current_gpio_io = new_gpio;
+
+ changed >>= 1;
+ new_gpio >>= 1;
+
+ outb(7, 0x370);
+ outb(7, 0x371);
+
+ for (port = 0xe1; changed && port < 0xe8; changed >>= 1) {
+ outb(port, 0x370);
+ outb(new_gpio & 1, 0x371);
+
+ port += 1;
+ new_gpio >>= 1;
+ }
+
+ outb(7, 0x370);
+ outb(8, 0x371);
+
+ for (port = 0xe8; changed && port < 0xec; changed >>= 1) {
+ outb(port, 0x370);
+ outb(new_gpio & 1, 0x371);
+
+ port += 1;
+ new_gpio >>= 1;
+ }
+}
+
+void __netwinder_text gpio_modify_io(int mask, int in)
+{
+ /* Open up the SuperIO chip */
+ outb(0x87, 0x370);
+ outb(0x87, 0x370);
+
+ __gpio_modify_io(mask, in);
+
+ /* Close up the EFER gate */
+ outb(0xaa, 0x370);
+}
+
+int __netwinder_text gpio_read(void)
+{
+ return inb(0x338) | inb(0x33a) << 8;
+}
+
+void __netwinder_text cpld_modify(int mask, int set)
+{
+ int msk;
+
+ current_cpld = (current_cpld & ~mask) | set;
+
+ gpio_modify_io(GPIO_DATA, 0);
+ gpio_modify_op(GPIO_IOLOAD, 0);
+
+ for (msk = 8; msk; msk >>= 1) {
+ int bit = current_cpld & msk;
+
+ gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0);
+ gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK);
+ }
+
+ gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0);
+ gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK);
+ gpio_modify_op(GPIO_IOLOAD, 0);
+}
+
+__initfunc(static void hw_init_cpld(void))
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ cpld_modify(-1, CPLD_UNMUTE | 4);
+ spin_unlock_irqrestore(&gpio_lock, flags);
}
+
+__initfunc(static void hw_init_wb553(void))
+{
+ unsigned long flags;
+#define WRITE_REG(r,v) do { outb((r), 0x370); outb((v), 0x371); } while (0)
+
+ /* Open up the SuperIO chip */
+ outb(0x87, 0x370);
+ outb(0x87, 0x370);
+
+ /* Set the serial interrupt numbers */
+ WRITE_REG(7, 5); /* keyboard subsection */
+ WRITE_REG(0x72, 5); /* interrupt number for mouse - IRQ5 */
+
+ WRITE_REG(7, 6); /* Infrared */
+ WRITE_REG(0x70, 6); /* IRQ 6 */
+
+ WRITE_REG(0x2a, 0xc1); /* Enable GP12, GP11, GP10 as I/O, CIRRX, IRRXH */
+
+ WRITE_REG(0x2b, 0x6b); /* Enable GP23, GP22, GP21, GP20, GP13 as I/O */
+
+ WRITE_REG(0x2c, 0x55); /* Enable GP17, GP16, GP15, GP14 as I/O */
+
+ current_gpio_io = -1;
+ __gpio_modify_io(-1, GPIO_DONE | GPIO_WDTIMER);
+
+ WRITE_REG(7, 7); /* Aux function group 1 (dev 7) */
+ WRITE_REG(0x60, 0x03); /* Group controlled by IO port 0x338 */
+ WRITE_REG(0x61, 0x38); /* GP 11, 12, 13, 14, 15, 16 */
+
+ WRITE_REG(0x70, 0x0a); /* IRQ10 for GP10 (Orange button) */
+
+ WRITE_REG(0xe0, 0x19); /* GP10 control reg set for debounce & input */
+ WRITE_REG(0x30, 0x01); /* Turn on section 7 (aux function group 1) */
+
+ WRITE_REG(7, 8); /* Aux function group 2 (dev 8) */
+ WRITE_REG(0x60, 0x03); /* Group controlled by IO port 0x33a */
+ WRITE_REG(0x61, 0x3a);
+
+ /* Clear watchdog timer regs */
+ WRITE_REG(0xf2, 0x00); /* Watchdog timeout value (disabled) */
+ WRITE_REG(0xf3, 0x00); /* Watchdog reg (reset to default) */
+ WRITE_REG(0xf4, 0x00); /* Reset if in timed out state (bit 0) */
+
+ /* T.B.D. set IRDA inputs (touch reg 2A, EC, ED) */
+ WRITE_REG(0x30, 0x01); /* Turn on section 8 (aux function group 2) */
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
+ spin_unlock_irqrestore(&gpio_loc, flags);
+
+ /* Close up the EFER gate */
+ outb(0xaa, 0x370);
+}
+
+static unsigned char rwa_unlock[] __initdata =
+{ 0x00, 0x00, 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b,
+ 0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74,
+ 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
+
+#ifndef DEBUG
+#define dprintk if (0) printk
+#else
+#define dprintk printk
+#endif
+
+__initfunc(static void hw_init_rwa010(void))
+{
+ unsigned char si[9];
+ int i, j;
+
+#define WRITE_RWA(r,v) do { outb((r), 0x279); outb((v), 0xa79); } while (0)
+
+ WRITE_RWA(2, 2);
+ mdelay(10);
+
+ for (i = 0; i < sizeof(rwa_unlock); i++)
+ outb(rwa_unlock[i], 0x279);
+
+ WRITE_RWA(3, 0);
+ WRITE_RWA(0, 128);
+
+ outb(1, 0x279);
+
+ mdelay(10);
+
+ dprintk("Identifier: ");
+ for (i = 0; i < 9; i++) {
+ si[i] = 0;
+ for (j = 0; j < 8; j++) {
+ int bit;
+ mdelay(1);
+ inb(0x203);
+ mdelay(1);
+ bit = inb(0x203);
+ dprintk("%02X ", bit);
+ si[i] |= bit << j;
+ }
+ mdelay(10);
+ dprintk("%02X ", si[i]);
+ }
+ dprintk("\n");
+
+ WRITE_RWA(6, 2); // Assign a card no = 2
+
+ dprintk("Card no = %d\n", inb(0x203));
+
+ WRITE_RWA(7, 3);
+ WRITE_RWA(0x30, 0);
+
+ WRITE_RWA(7, 4);
+ WRITE_RWA(0x30, 0);
+
+ WRITE_RWA(7, 2);
+ WRITE_RWA(0x30, 0);
+
+ WRITE_RWA(7, 5);
+
+ dprintk("Slider base: ");
+ WRITE_RWA(0x61, 1);
+ i = inb(0x203);
+
+ WRITE_RWA(0x60, 2);
+ dprintk("%02X%02X (201)\n", inb(0x203), i);
+
+ WRITE_RWA(0x30, 1);
+
+
+ WRITE_RWA(7, 0);
+
+ dprintk("WaveArtist base: ");
+ WRITE_RWA(0x61, 0x50);
+ i = inb(0x203);
+
+ WRITE_RWA(0x60, 0x02);
+ dprintk("%02X%02X (250),", inb(0x203), i);
+
+ WRITE_RWA(0x70, 3);
+ dprintk(" irq: %d (3),", inb(0x203));
+
+ WRITE_RWA(0x74, 7);
+ dprintk(" dma: %d (7)\n", inb(0x203));
+
+ WRITE_RWA(0x30, 1);
+
+ WRITE_RWA(7, 1);
+
+ dprintk("SoundBlaster base: ");
+ WRITE_RWA(0x61, 0x20);
+ i = inb(0x203);
+
+ WRITE_RWA(0x60, 0x02);
+ dprintk("%02X%02X (220),", inb(0x203), i);
+
+ dprintk(" irq: ");
+ WRITE_RWA(0x70, 3);
+ dprintk("%d (3),", inb(0x203));
+
+ dprintk(" 8-bit DMA: ");
+ WRITE_RWA(0x74, 1);
+ dprintk("%d (1)\n", inb(0x203));
+
+ dprintk("AdLib base: ");
+ WRITE_RWA(0x63, 0x88);
+ i = inb(0x203);
+
+ WRITE_RWA(0x62, 0x03);
+ dprintk("%02X%02X (388)\n", inb(0x203), i);
+
+ WRITE_RWA(0x30, 1);
+
+ outb(1, 0x226);
+ udelay(3);
+ outb(0, 0x226);
+
+ for (i = 0; i < 5; i++) {
+ if (inb(0x22e) & 0x80)
+ break;
+ mdelay(1);
+ }
+ if (i == 5)
+ printk("SoundBlaster: DSP reset failed\n");
+
+ dprintk("SoundBlaster DSP reset: %02X (AA)\n", inb(0x22a));
+
+ for (i = 0; i < 5; i++) {
+ if ((inb(0x22c) & 0x80) == 0)
+ break;
+ mdelay(1);
+ }
+
+ if (i == 5)
+ printk("SoundBlaster: DSP not ready\n");
+ else {
+ outb(0xe1, 0x22c);
+
+ dprintk("SoundBlaster DSP id: ");
+ i = inb(0x22a);
+ udelay(1);
+ i |= inb(0x22a) << 8;
+ dprintk("%04X\n", i);
+
+ for (i = 0; i < 5; i++) {
+ if ((inb(0x22c) & 0x80) == 0)
+ break;
+ mdelay(1);
+ }
+
+ if (i == 5)
+ printk("SoundBlaster: could not turn speaker off\n");
+
+ outb(0xd3, 0x22c);
+ }
+}
+
+__initfunc(void hw_init(void))
+{
+ unsigned long flags;
+
+ hw_init_wb553();
+ hw_init_cpld();
+ hw_init_rwa010();
+#if 0
+ /* does anyone want to have this in? */
+ drum();
+#endif
+
+#ifdef CONFIG_LEDS /* Clear both LEDs and start the LED driver up */
+ spin_lock_irqsave(&gpio_lock, flags);
+ gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, 0);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ leds_event(led_start);
+#else /* Set the green LED on and the red LED off */
+ spin_lock_irqsave(&gpio_lock, flags);
+ gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, GPIO_GREEN_LED);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+#endif /* CONFIG_LEDS */
+}
+
+EXPORT_SYMBOL(gpio_lock);
+EXPORT_SYMBOL(gpio_modify_op);
+EXPORT_SYMBOL(gpio_modify_io);
+EXPORT_SYMBOL(cpld_modify);
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/iic.c linux.ac/arch/arm/kernel/iic.c
--- linux.vanilla/arch/arm/kernel/iic.c Sun Nov 8 15:08:43 1998
+++ linux.ac/arch/arm/kernel/iic.c Sun Jan 24 21:11:31 1999
@@ -9,8 +9,11 @@
#include
#include
-#include
#include
+#include
+#include
+
+#define FORCE_ONES 0xdc
/*
* if delay loop has been calibrated then us that,
@@ -42,7 +45,7 @@
{
unsigned char out;
- out = inb(IOC_CONTROL) | 0xc2;
+ out = inb(IOC_CONTROL) | FORCE_ONES | 0x02;
outb(out, IOC_CONTROL);
iic_delay();
@@ -55,7 +58,7 @@
{
unsigned char out;
- out = inb(IOC_CONTROL) | 0xc3;
+ out = inb(IOC_CONTROL) | FORCE_ONES | 0x03;
iic_delay();
outb(out ^ 1, IOC_CONTROL);
@@ -69,7 +72,7 @@
unsigned char out, in;
int i;
- out = (inb(IOC_CONTROL) & 0xfc) | 0xc0;
+ out = (inb(IOC_CONTROL) & 0xfc) | FORCE_ONES;
outb(out, IOC_CONTROL);
for (i = 7; i >= 0; i--) {
@@ -110,7 +113,7 @@
unsigned char out, in;
int i;
- out = (inb(IOC_CONTROL) & 0xfc) | 0xc0;
+ out = (inb(IOC_CONTROL) & 0xfc) | FORCE_ONES;
outb(out, IOC_CONTROL);
in = 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/init_task.c linux.ac/arch/arm/kernel/init_task.c
--- linux.vanilla/arch/arm/kernel/init_task.c Tue Dec 22 23:19:26 1998
+++ linux.ac/arch/arm/kernel/init_task.c Sun Jan 24 21:11:31 1999
@@ -6,6 +6,7 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
+static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/ioport.c linux.ac/arch/arm/kernel/ioport.c
--- linux.vanilla/arch/arm/kernel/ioport.c Sun Nov 8 15:08:43 1998
+++ linux.ac/arch/arm/kernel/ioport.c Thu Jan 1 01:00:00 1970
@@ -1,29 +0,0 @@
-/*
- * linux/arch/arm/kernel/ioport.c
- *
- * Io-port support is not used for ARM
- */
-
-#include
-#include
-#include
-#include
-#include
-
-/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
-/*asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
-{
-}*/
-
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
-{
- return -ENOSYS;
-}
-
-asmlinkage int sys_iopl(long ebx,long ecx,long edx,
- long esi, long edi, long ebp, long eax, long ds,
- long es, long fs, long gs, long orig_eax,
- long eip,long cs,long eflags,long esp,long ss)
-{
- return -ENOSYS;
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/irq.c linux.ac/arch/arm/kernel/irq.c
--- linux.vanilla/arch/arm/kernel/irq.c Mon Dec 28 23:09:40 1998
+++ linux.ac/arch/arm/kernel/irq.c Sun Jan 24 21:11:31 1999
@@ -49,6 +49,7 @@
unsigned int local_bh_count[NR_CPUS];
unsigned int local_irq_count[NR_CPUS];
spinlock_t irq_controller_lock;
+int setup_arm_irq(int, struct irqaction *);
extern int get_fiq_list(char *);
extern void init_FIQ(void);
@@ -71,6 +72,12 @@
static struct irqdesc irq_desc[NR_IRQS];
/*
+ * Get architecture specific interrupt handlers
+ * and interrupt initialisation.
+ */
+#include
+
+/*
* Dummy mask/unmask handler
*/
static void dummy_mask_unmask_irq(unsigned int irq)
@@ -130,10 +137,14 @@
*/
asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
- struct irqdesc * desc = irq_desc + irq;
+ struct irqdesc * desc;
struct irqaction * action;
int status, cpu;
+ irq = fixup_irq(irq);
+
+ desc = irq_desc + irq;
+
spin_lock(&irq_controller_lock);
desc->mask_ack(irq);
spin_unlock(&irq_controller_lock);
@@ -261,10 +272,6 @@
return 0;
}
-/*
- * Using "struct sigaction" is slightly silly, but there
- * are historical reasons and it works well, so..
- */
int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long irq_flags, const char * devname, void *dev_id)
{
@@ -405,14 +412,9 @@
irq_found = NO_IRQ;
out:
spin_unlock_irq(&irq_controller_lock);
+printk("probe_irq_off: irq %d\n", irq_found);
return irq_found;
}
-
-/*
- * Get architecture specific interrupt handlers
- * and interrupt initialisation.
- */
-#include
__initfunc(void init_IRQ(void))
{
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/leds-ebsa285.c linux.ac/arch/arm/kernel/leds-ebsa285.c
--- linux.vanilla/arch/arm/kernel/leds-ebsa285.c Sun Nov 8 15:08:44 1998
+++ linux.ac/arch/arm/kernel/leds-ebsa285.c Sun Jan 24 21:11:31 1999
@@ -9,36 +9,72 @@
* - Amber - On if system is not idle
* - Red - currently unused
*/
+#include
+#include
+#include
+
#include
#include
+#include
#include
-static char led_state = XBUS_LED_RED | XBUS_LED_GREEN;
+static int led_state;
+static char ebsa_led_state = XBUS_LED_RED | XBUS_LED_GREEN;
void leds_event(led_event_t ledevt)
{
unsigned long flags;
+ switch (ledevt) {
+ case led_start:
+ led_state = !machine_is_cats();
+ return;
+
+ case led_stop:
+ led_state = 0;
+ return;
+
+ default:
+ break;
+ }
+
+ if (!led_state)
+ return;
+
save_flags_cli(flags);
switch(ledevt) {
+#ifdef CONFIG_LEDS_CPU
case led_idle_start:
- led_state |= XBUS_LED_AMBER;
+ ebsa_led_state |= XBUS_LED_AMBER;
break;
case led_idle_end:
- led_state &= ~XBUS_LED_AMBER;
+ ebsa_led_state &= ~XBUS_LED_AMBER;
break;
-
+#endif
+#ifdef CONFIG_LEDS_TIMER
case led_timer:
- led_state ^= XBUS_LED_GREEN;
+ ebsa_led_state ^= XBUS_LED_GREEN;
break;
-
+#endif
default:
break;
}
restore_flags(flags);
- *XBUS_LEDS = led_state;
+ switch (machine_type) {
+ case MACH_TYPE_EBSA285:
+ *XBUS_LEDS = led_state;
+ break;
+
+ case MACH_TYPE_NETWINDER:
+ spin_lock_irqsave(&gpio_lock, flags);
+ gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED,
+ (ebsa_led_state & XBUS_LED_AMBER ? GPIO_RED_LED : 0) |
+ (ebsa_led_state & XBUS_LED_GREEN ? GPIO_GREEN_LED : 0));
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ break;
+ }
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/process.c linux.ac/arch/arm/kernel/process.c
--- linux.vanilla/arch/arm/kernel/process.c Sun Nov 8 15:08:44 1998
+++ linux.ac/arch/arm/kernel/process.c Sun Jan 24 21:11:31 1999
@@ -55,46 +55,37 @@
}
/*
- * The idle loop on an arm..
+ * The idle loop on an ARM...
*/
asmlinkage int sys_idle(void)
{
- int ret = -EPERM;
-
- lock_kernel();
if (current->pid != 0)
- goto out;
+ return -EPERM;
+
/* endless idle loop with no priority at all */
- current->priority = -100;
- for (;;)
- {
+ while (1) {
+ if (!current->need_resched && !hlt_counter)
+ proc_idle();
+ current->policy = SCHED_YIELD;
+ schedule();
+#ifndef CONFIG_NO_PGT_CACHE
check_pgt_cache();
-#if 0 //def ARCH_IDLE_OK
- if (!hlt_counter && !current->need_resched)
- proc_idle ();
#endif
- run_task_queue(&tq_scheduler);
- schedule();
}
- ret = 0;
-out:
- unlock_kernel();
- return ret;
}
+static char reboot_mode = 'h';
+
__initfunc(void reboot_setup(char *str, int *ints))
{
+ reboot_mode = str[0];
}
-/*
- * This routine reboots the machine by resetting the expansion cards via
- * their loaders, turning off the processor cache (if ARM3), copying the
- * first instruction of the ROM to 0, and executing it there.
- */
void machine_restart(char * __unused)
{
- proc_hard_reset ();
- arch_hard_reset ();
+ arch_reset(reboot_mode);
+ panic("Reboot failed\n");
+ while (1);
}
void machine_halt(void)
@@ -150,6 +141,67 @@
}
/*
+ * Task structure and kernel stack allocation.
+ *
+ * Taken from the i386 version.
+ */
+#ifdef CONFIG_CPU_32
+#define EXTRA_TASK_STRUCT 8
+static struct task_struct *task_struct_stack[EXTRA_TASK_STRUCT];
+static int task_struct_stack_ptr = -1;
+#endif
+
+struct task_struct *alloc_task_struct(void)
+{
+ struct task_struct *tsk;
+
+#ifndef EXTRA_TASK_STRUCT
+ tsk = ll_alloc_task_struct();
+#else
+ int index;
+
+ index = task_struct_stack_ptr;
+ if (index >= EXTRA_TASK_STRUCT/2)
+ goto use_cache;
+
+ tsk = ll_alloc_task_struct();
+
+ if (!tsk) {
+ index = task_struct_stack_ptr;
+
+ if (index >= 0) {
+use_cache: tsk = task_struct_stack[index];
+ task_struct_stack_ptr = index - 1;
+ }
+ }
+#endif
+#ifdef CONFIG_SYSRQ
+ /* You need this if you want SYSRQ-T to give sensible stack
+ * usage information
+ */
+ if (tsk) {
+ char *p = (char *)tsk;
+ memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE);
+ }
+#endif
+
+ return tsk;
+}
+
+void free_task_struct(struct task_struct *p)
+{
+#ifdef EXTRA_TASK_STRUCT
+ int index = task_struct_stack_ptr + 1;
+
+ if (index < EXTRA_TASK_STRUCT) {
+ task_struct_stack[index] = p;
+ task_struct_stack_ptr = index;
+ } else
+#endif
+ ll_free_task_struct(p);
+}
+
+/*
* Free current thread data structures etc..
*/
void exit_thread(void)
@@ -179,9 +231,10 @@
childregs = ((struct pt_regs *)((unsigned long)p + 8192)) - 1;
*childregs = *regs;
childregs->ARM_r0 = 0;
+ childregs->ARM_sp = esp;
save = ((struct context_save_struct *)(childregs)) - 1;
- copy_thread_css(save);
+ init_thread_css(save);
p->tss.save = save;
return 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/setup.c linux.ac/arch/arm/kernel/setup.c
--- linux.vanilla/arch/arm/kernel/setup.c Tue Dec 22 23:19:27 1998
+++ linux.ac/arch/arm/kernel/setup.c Sun Jan 24 21:11:31 1999
@@ -56,12 +56,16 @@
#define SUPPORT_CPU_SA110
#endif
-#ifndef CONFIG_CMDLINE
-#define CONFIG_CMDLINE "root=/dev/nfs rw"
-#endif
#define MEM_SIZE (16*1024*1024)
#define COMMAND_LINE_SIZE 256
+#ifndef CONFIG_CMDLINE
+#define CONFIG_CMDLINE ""
+#endif
+
+extern void reboot_setup(char *str, int *ints);
+extern void disable_hlt(void);
+
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info = {
orig_video_lines: 30,
@@ -87,20 +91,26 @@
/*-- Match -- --- Mask -- -- Manu -- Processor uname -m --- ELF STUFF ---
--- processor asm funcs --- */
#if defined(CONFIG_CPU_26)
+ /* ARM2 fake ident */
{ 0x41560200, 0xfffffff0, "ARM/VLSI", "arm2" , "armv1" , "v1", 0,
&arm2_processor_functions },
+ /* ARM250 fake ident */
{ 0x41560250, 0xfffffff0, "ARM/VLSI", "arm250" , "armv2" , "v2", HWCAP_SWP,
&arm250_processor_functions },
+ /* ARM3 processors */
{ 0x41560300, 0xfffffff0, "ARM/VLSI", "arm3" , "armv2" , "v2", HWCAP_SWP,
&arm3_processor_functions },
#elif defined(CONFIG_CPU_32)
#ifdef SUPPORT_CPU_ARM6
+ /* ARM6 */
{ 0x41560600, 0xfffffff0, "ARM/VLSI", "arm6" , "armv3" , "v3", HWCAP_SWP,
&arm6_processor_functions },
+ /* ARM610 */
{ 0x41560610, 0xfffffff0, "ARM/VLSI", "arm610" , "armv3" , "v3", HWCAP_SWP,
&arm6_processor_functions },
#endif
#ifdef SUPPORT_CPU_ARM7
+ /* ARM7's have a strange numbering */
{ 0x41007000, 0xffffff00, "ARM/VLSI", "arm7" , "armv3" , "v3", HWCAP_SWP,
&arm7_processor_functions },
/* ARM710 IDs are non-standard */
@@ -108,8 +118,14 @@
&arm7_processor_functions },
#endif
#ifdef SUPPORT_CPU_SA110
- { 0x4401a100, 0xfffffff0, "DEC", "sa110" , "armv4" , "v3", HWCAP_SWP|HWCAP_HALF,
+#ifdef CONFIG_ARCH_RPC
+ /* Acorn RiscPC's can't handle ARMv4 half-word instructions */
+ { 0x4401a100, 0xfffffff0, "DEC", "sa110" , "armv4" , "v4", HWCAP_SWP,
&sa110_processor_functions },
+#else
+ { 0x4401a100, 0xfffffff0, "DEC", "sa110" , "armv4" , "v4", HWCAP_SWP|HWCAP_HALF,
+ &sa110_processor_functions },
+#endif
#endif
#endif
{ 0x00000000, 0x00000000, "***", "unknown", "unknown", "**", 0, NULL }
@@ -132,139 +148,10 @@
*/
/*
- * Risc-PC specific initialisation
- */
-#ifdef CONFIG_ARCH_RPC
-
-#include
-
-unsigned int vram_half_sam;
-
-static void
-setup_rpc(struct param_struct *params)
-{
- extern void init_dram_banks(const struct param_struct *params);
-
- init_dram_banks(params);
-
- switch (params->u1.s.pages_in_vram) {
- case 256:
- vram_half_sam = 1024;
- break;
- case 512:
- default:
- vram_half_sam = 2048;
- }
-}
-#else
-#define setup_rpc(x)
-#endif
-
-#ifdef PARAMS_BASE
-
-#ifdef CONFIG_ARCH_ACORN
-int memc_ctrl_reg;
-int number_ide_drives;
-int number_mfm_drives;
-#endif
-
-static struct param_struct *params = (struct param_struct *)PARAMS_BASE;
-
-__initfunc(static char *
-setup_params(unsigned long *mem_end_p))
-{
- ROOT_DEV = to_kdev_t(params->u1.s.rootdev);
- ORIG_X = params->u1.s.video_x;
- ORIG_Y = params->u1.s.video_y;
- ORIG_VIDEO_COLS = params->u1.s.video_num_cols;
- ORIG_VIDEO_LINES = params->u1.s.video_num_rows;
-
-#ifdef CONFIG_ARCH_ACORN
-#ifndef CONFIG_FB
- {
- extern int bytes_per_char_h;
- extern int bytes_per_char_v;
-
- bytes_per_char_h = params->u1.s.bytes_per_char_h;
- bytes_per_char_v = params->u1.s.bytes_per_char_v;
- }
-#endif
- memc_ctrl_reg = params->u1.s.memc_control_reg;
- number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3;
- number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3;
-
- setup_rpc(params);
-
- if (!(params->u1.s.flags & FLAG_READONLY))
- root_mountflags &= ~MS_RDONLY;
-#endif
-#ifdef CONFIG_BLK_DEV_RAM
- {
- extern int rd_doload;
- extern int rd_prompt;
- extern int rd_image_start;
-
- rd_image_start = params->u1.s.rd_start;
- rd_prompt = (params->u1.s.flags & FLAG_RDPROMPT) == 0;
- rd_doload = (params->u1.s.flags & FLAG_RDLOAD) == 0;
- }
-#endif
-
-#ifdef CONFIG_ARCH_ACORN
- *mem_end_p = GET_MEMORY_END(params);
-#elif defined(CONFIG_ARCH_EBSA285)
- *mem_end_p = PAGE_OFFSET + params->u1.s.page_size * params->u1.s.nr_pages;
-#else
- *mem_end_p = PAGE_OFFSET + MEM_SIZE;
-#endif
-
- return params->commandline;
-}
-
-#else
-
-static char default_command_line[] __initdata = CONFIG_CMDLINE;
-
-__initfunc(static char *
-setup_params(unsigned long *mem_end_p))
-{
- ROOT_DEV = 0x00ff;
-
-#ifdef CONFIG_BLK_DEV_RAM
- {
- extern int rd_doload;
- extern int rd_prompt;
- extern int rd_image_start;
-
- rd_image_start = 0;
- rd_prompt = 1;
- rd_doload = 1;
- }
-#endif
-
- *mem_end_p = PAGE_OFFSET + MEM_SIZE;
-
- return default_command_line;
-}
-#endif
-
-/*
* initial ram disk
*/
#ifdef CONFIG_BLK_DEV_INITRD
__initfunc(static void
-setup_initrd(const struct param_struct *params))
-{
- if (params->u1.s.initrd_start) {
- initrd_start = params->u1.s.initrd_start;
- initrd_end = initrd_start + params->u1.s.initrd_size;
- } else {
- initrd_start = 0;
- initrd_end = 0;
- }
-}
-
-__initfunc(static void
check_initrd(unsigned long mem_start, unsigned long mem_end))
{
if (initrd_end > mem_end) {
@@ -276,7 +163,6 @@
}
#else
-#define setup_initrd(p)
#define check_initrd(ms,me)
#endif
@@ -289,48 +175,48 @@
armidlist[armidindex].mask)
armidindex += 1;
- if (armidlist[armidindex].id == 0) {
-#ifdef CONFIG_ARCH_ACORN
- int i;
-
- for (i = 0; i < 3200; i++)
- ((unsigned long *)SCREEN2_BASE)[i] = 0x77113322;
-#endif
+ if (armidlist[armidindex].id == 0)
while (1);
- }
processor = *armidlist[armidindex].proc;
processor._proc_init();
}
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
static char command_line[COMMAND_LINE_SIZE] = { 0, };
char saved_command_line[COMMAND_LINE_SIZE];
__initfunc(static void
setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_end))
{
- char c, *to = command_line;
+ char c = ' ', *to = command_line;
int len = 0;
*mem_start = (unsigned long)&_end;
for (;;) {
- if (cmd_line[0] == ' ' &&
- cmd_line[1] == 'm' &&
- cmd_line[2] == 'e' &&
- cmd_line[3] == 'm' &&
- cmd_line[4] == '=') {
- *mem_end = simple_strtoul(cmd_line+5, &cmd_line, 0);
- switch(*cmd_line) {
- case 'M':
- case 'm':
- *mem_end <<= 10;
- case 'K':
- case 'k':
- *mem_end <<= 10;
+ if (c == ' ') {
+ if (cmd_line[0] == 'm' &&
+ cmd_line[1] == 'e' &&
+ cmd_line[2] == 'm' &&
+ cmd_line[3] == '=') {
+ *mem_end = simple_strtoul(cmd_line+4, &cmd_line, 0);
+ switch(*cmd_line) {
+ case 'M':
+ case 'm':
+ *mem_end <<= 10;
+ case 'K':
+ case 'k':
+ *mem_end <<= 10;
+ cmd_line++;
+ }
+ *mem_end = *mem_end + PAGE_OFFSET;
+ }
+ /* if there are two spaces, remove one */
+ if (*cmd_line == ' ') {
cmd_line++;
+ continue;
}
- *mem_end = *mem_end + PAGE_OFFSET;
}
c = *cmd_line++;
if (!c)
@@ -341,8 +227,49 @@
}
*to = '\0';
+
+ /* remove trailing spaces */
+ while (*--to == ' ' && to != command_line)
+ *to = '\0';
+}
+
+__initfunc(static void
+setup_ram(int doload, int prompt, int image_start))
+{
+#ifdef CONFIG_BLK_DEV_RAM
+ extern int rd_doload;
+ extern int rd_prompt;
+ extern int rd_image_start;
+
+ rd_image_start = image_start;
+ rd_prompt = prompt;
+ rd_doload = doload;
+#endif
+}
+
+/*
+ * initial ram disk
+ */
+__initfunc(static void
+setup_initrd(unsigned int start, unsigned int size))
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (start) {
+ initrd_start = start;
+ initrd_end = start + size;
+ } else {
+ initrd_start = 0;
+ initrd_end = 0;
+ }
+#endif
}
+#ifdef CONFIG_ARCH_ACORN
+int memc_ctrl_reg;
+int number_ide_drives;
+int number_mfm_drives;
+#endif
+
__initfunc(void
setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p))
{
@@ -350,6 +277,11 @@
unsigned long memory_end;
char endian = 'l';
char *from;
+#ifdef PARAMS_BASE
+ struct param_struct *params = (struct param_struct *)PARAMS_BASE;
+#else
+ struct param_struct *params = NULL;
+#endif
if (smptrap == 1)
return;
@@ -357,8 +289,83 @@
setup_processor();
- from = setup_params(&memory_end);
- setup_initrd(params);
+ init_task.mm->start_code = TASK_SIZE;
+ init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext;
+ init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata;
+ init_task.mm->brk = TASK_SIZE + (unsigned long) &_end;
+
+ /*
+ * Add your machine dependencies here
+ */
+ switch (machine_type) {
+ case MACH_TYPE_EBSA110:
+ /* EBSA110 locks if we execute 'wait for interrupt' */
+ disable_hlt();
+ params = NULL;
+ break;
+
+ case MACH_TYPE_CATS:
+ /* CATS must use soft-reboot */
+ reboot_setup("s", NULL);
+ break;
+
+ case MACH_TYPE_NETWINDER:
+ /* to be fixed in NeTTrom 2.0.6 */
+ params = NULL;
+ break;
+
+ default:
+ break;
+ }
+
+ if (params) {
+ memory_end = params->u1.s.page_size *
+ params->u1.s.nr_pages;
+
+ ROOT_DEV = to_kdev_t(params->u1.s.rootdev);
+ ORIG_X = params->u1.s.video_x;
+ ORIG_Y = params->u1.s.video_y;
+ ORIG_VIDEO_COLS = params->u1.s.video_num_cols;
+ ORIG_VIDEO_LINES = params->u1.s.video_num_rows;
+
+ setup_ram((params->u1.s.flags & FLAG_RDLOAD) == 0,
+ (params->u1.s.flags & FLAG_RDPROMPT) == 0,
+ params->u1.s.rd_start);
+
+ setup_initrd(params->u1.s.initrd_start,
+ params->u1.s.initrd_size);
+
+ if (!(params->u1.s.flags & FLAG_READONLY))
+ root_mountflags &= ~MS_RDONLY;
+
+#ifdef CONFIG_ARCH_ACORN
+ memc_ctrl_reg = params->u1.s.memc_control_reg;
+ number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3;
+ number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3;
+#ifndef CONFIG_FB
+ {
+ extern int bytes_per_char_h;
+ extern int bytes_per_char_v;
+
+ bytes_per_char_h = params->u1.s.bytes_per_char_h;
+ bytes_per_char_v = params->u1.s.bytes_per_char_v;
+ }
+#endif
+ setup_rpc(params);
+#endif
+
+ from = params->commandline;
+ } else {
+ memory_end = MEM_SIZE;
+ ROOT_DEV = 0x00ff;
+
+ setup_ram(1, 1, 0);
+ setup_initrd(0, 0);
+
+ from = default_command_line;
+ }
+
+ memory_end += PAGE_OFFSET;
/* Save unparsed command line copy for /proc/cmdline */
memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
@@ -367,14 +374,6 @@
setup_mem(from, memory_start_p, &memory_end);
check_initrd(*memory_start_p, memory_end);
- init_task.mm->start_code = TASK_SIZE;
- init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext;
- init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata;
- init_task.mm->brk = TASK_SIZE + (unsigned long) &_end;
-
- *cmdline_p = command_line;
- *memory_end_p = memory_end;
-
sprintf(system_utsname.machine, "%s%c", armidlist[armidindex].arch_vsn, endian);
sprintf(elf_platform, "%s%c", armidlist[armidindex].elf_vsn, endian);
@@ -385,6 +384,9 @@
conswitchp = &dummy_con;
#endif
#endif
+
+ *cmdline_p = command_line;
+ *memory_end_p = memory_end;
}
static const struct {
@@ -393,11 +395,12 @@
} machine_desc[] = {
{ "DEC-EBSA110", "DEC" },
{ "Acorn-RiscPC", "Acorn" },
- { "Nexus-NexusPCI", "PCI" },
+ { "unknown", "PCI" },
+ { "Nexus-FTV/PCI", "PCI" },
{ "DEC-EBSA285", "PCI" },
- { "Corel-Netwinder", "PCI/ISA" },
- { "Chalice-CATS", "PCI" },
- { "unknown-TBOX", "PCI" }
+ { "Corel-NetWinder", "PCI/ISA" },
+ { "Chalice-CATS", "PCI/ISA" },
+ { "unknown-TBOX", "none" }
};
#if defined(CONFIG_ARCH_ARC)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/signal.c linux.ac/arch/arm/kernel/signal.c
--- linux.vanilla/arch/arm/kernel/signal.c Sun Nov 8 15:08:43 1998
+++ linux.ac/arch/arm/kernel/signal.c Sun Jan 24 21:11:32 1999
@@ -28,7 +28,7 @@
asmlinkage int sys_wait4(pid_t pid, unsigned long * stat_addr,
int options, unsigned long *ru);
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs);
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
extern int ptrace_cancel_bpt (struct task_struct *);
extern int ptrace_set_bpt (struct task_struct *);
@@ -50,7 +50,7 @@
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(&saveset, regs))
+ if (do_signal(&saveset, regs, 0))
return regs->ARM_r0;
}
}
@@ -78,7 +78,7 @@
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(&saveset, regs))
+ if (do_signal(&saveset, regs, 0))
return regs->ARM_r0;
}
}
@@ -260,6 +260,18 @@
return err;
}
+static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ unsigned long framesize)
+{
+ unsigned long sp = regs->ARM_sp;
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if ((ka->sa.sa_flags & SA_ONSTACK) && ! on_sig_stack(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void *)(sp - framesize);
+}
+
static void setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs)
{
@@ -267,9 +279,9 @@
unsigned long retcode;
int err = 0;
- frame = (struct sigframe *)regs->ARM_sp - 1;
+ frame = get_sigframe(ka, regs, sizeof(*frame));
- if (!access_ok(VERIFT_WRITE, frame, sizeof (*frame)))
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto segv_and_exit;
err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
@@ -299,6 +311,11 @@
regs->ARM_sp = (unsigned long)frame;
regs->ARM_lr = retcode;
regs->ARM_pc = (unsigned long)ka->sa.sa_handler;
+#if defined(CONFIG_CPU_32)
+ /* Maybe we need to deliver a 32-bit signal to a 26-bit task. */
+ if (ka->sa.sa_flags & SA_THIRTYTWO)
+ regs->ARM_cpsr = USR_MODE;
+#endif
if (valid_user_regs(regs))
return;
@@ -315,7 +332,8 @@
unsigned long retcode;
int err = 0;
- frame = (struct rt_sigframe *)regs->ARM_sp - 1;
+ frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto segv_and_exit;
@@ -350,6 +368,11 @@
regs->ARM_sp = (unsigned long)frame;
regs->ARM_lr = retcode;
regs->ARM_pc = (unsigned long)ka->sa.sa_handler;
+#if defined(CONFIG_CPU_32)
+ /* Maybe we need to deliver a 32-bit signal to a 26-bit task. */
+ if (ka->sa.sa_flags & SA_THIRTYTWO)
+ regs->ARM_cpsr = USR_MODE;
+#endif
if (valid_user_regs(regs))
return;
@@ -393,18 +416,19 @@
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
{
- unsigned long instr, *pc = (unsigned long *)(instruction_pointer(regs)-4);
struct k_sigaction *ka;
siginfo_t info;
- int single_stepping, swi_instr;
+ int single_stepping;
+
+ if (!user_mode(regs))
+ return 0;
if (!oldset)
oldset = ¤t->blocked;
single_stepping = ptrace_cancel_bpt (current);
- swi_instr = (!get_user (instr, pc) && (instr & 0x0f000000) == 0x0f000000);
for (;;) {
unsigned long signr;
@@ -503,7 +527,7 @@
}
/* Are we from a system call? */
- if (swi_instr) {
+ if (syscall) {
switch (regs->ARM_r0) {
case -ERESTARTNOHAND:
regs->ARM_r0 = -EINTR;
@@ -527,7 +551,7 @@
return 1;
}
- if (swi_instr &&
+ if (syscall &&
(regs->ARM_r0 == -ERESTARTNOHAND ||
regs->ARM_r0 == -ERESTARTSYS ||
regs->ARM_r0 == -ERESTARTNOINTR)) {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/sys_arm.c linux.ac/arch/arm/kernel/sys_arm.c
--- linux.vanilla/arch/arm/kernel/sys_arm.c Tue Dec 22 23:19:27 1998
+++ linux.ac/arch/arm/kernel/sys_arm.c Sun Jan 24 21:11:32 1999
@@ -221,13 +221,7 @@
*/
asmlinkage int sys_fork(struct pt_regs *regs)
{
- int ret;
-
- lock_kernel();
- ret = do_fork(SIGCHLD, regs->ARM_sp, regs);
- unlock_kernel();
-
- return ret;
+ return do_fork(SIGCHLD, regs->ARM_sp, regs);
}
/* Clone a task - this clones the calling program thread.
@@ -235,14 +229,23 @@
*/
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs)
{
- int ret;
-
- lock_kernel();
if (!newsp)
newsp = regs->ARM_sp;
- ret = do_fork(clone_flags, newsp, regs);
- unlock_kernel();
- return ret;
+ return do_fork(clone_flags, newsp, regs);
+}
+
+asmlinkage int sys_vfork(struct pt_regs *regs)
+{
+ int child;
+ struct semaphore sem = MUTEX_LOCKED;
+
+ current->vfork_sem = &sem;
+ child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs);
+
+ if (child > 0)
+ down(&sem);
+
+ return child;
}
/* sys_execve() executes a new program.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/time.c linux.ac/arch/arm/kernel/time.c
--- linux.vanilla/arch/arm/kernel/time.c Sun Jan 24 19:55:30 1999
+++ linux.ac/arch/arm/kernel/time.c Sun Jan 24 21:11:32 1999
@@ -130,27 +130,12 @@
time_state = TIME_ERROR; /* p. 24, (a) */
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
- sti ();
+ sti();
}
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick.
- */
-static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- if (reset_timer ())
- do_timer(regs);
-
- update_rtc ();
-}
-
-static struct irqaction irqtimer = { timer_interrupt, 0, 0, "timer", NULL, NULL};
-
__initfunc(void time_init(void))
{
- xtime.tv_sec = setup_timer();
xtime.tv_usec = 0;
- setup_arm_irq(IRQ_TIMER, &irqtimer);
+ setup_timer();
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/traps.c linux.ac/arch/arm/kernel/traps.c
--- linux.vanilla/arch/arm/kernel/traps.c Tue Dec 22 23:19:27 1998
+++ linux.ac/arch/arm/kernel/traps.c Sun Jan 24 21:11:32 1999
@@ -54,7 +54,7 @@
if (stackptr < PAGE_OFFSET || stackptr + size > (unsigned long)high_memory)
return -EFAULT;
#endif
- return 0;
+ return 0;
}
/*
@@ -199,9 +199,8 @@
void bad_user_access_alignment (const void *ptr)
{
- void *pc;
- __asm__("mov %0, lr\n": "=r" (pc));
- printk (KERN_ERR "bad_user_access_alignment called: ptr = %p, pc = %p\n", ptr, pc);
+ printk (KERN_ERR "bad_user_access_alignment called: ptr = %p, pc = %p\n", ptr,
+ __builtin_return_address(0));
current->tss.error_code = 0;
current->tss.trap_no = 11;
force_sig (SIGBUS, current);
@@ -210,6 +209,10 @@
asmlinkage void do_undefinstr (int address, struct pt_regs *regs, int mode)
{
+#ifdef CONFIG_DEBUG_USER
+ printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n",
+ current->comm, current->pid, instruction_pointer(regs));
+#endif
current->tss.error_code = 0;
current->tss.trap_no = 6;
force_sig (SIGILL, current);
@@ -218,6 +221,10 @@
asmlinkage void do_excpt (int address, struct pt_regs *regs, int mode)
{
+#ifdef CONFIG_DEBUG_USER
+ printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n",
+ current->comm, current->pid, instruction_pointer(regs));
+#endif
current->tss.error_code = 0;
current->tss.trap_no = 11;
force_sig (SIGBUS, current);
@@ -249,19 +256,14 @@
*/
asmlinkage void math_state_restore (void)
{
- current->used_math = 1;
+ current->used_math = 1;
}
-asmlinkage void arm_syscall (int no, struct pt_regs *regs)
+asmlinkage int arm_syscall (int no, struct pt_regs *regs)
{
switch (no) {
case 0: /* branch through 0 */
force_sig(SIGSEGV, current);
-// if (user_mode(regs)) {
-// dump_state("branch through zero", regs, 0);
-// if (regs->ARM_fp)
-// c_backtrace (regs->ARM_fp, processor_mode(regs));
-// }
die_if_kernel ("branch through zero", regs, 0, SIGSEGV);
break;
@@ -271,21 +273,54 @@
force_sig (SIGTRAP, current);
break;
+ case 2: /* sys_cacheflush */
+#ifdef CONFIG_CPU_32
+ /* r0 = start, r1 = length, r2 = flags */
+ processor.u.armv3v4._flush_cache_area(regs->ARM_r0,
+ regs->ARM_r1,
+ 1);
+#endif
+ break;
+
default:
+ /* Calls 9f00xx..9f07ff are defined to return -ENOSYS
+ if not implemented, rather than raising SIGILL. This
+ way the calling program can gracefully determine whether
+ a feature is supported. */
+ if (no <= 0x7ff)
+ return -ENOSYS;
+#ifdef CONFIG_DEBUG_USER
+ /* experiance shows that these seem to indicate that
+ * something catastrophic has happened
+ */
printk ("[%d] %s: arm syscall %d\n", current->pid, current->comm, no);
- force_sig (SIGILL, current);
if (user_mode(regs)) {
show_regs (regs);
c_backtrace (regs->ARM_fp, processor_mode(regs));
}
+#endif
+ force_sig (SIGILL, current);
die_if_kernel ("Oops", regs, no, SIGILL);
break;
}
+ return 0;
}
asmlinkage void deferred(int n, struct pt_regs *regs)
{
- dump_state("old system call", regs, n);
+ /* You might think just testing `handler' would be enough, but PER_LINUX
+ points it to no_lcall7 to catch undercover SVr4 binaries. Gutted. */
+ if (current->personality != PER_LINUX && current->exec_domain->handler) {
+ /* Hand it off to iBCS. The extra parameter and consequent type
+ forcing is necessary because of the weird ARM calling convention. */
+ void (*handler)(int nr, struct pt_regs *regs) = (void *)current->exec_domain->handler;
+ (*handler)(n, regs);
+ return;
+ }
+#ifdef CONFIG_DEBUG_USER
+ printk(KERN_ERR "[%d] %s: old system call.\n", current->pid,
+ current->comm);
+#endif
force_sig (SIGILL, current);
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/lib/Makefile linux.ac/arch/arm/lib/Makefile
--- linux.vanilla/arch/arm/lib/Makefile Tue Dec 22 23:19:27 1998
+++ linux.ac/arch/arm/lib/Makefile Sun Jan 24 21:11:32 1999
@@ -6,7 +6,7 @@
L_TARGET := lib.a
L_OBJS := backtrace.o bitops.o checksum.o delay.o io.o memcpy.o \
- system.o string.o uaccess.o
+ semaphore.o string.o system.o uaccess.o
ifeq ($(PROCESSOR),armo)
L_OBJS += uaccess-armo.o
@@ -24,10 +24,6 @@
ifeq ($(MACHINE),ebsa110)
L_OBJS += io-ebsa110.o
-endif
-
-ifeq ($(MACHINE),vnc)
- L_OBJS += io-ebsa285.o
endif
ifeq ($(MACHINE),ebsa285)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/lib/checksum.S linux.ac/arch/arm/lib/checksum.S
--- linux.vanilla/arch/arm/lib/checksum.S Sun Nov 8 15:08:44 1998
+++ linux.ac/arch/arm/lib/checksum.S Sun Jan 24 21:11:32 1999
@@ -520,13 +520,13 @@
LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
ldr r4, [r0], #4
tst r2, #2
- beq Lexit
+ beq Lexit_r4
adcs r3, r3, r4, lsl #16
strb r4, [r1], #1
mov r4, r4, lsr #8
strb r4, [r1], #1
mov r4, r4, lsr #8
- b Lexit
+ b Lexit_r4
Ltoo_small: teq r2, #0
LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
@@ -538,10 +538,12 @@
adds r3, r3, ip
strb ip, [r1], #1
strb r8, [r1], #1
-Lexit: tst r2, #1
-Ltoo_small1: ldrneb ip, [r0], #1
- strneb ip, [r1], #1
- adcnes r3, r3, ip
+ tst r2, #1
+Ltoo_small1: ldrneb r4, [r0], #1
+Lexit_r4: tst r2, #1
+ strneb r4, [r1], #1
+ andne r4, r4, #255
+ adcnes r3, r3, r4
adcs r0, r3, #0
LOADREGS(ea,fp,{r4 - r8, fp, sp, pc})
@@ -598,13 +600,13 @@
adceq r0, r3, #0
LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
tst r2, #2
- beq Lexit
+ beq Lexit_r4
adcs r3, r3, r4, lsl #16
strb r4, [r1], #1
mov r4, r4, lsr #8
strb r4, [r1], #1
mov r4, r4, lsr #8
- b Lexit
+ b Lexit_r4
Lsrc2_aligned: mov r4, r4, lsr #16
adds r3, r3, #0
@@ -650,13 +652,13 @@
adceq r0, r3, #0
LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
tst r2, #2
- beq Lexit
+ beq Lexit_r4
adcs r3, r3, r4, lsl #16
strb r4, [r1], #1
mov r4, r4, lsr #8
strb r4, [r1], #1
ldrb r4, [r0], #1
- b Lexit
+ b Lexit_r4
Lsrc3_aligned: mov r4, r4, lsr #24
adds r3, r3, #0
@@ -702,14 +704,14 @@
adceq r0, r3, #0
LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
tst r2, #2
- beq Lexit
+ beq Lexit_r4
adcs r3, r3, r4, lsl #16
strb r4, [r1], #1
ldr r4, [r0], #4
strb r4, [r1], #1
adcs r3, r3, r4, lsl #24
mov r4, r4, lsr #8
- b Lexit
+ b Lexit_r4
ENTRY(__csum_ipv6_magic)
stmfd sp!, {lr}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/lib/io-ebsa285.S linux.ac/arch/arm/lib/io-ebsa285.S
--- linux.vanilla/arch/arm/lib/io-ebsa285.S Tue Dec 22 23:19:27 1998
+++ linux.ac/arch/arm/lib/io-ebsa285.S Sun Jan 24 21:11:32 1999
@@ -1,8 +1,12 @@
#include
+ .macro ioaddr, rd,rn
+ add \rd, \rn, #0xff000000
+ add \rd, \rd, #0x00e00000
+ .endm
+
ENTRY(insl)
- add r0, r0, #0xff000000
- add r0, r0, #0x00e00000
+ ioaddr r0, r0
ands ip, r1, #3
bne 2f
@@ -14,49 +18,48 @@
2: cmp ip, #2
ldr ip, [r0]
- blt 3f
- bgt 4f
+ blt 4f
+ bgt 6f
strh ip, [r1], #2
mov ip, ip, lsr #16
-1: subs r2, r2, #1
+3: subs r2, r2, #1
ldrne r3, [r0]
orrne ip, ip, r3, lsl #16
strne ip, [r1], #4
movne ip, r3, lsr #16
- bne 1b
+ bne 3b
strh ip, [r1], #2
mov pc, lr
-3: strb ip, [r1], #1
+4: strb ip, [r1], #1
mov ip, ip, lsr #8
strh ip, [r1], #2
mov ip, ip, lsr #16
-1: subs r2, r2, #1
+5: subs r2, r2, #1
ldrne r3, [r0]
orrne ip, ip, r3, lsl #8
strne ip, [r1], #4
movne ip, r3, lsr #24
- bne 1b
+ bne 5b
strb ip, [r1], #1
mov pc, lr
-4: strb ip, [r1], #1
+6: strb ip, [r1], #1
mov ip, ip, lsr #8
-1: subs r2, r2, #1
+7: subs r2, r2, #1
ldrne r3, [r0]
orrne ip, ip, r3, lsl #24
strne ip, [r1], #4
movne ip, r3, lsr #8
- bne 1b
+ bne 7b
strb ip, [r1], #1
mov ip, ip, lsr #8
strh ip, [r1], #2
mov pc, lr
ENTRY(outsl)
- add r0, r0, #0xff000000
- add r0, r0, #0x00e00000
+ ioaddr r0, r0
ands ip, r1, #3
bne 2f
@@ -70,31 +73,31 @@
cmp ip, #2
ldr ip, [r1], #4
mov ip, ip, lsr #16
- blt 3f
- bgt 4f
+ blt 4f
+ bgt 5f
-1: ldr r3, [r1], #4
+3: ldr r3, [r1], #4
orr ip, ip, r3, lsl #16
str ip, [r0]
mov ip, r3, lsr #16
subs r2, r2, #1
- bne 1b
+ bne 3b
mov pc, lr
-3: ldr r3, [r1], #4
+4: ldr r3, [r1], #4
orr ip, ip, r3, lsl #8
str ip, [r0]
mov ip, r3, lsr #24
subs r2, r2, #1
- bne 3b
+ bne 4b
mov pc, lr
-4: ldr r3, [r1], #4
+5: ldr r3, [r1], #4
orr ip, ip, r3, lsl #24
str ip, [r0]
mov ip, r3, lsr #8
subs r2, r2, #1
- bne 4b
+ bne 5b
mov pc, lr
/* Nobody could say these are optimal, but not to worry. */
@@ -102,8 +105,7 @@
ENTRY(outswb)
mov r2, r2, lsr #1
ENTRY(outsw)
- add r0, r0, #0xff000000
- add r0, r0, #0x00e00000
+ ioaddr r0, r0
1: subs r2, r2, #1
ldrgeh r3, [r1], #2
strgeh r3, [r0]
@@ -114,8 +116,7 @@
mov r2, r2, lsr #1
ENTRY(insw)
stmfd sp!, {r4, r5, lr}
- add r0, r0, #0xff000000
- add r0, r0, #0x00e00000
+ ioaddr r0, r0
@ + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17
subs ip, r2, #8
blo too_little
@@ -176,8 +177,7 @@
ENTRY(insb)
- add r0, r0, #0xff000000
- add r0, r0, #0x00e00000
+ ioaddr r0, r0
1: teq r2, #0
ldrneb r3, [r0]
strneb r3, [r1], #1
@@ -187,8 +187,7 @@
ENTRY(outsb)
- add r0, r0, #0xff000000
- add r0, r0, #0x00e00000
+ ioaddr r0, r0
1: teq r2, #0
ldrneb r3, [r1], #1
strneb r3, [r0]
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/lib/semaphore.S linux.ac/arch/arm/lib/semaphore.S
--- linux.vanilla/arch/arm/lib/semaphore.S Thu Jan 1 01:00:00 1970
+++ linux.ac/arch/arm/lib/semaphore.S Sun Jan 24 21:11:32 1999
@@ -0,0 +1,29 @@
+/*
+ * linux/arch/arm/lib/semaphore.S
+ *
+ * Idea from i386 code, Copyright Linus Torvalds.
+ * Converted for ARM by Russell King
+ */
+#include
+#include
+
+/*
+ * The semaphore operations have a special calling sequence
+ * that allows us to keep the distruption of the main code
+ * path to a minimum. These routines save and restore the
+ * registers that will be touched by __down etc.
+ */
+ENTRY(__down_failed)
+ stmfd sp!, {r0 - r3, ip, lr}
+ bl SYMBOL_NAME(__down)
+ LOADREGS(fd, sp!, {r0 - r3, ip, pc})
+
+ENTRY(__down_interruptible_failed)
+ stmfd sp!, {r1 - r3, ip, lr}
+ bl SYMBOL_NAME(__down_interruptible)
+ LOADREGS(fd, sp!, {r1 - r3, ip, pc})
+
+ENTRY(__up_wakeup)
+ stmfd sp!, {r0 - r3, ip, lr}
+ bl SYMBOL_NAME(__up)
+ LOADREGS(fd, sp!, {r0 - r3, ip, pc})
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/Makefile linux.ac/arch/arm/mm/Makefile
--- linux.vanilla/arch/arm/mm/Makefile Sun Nov 8 15:08:44 1998
+++ linux.ac/arch/arm/mm/Makefile Sun Jan 24 21:11:32 1999
@@ -22,7 +22,7 @@
endif
ifeq ($(PROCESSOR),armv)
- O_OBJS += small_page.o proc-arm6,7.o proc-sa110.o
+ O_OBJS += small_page.o proc-arm6,7.o proc-sa110.o ioremap.o
endif
include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/fault-armo.c linux.ac/arch/arm/mm/fault-armo.c
--- linux.vanilla/arch/arm/mm/fault-armo.c Tue Dec 22 23:19:28 1998
+++ linux.ac/arch/arm/mm/fault-armo.c Sun Jan 24 21:11:32 1999
@@ -157,19 +157,17 @@
bad_area:
up(&mm->mmap_sem);
if (mode & FAULT_CODE_USER) {
-//extern int console_loglevel;
-//cli();
tsk->tss.error_code = mode;
tsk->tss.trap_no = 14;
-//console_loglevel = 9;
+#ifdef CONFIG_DEBUG_USER
printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
-//#ifdef DEBUG
+#ifdef DEBUG
show_regs (regs);
c_backtrace (regs->ARM_fp, 0);
-//#endif
+#endif
+#endif
force_sig(SIGSEGV, tsk);
-//while (1);
goto out;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/fault-armv.c linux.ac/arch/arm/mm/fault-armv.c
--- linux.vanilla/arch/arm/mm/fault-armv.c Tue Dec 22 23:19:28 1998
+++ linux.ac/arch/arm/mm/fault-armv.c Sun Jan 24 21:11:32 1999
@@ -5,6 +5,7 @@
* Modifications for ARM processor (c) 1995, 1996 Russell King
*/
+#include
#include
#include
#include
@@ -16,10 +17,13 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
+#include
#define FAULT_CODE_READ 0x02
#define FAULT_CODE_USER 0x01
@@ -48,8 +52,8 @@
if (pgd) {
init = pgd_offset(&init_mm, 0);
- memzero ((void *)pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
- memcpy (pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+ memzero((void *)pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+ memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
}
return pgd;
@@ -62,14 +66,14 @@
pte = (pte_t *) get_small_page(GFP_KERNEL);
if (pmd_none(*pmd)) {
if (pte) {
- memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ memzero(pte, PTRS_PER_PTE * BYTES_PER_PTR);
set_pmd(pmd, mk_user_pmd(pte));
return pte + offset;
}
set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
return NULL;
}
- free_small_page ((unsigned long) pte);
+ free_small_page((unsigned long) pte);
if (pmd_bad(*pmd)) {
__bad_pmd(pmd);
return NULL;
@@ -84,14 +88,14 @@
pte = (pte_t *) get_small_page(GFP_KERNEL);
if (pmd_none(*pmd)) {
if (pte) {
- memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ memzero(pte, PTRS_PER_PTE * BYTES_PER_PTR);
set_pmd(pmd, mk_kernel_pmd(pte));
return pte + offset;
}
set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
return NULL;
}
- free_small_page ((unsigned long) pte);
+ free_small_page((unsigned long) pte);
if (pmd_bad(*pmd)) {
__bad_pmd_kernel(pmd);
return NULL;
@@ -102,7 +106,7 @@
extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
#ifdef DEBUG
-static int sp_valid (unsigned long *sp)
+static int sp_valid(unsigned long *sp)
{
unsigned long addr = (unsigned long) sp;
@@ -114,7 +118,7 @@
}
#endif
-static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
+static void kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs,
struct task_struct *tsk, struct mm_struct *mm)
{
/*
@@ -123,26 +127,26 @@
*/
pgd_t *pgd;
if (addr < PAGE_SIZE)
- printk (KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
else
- printk (KERN_ALERT "Unable to handle kernel paging request");
- printk (" at virtual address %08lx\n", addr);
- printk (KERN_ALERT "current->tss.memmap = %08lX\n", tsk->tss.memmap);
- pgd = pgd_offset (mm, addr);
- printk (KERN_ALERT "*pgd = %08lx", pgd_val (*pgd));
- if (!pgd_none (*pgd)) {
+ printk(KERN_ALERT "Unable to handle kernel paging request");
+ printk(" at virtual address %08lx\n", addr);
+ printk(KERN_ALERT "current->tss.memmap = %08lX\n", tsk->tss.memmap);
+ pgd = pgd_offset(mm, addr);
+ printk(KERN_ALERT "*pgd = %08lx", pgd_val(*pgd));
+ if (!pgd_none(*pgd)) {
pmd_t *pmd;
- pmd = pmd_offset (pgd, addr);
- printk (", *pmd = %08lx", pmd_val (*pmd));
- if (!pmd_none (*pmd))
- printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr)));
- }
- printk ("\n");
- die_if_kernel ("Oops", regs, mode, SIGKILL);
- do_exit (SIGKILL);
+ pmd = pmd_offset(pgd, addr);
+ printk(", *pmd = %08lx", pmd_val(*pmd));
+ if (!pmd_none(*pmd))
+ printk(", *pte = %08lx", pte_val(*pte_offset(pmd, addr)));
+ }
+ printk("\n");
+ die_if_kernel("Oops", regs, mode, SIGKILL);
+ do_exit(SIGKILL);
}
-static void page_fault (unsigned long addr, int mode, struct pt_regs *regs)
+static void do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
{
struct task_struct *tsk;
struct mm_struct *mm;
@@ -154,12 +158,12 @@
mm = tsk->mm;
down(&mm->mmap_sem);
- vma = find_vma (mm, addr);
+ vma = find_vma(mm, addr);
if (!vma)
goto bad_area;
if (vma->vm_start <= addr)
goto good_area;
- if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack (vma, addr))
+ if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack(vma, addr))
goto bad_area;
/*
@@ -174,7 +178,7 @@
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
}
- handle_mm_fault (tsk, vma, addr & PAGE_MASK, !(mode & FAULT_CODE_READ));
+ handle_mm_fault(tsk, vma, addr & PAGE_MASK, !(mode & FAULT_CODE_READ));
up(&mm->mmap_sem);
goto out;
@@ -187,21 +191,23 @@
if (mode & FAULT_CODE_USER) {
tsk->tss.error_code = mode;
tsk->tss.trap_no = 14;
- printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
+#ifdef CONFIG_DEBUG_USER
+ printk("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
#ifdef DEBUG
{
unsigned int i, j;
unsigned long *sp = (unsigned long *) (regs->ARM_sp - 128);
- for (j = 0; j < 20 && sp_valid (sp); j++) {
- printk ("%p: ", sp);
- for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++)
- printk ("%08lx ", *sp);
- printk ("\n");
+ for (j = 0; j < 20 && sp_valid(sp); j++) {
+ printk("%p: ", sp);
+ for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++)
+ printk("%08lx ", *sp);
+ printk("\n");
}
}
- show_regs (regs);
- c_backtrace (regs->ARM_fp, regs->ARM_cpsr);
+ show_regs(regs);
+ c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
+#endif
#endif
force_sig(SIGSEGV, tsk);
goto out;
@@ -209,92 +215,363 @@
/* Are we prepared to handle this kernel fault? */
if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
+#ifdef DEBUG
printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
tsk->comm, regs->ARM_pc, addr, fixup);
+#endif
regs->ARM_pc = fixup;
goto out;
}
- kernel_page_fault (addr, mode, regs, tsk, mm);
+ kernel_page_fault(addr, mode, regs, tsk, mm);
out:
unlock_kernel();
}
+#ifdef CONFIG_ALIGNMENT_TRAP
+/*
+ * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
+ * /proc/sys/debug/alignment, modified and integrated into
+ * Linux 2.1 by Russell King
+ *
+ * NOTE!!! This is not portable onto the ARM6/ARM7 processors yet. Also,
+ * it seems to give a severe performance impact (1 abort/ms - NW runs at
+ * ARM6 speeds) with GCC 2.7.2.2 - needs checking with a later GCC/EGCS.
+ *
+ * IMHO, I don't think that the trap handler is advantageous on ARM6,7
+ * processors (they'll run like an ARM3). We'll see.
+ */
+#define CODING_BITS(i) (i & 0x0e000000)
+
+#define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */
+#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */
+#define LDST_U_BIT(i) (i & (1 << 23)) /* Add offset */
+#define LDST_W_BIT(i) (i & (1 << 21)) /* Writeback */
+#define LDST_L_BIT(i) (i & (1 << 20)) /* Load */
+
+#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */
+#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */
+
+#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
+#define RD_BITS(i) ((i >> 12) & 15) /* Rd */
+#define RM_BITS(i) (i & 15) /* Rm */
+
+#define REGMASK_BITS(i) (i & 0xffff)
+#define OFFSET_BITS(i) (i & 0x0fff)
+
+#define IS_SHIFT(i) (i & 0x0ff0)
+#define SHIFT_BITS(i) ((i >> 7) & 0x1f)
+#define SHIFT_TYPE(i) (i & 0x60)
+#define SHIFT_LSL 0x00
+#define SHIFT_LSR 0x20
+#define SHIFT_ASR 0x40
+#define SHIFT_RORRRX 0x60
+
+static unsigned long ai_user;
+static unsigned long ai_sys;
+static unsigned long ai_skipped;
+static unsigned long ai_half;
+static unsigned long ai_word;
+static unsigned long ai_multi;
+
+static int proc_alignment_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ int len;
+
+ p += sprintf(p, "User:\t\t%li\n", ai_user);
+ p += sprintf(p, "System:\t\t%li\n", ai_sys);
+ p += sprintf(p, "Skipped:\t%li\n", ai_skipped);
+ p += sprintf(p, "Half:\t\t%li\n", ai_half);
+ p += sprintf(p, "Word:\t\t%li\n", ai_word);
+ p += sprintf(p, "Multi:\t\t%li\n", ai_multi);
+
+ len = (p - page) - off;
+ if (len < 0)
+ len = 0;
+
+ *eof = (len <= count) ? 1 : 0;
+ *start = page + off;
+
+ return len;
+}
+
/*
- * Handle a data abort. Note that we have to handle a range of addresses
- * on ARM2/3 for ldm. If both pages are zero-mapped, then we have to force
- * a copy-on-write
+ * This needs to be done after sysctl_init, otherwise sys/
+ * will be overwritten.
*/
+void __init alignment_init(void)
+{
+ struct proc_dir_entry *e;
+
+ e = create_proc_entry("sys/debug/alignment", S_IFREG | S_IRUGO, NULL);
+
+ if (e)
+ e->read_proc = proc_alignment_read;
+}
+
+static void
+do_alignment_exception(struct pt_regs *regs)
+{
+ unsigned int instr, rd, rn, correction, nr_regs, regbits;
+ unsigned long eaddr;
+ union { unsigned long un; signed long sn; } offset;
+
+ if (user_mode(regs)) {
+ set_cr(cr_no_alignment);
+ ai_user += 1;
+ return;
+ }
+
+ ai_sys += 1;
+
+ instr = *(unsigned long *)instruction_pointer(regs);
+ correction = 4; /* sometimes 8 on ARMv3 */
+ regs->ARM_pc += correction + 4;
+
+ rd = RD_BITS(instr);
+ rn = RN_BITS(instr);
+ eaddr = regs->uregs[rn];
+
+ switch(CODING_BITS(instr)) {
+ case 0x00000000:
+ if ((instr & 0x0ff00ff0) == 0x01000090) {
+ ai_skipped += 1;
+ printk(KERN_ERR "Unaligned trap: not handling swp instruction\n");
+ break;
+ }
+
+ if (((instr & 0x0e000090) == 0x00000090) && (instr & 0x60) != 0) {
+ ai_half += 1;
+ if (LDSTH_I_BIT(instr))
+ offset.un = (instr & 0xf00) >> 4 | (instr & 15);
+ else
+ offset.un = regs->uregs[RM_BITS(instr)];
+
+ if (LDST_P_BIT(instr)) {
+ if (LDST_U_BIT(instr))
+ eaddr += offset.un;
+ else
+ eaddr -= offset.un;
+ }
+
+ if (LDST_L_BIT(instr))
+ regs->uregs[rd] = get_unaligned((unsigned short *)eaddr);
+ else
+ put_unaligned(regs->uregs[rd], (unsigned short *)eaddr);
+
+ /* signed half-word? */
+ if (instr & 0x40)
+ regs->uregs[rd] = (long)((short) regs->uregs[rd]);
+
+ if (!LDST_P_BIT(instr)) {
+ if (LDST_U_BIT(instr))
+ eaddr += offset.un;
+ else
+ eaddr -= offset.un;
+ regs->uregs[rn] = eaddr;
+ } else if (LDST_W_BIT(instr))
+ regs->uregs[rn] = eaddr;
+ break;
+ }
+
+ default:
+ ai_skipped += 1;
+ panic("Alignment trap: not handling instruction %08X at %08lX",
+ instr, regs->ARM_pc - correction - 4);
+ break;
+
+ case 0x04000000:
+ offset.un = OFFSET_BITS(instr);
+ goto ldr_str;
+
+ case 0x06000000:
+ offset.un = regs->uregs[RM_BITS(instr)];
+
+ if (IS_SHIFT(instr)) {
+ unsigned int shiftval = SHIFT_BITS(instr);
+
+ switch(SHIFT_TYPE(instr)) {
+ case SHIFT_LSL:
+ offset.un <<= shiftval;
+ break;
+
+ case SHIFT_LSR:
+ offset.un >>= shiftval;
+ break;
+
+ case SHIFT_ASR:
+ offset.sn >>= shiftval;
+ break;
+
+ case SHIFT_RORRRX:
+ if (shiftval == 0) {
+ offset.un >>= 1;
+ if (regs->ARM_cpsr & CC_C_BIT)
+ offset.un |= 1 << 31;
+ } else
+ offset.un = offset.un >> shiftval |
+ offset.un << (32 - shiftval);
+ break;
+ }
+ }
+
+ ldr_str:
+ ai_word += 1;
+ if (LDST_P_BIT(instr)) {
+ if (LDST_U_BIT(instr))
+ eaddr += offset.un;
+ else
+ eaddr -= offset.un;
+ } else {
+ if (LDST_W_BIT(instr))
+ printk(KERN_ERR "Not handling ldrt/strt correctly\n");
+ }
+
+ if (LDST_L_BIT(instr)) {
+ regs->uregs[rd] = get_unaligned((unsigned long *)eaddr);
+ if (rd == 15)
+ correction = 0;
+ } else
+ put_unaligned(regs->uregs[rd], (unsigned long *)eaddr);
+
+ if (!LDST_P_BIT(instr)) {
+ if (LDST_U_BIT(instr))
+ eaddr += offset.un;
+ else
+ eaddr -= offset.un;
+
+ regs->uregs[rn] = eaddr;
+ } else if (LDST_W_BIT(instr))
+ regs->uregs[rn] = eaddr;
+ break;
+
+ case 0x08000000:
+ if (LDM_S_BIT(instr))
+ panic("Alignment trap: not handling LDM with s-bit\n");
+ ai_multi += 1;
+
+ for (regbits = REGMASK_BITS(instr), nr_regs = 0; regbits; regbits >>= 1)
+ nr_regs += 4;
+
+ if (!LDST_U_BIT(instr))
+ eaddr -= nr_regs;
+
+ if ((LDST_U_BIT(instr) == 0 && LDST_P_BIT(instr) == 0) ||
+ (LDST_U_BIT(instr) && LDST_P_BIT(instr)))
+ eaddr += 4;
+
+ for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1)
+ if (regbits & 1) {
+ if (LDST_L_BIT(instr)) {
+ regs->uregs[rd] = get_unaligned((unsigned long *)eaddr);
+ if (rd == 15)
+ correction = 0;
+ } else
+ put_unaligned(regs->uregs[rd], (unsigned long *)eaddr);
+ eaddr += 4;
+ }
+
+ if (LDST_W_BIT(instr)) {
+ if (LDST_P_BIT(instr) && !LDST_U_BIT(instr))
+ eaddr -= nr_regs;
+ else if (LDST_P_BIT(instr))
+ eaddr -= 4;
+ else if (!LDST_U_BIT(instr))
+ eaddr -= 4 + nr_regs;
+ regs->uregs[rn] = eaddr;
+ }
+ break;
+ }
+
+ regs->ARM_pc -= correction;
+}
+
+#endif
+
asmlinkage void
-do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
+do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
{
if (user_mode(regs))
error_code |= FAULT_CODE_USER;
+
#define DIE(signr,nam)\
force_sig(signr, current);\
die_if_kernel(nam, regs, fsr, signr);\
- break;
+ break
switch (fsr & 15) {
case 2:
- DIE(SIGKILL, "Terminal exception")
+ DIE(SIGKILL, "Terminal exception");
case 0:
- DIE(SIGSEGV, "Vector exception")
+ DIE(SIGSEGV, "Vector exception");
case 1:
case 3:
- DIE(SIGBUS, "Alignment exception")
+#ifdef CONFIG_ALIGNMENT_TRAP
+ do_alignment_exception(regs);
+#else
+ /* this should never happen */
+ DIE(SIGBUS, "Alignment exception");
+#endif
+ break;
+
case 12:
case 14:
- DIE(SIGBUS, "External abort on translation")
+ DIE(SIGBUS, "External abort on translation");
case 9:
case 11:
- DIE(SIGSEGV, "Domain fault")
+ DIE(SIGSEGV, "Domain fault");
case 13:/* permission fault on section */
+#ifdef CONFIG_DEBUG_USER
+ printk("%s: permission fault on section, address=0x%08lx, code %d\n",
+ current->comm, addr, error_code);
#ifdef DEBUG
{
unsigned int i, j;
unsigned long *sp;
- printk ("%s: section permission fault (bad address=0x%08lx, code %d)\n",
- current->comm, addr, error_code);
sp = (unsigned long *) (regs->ARM_sp - 128);
- for (j = 0; j < 20 && sp_valid (sp); j++) {
- printk ("%p: ", sp);
- for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++)
- printk ("%08lx ", *sp);
- printk ("\n");
+ for (j = 0; j < 20 && sp_valid(sp); j++) {
+ printk("%p: ", sp);
+ for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++)
+ printk("%08lx ", *sp);
+ printk("\n");
}
- show_regs (regs);
+ show_regs(regs);
c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
}
#endif
- DIE(SIGSEGV, "Permission fault")
+#endif
+ DIE(SIGSEGV, "Permission fault");
case 15:/* permission fault on page */
case 5: /* page-table entry descriptor fault */
case 7: /* first-level descriptor fault */
- page_fault (addr, error_code, regs);
+ do_page_fault(addr, error_code, regs);
break;
case 4:
case 6:
- DIE(SIGBUS, "External abort on linefetch")
+ DIE(SIGBUS, "External abort on linefetch");
case 8:
case 10:
- DIE(SIGBUS, "External abort on non-linefetch")
+ DIE(SIGBUS, "External abort on non-linefetch");
}
}
asmlinkage int
-do_PrefetchAbort (unsigned long addr, struct pt_regs *regs)
+do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
{
#if 0
- /* does this still apply ? */
+ /* does this still apply? It doesn't seem to happen, so
+ * I guess not.
+ */
if (the memc mapping for this page exists - can check now...) {
- printk ("Page in, but got abort (undefined instruction?)\n");
+ printk("Page in, but got abort (undefined instruction?)\n");
return 0;
}
#endif
- page_fault (addr, FAULT_CODE_USER|FAULT_CODE_READ, regs);
+ do_page_fault(addr, FAULT_CODE_USER|FAULT_CODE_READ, regs);
return 1;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/init.c linux.ac/arch/arm/mm/init.c
--- linux.vanilla/arch/arm/mm/init.c Tue Dec 22 23:19:28 1998
+++ linux.ac/arch/arm/mm/init.c Sun Jan 24 21:11:32 1999
@@ -137,6 +137,9 @@
flush_tlb_all();
update_memc_all();
+ end_mem &= PAGE_MASK;
+ high_memory = (void *)end_mem;
+
return free_area_init(start_mem, end_mem);
}
@@ -161,19 +164,18 @@
/* mark usable pages in the mem_map[] */
mark_usable_memory_areas(&start_mem, end_mem);
+#define BETWEEN(w,min,max) ((w) >= (unsigned long)(min) && \
+ (w) < (unsigned long)(max))
+
for (tmp = PAGE_OFFSET; tmp < end_mem ; tmp += PAGE_SIZE) {
if (PageReserved(mem_map+MAP_NR(tmp))) {
- if (tmp >= KERNTOPHYS(_stext) &&
- tmp < KERNTOPHYS(_edata)) {
- if (tmp < KERNTOPHYS(_etext))
- codepages++;
- else
- datapages++;
- } else if (tmp >= KERNTOPHYS(__init_begin)
- && tmp < KERNTOPHYS(__init_end))
+ if (BETWEEN(tmp, &__init_begin, &__init_end))
initpages++;
- else if (tmp >= KERNTOPHYS(__bss_start)
- && tmp < (unsigned long) start_mem)
+ else if (BETWEEN(tmp, &_stext, &_etext))
+ codepages++;
+ else if (BETWEEN(tmp, &_etext, &_edata))
+ datapages++;
+ else if (BETWEEN(tmp, &__bss_start, start_mem))
datapages++;
else
reservedpages++;
@@ -181,13 +183,16 @@
}
atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
#ifdef CONFIG_BLK_DEV_INITRD
- if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end))
+ if (!initrd_start || !BETWEEN(tmp, initrd_start, initrd_end))
#endif
free_page(tmp);
}
- printk ("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+
+#undef BETWEEN
+
+ printk ("Memory: %luk/%luM available (%dk code, %dk reserved, %dk data, %dk init)\n",
(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
- max_mapnr << (PAGE_SHIFT-10),
+ max_mapnr >> (20 - PAGE_SHIFT),
codepages << (PAGE_SHIFT-10),
reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
@@ -203,17 +208,45 @@
#endif
}
-void free_initmem (void)
+static void free_area(unsigned long addr, unsigned long end, char *s)
{
- unsigned long addr;
+ unsigned int size = (end - addr) >> 10;
- addr = (unsigned long)(&__init_begin);
- for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ for (; addr < end; addr += PAGE_SIZE) {
mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
atomic_set(&mem_map[MAP_NR(addr)].count, 1);
free_page(addr);
}
- printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+
+ if (size)
+ printk(" %dk %s", size, s);
+}
+
+void free_initmem (void)
+{
+ printk("Freeing unused kernel memory:");
+
+ free_area((unsigned long)(&__init_begin),
+ (unsigned long)(&__init_end),
+ "init");
+
+#ifdef CONFIG_FOOTBRIDGE
+ {
+ extern int __netwinder_begin, __netwinder_end, __ebsa285_begin, __ebsa285_end;
+
+ if (!machine_is_netwinder())
+ free_area((unsigned long)(&__netwinder_begin),
+ (unsigned long)(&__netwinder_end),
+ "netwinder");
+
+ if (!machine_is_ebsa285() && !machine_is_cats())
+ free_area((unsigned long)(&__ebsa285_begin),
+ (unsigned long)(&__ebsa285_end),
+ "ebsa285/cats");
+ }
+#endif
+
+ printk("\n");
}
void si_meminfo(struct sysinfo *val)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/ioremap.c linux.ac/arch/arm/mm/ioremap.c
--- linux.vanilla/arch/arm/mm/ioremap.c Thu Jan 1 01:00:00 1970
+++ linux.ac/arch/arm/mm/ioremap.c Sun Jan 24 21:11:32 1999
@@ -0,0 +1,153 @@
+/*
+ * arch/arm/mm/ioremap.c
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ *
+ * Hacked for ARM by Phil Blundell
+ * Hacked to allow all architectures to build, and various cleanups
+ * by Russell King
+ */
+
+/*
+ * This allows a driver to remap an arbitrary region of bus memory into
+ * virtual space. One should *only* use readl, writel, memcpy_toio and
+ * so on with such remapped areas.
+ *
+ * Because the ARM only has a 32-bit address space we can't address the
+ * whole of the (physical) PCI space at once. PCI huge-mode addressing
+ * allows us to circumvent this restriction by splitting PCI space into
+ * two 2GB chunks and mapping only one at a time into processor memory.
+ * We use MMU protection domains to trap any attempt to access the bank
+ * that is not currently mapped. (This isn't fully implemented yet.)
+ *
+ * DC21285 currently has a bug in that the PCI address extension
+ * register affects the address of any writes waiting in the outbound
+ * FIFO. Unfortunately, it is not possible to tell the DC21285 to
+ * flush this - flushing the area causes the bus to lock.
+ */
+
+#include
+#include
+
+/*
+ * Only include this if we have valid_ioaddr() is defined
+ */
+#ifdef valid_ioaddr
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+ unsigned long phys_addr, pgprot_t pgprot)
+{
+ unsigned long end;
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ if (!pte_none(*pte))
+ printk("remap_area_pte: page already exists\n");
+ set_pte(pte, mk_pte_phys(phys_addr, pgprot));
+ address += PAGE_SIZE;
+ phys_addr += PAGE_SIZE;
+ pte++;
+ } while (address < end);
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+ unsigned long phys_addr, unsigned long flags)
+{
+ unsigned long end;
+ pgprot_t pgprot;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+
+ phys_addr -= address;
+ pgprot = __pgprot(PTE_TYPE_SMALL | _PTE_WRITE | flags);
+ do {
+ pte_t * pte = pte_alloc_kernel(pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ remap_area_pte(pte, address, end - address, address + phys_addr, pgprot);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address < end);
+ return 0;
+}
+
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+ unsigned long size, unsigned long flags)
+{
+ pgd_t * dir;
+ unsigned long end = address + size;
+
+ phys_addr -= address;
+ dir = pgd_offset(&init_mm, address);
+ flush_cache_all();
+ while (address < end) {
+ pmd_t *pmd = pmd_alloc_kernel(dir, address);
+ if (!pmd)
+ return -ENOMEM;
+ if (remap_area_pmd(pmd, address, end - address,
+ phys_addr + address, flags))
+ return -ENOMEM;
+ set_pgdir(address, *dir);
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ }
+ flush_tlb_all();
+ return 0;
+}
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+ void * addr;
+ struct vm_struct * area;
+ unsigned long offset;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ size = PAGE_ALIGN(size + offset);
+
+ /*
+ * Don't allow mappings that wrap..
+ */
+ if (!size || size > phys_addr + size)
+ return NULL;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size);
+ if (!area)
+ return NULL;
+ addr = area->addr;
+ if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+ return (void *) (offset + (char *)addr);
+}
+
+void iounmap(void *addr)
+{
+ return vfree((void *) (PAGE_MASK & (unsigned long) addr));
+}
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/mm-ebsa285.c linux.ac/arch/arm/mm/mm-ebsa285.c
--- linux.vanilla/arch/arm/mm/mm-ebsa285.c Tue Dec 22 23:19:28 1998
+++ linux.ac/arch/arm/mm/mm-ebsa285.c Sun Jan 24 21:11:32 1999
@@ -16,24 +16,23 @@
#include
/*
- * This is to allow us to fiddle with the EEPROM
- * This entry will go away in time, once the fmu
- * can mmap() the flash.
+ * The first entry allows us to fiddle with the EEPROM from user-space.
+ * This entry will go away in time, once the fmu32 can mmap() the
+ * flash. It can't at the moment.
*
- * These ones are so that we can fiddle
- * with the various cards (eg VGA)
- * until we're happy with them...
+ * If you want to fiddle with PCI VGA cards from user space, then
+ * change the '0, 1 }' for the PCI MEM and PCI IO to '1, 1 }'
+ * You can then access the PCI bus at 0xe0000000 and 0xffe00000.
*/
#define MAPPING \
{ 0xd8000000, DC21285_FLASH, 0x00400000, DOMAIN_USER, 1, 1 }, /* EEPROM */ \
- { 0xdc000000, 0x7c000000, 0x00100000, DOMAIN_USER, 1, 1 }, /* VGA */ \
- { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_USER, 1, 1 }, /* VGA */ \
+ { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_IO , 0, 1 }, /* PCI memory */ \
{ 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \
{ 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \
{ PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \
{ 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \
- { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \
- { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \
+ { ARMCSR_BASE,DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \
+ { PCIO_BASE, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \
{ 0xfff00000, 0x40000000, 0x00100000, DOMAIN_IO , 0, 1 }, /* X-Bus */
#include "mm-armv.c"
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/mm-vnc.c linux.ac/arch/arm/mm/mm-vnc.c
--- linux.vanilla/arch/arm/mm/mm-vnc.c Tue Dec 22 23:19:28 1998
+++ linux.ac/arch/arm/mm/mm-vnc.c Thu Jan 1 01:00:00 1970
@@ -1,31 +0,0 @@
-/*
- * arch/arm/mm/mm-vnc.c
- *
- * Extra MM routines for the Corel VNC architecture
- *
- * Copyright (C) 1998 Russell King
- */
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-/* Table describing the MMU translation mapping
- * mainly used to set up the I/O mappings.
- */
-#define MAPPING \
- { 0xd0000000, DC21285_FLASH, 0x00800000, DOMAIN_IO , 0, 1 }, /* Flash */ \
- { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_IO , 0, 1 }, /* PCI Mem */ \
- { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \
- { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \
- { PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \
- { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \
- { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \
- { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \
-
-#include "mm-armv.c"
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/mm/proc-sa110.S linux.ac/arch/arm/mm/proc-sa110.S
--- linux.vanilla/arch/arm/mm/proc-sa110.S Tue Dec 22 23:19:28 1998
+++ linux.ac/arch/arm/mm/proc-sa110.S Sun Jan 24 21:11:32 1999
@@ -8,6 +8,7 @@
*/
#include
#include
+#include
#include "../lib/constants.h"
/* This is the maximum size of an area which will be flushed. If the area
@@ -21,7 +22,6 @@
/*
* Function: sa110_flush_cache_all (void)
- *
* Purpose : Flush all cache lines
*/
.align 5
@@ -33,7 +33,7 @@
ands r1, r1, #1
eor r1, r1, #1
str r1, [r3]
- ldr ip, =0xdf000000
+ ldr ip, =FLUSH_BASE
addne ip, ip, #32768
add r1, ip, #16384 @ only necessary for 16k
1: ldr r3, [ip], #32
@@ -47,11 +47,9 @@
/*
* Function: sa110_flush_cache_area (unsigned long address, int end, int flags)
- *
* Params : address Area start address
* : end Area end address
* : flags b0 = I cache as well
- *
* Purpose : clean & flush all cache lines associated with this area of memory
*/
.align 5
@@ -74,10 +72,8 @@
/*
* Function: sa110_cache_wback_area(unsigned long address, unsigned long end)
- *
* Params : address Area start address
* : end Area end address
- *
* Purpose : ensure all dirty cachelines in the specified area have been
* written out to memory (for DMA)
*/
@@ -99,13 +95,10 @@
/*
* Function: sa110_cache_purge_area(unsigned long address, unsigned long end)
- *
* Params : address Area start address
* : end Area end address
- *
* Purpose : throw away all D-cached data in specified region without
* an obligation to write it ack.
- *
* Note : Must clean the D-cached entries around the boundaries if the
* start and/or end address are not cache aligned.
*/
@@ -124,9 +117,7 @@
/*
* Function: sa110_flush_cache_entry (unsigned long address)
- *
* Params : address Address of cache line to flush
- *
* Purpose : clean & flush an entry
*/
.align 5
@@ -139,9 +130,7 @@
/*
* Function: sa110_flush_cache_pte (unsigned long address)
- *
* Params : address Address of cache line to clean
- *
* Purpose : Ensure that physical memory reflects cache at this location
* for page table purposes.
*/
@@ -151,11 +140,9 @@
/*
* Function: sa110_flush_ram_page (unsigned long page)
- *
* Params : address Area start address
* : size size of area
* : flags b0 = I cache as well
- *
* Purpose : clean & flush all cache lines associated with this area of memory
*/
.align 5
@@ -176,7 +163,6 @@
/*
* Function: sa110_flush_tlb_all (void)
- *
* Purpose : flush all TLB entries in all caches
*/
.align 5
@@ -188,11 +174,9 @@
/*
* Function: sa110_flush_tlb_area (unsigned long address, unsigned long end, int flags)
- *
* Params : address Area start address
* : end Area end address
* : flags b0 = I cache as well
- *
* Purpose : flush a TLB entry
*/
.align 5
@@ -221,13 +205,10 @@
mov pc, lr
/*
* Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next)
- *
* Params : prev Old task structure
* : next New task structure for process to run
- *
* Purpose : Perform a task switch, saving the old processes state, and restoring
* the new.
- *
* Notes : We don't fiddle with the FP registers here - we postpone this until
* the new task actually uses FP. This way, we don't swap FP for tasks
* that do not require it.
@@ -237,6 +218,7 @@
stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack
mrs ip, cpsr
stmfd sp!, {ip} @ Save cpsr_SVC
+@ ldr r2, [r0, #TSS_MEMMAP] @ Get old page tables
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
ldr r0, [r1, #TSK_ADDR_LIMIT]
@@ -245,12 +227,21 @@
movne r0, #DOM_USERDOMAIN
mcr p15, 0, r0, c3, c0 @ Set segment
ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer
+/*
+ * Flushing the cache is nightmarishly slow, so we take any excuse
+ * to get out of it. If the old page table is the same as the new,
+ * this is a CLONE_VM relative of the old task and there is no need
+ * to flush. The overhead of the tests isn't even on the radar
+ * compared to the cost of the flush itself.
+ */
+ teq r0, r2
+ beq 2f
ldr r3, =Lclean_switch
ldr r2, [r3]
ands r2, r2, #1
eor r2, r2, #1
str r2, [r3]
- ldr r2, =0xdf000000
+ ldr r2, =FLUSH_BASE
addne r2, r2, #32768
add r1, r2, #16384 @ only necessary for 16k
1: ldr r3, [r2], #32
@@ -261,17 +252,14 @@
mcr p15, 0, r1, c7, c10, 4 @ drain WB
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
mcr p15, 0, r1, c8, c7, 0 @ flush TLBs
- ldmfd sp!, {ip}
+2: ldmfd sp!, {ip}
msr spsr, ip @ Save tasks CPSR into SPSR for this return
ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously
/*
* Function: sa110_data_abort ()
- *
* Params : r0 = address of aborted instruction
- *
* Purpose : obtain information about current aborted instruction
- *
* Returns : r0 = address of abort
* : r1 = FSR
* : r2 != 0 if writing
@@ -289,10 +277,8 @@
/*
* Function: sa110_set_pmd ()
- *
* Params : r0 = Address to set
* : r1 = value to set
- *
* Purpose : Set a PMD and flush it out of any WB cache
*/
.align 5
@@ -304,20 +290,19 @@
* Function: sa110_check_bugs (void)
* : sa110_proc_init (void)
* : sa110_proc_fin (void)
- *
* Notes : This processor does not require these
*/
_sa110_check_bugs:
mrs ip, cpsr
bic ip, ip, #F_BIT
msr cpsr, ip
+
_sa110_proc_init:
_sa110_proc_fin:
mov pc, lr
/*
* Function: sa110_reset
- *
* Notes : This sets up everything for a reset
*/
_sa110_reset: mrs r1, cpsr
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/vmlinux-armv.lds linux.ac/arch/arm/vmlinux-armv.lds
--- linux.vanilla/arch/arm/vmlinux-armv.lds Sun Nov 8 15:08:45 1998
+++ linux.ac/arch/arm/vmlinux-armv.lds Sun Jan 24 21:11:32 1999
@@ -7,50 +7,64 @@
ENTRY(_start)
SECTIONS
{
- _text = .; /* Text and read-only data */
- .text : {
+ _text = .; /* Text and read-only data */
+ .text : { } /* Set text start address */
+
+ __init_begin = .; /* Init code and data */
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __ebsa285_begin = .;
+ .text.ebsa285 : { *(.text.ebsa285) }
+ .data.ebsa285 : { *(.data.ebsa285) }
+ . = ALIGN(4096);
+ __ebsa285_end = .;
+
+ __netwinder_begin = .;
+ .text.netwinder : { *(.text.netwinder) }
+ .data.netwinder : { *(.data.netwinder) }
+ . = ALIGN(4096);
+ __netwinder_end = .;
+
+ .text.real : { /* Real text segment */
*(.text)
*(.fixup)
*(.gnu.warning)
- } = 0x9090
+ }
+
.text.lock : { *(.text.lock) } /* out-of-line lock text */
.rodata : { *(.rodata) }
.kstrtab : { *(.kstrtab) }
- . = ALIGN(16); /* Exception table */
+ . = ALIGN(16); /* Exception table */
__start___ex_table = .;
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
- __start___ksymtab = .; /* Kernel symbol table */
+ __start___ksymtab = .; /* Kernel symbol table */
__ksymtab : { *(__ksymtab) }
__stop___ksymtab = .;
- _etext = .; /* End of text section */
+ _etext = .; /* End of text section */
. = ALIGN(8192);
- .data : { /* Data */
+ .data : { /* Data */
*(.init.task)
*(.data)
CONSTRUCTORS
}
- _edata = .; /* End of data section */
-
- . = ALIGN(4096); /* Init code and data */
- __init_begin = .;
- .text.init : { *(.text.init) }
- .data.init : { *(.data.init) }
- . = ALIGN(4096);
- __init_end = .;
+ _edata = .; /* End of data section */
- __bss_start = .; /* BSS */
+ __bss_start = .; /* BSS */
.bss : {
*(.bss)
}
_end = . ;
- /* Stabs debugging sections. */
+ /* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/defconfig linux.ac/arch/i386/defconfig
--- linux.vanilla/arch/i386/defconfig Tue Feb 23 14:21:32 1999
+++ linux.ac/arch/i386/defconfig Fri Feb 26 01:59:54 1999
@@ -104,7 +104,6 @@
CONFIG_PACKET=y
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -121,7 +120,6 @@
# (it is safe to leave these untouched)
#
# CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
#
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/init_task.c linux.ac/arch/i386/kernel/init_task.c
--- linux.vanilla/arch/i386/kernel/init_task.c Sun Nov 8 15:08:22 1998
+++ linux.ac/arch/i386/kernel/init_task.c Fri Dec 4 17:14:23 1998
@@ -7,7 +7,6 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/mca.c linux.ac/arch/i386/kernel/mca.c
--- linux.vanilla/arch/i386/kernel/mca.c Sun Nov 8 15:08:22 1998
+++ linux.ac/arch/i386/kernel/mca.c Fri Feb 26 01:54:39 1999
@@ -747,10 +747,10 @@
mca_info->slot[slot].pos[1], mca_info->slot[slot].pos[0] );
len += sprintf( buf+len, "Enabled: %s\nPOS: ",
mca_isenabled(slot) ? "Yes" : "No" );
- len += sprintf( buf+len, "Driver Installed: %s\n",
- mca_is_adapter_used(slot) ? "Yes" : "No" );
for (i=0; i<8; i++) {
len += sprintf(buf+len, "%02x ", mca_info->slot[slot].pos[i]);
+ len += sprintf( buf+len, "\nDriver Installed: %s\n",
+ mca_is_adapter_used(slot) ? "Yes" : "No" );
}
buf[len++] = '\n';
buf[len] = 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/ptrace.c linux.ac/arch/i386/kernel/ptrace.c
--- linux.vanilla/arch/i386/kernel/ptrace.c Thu Jan 14 01:25:21 1999
+++ linux.ac/arch/i386/kernel/ptrace.c Wed Feb 24 16:38:51 1999
@@ -354,6 +354,7 @@
{
struct task_struct *child;
struct user * dummy = NULL;
+ unsigned long flags;
int i, ret;
lock_kernel();
@@ -391,15 +392,15 @@
if (child->flags & PF_PTRACED)
goto out;
child->flags |= PF_PTRACED;
- if (child->p_pptr != current) {
- unsigned long flags;
- write_lock_irqsave(&tasklist_lock, flags);
+ write_lock_irqsave(&tasklist_lock, flags);
+ if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
- write_unlock_irqrestore(&tasklist_lock, flags);
}
+ write_unlock_irqrestore(&tasklist_lock, flags);
+
send_sig(SIGSTOP, child, 1);
ret = 0;
goto out;
@@ -559,7 +560,6 @@
}
case PTRACE_DETACH: { /* detach a process that was attached. */
- unsigned long flags;
long tmp;
ret = -EIO;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/setup.c linux.ac/arch/i386/kernel/setup.c
--- linux.vanilla/arch/i386/kernel/setup.c Tue Feb 23 14:21:32 1999
+++ linux.ac/arch/i386/kernel/setup.c Fri Feb 26 23:26:38 1999
@@ -381,7 +381,17 @@
}
-__initfunc(static int amd_model(struct cpuinfo_x86 *c))
+#define rdmsr(msr,val1,val2) \
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (val1), "=d" (val2) \
+ : "c" (msr))
+
+#define wrmsr(msr,val1,val2) \
+ __asm__ __volatile__("wrmsr" \
+ : /* no outputs */ \
+ : "c" (msr), "a" (val1), "d" (val2))
+
+__initfunc(static int get_model_name(struct cpuinfo_x86 *c))
{
unsigned int n, dummy, *v;
@@ -401,6 +411,76 @@
return 1;
}
+__initfunc(static int amd_model(struct cpuinfo_x86 *c))
+{
+ u32 l, h;
+ unsigned long flags;
+ int mbytes = max_mapnr >> (20-PAGE_SHIFT);
+
+ int r=get_model_name(c);
+
+ /*
+ * Now do the cache operations.
+ */
+
+ switch(c->x86)
+ {
+ case 5:
+ if( c->x86_model < 6 )
+ {
+ /* Anyone with a K5 want to fill this in */
+ break;
+ }
+
+ /* K6 with old style WHCR */
+ if( c->x86_model < 8 ||
+ (c->x86_model== 8 && c->x86_mask < 8))
+ {
+ /* We can only write allocate on the low 508Mb */
+ if(mbytes>508)
+ mbytes=508;
+
+ rdmsr(0xC0000082, l, h);
+ if(l==0 && h==0)
+ {
+ l=(1<<0)|(mbytes/4);
+ save_flags(flags);
+ __cli();
+ __asm__ __volatile__ ("wbinvd": : :"memory");
+ wrmsr(0xC0000082, l, h);
+ restore_flags(flags);
+ printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
+ mbytes);
+
+ }
+ break;
+ }
+ if (c->x86_model == 8 || c->x86_model == 9)
+ {
+ /* The more serious chips .. */
+
+ if(mbytes>4092)
+ mbytes=4092;
+ rdmsr(0xC0000082, l, h);
+ if(l==0 && h==0)
+ {
+ l=(mbytes<<22)|(1<<16);
+ save_flags(flags);
+ __cli();
+ __asm__ __volatile__ ("wbinvd": : :"memory");
+ wrmsr(0xC0000082, l, h);
+ restore_flags(flags);
+ printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n",
+ mbytes);
+ }
+ break;
+ }
+ break;
+ }
+ return r;
+}
+
+
/*
* Read Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
*/
@@ -517,7 +597,7 @@
/* GXm supports extended cpuid levels 'ala' AMD */
if (c->cpuid_level == 2) {
- amd_model(c); /* get CPU marketing name */
+ get_model_name(c); /* get CPU marketing name */
c->x86_capability&=~X86_FEATURE_TSC;
return;
}
@@ -726,15 +806,6 @@
}
-#define rdmsr(msr,val1,val2) \
- __asm__ __volatile__("rdmsr" \
- : "=a" (val1), "=d" (val2) \
- : "c" (msr))
-
-#define wrmsr(msr,val1,val2) \
- __asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (msr), "a" (val1), "d" (val2))
static char *cpu_vendor_names[] __initdata = {
"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" };
@@ -785,8 +856,8 @@
static char *x86_cap_flags[] = {
"fpu", "vme", "de", "pse", "tsc", "msr", "6", "mce",
"cx8", "9", "10", "sep", "12", "pge", "14", "cmov",
- "16", "17", "18", "19", "20", "21", "22", "mmx",
- "24", "25", "26", "27", "28", "29", "30", "31"
+ "16", "17", "snum", "19", "20", "21", "22", "mmx",
+ "24", "kni", "26", "27", "28", "29", "30", "31"
};
struct cpuinfo_x86 *c = cpu_data;
int i, n;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/m68k/defconfig linux.ac/arch/m68k/defconfig
--- linux.vanilla/arch/m68k/defconfig Sun Jan 24 19:55:30 1999
+++ linux.ac/arch/m68k/defconfig Fri Feb 26 01:59:54 1999
@@ -78,7 +78,6 @@
CONFIG_PACKET=y
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -95,7 +94,6 @@
# (it is safe to leave these untouched)
#
# CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
# CONFIG_SKB_LARGE is not set
# CONFIG_IPV6 is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/m68k/kernel/process.c linux.ac/arch/m68k/kernel/process.c
--- linux.vanilla/arch/m68k/kernel/process.c Sun Jan 24 19:55:31 1999
+++ linux.ac/arch/m68k/kernel/process.c Sun Jan 24 20:22:53 1999
@@ -40,7 +40,6 @@
*/
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/defconfig linux.ac/arch/mips/defconfig
--- linux.vanilla/arch/mips/defconfig Sun Nov 8 15:08:30 1998
+++ linux.ac/arch/mips/defconfig Fri Feb 26 01:59:54 1999
@@ -90,7 +90,6 @@
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -107,7 +106,6 @@
# (it is safe to leave these untouched)
#
# CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
# CONFIG_SKB_LARGE is not set
#
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/init_task.c linux.ac/arch/mips/kernel/init_task.c
--- linux.vanilla/arch/mips/kernel/init_task.c Sun Nov 8 15:08:29 1998
+++ linux.ac/arch/mips/kernel/init_task.c Fri Dec 4 17:14:23 1998
@@ -6,7 +6,6 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct files * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irixioctl.c linux.ac/arch/mips/kernel/irixioctl.c
--- linux.vanilla/arch/mips/kernel/irixioctl.c Sun Nov 8 15:08:29 1998
+++ linux.ac/arch/mips/kernel/irixioctl.c Fri Dec 4 17:14:23 1998
@@ -33,7 +33,7 @@
{
struct file *filp;
- if(fd >= NR_OPEN || !(filp = current->files->fd[fd]))
+ if(fd >= current->files->max_fds || !(filp = current->files->fd[fd]))
return ((struct tty_struct *) 0);
if(filp->private_data) {
struct tty_struct *ttyp = (struct tty_struct *) filp->private_data;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/sysirix.c linux.ac/arch/mips/kernel/sysirix.c
--- linux.vanilla/arch/mips/kernel/sysirix.c Sun Nov 8 15:10:06 1998
+++ linux.ac/arch/mips/kernel/sysirix.c Fri Dec 4 17:14:23 1998
@@ -788,7 +788,8 @@
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
if (error)
goto out;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if (fd >= current->files->max_fds ||
+ !(file = current->files->fd[fd])) {
error = -EBADF;
goto out;
}
@@ -1111,7 +1112,8 @@
lock_kernel();
if(!(flags & MAP_ANONYMOUS)) {
- if(fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if(fd >= current->files->max_fds ||
+ !(file = current->files->fd[fd])) {
retval = -EBADF;
goto out;
}
@@ -1583,7 +1585,8 @@
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if (error)
goto out;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if (fd >= current->files->max_fds ||
+ !(file = current->files->fd[fd])) {
error = -EBADF;
goto out;
}
@@ -1727,7 +1730,8 @@
}
if(!(flags & MAP_ANONYMOUS)) {
- if(fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if(fd >= current->files->max_fds ||
+ !(file = current->files->fd[fd])) {
error = -EBADF;
goto out;
}
@@ -1879,7 +1883,8 @@
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if (error)
goto out;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if (fd >= current->files->max_fds ||
+ !(file = current->files->fd[fd])) {
error = -EBADF;
goto out;
}
@@ -2040,7 +2045,8 @@
current->pid, fd, dirent, count, eob);
#endif
error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ if (fd >= current->files->max_fds ||
+ !(file = current->files->fd[fd]))
goto out;
dentry = file->f_dentry;
@@ -2151,7 +2157,8 @@
current->pid, fd, dirent, cnt);
#endif
error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ if (fd >= current->files->max_fds ||
+ !(file = current->files->fd[fd]))
goto out;
dentry = file->f_dentry;
@@ -2212,7 +2219,8 @@
current->pid, fd, dirent, cnt);
#endif
error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ if (fd >= current->files->max_fds ||
+ !(file = current->files->fd[fd]))
goto out;
dentry = file->f_dentry;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/apus_defconfig linux.ac/arch/ppc/apus_defconfig
--- linux.vanilla/arch/ppc/apus_defconfig Mon Dec 28 23:09:41 1998
+++ linux.ac/arch/ppc/apus_defconfig Fri Feb 26 01:59:54 1999
@@ -100,7 +100,6 @@
# CONFIG_RTNETLINK is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -118,7 +117,6 @@
# (it is safe to leave these untouched)
#
CONFIG_INET_RARP=y
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/chrp_defconfig linux.ac/arch/ppc/chrp_defconfig
--- linux.vanilla/arch/ppc/chrp_defconfig Mon Dec 28 23:09:41 1998
+++ linux.ac/arch/ppc/chrp_defconfig Fri Feb 26 01:59:54 1999
@@ -85,7 +85,6 @@
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -99,7 +98,6 @@
CONFIG_IP_ALIAS=y
# CONFIG_SYN_COOKIES is not set
CONFIG_INET_RARP=y
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_IPX is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/common_defconfig linux.ac/arch/ppc/common_defconfig
--- linux.vanilla/arch/ppc/common_defconfig Sat Jan 9 21:50:36 1999
+++ linux.ac/arch/ppc/common_defconfig Fri Feb 26 01:59:54 1999
@@ -87,7 +87,6 @@
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -100,7 +99,6 @@
# CONFIG_IP_ALIAS is not set
CONFIG_SYN_COOKIES=y
# CONFIG_INET_RARP is not set
-# CONFIG_IP_NOSR is not set
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_IPX is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/defconfig linux.ac/arch/ppc/defconfig
--- linux.vanilla/arch/ppc/defconfig Wed Jan 6 23:02:18 1999
+++ linux.ac/arch/ppc/defconfig Fri Feb 26 01:59:55 1999
@@ -102,7 +102,6 @@
# CONFIG_RTNETLINK is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -120,7 +119,6 @@
# (it is safe to leave these untouched)
#
CONFIG_INET_RARP=y
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/process.c linux.ac/arch/ppc/kernel/process.c
--- linux.vanilla/arch/ppc/kernel/process.c Sat Jan 9 21:50:36 1999
+++ linux.ac/arch/ppc/kernel/process.c Sat Jan 9 21:57:09 1999
@@ -67,7 +67,6 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/syscalls.c linux.ac/arch/ppc/kernel/syscalls.c
--- linux.vanilla/arch/ppc/kernel/syscalls.c Sun Nov 8 15:08:33 1998
+++ linux.ac/arch/ppc/kernel/syscalls.c Fri Dec 4 17:14:34 1998
@@ -205,7 +205,8 @@
lock_kernel();
if (!(flags & MAP_ANONYMOUS)) {
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ if (fd >= current->files->max_fds ||
+ !(file = current->files->fd[fd]))
goto out;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/mbx_defconfig linux.ac/arch/ppc/mbx_defconfig
--- linux.vanilla/arch/ppc/mbx_defconfig Mon Dec 28 23:09:41 1998
+++ linux.ac/arch/ppc/mbx_defconfig Fri Feb 26 01:59:55 1999
@@ -14,7 +14,6 @@
# CONFIG_ALL_PPC is not set
# CONFIG_APUS is not set
CONFIG_MBX=y
-CONFIG_SMP=n
CONFIG_MACH_SPECIFIC=y
CONFIG_SERIAL_CONSOLE=y
@@ -75,7 +74,6 @@
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -90,7 +88,6 @@
# CONFIG_IP_ALIAS is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
# CONFIG_SKB_LARGE is not set
# CONFIG_IPV6 is not set
# CONFIG_IPX is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/pmac_defconfig linux.ac/arch/ppc/pmac_defconfig
--- linux.vanilla/arch/ppc/pmac_defconfig Wed Jan 6 23:02:18 1999
+++ linux.ac/arch/ppc/pmac_defconfig Fri Feb 26 01:59:55 1999
@@ -102,7 +102,6 @@
# CONFIG_RTNETLINK is not set
# CONFIG_NETLINK_DEV is not set
# CONFIG_FIREWALL is not set
-CONFIG_NET_ALIAS=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -120,7 +119,6 @@
# (it is safe to leave these untouched)
#
CONFIG_INET_RARP=y
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/prep_defconfig linux.ac/arch/ppc/prep_defconfig
--- linux.vanilla/arch/ppc/prep_defconfig Mon Dec 28 23:09:41 1998
+++ linux.ac/arch/ppc/prep_defconfig Fri Feb 26 01:59:55 1999
@@ -84,7 +84,6 @@
# CONFIG_PACKET is not set
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -97,7 +96,6 @@
# CONFIG_IP_ALIAS is not set
CONFIG_SYN_COOKIES=y
# CONFIG_INET_RARP is not set
-# CONFIG_IP_NOSR is not set
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_IPX is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/defconfig linux.ac/arch/sparc/defconfig
--- linux.vanilla/arch/sparc/defconfig Tue Dec 22 23:19:33 1998
+++ linux.ac/arch/sparc/defconfig Fri Feb 26 01:59:55 1999
@@ -101,7 +101,6 @@
CONFIG_PACKET=y
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -118,7 +117,6 @@
# (it is safe to leave these untouched)
#
CONFIG_INET_RARP=m
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
CONFIG_IPV6=m
# CONFIG_IPV6_EUI64 is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/init_task.c linux.ac/arch/sparc/kernel/init_task.c
--- linux.vanilla/arch/sparc/kernel/init_task.c Sun Nov 8 15:10:06 1998
+++ linux.ac/arch/sparc/kernel/init_task.c Fri Dec 4 17:14:35 1998
@@ -6,7 +6,6 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/defconfig linux.ac/arch/sparc64/defconfig
--- linux.vanilla/arch/sparc64/defconfig Tue Dec 22 23:19:34 1998
+++ linux.ac/arch/sparc64/defconfig Fri Feb 26 01:59:55 1999
@@ -128,7 +128,6 @@
CONFIG_PACKET=y
# CONFIG_NETLINK is not set
# CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
@@ -145,7 +144,6 @@
# (it is safe to leave these untouched)
#
CONFIG_INET_RARP=m
-CONFIG_IP_NOSR=y
CONFIG_SKB_LARGE=y
CONFIG_IPV6=m
# CONFIG_IPV6_EUI64 is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/init_task.c linux.ac/arch/sparc64/kernel/init_task.c
--- linux.vanilla/arch/sparc64/kernel/init_task.c Sun Nov 8 15:08:40 1998
+++ linux.ac/arch/sparc64/kernel/init_task.c Fri Dec 4 17:14:35 1998
@@ -6,7 +6,6 @@
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/Config.in linux.ac/drivers/acorn/block/Config.in
--- linux.vanilla/drivers/acorn/block/Config.in Sun Nov 8 15:08:19 1998
+++ linux.ac/drivers/acorn/block/Config.in Sun Jan 24 23:54:36 1999
@@ -11,6 +11,7 @@
fi
tristate 'MFM harddisk support' CONFIG_BLK_DEV_MFM
+tristate 'Old Archimedes floppy (1772) support' CONFIG_BLK_DEV_FD1772
if [ "$CONFIG_BLK_DEV_MFM" != "n" ]; then
bool ' Autodetect hard drive geometry' CONFIG_BLK_DEV_MFM_AUTODETECT
fi
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/Makefile linux.ac/drivers/acorn/block/Makefile
--- linux.vanilla/drivers/acorn/block/Makefile Sun Nov 8 15:08:19 1998
+++ linux.ac/drivers/acorn/block/Makefile Sun Jan 24 23:54:36 1999
@@ -14,13 +14,11 @@
M_OBJS :=
MOD_LIST_NAME := ACORN_BLOCK_MODULES
-ifeq ($(CONFIG_ARCH_ARC),y)
- ifeq ($(CONFIG_BLK_DEV_FD),y)
- L_OBJS += fd1772.o fd1772dma.o
- else
- ifeq ($(CONFIG_BLK_DEV_FD),m)
- M_OBJS += fd1772_mod.o
- endif
+ifeq ($(CONFIG_BLK_DEV_FD1772),y)
+ L_OBJS += fd1772.o fd1772dma.o
+else
+ ifeq ($(CONFIG_BLK_DEV_FD1772),m)
+ M_OBJS += fd1772_mod.o
endif
endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/fd1772.c linux.ac/drivers/acorn/block/fd1772.c
--- linux.vanilla/drivers/acorn/block/fd1772.c Sat Jan 9 21:50:36 1999
+++ linux.ac/drivers/acorn/block/fd1772.c Sun Jan 24 23:54:36 1999
@@ -136,6 +136,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/ide-ics.c linux.ac/drivers/acorn/block/ide-ics.c
--- linux.vanilla/drivers/acorn/block/ide-ics.c Tue Dec 22 23:19:34 1998
+++ linux.ac/drivers/acorn/block/ide-ics.c Sun Jan 24 23:54:36 1999
@@ -81,6 +81,8 @@
icside_irqenable_arcin_v5,
icside_irqdisable_arcin_v5,
NULL,
+ NULL,
+ NULL,
NULL
};
@@ -106,9 +108,22 @@
inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_2);
}
+/* Prototype: icside_irqprobe(struct expansion_card *ec)
+ * Purpose : detect an active interrupt from card
+ */
+static int icside_irqpending_arcin_v6(struct expansion_card *ec)
+{
+ unsigned int ide_base_port = (unsigned int)ec->irq_data;
+
+ return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
+ inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
+}
+
static const expansioncard_ops_t icside_ops_arcin_v6 = {
icside_irqenable_arcin_v6,
icside_irqdisable_arcin_v6,
+ icside_irqpending_arcin_v6,
+ NULL,
NULL,
NULL
};
@@ -220,8 +235,6 @@
case ics_if_arcin_v6:
port = ecard_address (ec, ECARD_IOC, ECARD_FAST);
- ec->irqaddr = ioaddr(port + ICS_ARCIN_V6_INTRSTAT_1);
- ec->irqmask = 1;
ec->irq_data = (void *)port;
ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/ide-rapide.c linux.ac/drivers/acorn/block/ide-rapide.c
--- linux.vanilla/drivers/acorn/block/ide-rapide.c Sun Nov 8 15:08:19 1998
+++ linux.ac/drivers/acorn/block/ide-rapide.c Sun Jan 24 23:54:36 1999
@@ -13,7 +13,6 @@
#include
#include
#include
-#include
#include "../../block/ide.h"
@@ -28,14 +27,20 @@
static inline int rapide_register(struct expansion_card *ec)
{
unsigned long port = ecard_address (ec, ECARD_MEMC, 0);
- ide_ioregspec_t spec;
+ hw_regs_t hw;
- spec.base = port;
- spec.ctrl = port + 0x206;
- spec.offset = 1 << 4;
- spec.irq = ec->irq;
+ int i;
- return ide_register_port(&spec);
+ memset(&hw, 0, sizeof(hw));
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw.io_ports[i] = (ide_ioreg_t)port;
+ port += 1 << 4;
+ }
+ hw.io_ports[IDE_CONTROL_OFFSET] = port + 0x206;
+ hw.irq = ec->irq;
+
+ return ide_register_hw(&hw, NULL);
}
int rapide_init(void)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/block/mfmhd.c linux.ac/drivers/acorn/block/mfmhd.c
--- linux.vanilla/drivers/acorn/block/mfmhd.c Sun Nov 8 15:08:19 1998
+++ linux.ac/drivers/acorn/block/mfmhd.c Sun Jan 24 23:54:36 1999
@@ -123,6 +123,7 @@
#include
#include
#include
+#include
/*
* This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/char/Config.in linux.ac/drivers/acorn/char/Config.in
--- linux.vanilla/drivers/acorn/char/Config.in Tue Dec 22 23:19:34 1998
+++ linux.ac/drivers/acorn/char/Config.in Thu Jan 1 01:00:00 1970
@@ -1,15 +0,0 @@
-if [ "$CONFIG_SERIAL" != "n" ]; then
- tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL
- tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
-fi
-
-if [ "$CONFIG_MOUSE" = "y" ]; then
- if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
- if [ "$CONFIG_ARCH_RPC" != "y" ]; then
- define_bool CONFIG_KBDMOUSE y
- else
- define_bool CONFIG_RPCMOUSE y
- fi
- fi
-fi
-
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/char/keyb_ps2.c linux.ac/drivers/acorn/char/keyb_ps2.c
--- linux.vanilla/drivers/acorn/char/keyb_ps2.c Tue Dec 22 23:19:34 1998
+++ linux.ac/drivers/acorn/char/keyb_ps2.c Sun Jan 24 23:54:37 1999
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
#include
extern void kbd_reset_kdown(void);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/char/mouse_rpc.c linux.ac/drivers/acorn/char/mouse_rpc.c
--- linux.vanilla/drivers/acorn/char/mouse_rpc.c Tue Dec 22 23:19:34 1998
+++ linux.ac/drivers/acorn/char/mouse_rpc.c Sun Jan 24 23:54:37 1999
@@ -1,5 +1,5 @@
/*
- * linux/drivers/char/rpcmouse.c
+ * linux/drivers/char/mouse_rpc.c
*
* Copyright (C) 1996-1998 Russell King
*
@@ -16,6 +16,7 @@
#include
#include
#include
+#include
#include "../../char/mouse.h"
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/net/ether1.c linux.ac/drivers/acorn/net/ether1.c
--- linux.vanilla/drivers/acorn/net/ether1.c Mon Dec 28 23:09:41 1998
+++ linux.ac/drivers/acorn/net/ether1.c Sun Jan 24 23:54:37 1999
@@ -128,7 +128,7 @@
{
int used;
- addr = IO_BASE + (addr << 2);
+ addr = ioaddr(addr);
__asm__ __volatile__(
"subs %3, %3, #2
@@ -171,7 +171,7 @@
{
int used;
- addr = IO_BASE + (addr << 2);
+ addr = ioaddr(addr);
__asm__ __volatile__(
"subs %3, %3, #2
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/net/ether3.c linux.ac/drivers/acorn/net/ether3.c
--- linux.vanilla/drivers/acorn/net/ether3.c Sun Nov 8 15:08:20 1998
+++ linux.ac/drivers/acorn/net/ether3.c Sun Jan 24 23:54:37 1999
@@ -33,11 +33,13 @@
* packet starts two bytes from the end of the
* buffer, it corrupts the receiver chain, and
* never updates the transmit status correctly.
+ * 1.14 RMK 07/01/1998 Added initial code for ETHERB addressing.
+ *
* TODO:
* When we detect a fatal error on the interface, we should restart it.
*/
-static char *version = "ether3 ethernet driver (c) 1995-1998 R.M.King v1.13\n";
+static char *version = "ether3 ethernet driver (c) 1995-1999 R.M.King v1.14\n";
#include
#include
@@ -471,6 +473,25 @@
return error;
}
+static void
+ether3_get_dev(struct device *dev, struct expansion_card *ec)
+{
+ ecard_claim(ec);
+
+ dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
+ dev->irq = ec->irq;
+
+ if (ec->cid.manufacturer == MANU_ANT &&
+ ec->cid.product == PROD_ANT_ETHERB) {
+ dev->base_addr += 0x200;
+ }
+
+ ec->irqaddr = ioaddr(dev->base_addr);
+ ec->irqmask = 0xf0;
+
+ ether3_addr(dev->dev_addr, ec);
+}
+
#ifndef MODULE
__initfunc(int
ether3_probe(struct device *dev))
@@ -485,12 +506,8 @@
if ((ec = ecard_find(0, ether3_cids)) == NULL)
return ENODEV;
- dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
- dev->irq = ec->irq;
-
- ecard_claim(ec);
+ ether3_get_dev(dev, ec);
- ether3_addr(dev->dev_addr, ec);
return ether3_probe1(dev);
}
#endif
@@ -942,17 +959,13 @@
my_ethers[i] = (struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);
memset(my_ethers[i], 0, sizeof(struct device));
- my_ethers[i]->irq = ec[i]->irq;
- my_ethers[i]->base_addr= ecard_address(ec[i], ECARD_MEMC, 0);
my_ethers[i]->init = ether3_probe1;
my_ethers[i]->name = ethernames[i];
- ether3_addr(my_ethers[i]->dev_addr, ec[i]);
-
- ecard_claim(ec[i]);
+ ether3_get_dev(my_ethers[i], ec[i]);
if(register_netdev(my_ethers[i]) != 0) {
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < MAX_ECARDS; i++) {
if(my_ethers[i]) {
kfree(my_ethers[i]);
my_ethers[i] = NULL;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/net/etherh.c linux.ac/drivers/acorn/net/etherh.c
--- linux.vanilla/drivers/acorn/net/etherh.c Tue Dec 22 23:19:35 1998
+++ linux.ac/drivers/acorn/net/etherh.c Sun Jan 24 23:54:37 1999
@@ -461,6 +461,8 @@
etherh_irq_enable,
etherh_irq_disable,
NULL,
+ NULL,
+ NULL,
NULL
};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/acornscsi.c linux.ac/drivers/acorn/scsi/acornscsi.c
--- linux.vanilla/drivers/acorn/scsi/acornscsi.c Mon Dec 28 23:09:41 1998
+++ linux.ac/drivers/acorn/scsi/acornscsi.c Sun Jan 24 23:54:37 1999
@@ -21,6 +21,8 @@
* 12-Oct-1997 RMK Added catch for re-entering interrupt routine.
* 15-Oct-1997 RMK Improved handling of commands.
* 27-Jun-1998 RMK Changed asm/delay.h to linux/delay.h.
+ * 13-Dec-1998 RMK Better abort code and command handling. Extra state
+ * transitions added to allow dodgy devices to work.
*/
#define DEBUG_NO_WRITE 1
#define DEBUG_QUEUES 2
@@ -35,7 +37,7 @@
#define DEBUG_RESET 1024
#define DEBUG_ALL (DEBUG_RESET|DEBUG_MESSAGES|DEBUG_LINK|DEBUG_WRITE|\
DEBUG_PHASES|DEBUG_CONNECT|DEBUG_DISCON|DEBUG_ABORT|\
- DEBUG_DMA|DEBUG_QUEUES|DEBUG_NO_WRITE)
+ DEBUG_DMA|DEBUG_QUEUES)
/* DRIVER CONFIGURATION
*
@@ -186,26 +188,7 @@
#define DMAC_BUFFER_SIZE 65536
#endif
-/*
- * This is used to dump the previous states of the SBIC
- */
-static struct status_entry {
- unsigned long when;
- unsigned char ssr;
- unsigned char ph;
- unsigned char irq;
- unsigned char unused;
-} status[9][16];
-static unsigned char status_ptr[9];
-
-#define ADD_STATUS(_q,_ssr,_ph,_irq) \
-({ \
- status[(_q)][status_ptr[(_q)]].when = jiffies; \
- status[(_q)][status_ptr[(_q)]].ssr = (_ssr); \
- status[(_q)][status_ptr[(_q)]].ph = (_ph); \
- status[(_q)][status_ptr[(_q)]].irq = (_irq); \
- status_ptr[(_q)] = (status_ptr[(_q)] + 1) & 15; \
-})
+#define STATUS_BUFFER_TO_PRINT 24
unsigned int sdtr_period = SDTR_PERIOD;
unsigned int sdtr_size = SDTR_SIZE;
@@ -214,31 +197,31 @@
PROC_SCSI_EATA, 9, "acornscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2
};
-static void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result);
-static int acornscsi_reconnect_finish (AS_Host *host);
-static void acornscsi_dma_cleanup (AS_Host *host);
-static void acornscsi_abortcmd (AS_Host *host, unsigned char tag);
+static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result);
+static int acornscsi_reconnect_finish(AS_Host *host);
+static void acornscsi_dma_cleanup(AS_Host *host);
+static void acornscsi_abortcmd(AS_Host *host, unsigned char tag);
/* ====================================================================================
* Miscellaneous
*/
static inline void
-sbic_arm_write (unsigned int io_port, int reg, int value)
+sbic_arm_write(unsigned int io_port, int reg, int value)
{
- outb_t (reg, io_port);
- outb_t (value, io_port + 4);
+ outb_t(reg, io_port);
+ outb_t(value, io_port + 4);
}
#define sbic_arm_writenext(io,val) \
- outb_t ((val), (io) + 4)
+ outb_t((val), (io) + 4)
static inline
-int sbic_arm_read (unsigned int io_port, int reg)
+int sbic_arm_read(unsigned int io_port, int reg)
{
if(reg == ASR)
return inl_t(io_port) & 255;
- outb_t (reg, io_port);
+ outb_t(reg, io_port);
return inl_t(io_port + 4) & 255;
}
@@ -247,129 +230,165 @@
#ifdef USE_DMAC
#define dmac_read(io_port,reg) \
- inb ((io_port) + (reg))
+ inb((io_port) + (reg))
#define dmac_write(io_port,reg,value) \
- ({ outb ((value), (io_port) + (reg)); })
+ ({ outb((value), (io_port) + (reg)); })
#define dmac_clearintr(io_port) \
- ({ outb (0, (io_port)); })
+ ({ outb(0, (io_port)); })
static inline
-unsigned int dmac_address (unsigned int io_port)
+unsigned int dmac_address(unsigned int io_port)
{
- return dmac_read (io_port, TXADRHI) << 16 |
- dmac_read (io_port, TXADRMD) << 8 |
- dmac_read (io_port, TXADRLO);
+ return dmac_read(io_port, TXADRHI) << 16 |
+ dmac_read(io_port, TXADRMD) << 8 |
+ dmac_read(io_port, TXADRLO);
}
static
-void acornscsi_dumpdma (AS_Host *host, char *where)
+void acornscsi_dumpdma(AS_Host *host, char *where)
{
unsigned int mode, addr, len;
- mode = dmac_read (host->dma.io_port, MODECON);
- addr = dmac_address (host->dma.io_port);
- len = dmac_read (host->dma.io_port, TXCNTHI) << 8 |
- dmac_read (host->dma.io_port, TXCNTLO);
+ mode = dmac_read(host->dma.io_port, MODECON);
+ addr = dmac_address(host->dma.io_port);
+ len = dmac_read(host->dma.io_port, TXCNTHI) << 8 |
+ dmac_read(host->dma.io_port, TXCNTLO);
- printk ("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
+ printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
host->host->host_no, where,
mode, addr, (len + 1) & 0xffff,
- dmac_read (host->dma.io_port, MASKREG));
+ dmac_read(host->dma.io_port, MASKREG));
- printk ("DMA @%06x, ", host->dma.start_addr);
- printk ("BH @%p +%04x, ", host->scsi.SCp.ptr,
+ printk("DMA @%06x, ", host->dma.start_addr);
+ printk("BH @%p +%04x, ", host->scsi.SCp.ptr,
host->scsi.SCp.this_residual);
- printk ("DT @+%04x ST @+%04x", host->dma.transferred,
+ printk("DT @+%04x ST @+%04x", host->dma.transferred,
host->scsi.SCp.scsi_xferred);
- printk ("\n");
+ printk("\n");
}
#endif
static
-unsigned long acornscsi_sbic_xfcount (AS_Host *host)
+unsigned long acornscsi_sbic_xfcount(AS_Host *host)
{
unsigned long length;
- length = sbic_arm_read (host->scsi.io_port, TRANSCNTH) << 16;
- length |= sbic_arm_readnext (host->scsi.io_port) << 8;
- length |= sbic_arm_readnext (host->scsi.io_port);
+ length = sbic_arm_read(host->scsi.io_port, TRANSCNTH) << 16;
+ length |= sbic_arm_readnext(host->scsi.io_port) << 8;
+ length |= sbic_arm_readnext(host->scsi.io_port);
return length;
}
-static
-int acornscsi_sbic_issuecmd (AS_Host *host, int command)
+static int
+acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg)
{
- int asr;
+ int asr;
- do {
- asr = sbic_arm_read (host->scsi.io_port, ASR);
- } while (asr & ASR_CIP);
+ do {
+ asr = sbic_arm_read(host->scsi.io_port, ASR);
+
+ if ((asr & stat_mask) == stat)
+ return 0;
+
+ udelay(1);
+ } while (--timeout);
+
+ printk("scsi%d: timeout while %s\n", host->host->host_no, msg);
+
+ return -1;
+}
+
+static
+int acornscsi_sbic_issuecmd(AS_Host *host, int command)
+{
+ if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command"))
+ return -1;
- sbic_arm_write (host->scsi.io_port, CMND, command);
+ sbic_arm_write(host->scsi.io_port, CMND, command);
return 0;
}
static void
-acornscsi_csdelay (unsigned int cs)
+acornscsi_csdelay(unsigned int cs)
{
unsigned long target_jiffies, flags;
target_jiffies = jiffies + 1 + cs * HZ / 100;
- save_flags (flags);
- sti ();
+ save_flags(flags);
+ sti();
while (time_before(jiffies, target_jiffies)) barrier();
- restore_flags (flags);
+ restore_flags(flags);
}
static
-void acornscsi_resetcard (AS_Host *host)
+void acornscsi_resetcard(AS_Host *host)
{
- unsigned int i;
+ unsigned int i, timeout;
/* assert reset line */
host->card.page_reg = 0x80;
- outb (host->card.page_reg, host->card.io_page);
+ outb(host->card.page_reg, host->card.io_page);
/* wait 3 cs. SCSI standard says 25ms. */
- acornscsi_csdelay (3);
+ acornscsi_csdelay(3);
host->card.page_reg = 0;
- outb (host->card.page_reg, host->card.io_page);
+ outb(host->card.page_reg, host->card.io_page);
/*
* Should get a reset from the card
*/
- while (!(inb (host->card.io_intr) & 8));
- sbic_arm_read (host->scsi.io_port, ASR);
- sbic_arm_read (host->scsi.io_port, SSR);
+ timeout = 1000;
+ do {
+ if (inb(host->card.io_intr) & 8)
+ break;
+ udelay(1);
+ } while (--timeout);
+
+ if (timeout == 0)
+ printk("scsi%d: timeout while resetting card\n",
+ host->host->host_no);
+
+ sbic_arm_read(host->scsi.io_port, ASR);
+ sbic_arm_read(host->scsi.io_port, SSR);
/* setup sbic - WD33C93A */
- sbic_arm_write (host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
- sbic_arm_write (host->scsi.io_port, CMND, CMND_RESET);
+ sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
+ sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET);
/*
* Command should cause a reset interrupt
*/
- while (!(inb (host->card.io_intr) & 8));
- sbic_arm_read (host->scsi.io_port, ASR);
- if (sbic_arm_read (host->scsi.io_port, SSR) != 0x01)
- printk (KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n",
+ timeout = 1000;
+ do {
+ if (inb(host->card.io_intr) & 8)
+ break;
+ udelay(1);
+ } while (--timeout);
+
+ if (timeout == 0)
+ printk("scsi%d: timeout while resetting card\n",
host->host->host_no);
- sbic_arm_write (host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
- sbic_arm_write (host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
- sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
- sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
+ sbic_arm_read(host->scsi.io_port, ASR);
+ if (sbic_arm_read(host->scsi.io_port, SSR) != 0x01)
+ printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n",
+ host->host->host_no);
+
+ sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
+ sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
+ sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
+ sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
host->card.page_reg = 0x40;
- outb (host->card.page_reg, host->card.io_page);
+ outb(host->card.page_reg, host->card.io_page);
/* setup dmac - uPC71071 */
dmac_write(host->dma.io_port, INIT, 0);
@@ -391,7 +410,7 @@
}
/* wait 25 cs. SCSI standard says 250ms. */
- acornscsi_csdelay (25);
+ acornscsi_csdelay(25);
}
/*=============================================================================================
@@ -461,80 +480,101 @@
};
static
-void print_scsi_status (unsigned int ssr)
+void print_scsi_status(unsigned int ssr)
{
if (acornscsi_map[ssr] != -1)
- printk ("%s:%s",
+ printk("%s:%s",
acornscsi_interrupttype[(ssr >> 4)],
acornscsi_interruptcode[acornscsi_map[ssr]]);
else
- printk ("%X:%X", ssr >> 4, ssr & 0x0f);
+ printk("%X:%X", ssr >> 4, ssr & 0x0f);
}
#endif
static
-void print_sbic_status (int asr, int ssr, int cmdphase)
+void print_sbic_status(int asr, int ssr, int cmdphase)
{
#ifdef CONFIG_ACORNSCSI_CONSTANTS
- printk ("sbic: %c%c%c%c%c%c ",
+ printk("sbic: %c%c%c%c%c%c ",
asr & ASR_INT ? 'I' : 'i',
asr & ASR_LCI ? 'L' : 'l',
asr & ASR_BSY ? 'B' : 'b',
asr & ASR_CIP ? 'C' : 'c',
asr & ASR_PE ? 'P' : 'p',
asr & ASR_DBR ? 'D' : 'd');
- printk ("scsi: ");
- print_scsi_status (ssr);
- printk (" ph %02X\n", cmdphase);
+ printk("scsi: ");
+ print_scsi_status(ssr);
+ printk(" ph %02X\n", cmdphase);
#else
- printk ("sbic: %02X scsi: %X:%X ph: %02X\n",
+ printk("sbic: %02X scsi: %X:%X ph: %02X\n",
asr, (ssr & 0xf0)>>4, ssr & 0x0f, cmdphase);
#endif
}
-static
-void acornscsi_dumplog (AS_Host *host, int target)
+static void
+acornscsi_dumplogline(AS_Host *host, int target, int line)
{
- unsigned int prev;
- do {
- signed int statptr;
+ unsigned long prev;
+ signed int ptr;
- printk ("%c:", target == 8 ? 'H' : ('0' + target));
- statptr = status_ptr[target] - 10;
+ ptr = host->status_ptr[target] - STATUS_BUFFER_TO_PRINT;
+ if (ptr < 0)
+ ptr += STATUS_BUFFER_SIZE;
- if (statptr < 0)
- statptr += 16;
+ printk("%c: %3s:", target == 8 ? 'H' : '0' + target,
+ line == 0 ? "ph" : line == 1 ? "ssr" : "int");
- prev = status[target][statptr].when;
+ prev = host->status[target][ptr].when;
- for (; statptr != status_ptr[target]; statptr = (statptr + 1) & 15) {
- if (status[target][statptr].when) {
-#ifdef CONFIG_ACORNSCSI_CONSTANTS
- printk ("%c%02X:S=",
- status[target][statptr].irq ? '-' : ' ',
- status[target][statptr].ph);
- print_scsi_status (status[target][statptr].ssr);
-#else
- printk ("%c%02X:%02X",
- status[target][statptr].irq ? '-' : ' ',
- status[target][statptr].ph,
- status[target][statptr].ssr);
-#endif
- printk ("+%02ld",
- (status[target][statptr].when - prev) < 100 ?
- (status[target][statptr].when - prev) : 99);
- prev = status[target][statptr].when;
- }
+ for (; ptr != host->status_ptr[target]; ptr = (ptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
+ unsigned long time_diff;
+
+ if (!host->status[target][ptr].when)
+ continue;
+
+ switch (line) {
+ case 0:
+ printk("%c%02X", host->status[target][ptr].irq ? '-' : ' ',
+ host->status[target][ptr].ph);
+ break;
+
+ case 1:
+ printk(" %02X", host->status[target][ptr].ssr);
+ break;
+
+ case 2:
+ time_diff = host->status[target][ptr].when - prev;
+ prev = host->status[target][ptr].when;
+ if (time_diff == 0)
+ printk("==^");
+ else if (time_diff >= 100)
+ printk(" ");
+ else
+ printk(" %02ld", time_diff);
+ break;
+ }
}
- printk ("\n");
+
+ printk("\n");
+}
+
+static
+void acornscsi_dumplog(AS_Host *host, int target)
+{
+ do {
+ acornscsi_dumplogline(host, target, 0);
+ acornscsi_dumplogline(host, target, 1);
+ acornscsi_dumplogline(host, target, 2);
+
if (target == 8)
break;
+
target = 8;
} while (1);
}
static
-char acornscsi_target (AS_Host *host)
+char acornscsi_target(AS_Host *host)
{
if (host->SCpnt)
return '0' + host->SCpnt->target;
@@ -542,7 +582,7 @@
}
/*
- * Prototype: cmdtype_t acornscsi_cmdtype (int command)
+ * Prototype: cmdtype_t acornscsi_cmdtype(int command)
* Purpose : differentiate READ from WRITE from other commands
* Params : command - command to interpret
* Returns : CMD_READ - command reads data,
@@ -550,7 +590,7 @@
* CMD_MISC - everything else
*/
static inline
-cmdtype_t acornscsi_cmdtype (int command)
+cmdtype_t acornscsi_cmdtype(int command)
{
switch (command) {
case WRITE_6: case WRITE_10: case WRITE_12:
@@ -563,7 +603,7 @@
}
/*
- * Prototype: int acornscsi_datadirection (int command)
+ * Prototype: int acornscsi_datadirection(int command)
* Purpose : differentiate between commands that have a DATA IN phase
* and a DATA OUT phase
* Params : command - command to interpret
@@ -571,7 +611,7 @@
* DATADIR_IN - data in phase expected
*/
static
-datadir_t acornscsi_datadirection (int command)
+datadir_t acornscsi_datadirection(int command)
{
switch (command) {
case CHANGE_DEFINITION: case COMPARE: case COPY:
@@ -605,13 +645,13 @@
};
/*
- * Prototype: int acornscsi_getperiod (unsigned char syncxfer)
+ * Prototype: int acornscsi_getperiod(unsigned char syncxfer)
* Purpose : period for the synchronous transfer setting
* Params : syncxfer SYNCXFER register value
* Returns : period in ns.
*/
static
-int acornscsi_getperiod (unsigned char syncxfer)
+int acornscsi_getperiod(unsigned char syncxfer)
{
int i;
@@ -626,14 +666,14 @@
}
/*
- * Prototype: int round_period (unsigned int period)
+ * Prototype: int round_period(unsigned int period)
* Purpose : return index into above table for a required REQ period
* Params : period - time (ns) for REQ
* Returns : table index
* Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
*/
static inline
-int round_period (unsigned int period)
+int round_period(unsigned int period)
{
int i;
@@ -646,7 +686,7 @@
}
/*
- * Prototype: unsigned char calc_sync_xfer (unsigned int period, unsigned int offset)
+ * Prototype: unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
* Purpose : calculate value for 33c93s SYNC register
* Params : period - time (ns) for REQ
* offset - offset in bytes between REQ/ACK
@@ -654,7 +694,7 @@
* Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
*/
static
-unsigned char calc_sync_xfer (unsigned int period, unsigned int offset)
+unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
{
return sync_xfer_table[round_period(period)].reg_value |
((offset < SDTR_SIZE) ? offset : SDTR_SIZE);
@@ -664,14 +704,14 @@
* Command functions
*/
/*
- * Function: acornscsi_kick (AS_Host *host)
+ * Function: acornscsi_kick(AS_Host *host)
* Purpose : kick next command to interface
* Params : host - host to send command to
* Returns : INTR_IDLE if idle, otherwise INTR_PROCESSING
* Notes : interrupts are always disabled!
*/
static
-intr_ret_t acornscsi_kick (AS_Host *host)
+intr_ret_t acornscsi_kick(AS_Host *host)
{
int from_queue = 0;
Scsi_Cmnd *SCpnt;
@@ -682,7 +722,7 @@
/* retrieve next command */
if (!SCpnt) {
- SCpnt = queue_remove_exclude (&host->queues.issue, host->busyluns);
+ SCpnt = queue_remove_exclude(&host->queues.issue, host->busyluns);
if (!SCpnt)
return INTR_IDLE;
@@ -690,11 +730,11 @@
}
if (host->scsi.disconnectable && host->SCpnt) {
- queue_add_cmd_tail (&host->queues.disconnected, host->SCpnt);
+ queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
host->scsi.disconnectable = 0;
#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
- DBG(host->SCpnt, printk ("scsi%d.%c: moved command to disconnected queue\n",
- host->host->host_no, acornscsi_target (host)));
+ DBG(host->SCpnt, printk("scsi%d.%c: moved command to disconnected queue\n",
+ host->host->host_no, acornscsi_target(host)));
#endif
host->SCpnt = NULL;
}
@@ -703,9 +743,9 @@
* If we have an interrupt pending, then we may have been reselected.
* In this case, we don't want to write to the registers
*/
- if (!(sbic_arm_read (host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) {
- sbic_arm_write (host->scsi.io_port, DESTID, SCpnt->target);
- sbic_arm_write (host->scsi.io_port, CMND, CMND_SELWITHATN);
+ if (!(sbic_arm_read(host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) {
+ sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->target);
+ sbic_arm_write(host->scsi.io_port, CMND, CMND_SELWITHATN);
}
/*
@@ -717,9 +757,10 @@
host->scsi.SCp = SCpnt->SCp;
host->dma.xfer_setup = 0;
host->dma.xfer_required = 0;
+ host->dma.xfer_done = 0;
#if (DEBUG & (DEBUG_ABORT|DEBUG_CONNECT))
- DBG(SCpnt,printk ("scsi%d.%c: starting cmd %02X\n",
+ DBG(SCpnt,printk("scsi%d.%c: starting cmd %02X\n",
host->host->host_no, '0' + SCpnt->target,
SCpnt->cmnd[0]));
#endif
@@ -736,11 +777,11 @@
SCpnt->tag = SCpnt->device->current_tag;
} else
#endif
- set_bit (SCpnt->target * 8 + SCpnt->lun, host->busyluns);
+ set_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
host->stats.removes += 1;
- switch (acornscsi_cmdtype (SCpnt->cmnd[0])) {
+ switch (acornscsi_cmdtype(SCpnt->cmnd[0])) {
case CMD_WRITE:
host->stats.writes += 1;
break;
@@ -757,25 +798,25 @@
}
/*
- * Function: void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
+ * Function: void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
* Purpose : complete processing for command
* Params : host - interface that completed
* result - driver byte of result
*/
static
-void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
+void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result)
{
Scsi_Cmnd *SCpnt = *SCpntp;
/* clean up */
- sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
+ sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
host->stats.fins += 1;
if (SCpnt) {
*SCpntp = NULL;
- acornscsi_dma_cleanup (host);
+ acornscsi_dma_cleanup(host);
SCpnt->result = result << 16 | host->scsi.SCp.Message << 8 | host->scsi.SCp.Status;
@@ -787,35 +828,63 @@
* It doesn't appear to be set to something meaningful by the higher
* levels all the time.
*/
- if (host->scsi.SCp.ptr && result == DID_OK &&
- acornscsi_cmdtype (SCpnt->cmnd[0]) != CMD_MISC) {
- switch (status_byte (SCpnt->result)) {
- case CHECK_CONDITION:
- case COMMAND_TERMINATED:
- case BUSY:
- case QUEUE_FULL:
- case RESERVATION_CONFLICT:
- break;
+ if (result == DID_OK) {
+ int xfer_warn = 0;
- default:
- printk (KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=",
- host->host->host_no, SCpnt->result);
- print_command (SCpnt->cmnd);
- acornscsi_dumpdma (host, "done");
- acornscsi_dumplog (host, SCpnt->target);
- SCpnt->result &= 0xffff;
- SCpnt->result |= DID_ERROR << 16;
- }
+ if (SCpnt->underflow == 0) {
+ if (host->scsi.SCp.ptr &&
+ acornscsi_cmdtype(SCpnt->cmnd[0]) != CMD_MISC)
+ xfer_warn = 1;
+ } else {
+ if (host->scsi.SCp.scsi_xferred < SCpnt->underflow ||
+ host->scsi.SCp.scsi_xferred != host->dma.transferred)
+ xfer_warn = 1;
+ }
+
+ /* ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.6)
+ * Targets which break data transfers into multiple
+ * connections shall end each successful connection
+ * (except possibly the last) with a SAVE DATA
+ * POINTER - DISCONNECT message sequence.
+ *
+ * This makes it difficult to ensure that a transfer has
+ * completed. If we reach the end of a transfer during
+ * the command, then we can only have finished the transfer.
+ * therefore, if we seem to have some data remaining, this
+ * is not a problem.
+ */
+ if (host->dma.xfer_done)
+ xfer_warn = 0;
+
+ if (xfer_warn) {
+ switch (status_byte(SCpnt->result)) {
+ case CHECK_CONDITION:
+ case COMMAND_TERMINATED:
+ case BUSY:
+ case QUEUE_FULL:
+ case RESERVATION_CONFLICT:
+ break;
+
+ default:
+ printk(KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=",
+ host->host->host_no, SCpnt->result);
+ print_command(SCpnt->cmnd);
+ acornscsi_dumpdma(host, "done");
+ acornscsi_dumplog(host, SCpnt->target);
+ SCpnt->result &= 0xffff;
+ SCpnt->result |= DID_ERROR << 16;
+ }
+ }
}
if (!SCpnt->scsi_done)
- panic ("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
+ panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no);
- clear_bit (SCpnt->target * 8 + SCpnt->lun, host->busyluns);
+ clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
- SCpnt->scsi_done (SCpnt);
+ SCpnt->scsi_done(SCpnt);
} else
- printk ("scsi%d: null command in acornscsi_done", host->host->host_no);
+ printk("scsi%d: null command in acornscsi_done", host->host->host_no);
host->scsi.phase = PHASE_IDLE;
}
@@ -828,7 +897,7 @@
* Notes : this will only be one SG entry or less
*/
static
-void acornscsi_data_updateptr (AS_Host *host, Scsi_Pointer *SCp, unsigned int length)
+void acornscsi_data_updateptr(AS_Host *host, Scsi_Pointer *SCp, unsigned int length)
{
SCp->ptr += length;
SCp->this_residual -= length;
@@ -839,13 +908,15 @@
SCp->buffers_residual--;
SCp->ptr = (char *)SCp->buffer->address;
SCp->this_residual = SCp->buffer->length;
- } else
+ } else {
SCp->ptr = NULL;
+ host->dma.xfer_done = 1;
+ }
}
}
/*
- * Prototype: void acornscsi_data_read (AS_Host *host, char *ptr,
+ * Prototype: void acornscsi_data_read(AS_Host *host, char *ptr,
* unsigned int start_addr, unsigned int length)
* Purpose : read data from DMA RAM
* Params : host - host to transfer from
@@ -855,16 +926,16 @@
* Notes : this will only be one SG entry or less
*/
static
-void acornscsi_data_read (AS_Host *host, char *ptr,
+void acornscsi_data_read(AS_Host *host, char *ptr,
unsigned int start_addr, unsigned int length)
{
- extern void __acornscsi_in (int port, char *buf, int len);
+ extern void __acornscsi_in(int port, char *buf, int len);
unsigned int page, offset, len = length;
page = (start_addr >> 12);
offset = start_addr & ((1 << 12) - 1);
- outb ((page & 0x3f) | host->card.page_reg, host->card.io_page);
+ outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
while (len > 0) {
unsigned int this_len;
@@ -874,7 +945,7 @@
else
this_len = len;
- __acornscsi_in (host->card.io_ram + (offset << 1), ptr, this_len);
+ __acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len);
offset += this_len;
ptr += this_len;
@@ -883,14 +954,14 @@
if (offset == (1 << 12)) {
offset = 0;
page ++;
- outb ((page & 0x3f) | host->card.page_reg, host->card.io_page);
+ outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
}
}
- outb (host->card.page_reg, host->card.io_page);
+ outb(host->card.page_reg, host->card.io_page);
}
/*
- * Prototype: void acornscsi_data_write (AS_Host *host, char *ptr,
+ * Prototype: void acornscsi_data_write(AS_Host *host, char *ptr,
* unsigned int start_addr, unsigned int length)
* Purpose : write data to DMA RAM
* Params : host - host to transfer from
@@ -900,16 +971,16 @@
* Notes : this will only be one SG entry or less
*/
static
-void acornscsi_data_write (AS_Host *host, char *ptr,
+void acornscsi_data_write(AS_Host *host, char *ptr,
unsigned int start_addr, unsigned int length)
{
- extern void __acornscsi_out (int port, char *buf, int len);
+ extern void __acornscsi_out(int port, char *buf, int len);
unsigned int page, offset, len = length;
page = (start_addr >> 12);
offset = start_addr & ((1 << 12) - 1);
- outb ((page & 0x3f) | host->card.page_reg, host->card.io_page);
+ outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
while (len > 0) {
unsigned int this_len;
@@ -919,7 +990,7 @@
else
this_len = len;
- __acornscsi_out (host->card.io_ram + (offset << 1), ptr, this_len);
+ __acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len);
offset += this_len;
ptr += this_len;
@@ -928,10 +999,10 @@
if (offset == (1 << 12)) {
offset = 0;
page ++;
- outb ((page & 0x3f) | host->card.page_reg, host->card.io_page);
+ outb((page & 0x3f) | host->card.page_reg, host->card.io_page);
}
}
- outb (host->card.page_reg, host->card.io_page);
+ outb(host->card.page_reg, host->card.io_page);
}
/* =========================================================================================
@@ -939,25 +1010,25 @@
*/
#ifdef USE_DMAC
/*
- * Prototype: void acornscsi_dmastop (AS_Host *host)
+ * Prototype: void acornscsi_dmastop(AS_Host *host)
* Purpose : stop all DMA
* Params : host - host on which to stop DMA
* Notes : This is called when leaving DATA IN/OUT phase,
* or when interface is RESET
*/
static inline
-void acornscsi_dma_stop (AS_Host *host)
+void acornscsi_dma_stop(AS_Host *host)
{
- dmac_write (host->dma.io_port, MASKREG, MASK_ON);
- dmac_clearintr (host->dma.io_intr_clear);
+ dmac_write(host->dma.io_port, MASKREG, MASK_ON);
+ dmac_clearintr(host->dma.io_intr_clear);
#if (DEBUG & DEBUG_DMA)
- DBG(host->SCpnt, acornscsi_dumpdma (host, "stop"));
+ DBG(host->SCpnt, acornscsi_dumpdma(host, "stop"));
#endif
}
/*
- * Function: void acornscsi_dma_setup (AS_Host *host, dmadir_t direction)
+ * Function: void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
* Purpose : setup DMA controller for data transfer
* Params : host - host to setup
* direction - data transfer direction
@@ -965,19 +1036,19 @@
* while we're in a DATA I/O phase
*/
static
-void acornscsi_dma_setup (AS_Host *host, dmadir_t direction)
+void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
{
unsigned int address, length, mode;
host->dma.direction = direction;
- dmac_write (host->dma.io_port, MASKREG, MASK_ON);
+ dmac_write(host->dma.io_port, MASKREG, MASK_ON);
if (direction == DMA_OUT) {
#if (DEBUG & DEBUG_NO_WRITE)
if (NO_WRITE & (1 << host->SCpnt->target)) {
- printk (KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n",
- host->host->host_no, acornscsi_target (host));
+ printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n",
+ host->host->host_no, acornscsi_target(host));
return;
}
#endif
@@ -988,7 +1059,7 @@
/*
* Allocate some buffer space, limited to half the buffer size
*/
- length = min (host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
+ length = min(host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
if (length) {
host->dma.start_addr = address = host->dma.free_addr;
host->dma.free_addr = (host->dma.free_addr + length) &
@@ -998,27 +1069,27 @@
* Transfer data to DMA memory
*/
if (direction == DMA_OUT)
- acornscsi_data_write (host, host->scsi.SCp.ptr, host->dma.start_addr,
+ acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
length);
length -= 1;
- dmac_write (host->dma.io_port, TXCNTLO, length);
- dmac_write (host->dma.io_port, TXCNTHI, length >> 8);
- dmac_write (host->dma.io_port, TXADRLO, address);
- dmac_write (host->dma.io_port, TXADRMD, address >> 8);
- dmac_write (host->dma.io_port, TXADRHI, 0);
- dmac_write (host->dma.io_port, MODECON, mode);
- dmac_write (host->dma.io_port, MASKREG, MASK_OFF);
+ dmac_write(host->dma.io_port, TXCNTLO, length);
+ dmac_write(host->dma.io_port, TXCNTHI, length >> 8);
+ dmac_write(host->dma.io_port, TXADRLO, address);
+ dmac_write(host->dma.io_port, TXADRMD, address >> 8);
+ dmac_write(host->dma.io_port, TXADRHI, 0);
+ dmac_write(host->dma.io_port, MODECON, mode);
+ dmac_write(host->dma.io_port, MASKREG, MASK_OFF);
#if (DEBUG & DEBUG_DMA)
- DBG(host->SCpnt, acornscsi_dumpdma (host, "strt"));
+ DBG(host->SCpnt, acornscsi_dumpdma(host, "strt"));
#endif
host->dma.xfer_setup = 1;
}
}
/*
- * Function: void acornscsi_dma_cleanup (AS_Host *host)
+ * Function: void acornscsi_dma_cleanup(AS_Host *host)
* Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct
* Params : host - host to finish
* Notes : This is called when a command is:
@@ -1026,10 +1097,10 @@
* : This must not return until all transfers are completed.
*/
static
-void acornscsi_dma_cleanup (AS_Host *host)
+void acornscsi_dma_cleanup(AS_Host *host)
{
- dmac_write (host->dma.io_port, MASKREG, MASK_ON);
- dmac_clearintr (host->dma.io_intr_clear);
+ dmac_write(host->dma.io_port, MASKREG, MASK_ON);
+ dmac_clearintr(host->dma.io_intr_clear);
/*
* Check for a pending transfer
@@ -1037,7 +1108,7 @@
if (host->dma.xfer_required) {
host->dma.xfer_required = 0;
if (host->dma.direction == DMA_IN)
- acornscsi_data_read (host, host->dma.xfer_ptr,
+ acornscsi_data_read(host, host->dma.xfer_ptr,
host->dma.xfer_start, host->dma.xfer_length);
}
@@ -1056,17 +1127,17 @@
/*
* Calculate number of bytes transferred from DMA.
*/
- transferred = dmac_address (host->dma.io_port) - host->dma.start_addr;
+ transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
host->dma.transferred += transferred;
if (host->dma.direction == DMA_IN)
- acornscsi_data_read (host, host->scsi.SCp.ptr,
+ acornscsi_data_read(host, host->scsi.SCp.ptr,
host->dma.start_addr, transferred);
/*
* Update SCSI pointers
*/
- acornscsi_data_updateptr (host, &host->scsi.SCp, transferred);
+ acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
#if (DEBUG & DEBUG_DMA)
DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo"));
#endif
@@ -1074,7 +1145,7 @@
}
/*
- * Function: void acornscsi_dmacintr (AS_Host *host)
+ * Function: void acornscsi_dmacintr(AS_Host *host)
* Purpose : handle interrupts from DMAC device
* Params : host - host to process
* Notes : If reading, we schedule the read to main memory &
@@ -1084,21 +1155,21 @@
* : Called whenever DMAC finished it's current transfer.
*/
static
-void acornscsi_dma_intr (AS_Host *host)
+void acornscsi_dma_intr(AS_Host *host)
{
unsigned int address, length, transferred;
#if (DEBUG & DEBUG_DMA)
- DBG(host->SCpnt, acornscsi_dumpdma (host, "inti"));
+ DBG(host->SCpnt, acornscsi_dumpdma(host, "inti"));
#endif
- dmac_write (host->dma.io_port, MASKREG, MASK_ON);
- dmac_clearintr (host->dma.io_intr_clear);
+ dmac_write(host->dma.io_port, MASKREG, MASK_ON);
+ dmac_clearintr(host->dma.io_intr_clear);
/*
* Calculate amount transferred via DMA
*/
- transferred = dmac_address (host->dma.io_port) - host->dma.start_addr;
+ transferred = dmac_address(host->dma.io_port) - host->dma.start_addr;
host->dma.transferred += transferred;
/*
@@ -1111,12 +1182,12 @@
host->dma.xfer_required = 1;
}
- acornscsi_data_updateptr (host, &host->scsi.SCp, transferred);
+ acornscsi_data_updateptr(host, &host->scsi.SCp, transferred);
/*
* Allocate some buffer space, limited to half the on-board RAM size
*/
- length = min (host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
+ length = min(host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2);
if (length) {
host->dma.start_addr = address = host->dma.free_addr;
host->dma.free_addr = (host->dma.free_addr + length) &
@@ -1126,19 +1197,19 @@
* Transfer data to DMA memory
*/
if (host->dma.direction == DMA_OUT)
- acornscsi_data_write (host, host->scsi.SCp.ptr, host->dma.start_addr,
+ acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr,
length);
length -= 1;
- dmac_write (host->dma.io_port, TXCNTLO, length);
- dmac_write (host->dma.io_port, TXCNTHI, length >> 8);
- dmac_write (host->dma.io_port, TXADRLO, address);
- dmac_write (host->dma.io_port, TXADRMD, address >> 8);
- dmac_write (host->dma.io_port, TXADRHI, 0);
- dmac_write (host->dma.io_port, MASKREG, MASK_OFF);
+ dmac_write(host->dma.io_port, TXCNTLO, length);
+ dmac_write(host->dma.io_port, TXCNTHI, length >> 8);
+ dmac_write(host->dma.io_port, TXADRLO, address);
+ dmac_write(host->dma.io_port, TXADRMD, address >> 8);
+ dmac_write(host->dma.io_port, TXADRHI, 0);
+ dmac_write(host->dma.io_port, MASKREG, MASK_OFF);
#if (DEBUG & DEBUG_DMA)
- DBG(host->SCpnt, acornscsi_dumpdma (host, "into"));
+ DBG(host->SCpnt, acornscsi_dumpdma(host, "into"));
#endif
} else {
host->dma.xfer_setup = 0;
@@ -1149,48 +1220,48 @@
* attention condition. We continue giving one byte until
* the device recognises the attention.
*/
- if (dmac_read (host->dma.io_port, STATUS) & STATUS_RQ0) {
- acornscsi_abortcmd (host, host->SCpnt->tag);
+ if (dmac_read(host->dma.io_port, STATUS) & STATUS_RQ0) {
+ acornscsi_abortcmd(host, host->SCpnt->tag);
- dmac_write (host->dma.io_port, TXCNTLO, 0);
- dmac_write (host->dma.io_port, TXCNTHI, 0);
- dmac_write (host->dma.io_port, TXADRLO, 0);
- dmac_write (host->dma.io_port, TXADRMD, 0);
- dmac_write (host->dma.io_port, TXADRHI, 0);
- dmac_write (host->dma.io_port, MASKREG, MASK_OFF);
+ dmac_write(host->dma.io_port, TXCNTLO, 0);
+ dmac_write(host->dma.io_port, TXCNTHI, 0);
+ dmac_write(host->dma.io_port, TXADRLO, 0);
+ dmac_write(host->dma.io_port, TXADRMD, 0);
+ dmac_write(host->dma.io_port, TXADRHI, 0);
+ dmac_write(host->dma.io_port, MASKREG, MASK_OFF);
}
#endif
}
}
/*
- * Function: void acornscsi_dma_xfer (AS_Host *host)
+ * Function: void acornscsi_dma_xfer(AS_Host *host)
* Purpose : transfer data between AcornSCSI and memory
* Params : host - host to process
*/
static
-void acornscsi_dma_xfer (AS_Host *host)
+void acornscsi_dma_xfer(AS_Host *host)
{
host->dma.xfer_required = 0;
if (host->dma.direction == DMA_IN)
- acornscsi_data_read (host, host->dma.xfer_ptr,
+ acornscsi_data_read(host, host->dma.xfer_ptr,
host->dma.xfer_start, host->dma.xfer_length);
}
/*
- * Function: void acornscsi_dma_adjust (AS_Host *host)
+ * Function: void acornscsi_dma_adjust(AS_Host *host)
* Purpose : adjust DMA pointers & count for bytes transfered to
* SBIC but not SCSI bus.
* Params : host - host to adjust DMA count for
*/
static
-void acornscsi_dma_adjust (AS_Host *host)
+void acornscsi_dma_adjust(AS_Host *host)
{
if (host->dma.xfer_setup) {
signed long transferred;
#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
- DBG(host->SCpnt, acornscsi_dumpdma (host, "adji"));
+ DBG(host->SCpnt, acornscsi_dumpdma(host, "adji"));
#endif
/*
* Calculate correct DMA address - DMA is ahead of SCSI bus while
@@ -1205,17 +1276,17 @@
*/
transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred;
if (transferred < 0)
- printk ("scsi%d.%c: Ack! DMA write correction %ld < 0!\n",
- host->host->host_no, acornscsi_target (host), transferred);
+ printk("scsi%d.%c: Ack! DMA write correction %ld < 0!\n",
+ host->host->host_no, acornscsi_target(host), transferred);
else if (transferred == 0)
host->dma.xfer_setup = 0;
else {
transferred += host->dma.start_addr;
- dmac_write (host->dma.io_port, TXADRLO, transferred);
- dmac_write (host->dma.io_port, TXADRMD, transferred >> 8);
- dmac_write (host->dma.io_port, TXADRHI, transferred >> 16);
+ dmac_write(host->dma.io_port, TXADRLO, transferred);
+ dmac_write(host->dma.io_port, TXADRMD, transferred >> 8);
+ dmac_write(host->dma.io_port, TXADRHI, transferred >> 16);
#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE))
- DBG(host->SCpnt, acornscsi_dumpdma (host, "adjo"));
+ DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo"));
#endif
}
}
@@ -1225,66 +1296,88 @@
/* =========================================================================================
* Data I/O
*/
+static int
+acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout)
+{
+ unsigned int asr, timeout = max_timeout;
+ int my_ptr = *ptr;
+
+ while (my_ptr < len) {
+ asr = sbic_arm_read(host->scsi.io_port, ASR);
+
+ if (asr & ASR_DBR) {
+ timeout = max_timeout;
+
+ sbic_arm_write(host->scsi.io_port, DATA, bytes[my_ptr++]);
+ } else if (asr & ASR_INT)
+ break;
+ else if (--timeout == 0)
+ break;
+ udelay(1);
+ }
+
+ *ptr = my_ptr;
+
+ return (timeout == 0) ? -1 : 0;
+}
+
/*
- * Function: void acornscsi_sendcommand (AS_Host *host)
+ * Function: void acornscsi_sendcommand(AS_Host *host)
* Purpose : send a command to a target
* Params : host - host which is connected to target
*/
-static
-void acornscsi_sendcommand (AS_Host *host)
+static void
+acornscsi_sendcommand(AS_Host *host)
{
Scsi_Cmnd *SCpnt = host->SCpnt;
- unsigned int asr;
- unsigned char *cmdptr, *cmdend;
- sbic_arm_write (host->scsi.io_port, TRANSCNTH, 0);
- sbic_arm_writenext (host->scsi.io_port, 0);
- sbic_arm_writenext (host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command);
- acornscsi_sbic_issuecmd (host, CMND_XFERINFO);
-
- cmdptr = SCpnt->cmnd + host->scsi.SCp.sent_command;
- cmdend = SCpnt->cmnd + SCpnt->cmd_len;
-
- while (cmdptr < cmdend) {
- asr = sbic_arm_read (host->scsi.io_port, ASR);
- if (asr & ASR_DBR)
- sbic_arm_write (host->scsi.io_port, DATA, *cmdptr++);
- else if (asr & ASR_INT)
- break;
- }
- if (cmdptr >= cmdend)
- host->scsi.SCp.sent_command = cmdptr - SCpnt->cmnd;
+ sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0);
+ sbic_arm_writenext(host->scsi.io_port, 0);
+ sbic_arm_writenext(host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command);
+
+ acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
+
+ if (acornscsi_write_pio(host, SCpnt->cmnd,
+ (int *)&host->scsi.SCp.sent_command, SCpnt->cmd_len, 1000000))
+ printk("scsi%d: timeout while sending command\n", host->host->host_no);
+
host->scsi.phase = PHASE_COMMAND;
}
static
-void acornscsi_sendmessage (AS_Host *host)
+void acornscsi_sendmessage(AS_Host *host)
{
- unsigned int message_length = msgqueue_msglength (&host->scsi.msgs);
- int msgnr;
+ unsigned int message_length = msgqueue_msglength(&host->scsi.msgs);
+ unsigned int msgnr;
struct message *msg;
#if (DEBUG & DEBUG_MESSAGES)
- printk ("scsi%d.%c: sending message ",
- host->host->host_no, acornscsi_target (host));
+ printk("scsi%d.%c: sending message ",
+ host->host->host_no, acornscsi_target(host));
#endif
switch (message_length) {
case 0:
- acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT);
- while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
- sbic_arm_write (host->scsi.io_port, DATA, NOP);
+ acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
+
+ acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1");
+
+ sbic_arm_write(host->scsi.io_port, DATA, NOP);
+
host->scsi.last_message = NOP;
#if (DEBUG & DEBUG_MESSAGES)
- printk ("NOP");
+ printk("NOP");
#endif
break;
case 1:
- acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT);
+ acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
msg = msgqueue_getmsg(&host->scsi.msgs, 0);
- while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
- sbic_arm_write (host->scsi.io_port, DATA, msg->msg[0]);
+
+ acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2");
+
+ sbic_arm_write(host->scsi.io_port, DATA, msg->msg[0]);
+
host->scsi.last_message = msg->msg[0];
#if (DEBUG & DEBUG_MESSAGES)
print_msg(msg->msg);
@@ -1300,86 +1393,85 @@
* initiator. This provides an interlock so that the
* initiator can determine which message byte is rejected.
*/
- sbic_arm_write (host->scsi.io_port, TRANSCNTH, 0);
- sbic_arm_writenext (host->scsi.io_port, 0);
- sbic_arm_writenext (host->scsi.io_port, message_length);
- acornscsi_sbic_issuecmd (host, CMND_XFERINFO);
+ sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0);
+ sbic_arm_writenext(host->scsi.io_port, 0);
+ sbic_arm_writenext(host->scsi.io_port, message_length);
+ acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
msgnr = 0;
while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
- unsigned int asr, i;
+ unsigned int i;
#if (DEBUG & DEBUG_MESSAGES)
- print_msg (msg);
+ print_msg(msg);
#endif
- for (i = 0; i < msg->length;) {
- asr = sbic_arm_read (host->scsi.io_port, ASR);
- if (asr & ASR_DBR)
- sbic_arm_write (host->scsi.io_port, DATA, msg->msg[i++]);
- if (asr & ASR_INT)
- break;
- }
+ i = 0;
+ if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000))
+ printk("scsi%d: timeout while sending message\n", host->host->host_no);
+
host->scsi.last_message = msg->msg[0];
if (msg->msg[0] == EXTENDED_MESSAGE)
host->scsi.last_message |= msg->msg[2] << 8;
- if (asr & ASR_INT)
+
+ if (i != msg->length)
break;
}
break;
}
#if (DEBUG & DEBUG_MESSAGES)
- printk ("\n");
+ printk("\n");
#endif
}
/*
- * Function: void acornscsi_readstatusbyte (AS_Host *host)
+ * Function: void acornscsi_readstatusbyte(AS_Host *host)
* Purpose : Read status byte from connected target
* Params : host - host connected to target
*/
static
-void acornscsi_readstatusbyte (AS_Host *host)
+void acornscsi_readstatusbyte(AS_Host *host)
{
- acornscsi_sbic_issuecmd (host, CMND_XFERINFO|CMND_SBT);
- while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
-
- host->scsi.SCp.Status = sbic_arm_read (host->scsi.io_port, DATA);
+ acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT);
+ acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte");
+ host->scsi.SCp.Status = sbic_arm_read(host->scsi.io_port, DATA);
}
/*
- * Function: unsigned char acornscsi_readmessagebyte (AS_Host *host)
+ * Function: unsigned char acornscsi_readmessagebyte(AS_Host *host)
* Purpose : Read one message byte from connected target
* Params : host - host connected to target
*/
static
-unsigned char acornscsi_readmessagebyte (AS_Host *host)
+unsigned char acornscsi_readmessagebyte(AS_Host *host)
{
unsigned char message;
- acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT);
- while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
+ acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT);
- message = sbic_arm_read (host->scsi.io_port, DATA);
+ acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte");
+
+ message = sbic_arm_read(host->scsi.io_port, DATA);
/* wait for MSGIN-XFER-PAUSED */
- while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_INT) == 0);
- sbic_arm_read (host->scsi.io_port, SSR);
+ acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte");
+
+ sbic_arm_read(host->scsi.io_port, SSR);
return message;
}
/*
- * Function: void acornscsi_message (AS_Host *host)
+ * Function: void acornscsi_message(AS_Host *host)
* Purpose : Read complete message from connected target & action message
* Params : host - host connected to target
*/
static
-void acornscsi_message (AS_Host *host)
+void acornscsi_message(AS_Host *host)
{
unsigned char message[16];
unsigned int msgidx = 0, msglen = 1;
do {
- message[msgidx] = acornscsi_readmessagebyte (host);
+ message[msgidx] = acornscsi_readmessagebyte(host);
switch (msgidx) {
case 0:
@@ -1395,17 +1487,17 @@
}
msgidx += 1;
if (msgidx < msglen) {
- acornscsi_sbic_issuecmd (host, CMND_NEGATEACK);
+ acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
/* wait for next msg-in */
- while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_INT) == 0);
- sbic_arm_read (host->scsi.io_port, SSR);
+ acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack");
+ sbic_arm_read(host->scsi.io_port, SSR);
}
} while (msgidx < msglen);
#if (DEBUG & DEBUG_MESSAGES)
printk("scsi%d.%c: message in: ",
- host->host->host_no, acornscsi_target (host));
+ host->host->host_no, acornscsi_target(host));
print_msg(message);
printk("\n");
#endif
@@ -1419,7 +1511,7 @@
*/
if (message[0] == SIMPLE_QUEUE_TAG)
host->scsi.reconnected.tag = message[1];
- if (acornscsi_reconnect_finish (host))
+ if (acornscsi_reconnect_finish(host))
host->scsi.phase = PHASE_MSGIN;
}
@@ -1429,7 +1521,7 @@
case COMMAND_COMPLETE:
if (host->scsi.phase != PHASE_STATUSIN) {
printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
- host->host->host_no, acornscsi_target (host));
+ host->host->host_no, acornscsi_target(host));
acornscsi_dumplog(host, host->SCpnt->target);
}
host->scsi.phase = PHASE_DONE;
@@ -1443,7 +1535,7 @@
* direct the initiator to copy the active data pointer to
* the saved data pointer for the current I/O process.
*/
- acornscsi_dma_cleanup (host);
+ acornscsi_dma_cleanup(host);
host->SCpnt->SCp = host->scsi.SCp;
host->SCpnt->SCp.sent_command = 0;
host->scsi.phase = PHASE_MSGIN;
@@ -1459,7 +1551,7 @@
* status pointers shall be restored to the beginning of
* the present command and status areas.'
*/
- acornscsi_dma_cleanup (host);
+ acornscsi_dma_cleanup(host);
host->scsi.SCp = host->SCpnt->SCp;
host->scsi.phase = PHASE_MSGIN;
break;
@@ -1474,7 +1566,7 @@
* message. When reconnection is completed, the most recent
* saved pointer values are restored.'
*/
- acornscsi_dma_cleanup (host);
+ acornscsi_dma_cleanup(host);
host->scsi.phase = PHASE_DISCONNECT;
break;
@@ -1493,8 +1585,8 @@
/*
* If we have any messages waiting to go out, then assert ATN now
*/
- if (msgqueue_msglength (&host->scsi.msgs))
- acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
+ if (msgqueue_msglength(&host->scsi.msgs))
+ acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
switch (host->scsi.last_message) {
#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
@@ -1507,21 +1599,21 @@
* message is received, it shall respond with a MESSAGE REJECT
* message and accept the I/O process as if it were untagged.
*/
- printk (KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
- host->host->host_no, acornscsi_target (host));
+ printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
+ host->host->host_no, acornscsi_target(host));
host->SCpnt->device->tagged_queue = 0;
- set_bit (host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns);
+ set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns);
break;
#endif
case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
/*
* Target can't handle synchronous transfers
*/
- printk (KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n",
- host->host->host_no, acornscsi_target (host));
+ printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n",
+ host->host->host_no, acornscsi_target(host));
host->device[host->SCpnt->target].sync_xfer = SYNCHTRANSFER_2DBA;
host->device[host->SCpnt->target].sync_state = SYNC_ASYNCHRONOUS;
- sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
+ sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
break;
default:
@@ -1535,8 +1627,8 @@
case SIMPLE_QUEUE_TAG:
/* tag queue reconnect... message[1] = queue tag. Print something to indicate something happened! */
- printk ("scsi%d.%c: reconnect queue tag %02X\n",
- host->host->host_no, acornscsi_target (host),
+ printk("scsi%d.%c: reconnect queue tag %02X\n",
+ host->host->host_no, acornscsi_target(host),
message[1]);
break;
@@ -1552,26 +1644,26 @@
* and the target retries fail, then we fallback to asynchronous mode
*/
host->device[host->SCpnt->target].sync_state = SYNC_COMPLETED;
- printk (KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n",
+ printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n",
host->host->host_no, acornscsi_target(host),
message[4], message[3] * 4);
host->device[host->SCpnt->target].sync_xfer =
- calc_sync_xfer (message[3] * 4, message[4]);
+ calc_sync_xfer(message[3] * 4, message[4]);
} else {
unsigned char period, length;
/*
* Target requested synchronous transfers. The agreement is only
* to be in operation AFTER the target leaves message out phase.
*/
- acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
- period = max (message[3], sdtr_period / 4);
- length = min (message[4], sdtr_size);
- msgqueue_addmsg (&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3,
+ acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
+ period = max(message[3], sdtr_period / 4);
+ length = min(message[4], sdtr_size);
+ msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3,
EXTENDED_SDTR, period, length);
host->device[host->SCpnt->target].sync_xfer =
- calc_sync_xfer (period * 4, length);
+ calc_sync_xfer(period * 4, length);
}
- sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
+ sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
break;
#else
/* We do not accept synchronous transfers. Respond with a
@@ -1584,9 +1676,9 @@
* to a wide data transfer request.
*/
default:
- acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
- msgqueue_flush (&host->scsi.msgs);
- msgqueue_addmsg (&host->scsi.msgs, 1, MESSAGE_REJECT);
+ acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
+ msgqueue_flush(&host->scsi.msgs);
+ msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
break;
}
break;
@@ -1607,19 +1699,19 @@
* if there are more linked commands available.
*/
if (!host->SCpnt->next_link) {
- printk (KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n",
- instance->host_no, acornscsi_target (host), host->SCpnt->tag);
- acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
- msgqueue_addmsg (&host->scsi.msgs, 1, ABORT);
+ printk(KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n",
+ instance->host_no, acornscsi_target(host), host->SCpnt->tag);
+ acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
+ msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
} else {
Scsi_Cmnd *SCpnt = host->SCpnt;
- acornscsi_dma_cleanup (host);
+ acornscsi_dma_cleanup(host);
host->SCpnt = host->SCpnt->next_link;
host->SCpnt->tag = SCpnt->tag;
SCpnt->result = DID_OK | host->scsi.SCp.Message << 8 | host->Scsi.SCp.Status;
- SCpnt->done (SCpnt);
+ SCpnt->done(SCpnt);
/* initialise host->SCpnt->SCp */
}
@@ -1628,42 +1720,42 @@
#endif
default: /* reject message */
- printk (KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n",
- host->host->host_no, acornscsi_target (host),
+ printk(KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n",
+ host->host->host_no, acornscsi_target(host),
message[0]);
- acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
- msgqueue_flush (&host->scsi.msgs);
- msgqueue_addmsg (&host->scsi.msgs, 1, MESSAGE_REJECT);
+ acornscsi_sbic_issuecmd(host, CMND_ASSERTATN);
+ msgqueue_flush(&host->scsi.msgs);
+ msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT);
host->scsi.phase = PHASE_MSGIN;
break;
}
- acornscsi_sbic_issuecmd (host, CMND_NEGATEACK);
+ acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
}
/*
- * Function: int acornscsi_buildmessages (AS_Host *host)
+ * Function: int acornscsi_buildmessages(AS_Host *host)
* Purpose : build the connection messages for a host
* Params : host - host to add messages to
*/
static
-void acornscsi_buildmessages (AS_Host *host)
+void acornscsi_buildmessages(AS_Host *host)
{
#if 0
/* does the device need resetting? */
if (cmd_reset) {
- msgqueue_addmsg (&host->scsi.msgs, 1, BUS_DEVICE_RESET);
+ msgqueue_addmsg(&host->scsi.msgs, 1, BUS_DEVICE_RESET);
return;
}
#endif
- msgqueue_addmsg (&host->scsi.msgs, 1,
+ msgqueue_addmsg(&host->scsi.msgs, 1,
IDENTIFY(host->device[host->SCpnt->target].disconnect_ok,
host->SCpnt->lun));
#if 0
/* does the device need the current command aborted */
if (cmd_aborted) {
- acornscsi_abortcmd (host->SCpnt->tag);
+ acornscsi_abortcmd(host->SCpnt->tag);
return;
}
#endif
@@ -1678,14 +1770,14 @@
tag_type = HEAD_OF_QUEUE_TAG;
else
tag_type = SIMPLE_QUEUE_TAG;
- msgqueue_addmsg (&host->scsi.msgs, 2, tag_type, host->SCpnt->tag);
+ msgqueue_addmsg(&host->scsi.msgs, 2, tag_type, host->SCpnt->tag);
}
#endif
#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
if (host->device[host->SCpnt->target].sync_state == SYNC_NEGOCIATE) {
host->device[host->SCpnt->target].sync_state = SYNC_SENT_REQUEST;
- msgqueue_addmsg (&host->scsi.msgs, 5,
+ msgqueue_addmsg(&host->scsi.msgs, 5,
EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
sdtr_period / 4, sdtr_size);
}
@@ -1693,29 +1785,29 @@
}
/*
- * Function: int acornscsi_starttransfer (AS_Host *host)
+ * Function: int acornscsi_starttransfer(AS_Host *host)
* Purpose : transfer data to/from connected target
* Params : host - host to which target is connected
* Returns : 0 if failure
*/
static
-int acornscsi_starttransfer (AS_Host *host)
+int acornscsi_starttransfer(AS_Host *host)
{
int residual;
if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) {
- printk (KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n",
- host->host->host_no, acornscsi_target (host));
+ printk(KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n",
+ host->host->host_no, acornscsi_target(host));
return 0;
}
residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
- sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
- sbic_arm_writenext (host->scsi.io_port, residual >> 16);
- sbic_arm_writenext (host->scsi.io_port, residual >> 8);
- sbic_arm_writenext (host->scsi.io_port, residual);
- acornscsi_sbic_issuecmd (host, CMND_XFERINFO);
+ sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
+ sbic_arm_writenext(host->scsi.io_port, residual >> 16);
+ sbic_arm_writenext(host->scsi.io_port, residual >> 8);
+ sbic_arm_writenext(host->scsi.io_port, residual);
+ acornscsi_sbic_issuecmd(host, CMND_XFERINFO);
return 1;
}
@@ -1723,7 +1815,7 @@
* Connection & Disconnection
*/
/*
- * Function : acornscsi_reconnect (AS_Host *host)
+ * Function : acornscsi_reconnect(AS_Host *host)
* Purpose : reconnect a previously disconnected command
* Params : host - host specific data
* Remarks : SCSI spec says:
@@ -1731,27 +1823,27 @@
* of saved pointers upon reconnection of the I/O process'
*/
static
-int acornscsi_reconnect (AS_Host *host)
+int acornscsi_reconnect(AS_Host *host)
{
unsigned int target, lun, ok = 0;
- target = sbic_arm_read (host->scsi.io_port, SOURCEID);
+ target = sbic_arm_read(host->scsi.io_port, SOURCEID);
if (!(target & 8))
- printk (KERN_ERR "scsi%d: invalid source id after reselection "
+ printk(KERN_ERR "scsi%d: invalid source id after reselection "
"- device fault?\n",
host->host->host_no);
target &= 7;
if (host->SCpnt && !host->scsi.disconnectable) {
- printk (KERN_ERR "scsi%d.%d: reconnected while command in "
+ printk(KERN_ERR "scsi%d.%d: reconnected while command in "
"progress to target %d?\n",
host->host->host_no, target, host->SCpnt->target);
host->SCpnt = NULL;
}
- lun = sbic_arm_read (host->scsi.io_port, DATA) & 7;
+ lun = sbic_arm_read(host->scsi.io_port, DATA) & 7;
host->scsi.reconnected.target = target;
host->scsi.reconnected.lun = lun;
@@ -1761,7 +1853,7 @@
host->SCpnt->target == target && host->SCpnt->lun == lun)
ok = 1;
- if (!ok && queue_probetgtlun (&host->queues.disconnected, target, lun))
+ if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun))
ok = 1;
ADD_STATUS(target, 0x81, host->scsi.phase, 0);
@@ -1770,26 +1862,28 @@
host->scsi.phase = PHASE_RECONNECTED;
} else {
/* this doesn't seem to work */
- printk (KERN_ERR "scsi%d.%c: reselected with no command "
+ printk(KERN_ERR "scsi%d.%c: reselected with no command "
"to reconnect with\n",
host->host->host_no, '0' + target);
- acornscsi_dumplog (host, target);
- acornscsi_sbic_issuecmd (host, CMND_ASSERTATN);
- msgqueue_addmsg (&host->scsi.msgs, 1, ABORT);
- host->scsi.phase = PHASE_ABORTED;
+ acornscsi_dumplog(host, target);
+ acornscsi_abortcmd(host, 0);
+ if (host->SCpnt) {
+ queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
+ host->SCpnt = NULL;
+ }
}
- acornscsi_sbic_issuecmd (host, CMND_NEGATEACK);
+ acornscsi_sbic_issuecmd(host, CMND_NEGATEACK);
return !ok;
}
/*
- * Function: int acornscsi_reconect_finish (AS_Host *host)
+ * Function: int acornscsi_reconect_finish(AS_Host *host)
* Purpose : finish reconnecting a command
* Params : host - host to complete
* Returns : 0 if failed
*/
static
-int acornscsi_reconnect_finish (AS_Host *host)
+int acornscsi_reconnect_finish(AS_Host *host)
{
if (host->scsi.disconnectable && host->SCpnt) {
host->scsi.disconnectable = 0;
@@ -1797,45 +1891,44 @@
host->SCpnt->lun == host->scsi.reconnected.lun &&
host->SCpnt->tag == host->scsi.reconnected.tag) {
#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
- DBG(host->SCpnt, printk ("scsi%d.%c: reconnected",
- host->host->host_no, acornscsi_target (host)));
+ DBG(host->SCpnt, printk("scsi%d.%c: reconnected",
+ host->host->host_no, acornscsi_target(host)));
#endif
} else {
- queue_add_cmd_tail (&host->queues.disconnected, host->SCpnt);
+ queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt);
#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
- DBG(host->SCpnt, printk ("scsi%d.%c: had to move command "
+ DBG(host->SCpnt, printk("scsi%d.%c: had to move command "
"to disconnected queue\n",
- host->host->host_no, acornscsi_target (host)));
+ host->host->host_no, acornscsi_target(host)));
#endif
host->SCpnt = NULL;
}
}
if (!host->SCpnt) {
- host->SCpnt = queue_remove_tgtluntag (&host->queues.disconnected,
+ host->SCpnt = queue_remove_tgtluntag(&host->queues.disconnected,
host->scsi.reconnected.target,
host->scsi.reconnected.lun,
host->scsi.reconnected.tag);
#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
- DBG(host->SCpnt, printk ("scsi%d.%c: had to get command",
- host->host->host_no, acornscsi_target (host)));
+ DBG(host->SCpnt, printk("scsi%d.%c: had to get command",
+ host->host->host_no, acornscsi_target(host)));
#endif
}
- if (!host->SCpnt) {
- acornscsi_abortcmd (host, host->scsi.reconnected.tag);
- host->scsi.phase = PHASE_ABORTED;
- } else {
+ if (!host->SCpnt)
+ acornscsi_abortcmd(host, host->scsi.reconnected.tag);
+ else {
/*
* Restore data pointer from SAVED pointers.
*/
host->scsi.SCp = host->SCpnt->SCp;
#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
- printk (", data pointers: [%p, %X]",
+ printk(", data pointers: [%p, %X]",
host->scsi.SCp.ptr, host->scsi.SCp.this_residual);
#endif
}
#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON))
- printk ("\n");
+ printk("\n");
#endif
host->dma.transferred = host->scsi.SCp.scsi_xferred;
@@ -1844,47 +1937,48 @@
}
/*
- * Function: void acornscsi_disconnect_unexpected (AS_Host *host)
+ * Function: void acornscsi_disconnect_unexpected(AS_Host *host)
* Purpose : handle an unexpected disconnect
* Params : host - host on which disconnect occurred
*/
static
-void acornscsi_disconnect_unexpected (AS_Host *host)
+void acornscsi_disconnect_unexpected(AS_Host *host)
{
- printk (KERN_ERR "scsi%d.%c: unexpected disconnect\n",
- host->host->host_no, acornscsi_target (host));
+ printk(KERN_ERR "scsi%d.%c: unexpected disconnect\n",
+ host->host->host_no, acornscsi_target(host));
#if (DEBUG & DEBUG_ABORT)
- acornscsi_dumplog (host, 8);
+ acornscsi_dumplog(host, 8);
#endif
- acornscsi_done (host, &host->SCpnt, DID_ABORT);
+ acornscsi_done(host, &host->SCpnt, DID_ERROR);
}
/*
- * Function: void acornscsi_abortcmd (AS_host *host, unsigned char tag)
+ * Function: void acornscsi_abortcmd(AS_host *host, unsigned char tag)
* Purpose : abort a currently executing command
* Params : host - host with connected command to abort
* tag - tag to abort
*/
static
-void acornscsi_abortcmd (AS_Host *host, unsigned char tag)
+void acornscsi_abortcmd(AS_Host *host, unsigned char tag)
{
- sbic_arm_write (host->scsi.io_port, CMND, CMND_ASSERTATN);
+ host->scsi.phase = PHASE_ABORTED;
+ sbic_arm_write(host->scsi.io_port, CMND, CMND_ASSERTATN);
- msgqueue_flush (&host->scsi.msgs);
+ msgqueue_flush(&host->scsi.msgs);
#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
if (tag)
- msgqueue_addmsg (&host->scsi.msgs, 2, ABORT_TAG, tag);
+ msgqueue_addmsg(&host->scsi.msgs, 2, ABORT_TAG, tag);
else
#endif
- msgqueue_addmsg (&host->scsi.msgs, 1, ABORT);
+ msgqueue_addmsg(&host->scsi.msgs, 1, ABORT);
}
/* ==========================================================================================
* Interrupt routines.
*/
/*
- * Function: int acornscsi_sbicintr (AS_Host *host)
+ * Function: int acornscsi_sbicintr(AS_Host *host)
* Purpose : handle interrupts from SCSI device
* Params : host - host to process
* Returns : INTR_PROCESS if expecting another SBIC interrupt
@@ -1892,15 +1986,15 @@
* INTR_NEXT_COMMAND if we have finished processing the command
*/
static
-intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq)
+intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq)
{
unsigned int asr, ssr;
- asr = sbic_arm_read (host->scsi.io_port, ASR);
+ asr = sbic_arm_read(host->scsi.io_port, ASR);
if (!(asr & ASR_INT))
return INTR_IDLE;
- ssr = sbic_arm_read (host->scsi.io_port, SSR);
+ ssr = sbic_arm_read(host->scsi.io_port, SSR);
#if (DEBUG & DEBUG_PHASES)
print_sbic_status(asr, ssr, host->scsi.phase);
@@ -1913,23 +2007,23 @@
switch (ssr) {
case 0x00: /* reset state - not advanced */
- printk (KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n",
+ printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n",
host->host->host_no);
/* setup sbic - WD33C93A */
- sbic_arm_write (host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
- sbic_arm_write (host->scsi.io_port, CMND, CMND_RESET);
+ sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);
+ sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET);
return INTR_IDLE;
case 0x01: /* reset state - advanced */
- sbic_arm_write (host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
- sbic_arm_write (host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
- sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
- sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
- msgqueue_flush (&host->scsi.msgs);
+ sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);
+ sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);
+ sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);
+ sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);
+ msgqueue_flush(&host->scsi.msgs);
return INTR_IDLE;
case 0x41: /* unexpected disconnect aborted command */
- acornscsi_disconnect_unexpected (host);
+ acornscsi_disconnect_unexpected(host);
return INTR_NEXT_COMMAND;
}
@@ -1939,35 +2033,35 @@
case 0x11: /* -> PHASE_CONNECTED */
/* BUS FREE -> SELECTION */
host->scsi.phase = PHASE_CONNECTED;
- msgqueue_flush (&host->scsi.msgs);
+ msgqueue_flush(&host->scsi.msgs);
host->dma.transferred = host->scsi.SCp.scsi_xferred;
/* 33C93 gives next interrupt indicating bus phase */
- asr = sbic_arm_read (host->scsi.io_port, ASR);
+ asr = sbic_arm_read(host->scsi.io_port, ASR);
if (!(asr & ASR_INT))
break;
- ssr = sbic_arm_read (host->scsi.io_port, SSR);
+ ssr = sbic_arm_read(host->scsi.io_port, SSR);
ADD_STATUS(8, ssr, host->scsi.phase, 1);
ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, 1);
goto connected;
case 0x42: /* select timed out */
/* -> PHASE_IDLE */
- acornscsi_done (host, &host->SCpnt, DID_NO_CONNECT);
+ acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT);
return INTR_NEXT_COMMAND;
case 0x81: /* -> PHASE_RECONNECTED or PHASE_ABORTED */
/* BUS FREE -> RESELECTION */
host->origSCpnt = host->SCpnt;
host->SCpnt = NULL;
- msgqueue_flush (&host->scsi.msgs);
- acornscsi_reconnect (host);
+ msgqueue_flush(&host->scsi.msgs);
+ acornscsi_reconnect(host);
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
- acornscsi_abortcmd (host, host->SCpnt->tag);
+ printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+ acornscsi_abortcmd(host, host->SCpnt->tag);
}
return INTR_PROCESSING;
@@ -1977,12 +2071,12 @@
#ifdef NONSTANDARD
case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
/* SELECTION -> COMMAND */
- acornscsi_sendcommand (host);
+ acornscsi_sendcommand(host);
break;
case 0x8b: /* -> PHASE_STATUS */
/* SELECTION -> STATUS */
- acornscsi_readstatusbyte (host);
+ acornscsi_readstatusbyte(host);
host->scsi.phase = PHASE_STATUSIN;
break;
#endif
@@ -1990,55 +2084,57 @@
case 0x8e: /* -> PHASE_MSGOUT */
/* SELECTION ->MESSAGE OUT */
host->scsi.phase = PHASE_MSGOUT;
- acornscsi_buildmessages (host);
- acornscsi_sendmessage (host);
+ acornscsi_buildmessages(host);
+ acornscsi_sendmessage(host);
break;
/* these should not happen */
case 0x85: /* target disconnected */
- acornscsi_done (host, &host->SCpnt, DID_ERROR);
+ acornscsi_done(host, &host->SCpnt, DID_ERROR);
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
- acornscsi_abortcmd (host, host->SCpnt->tag);
+ printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+ acornscsi_abortcmd(host, host->SCpnt->tag);
}
return INTR_PROCESSING;
case PHASE_MSGOUT: /* STATE: connected & sent IDENTIFY message */
/*
- * SCSI standard says th at a MESSAGE OUT phases can be followed by a DATA phase
+ * SCSI standard says that MESSAGE OUT phases can be followed by a
+ * DATA phase, STATUS phase, MESSAGE IN phase or COMMAND phase
*/
switch (ssr) {
- case 0x8a:
+ case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
case 0x1a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
/* MESSAGE OUT -> COMMAND */
- acornscsi_sendcommand (host);
+ acornscsi_sendcommand(host);
break;
+ case 0x8b: /* -> PHASE_STATUS */
case 0x1b: /* -> PHASE_STATUS */
/* MESSAGE OUT -> STATUS */
- acornscsi_readstatusbyte (host);
+ acornscsi_readstatusbyte(host);
host->scsi.phase = PHASE_STATUSIN;
break;
case 0x8e: /* -> PHASE_MSGOUT */
/* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */
- acornscsi_sendmessage (host);
+ acornscsi_sendmessage(host);
break;
- case 0x4f:
+ case 0x4f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
/* MESSAGE OUT -> MESSAGE IN */
- acornscsi_message (host);
+ acornscsi_message(host);
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
@@ -2047,43 +2143,43 @@
case 0x18: /* -> PHASE_DATAOUT */
/* COMMAND -> DATA OUT */
if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
- acornscsi_abortcmd (host, host->SCpnt->tag);
- acornscsi_dma_setup (host, DMA_OUT);
- if (!acornscsi_starttransfer (host))
- acornscsi_abortcmd (host, host->SCpnt->tag);
+ acornscsi_abortcmd(host, host->SCpnt->tag);
+ acornscsi_dma_setup(host, DMA_OUT);
+ if (!acornscsi_starttransfer(host))
+ acornscsi_abortcmd(host, host->SCpnt->tag);
host->scsi.phase = PHASE_DATAOUT;
return INTR_IDLE;
case 0x19: /* -> PHASE_DATAIN */
/* COMMAND -> DATA IN */
if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len)
- acornscsi_abortcmd (host, host->SCpnt->tag);
- acornscsi_dma_setup (host, DMA_IN);
- if (!acornscsi_starttransfer (host))
- acornscsi_abortcmd (host, host->SCpnt->tag);
+ acornscsi_abortcmd(host, host->SCpnt->tag);
+ acornscsi_dma_setup(host, DMA_IN);
+ if (!acornscsi_starttransfer(host))
+ acornscsi_abortcmd(host, host->SCpnt->tag);
host->scsi.phase = PHASE_DATAIN;
return INTR_IDLE;
case 0x1b: /* -> PHASE_STATUS */
/* COMMAND -> STATUS */
- acornscsi_readstatusbyte (host);
+ acornscsi_readstatusbyte(host);
host->scsi.phase = PHASE_STATUSIN;
break;
case 0x1e: /* -> PHASE_MSGOUT */
/* COMMAND -> MESSAGE OUT */
- acornscsi_sendmessage (host);
+ acornscsi_sendmessage(host);
break;
case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */
/* COMMAND -> MESSAGE IN */
- acornscsi_message (host);
+ acornscsi_message(host);
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
@@ -2094,19 +2190,19 @@
host->scsi.phase = PHASE_IDLE;
host->stats.disconnects += 1;
} else {
- printk (KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_NEXT_COMMAND;
case PHASE_IDLE: /* STATE: disconnected */
if (ssr == 0x81) /* -> PHASE_RECONNECTED or PHASE_ABORTED */
- acornscsi_reconnect (host);
+ acornscsi_reconnect(host);
else {
- printk (KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
@@ -2119,54 +2215,54 @@
* If we reconnected and we're not in MESSAGE IN phase after IDENTIFY,
* reconnect I_T_L command
*/
- if (ssr != 0x8f && !acornscsi_reconnect_finish (host))
+ if (ssr != 0x8f && !acornscsi_reconnect_finish(host))
return INTR_IDLE;
ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq);
switch (ssr) {
case 0x88: /* data out phase */
/* -> PHASE_DATAOUT */
/* MESSAGE IN -> DATA OUT */
- acornscsi_dma_setup (host, DMA_OUT);
- if (!acornscsi_starttransfer (host))
- acornscsi_abortcmd (host, host->SCpnt->tag);
+ acornscsi_dma_setup(host, DMA_OUT);
+ if (!acornscsi_starttransfer(host))
+ acornscsi_abortcmd(host, host->SCpnt->tag);
host->scsi.phase = PHASE_DATAOUT;
return INTR_IDLE;
case 0x89: /* data in phase */
/* -> PHASE_DATAIN */
/* MESSAGE IN -> DATA IN */
- acornscsi_dma_setup (host, DMA_IN);
- if (!acornscsi_starttransfer (host))
- acornscsi_abortcmd (host, host->SCpnt->tag);
+ acornscsi_dma_setup(host, DMA_IN);
+ if (!acornscsi_starttransfer(host))
+ acornscsi_abortcmd(host, host->SCpnt->tag);
host->scsi.phase = PHASE_DATAIN;
return INTR_IDLE;
case 0x8a: /* command out */
/* MESSAGE IN -> COMMAND */
- acornscsi_sendcommand (host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
+ acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */
break;
case 0x8b: /* status in */
/* -> PHASE_STATUSIN */
/* MESSAGE IN -> STATUS */
- acornscsi_readstatusbyte (host);
+ acornscsi_readstatusbyte(host);
host->scsi.phase = PHASE_STATUSIN;
break;
case 0x8e: /* message out */
/* -> PHASE_MSGOUT */
/* MESSAGE IN -> MESSAGE OUT */
- acornscsi_sendmessage (host);
+ acornscsi_sendmessage(host);
break;
case 0x8f: /* message in */
- acornscsi_message (host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
+ acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
@@ -2177,41 +2273,45 @@
*/
switch (ssr) {
case 0x19: /* -> PHASE_DATAIN */
- acornscsi_abortcmd (host, host->SCpnt->tag);
+ case 0x89: /* -> PHASE_DATAIN */
+ acornscsi_abortcmd(host, host->SCpnt->tag);
return INTR_IDLE;
- case 0x4b: /* -> PHASE_STATUSIN */
case 0x1b: /* -> PHASE_STATUSIN */
+ case 0x4b: /* -> PHASE_STATUSIN */
+ case 0x8b: /* -> PHASE_STATUSIN */
/* DATA IN -> STATUS */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
- acornscsi_sbic_xfcount (host);
- acornscsi_dma_stop (host);
- acornscsi_readstatusbyte (host);
+ acornscsi_sbic_xfcount(host);
+ acornscsi_dma_stop(host);
+ acornscsi_readstatusbyte(host);
host->scsi.phase = PHASE_STATUSIN;
break;
case 0x1e: /* -> PHASE_MSGOUT */
case 0x4e: /* -> PHASE_MSGOUT */
+ case 0x8e: /* -> PHASE_MSGOUT */
/* DATA IN -> MESSAGE OUT */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
- acornscsi_sbic_xfcount (host);
- acornscsi_dma_stop (host);
- acornscsi_sendmessage (host);
+ acornscsi_sbic_xfcount(host);
+ acornscsi_dma_stop(host);
+ acornscsi_sendmessage(host);
break;
case 0x1f: /* message in */
case 0x4f: /* message in */
+ case 0x8f: /* message in */
/* DATA IN -> MESSAGE IN */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
- acornscsi_sbic_xfcount (host);
- acornscsi_dma_stop (host);
- acornscsi_message (host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
+ acornscsi_sbic_xfcount(host);
+ acornscsi_dma_stop(host);
+ acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
@@ -2222,58 +2322,69 @@
*/
switch (ssr) {
case 0x18: /* -> PHASE_DATAOUT */
- acornscsi_abortcmd (host, host->SCpnt->tag);
+ case 0x88: /* -> PHASE_DATAOUT */
+ acornscsi_abortcmd(host, host->SCpnt->tag);
return INTR_IDLE;
- case 0x4b: /* -> PHASE_STATUSIN */
case 0x1b: /* -> PHASE_STATUSIN */
+ case 0x4b: /* -> PHASE_STATUSIN */
+ case 0x8b: /* -> PHASE_STATUSIN */
/* DATA OUT -> STATUS */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
- acornscsi_sbic_xfcount (host);
- acornscsi_dma_stop (host);
- acornscsi_dma_adjust (host);
- acornscsi_readstatusbyte (host);
+ acornscsi_sbic_xfcount(host);
+ acornscsi_dma_stop(host);
+ acornscsi_dma_adjust(host);
+ acornscsi_readstatusbyte(host);
host->scsi.phase = PHASE_STATUSIN;
break;
case 0x1e: /* -> PHASE_MSGOUT */
case 0x4e: /* -> PHASE_MSGOUT */
+ case 0x8e: /* -> PHASE_MSGOUT */
/* DATA OUT -> MESSAGE OUT */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
- acornscsi_sbic_xfcount (host);
- acornscsi_dma_stop (host);
- acornscsi_dma_adjust (host);
- acornscsi_sendmessage (host);
+ acornscsi_sbic_xfcount(host);
+ acornscsi_dma_stop(host);
+ acornscsi_dma_adjust(host);
+ acornscsi_sendmessage(host);
break;
case 0x1f: /* message in */
case 0x4f: /* message in */
+ case 0x8f: /* message in */
/* DATA OUT -> MESSAGE IN */
host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
- acornscsi_sbic_xfcount (host);
- acornscsi_dma_stop (host);
- acornscsi_dma_adjust (host);
- acornscsi_message (host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
+ acornscsi_sbic_xfcount(host);
+ acornscsi_dma_stop(host);
+ acornscsi_dma_adjust(host);
+ acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
case PHASE_STATUSIN: /* STATE: status in complete */
- if (ssr == 0x1f) /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
+ switch (ssr) {
+ case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
+ case 0x8f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
/* STATUS -> MESSAGE IN */
- acornscsi_message (host);
- else if (ssr == 0x1e) /* -> PHASE_MSGOUT */
+ acornscsi_message(host);
+ break;
+
+ case 0x1e: /* -> PHASE_MSGOUT */
+ case 0x8e: /* -> PHASE_MSGOUT */
/* STATUS -> MESSAGE OUT */
- acornscsi_sendmessage (host);
- else {
- printk (KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ acornscsi_sendmessage(host);
+ break;
+
+ default:
+ printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
@@ -2281,78 +2392,93 @@
switch (ssr) {
case 0x1e: /* -> PHASE_MSGOUT */
case 0x4e: /* -> PHASE_MSGOUT */
+ case 0x8e: /* -> PHASE_MSGOUT */
/* MESSAGE IN -> MESSAGE OUT */
- acornscsi_sendmessage (host);
+ acornscsi_sendmessage(host);
break;
case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */
case 0x2f:
case 0x4f:
case 0x8f:
- acornscsi_message (host);
+ acornscsi_message(host);
+ break;
+
+ case 0x85:
+ printk("scsi%d.%c: strange message in disconnection\n",
+ host->host->host_no, acornscsi_target(host));
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
+ acornscsi_done(host, &host->SCpnt, DID_ERROR);
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
case PHASE_DONE: /* STATE: received status & message */
switch (ssr) {
case 0x85: /* -> PHASE_IDLE */
- acornscsi_done (host, &host->SCpnt, DID_OK);
+ acornscsi_done(host, &host->SCpnt, DID_OK);
return INTR_NEXT_COMMAND;
+ case 0x1e:
case 0x8e:
- acornscsi_sendmessage (host);
+ acornscsi_sendmessage(host);
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
case PHASE_ABORTED:
switch (ssr) {
case 0x85:
- acornscsi_done (host, &host->SCpnt, DID_ABORT);
+ if (host->SCpnt)
+ acornscsi_done(host, &host->SCpnt, DID_ABORT);
+ else {
+ clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun,
+ host->busyluns);
+ host->scsi.phase = PHASE_IDLE;
+ }
return INTR_NEXT_COMMAND;
case 0x1e:
case 0x2e:
case 0x4e:
case 0x8e:
- acornscsi_sendmessage (host);
+ acornscsi_sendmessage(host);
break;
default:
- printk (KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
default:
- printk (KERN_ERR "scsi%d.%c: unknown driver phase %d\n",
- host->host->host_no, acornscsi_target (host), ssr);
- acornscsi_dumplog (host, host->SCpnt ? host->SCpnt->target : 8);
+ printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n",
+ host->host->host_no, acornscsi_target(host), ssr);
+ acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8);
}
return INTR_PROCESSING;
}
/*
- * Prototype: void acornscsi_intr (int irq, void *dev_id, struct pt_regs *regs)
+ * Prototype: void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
* Purpose : handle interrupts from Acorn SCSI card
* Params : irq - interrupt number
* dev_id - device specific data (AS_Host structure)
* regs - processor registers when interrupt occurred
*/
static
-void acornscsi_intr (int irq, void *dev_id, struct pt_regs *regs)
+void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
{
AS_Host *host = (AS_Host *)dev_id;
intr_ret_t ret;
@@ -2360,21 +2486,21 @@
int in_irq = 0;
if (host->scsi.interrupt)
- printk ("scsi%d: interrupt re-entered\n", host->host->host_no);
+ printk("scsi%d: interrupt re-entered\n", host->host->host_no);
host->scsi.interrupt = 1;
do {
ret = INTR_IDLE;
- iostatus = inb (host->card.io_intr);
+ iostatus = inb(host->card.io_intr);
if (iostatus & 2) {
- acornscsi_dma_intr (host);
- iostatus = inb (host->card.io_intr);
+ acornscsi_dma_intr(host);
+ iostatus = inb(host->card.io_intr);
}
if (iostatus & 8)
- ret = acornscsi_sbicintr (host, in_irq);
+ ret = acornscsi_sbicintr(host, in_irq);
/*
* If we have a transfer pending, start it.
@@ -2382,10 +2508,10 @@
* it's data
*/
if (host->dma.xfer_required)
- acornscsi_dma_xfer (host);
+ acornscsi_dma_xfer(host);
if (ret == INTR_NEXT_COMMAND)
- ret = acornscsi_kick (host);
+ ret = acornscsi_kick(host);
in_irq = 1;
} while (ret != INTR_IDLE);
@@ -2398,29 +2524,29 @@
*/
/*
- * Function : acornscsi_queuecmd (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+ * Function : acornscsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
* Purpose : queues a SCSI command
* Params : cmd - SCSI command
* done - function called on completion, with pointer to command descriptor
* Returns : 0, or < 0 on error.
*/
-int acornscsi_queuecmd (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{
AS_Host *host = (AS_Host *)SCpnt->host->hostdata;
if (!done) {
/* there should be some way of rejecting errors like this without panicing... */
- panic ("scsi%d: queuecommand called with NULL done function [cmd=%p]",
+ panic("scsi%d: queuecommand called with NULL done function [cmd=%p]",
SCpnt->host->host_no, SCpnt);
return -EINVAL;
}
#if (DEBUG & DEBUG_NO_WRITE)
- if (acornscsi_cmdtype (SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) {
- printk (KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n",
+ if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) {
+ printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n",
SCpnt->host->host_no, '0' + SCpnt->target);
SCpnt->result = DID_NO_CONNECT << 16;
- done (SCpnt);
+ done(SCpnt);
return 0;
}
#endif
@@ -2429,7 +2555,7 @@
SCpnt->host_scribble = NULL;
SCpnt->result = 0;
SCpnt->tag = 0;
- SCpnt->SCp.phase = (int)acornscsi_datadirection (SCpnt->cmnd[0]);
+ SCpnt->SCp.phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]);
SCpnt->SCp.sent_command = 0;
SCpnt->SCp.scsi_xferred = 0;
SCpnt->SCp.Status = 0;
@@ -2452,21 +2578,21 @@
{
unsigned long flags;
- if (!queue_add_cmd_ordered (&host->queues.issue, SCpnt)) {
+ if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) {
SCpnt->result = DID_ERROR << 16;
- done (SCpnt);
+ done(SCpnt);
return 0;
}
- save_flags_cli (flags);
+ save_flags_cli(flags);
if (host->scsi.phase == PHASE_IDLE)
- acornscsi_kick (host);
- restore_flags (flags);
+ acornscsi_kick(host);
+ restore_flags(flags);
}
return 0;
}
/*
- * Prototype: void acornscsi_reportstatus (Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
+ * Prototype: void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
* Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2
* Params : SCpntp1 - pointer to command to return
* SCpntp2 - pointer to command to check
@@ -2474,7 +2600,7 @@
* Returns : *SCpntp2 = NULL if *SCpntp1 is the same command structure as *SCpntp2.
*/
static inline
-void acornscsi_reportstatus (Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
+void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result)
{
Scsi_Cmnd *SCpnt = *SCpntp1;
@@ -2482,80 +2608,203 @@
*SCpntp1 = NULL;
SCpnt->result = result;
- SCpnt->scsi_done (SCpnt);
+ SCpnt->scsi_done(SCpnt);
}
if (SCpnt == *SCpntp2)
*SCpntp2 = NULL;
}
+enum res_abort { res_not_running, res_success, res_success_clear, res_snooze };
+
/*
- * Prototype: int acornscsi_abort (Scsi_Cmnd *SCpnt)
+ * Prototype: enum res acornscsi_do_abort(Scsi_Cmnd *SCpnt)
+ * Purpose : abort a command on this host
+ * Params : SCpnt - command to abort
+ * Returns : our abort status
+ */
+static enum res_abort
+acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
+{
+ enum res_abort res = res_not_running;
+
+ if (queue_removecmd(&host->queues.issue, SCpnt)) {
+ /*
+ * The command was on the issue queue, and has not been
+ * issued yet. We can remove the command from the queue,
+ * and acknowledge the abort. Neither the devices nor the
+ * interface know about the command.
+ */
+//#if (DEBUG & DEBUG_ABORT)
+ printk("on issue queue ");
+//#endif
+ res = res_success;
+ } else if (queue_removecmd(&host->queues.disconnected, SCpnt)) {
+ /*
+ * The command was on the disconnected queue. Simply
+ * acknowledge the abort condition, and when the target
+ * reconnects, we will give it an ABORT message. The
+ * target should then disconnect, and we will clear
+ * the busylun bit.
+ */
+//#if (DEBUG & DEBUG_ABORT)
+ printk("on disconnected queue ");
+//#endif
+ res = res_success;
+ } else if (host->SCpnt == SCpnt) {
+ unsigned long flags;
+
+//#if (DEBUG & DEBUG_ABORT)
+ printk("executing ");
+//#endif
+
+ save_flags(flags);
+ cli();
+ switch (host->scsi.phase) {
+ /*
+ * If the interface is idle, and the command is 'disconnectable',
+ * then it is the same as on the disconnected queue. We simply
+ * remove all traces of the command. When the target reconnects,
+ * we will give it an ABORT message since the command could not
+ * be found. When the target finally disconnects, we will clear
+ * the busylun bit.
+ */
+ case PHASE_IDLE:
+ if (host->scsi.disconnectable) {
+ host->scsi.disconnectable = 0;
+ host->SCpnt = NULL;
+ res = res_success;
+ }
+ break;
+
+ /*
+ * If the command has connected and done nothing further,
+ * simply force a disconnect. We also need to clear the
+ * busylun bit.
+ */
+ case PHASE_CONNECTED:
+ sbic_arm_write(host->scsi.io_port, CMND, CMND_DISCONNECT);
+ host->SCpnt = NULL;
+ res = res_success_clear;
+ break;
+
+ default:
+ acornscsi_abortcmd(host, host->SCpnt->tag);
+ res = res_snooze;
+ }
+ restore_flags(flags);
+ } else if (host->origSCpnt == SCpnt) {
+ /*
+ * The command will be executed next, but a command
+ * is currently using the interface. This is similar to
+ * being on the issue queue, except the busylun bit has
+ * been set.
+ */
+ host->origSCpnt = NULL;
+//#if (DEBUG & DEBUG_ABORT)
+ printk("waiting for execution ");
+//#endif
+ res = res_success_clear;
+ } else
+ printk("unknown ");
+
+ return res;
+}
+
+/*
+ * Prototype: int acornscsi_abort(Scsi_Cmnd *SCpnt)
* Purpose : abort a command on this host
* Params : SCpnt - command to abort
* Returns : one of SCSI_ABORT_ macros
*/
-int acornscsi_abort (Scsi_Cmnd *SCpnt)
+int acornscsi_abort(Scsi_Cmnd *SCpnt)
{
- AS_Host *host = (AS_Host *) SCpnt->host->hostdata;
- int result = SCSI_ABORT_NOT_RUNNING;
+ AS_Host *host = (AS_Host *) SCpnt->host->hostdata;
+ int result;
- host->stats.aborts += 1;
+ host->stats.aborts += 1;
#if (DEBUG & DEBUG_ABORT)
- {
- int asr, ssr;
- asr = sbic_arm_read (host->scsi.io_port, ASR);
- ssr = sbic_arm_read (host->scsi.io_port, SSR);
+ {
+ int asr, ssr;
+ asr = sbic_arm_read(host->scsi.io_port, ASR);
+ ssr = sbic_arm_read(host->scsi.io_port, SSR);
- printk (KERN_WARNING "acornscsi_abort: ");
- print_sbic_status(asr, ssr, host->scsi.phase);
- acornscsi_dumplog (host, SCpnt->target);
- }
+ printk(KERN_WARNING "acornscsi_abort: ");
+ print_sbic_status(asr, ssr, host->scsi.phase);
+ acornscsi_dumplog(host, SCpnt->target);
+ }
#endif
- if (queue_removecmd (&host->queues.issue, SCpnt)) {
- SCpnt->result = DID_ABORT << 16;
- SCpnt->scsi_done (SCpnt);
-#if (DEBUG & DEBUG_ABORT)
- printk ("scsi%d: command on issue queue\n", host->host->host_no);
-#endif
- result = SCSI_ABORT_SUCCESS;
- } else if (queue_cmdonqueue (&host->queues.disconnected, SCpnt)) {
- printk ("scsi%d: command on disconnected queue\n", host->host->host_no);
- result = SCSI_ABORT_SNOOZE;
- } else if (host->SCpnt == SCpnt) {
- acornscsi_abortcmd (host, host->SCpnt->tag);
- printk ("scsi%d: command executing\n", host->host->host_no);
- result = SCSI_ABORT_SNOOZE;
- } else if (host->origSCpnt == SCpnt) {
- host->origSCpnt = NULL;
- SCpnt->result = DID_ABORT << 16;
- SCpnt->scsi_done (SCpnt);
-#if (DEBUG & DEBUG_ABORT)
- printk ("scsi%d: command waiting for execution\n", host->host->host_no);
-#endif
- result = SCSI_ABORT_SUCCESS;
- }
+ printk("scsi%d: ", host->host->host_no);
+
+ switch (acornscsi_do_abort(host, SCpnt)) {
+ /*
+ * We managed to find the command and cleared it out.
+ * We do not expect the command to be executing on the
+ * target, but we have set the busylun bit.
+ */
+ case res_success_clear:
+//#if (DEBUG & DEBUG_ABORT)
+ printk("clear ");
+//#endif
+ clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns);
+
+ /*
+ * We found the command, and cleared it out. Either
+ * the command is still known to be executing on the
+ * target, or the busylun bit is not set.
+ */
+ case res_success:
+//#if (DEBUG & DEBUG_ABORT)
+ printk("success\n");
+//#endif
+ SCpnt->result = DID_ABORT << 16;
+ SCpnt->scsi_done(SCpnt);
+ result = SCSI_ABORT_SUCCESS;
+ break;
- if (result == SCSI_ABORT_NOT_RUNNING) {
- printk ("scsi%d: abort(): command not running\n", host->host->host_no);
- acornscsi_dumplog (host, SCpnt->target);
+ /*
+ * We did find the command, but unfortunately we couldn't
+ * unhook it from ourselves. Wait some more, and if it
+ * still doesn't complete, reset the interface.
+ */
+ case res_snooze:
+//#if (DEBUG & DEBUG_ABORT)
+ printk("snooze\n");
+//#endif
+ result = SCSI_ABORT_SNOOZE;
+ break;
+
+ /*
+ * The command could not be found (either because it completed,
+ * or it got dropped.
+ */
+ default:
+ case res_not_running:
+ acornscsi_dumplog(host, SCpnt->target);
#if (DEBUG & DEBUG_ABORT)
- result = SCSI_ABORT_SNOOZE;
+ result = SCSI_ABORT_SNOOZE;
+#else
+ result = SCSI_ABORT_NOT_RUNNING;
#endif
- }
- return result;
+//#if (DEBUG & DEBUG_ABORT)
+ printk("not running\n");
+//#endif
+ break;
+ }
+
+ return result;
}
/*
- * Prototype: int acornscsi_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+ * Prototype: int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
* Purpose : reset a command on this host/reset this host
* Params : SCpnt - command causing reset
* result - what type of reset to perform
* Returns : one of SCSI_RESET_ macros
*/
-int acornscsi_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
{
AS_Host *host = (AS_Host *)SCpnt->host->hostdata;
Scsi_Cmnd *SCptr;
@@ -2566,16 +2815,16 @@
{
int asr, ssr;
- asr = sbic_arm_read (host->scsi.io_port, ASR);
- ssr = sbic_arm_read (host->scsi.io_port, SSR);
+ asr = sbic_arm_read(host->scsi.io_port, ASR);
+ ssr = sbic_arm_read(host->scsi.io_port, SSR);
- printk (KERN_WARNING "acornscsi_reset: ");
+ printk(KERN_WARNING "acornscsi_reset: ");
print_sbic_status(asr, ssr, host->scsi.phase);
- acornscsi_dumplog (host, SCpnt->target);
+ acornscsi_dumplog(host, SCpnt->target);
}
#endif
- acornscsi_dma_stop (host);
+ acornscsi_dma_stop(host);
SCptr = host->SCpnt;
@@ -2583,19 +2832,19 @@
* do hard reset. This resets all devices on this host, and so we
* must set the reset status on all commands.
*/
- acornscsi_resetcard (host);
+ acornscsi_resetcard(host);
/*
* report reset on commands current connected/disconnected
*/
- acornscsi_reportstatus (&host->SCpnt, &SCptr, DID_RESET);
+ acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET);
- while ((SCptr = queue_remove (&host->queues.disconnected)) != NULL)
- acornscsi_reportstatus (&SCptr, &SCpnt, DID_RESET);
+ while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL)
+ acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET);
if (SCpnt) {
SCpnt->result = DID_RESET << 16;
- SCpnt->scsi_done (SCpnt);
+ SCpnt->scsi_done(SCpnt);
}
return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS;
@@ -2607,19 +2856,19 @@
static struct expansion_card *ecs[MAX_ECARDS];
/*
- * Prototype: void acornscsi_init (AS_Host *host)
+ * Prototype: void acornscsi_init(AS_Host *host)
* Purpose : initialise the AS_Host structure for one interface & setup hardware
* Params : host - host to setup
*/
static
-void acornscsi_init (AS_Host *host)
+void acornscsi_init(AS_Host *host)
{
- memset (&host->stats, 0, sizeof (host->stats));
- queue_initialise (&host->queues.issue);
- queue_initialise (&host->queues.disconnected);
- msgqueue_initialise (&host->scsi.msgs);
+ memset(&host->stats, 0, sizeof (host->stats));
+ queue_initialise(&host->queues.issue);
+ queue_initialise(&host->queues.disconnected);
+ msgqueue_initialise(&host->scsi.msgs);
- acornscsi_resetcard (host);
+ acornscsi_resetcard(host);
}
int acornscsi_detect(Scsi_Host_Template * tpnt)
@@ -2634,7 +2883,7 @@
for (i = 0; i < MAX_ECARDS; i++)
ecs[i] = NULL;
- ecard_startfind ();
+ ecard_startfind();
while(1) {
ecs[count] = ecard_find(0, acornscsi_cids);
@@ -2642,37 +2891,37 @@
break;
if (ecs[count]->irq == 0xff) {
- printk ("scsi: WD33C93 does not have IRQ enabled - ignoring\n");
+ printk("scsi: WD33C93 does not have IRQ enabled - ignoring\n");
continue;
}
ecard_claim(ecs[count]); /* Must claim here - card produces irq on reset */
- instance = scsi_register (tpnt, sizeof(AS_Host));
+ instance = scsi_register(tpnt, sizeof(AS_Host));
host = (AS_Host *)instance->hostdata;
- instance->io_port = ecard_address (ecs[count], ECARD_MEMC, 0);
+ instance->io_port = ecard_address(ecs[count], ECARD_MEMC, 0);
instance->irq = ecs[count]->irq;
host->host = instance;
- host->scsi.io_port = ioaddr (instance->io_port + 0x800);
+ host->scsi.io_port = ioaddr(instance->io_port + 0x800);
host->scsi.irq = instance->irq;
host->card.io_intr = POD_SPACE(instance->io_port) + 0x800;
host->card.io_page = POD_SPACE(instance->io_port) + 0xc00;
- host->card.io_ram = ioaddr (instance->io_port);
+ host->card.io_ram = ioaddr(instance->io_port);
host->dma.io_port = instance->io_port + 0xc00;
host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800;
ecs[count]->irqaddr = (char *)ioaddr(host->card.io_intr);
ecs[count]->irqmask = 0x0a;
- request_region (instance->io_port + 0x800, 2, "acornscsi(sbic)");
- request_region (host->card.io_intr, 1, "acornscsi(intr)");
- request_region (host->card.io_page, 1, "acornscsi(page)");
+ request_region(instance->io_port + 0x800, 2, "acornscsi(sbic)");
+ request_region(host->card.io_intr, 1, "acornscsi(intr)");
+ request_region(host->card.io_page, 1, "acornscsi(page)");
#ifdef USE_DMAC
- request_region (host->dma.io_port, 256, "acornscsi(dmac)");
+ request_region(host->dma.io_port, 256, "acornscsi(dmac)");
#endif
- request_region (instance->io_port, 2048, "acornscsi(ram)");
+ request_region(instance->io_port, 2048, "acornscsi(ram)");
if (request_irq(host->scsi.irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", host)) {
printk(KERN_CRIT "scsi%d: IRQ%d not free, interrupts disabled\n",
@@ -2680,7 +2929,7 @@
host->scsi.irq = NO_IRQ;
}
- acornscsi_init (host);
+ acornscsi_init(host);
++count;
}
@@ -2688,12 +2937,12 @@
}
/*
- * Function: int acornscsi_release (struct Scsi_Host *host)
+ * Function: int acornscsi_release(struct Scsi_Host *host)
* Purpose : release all resources used by this adapter
* Params : host - driver structure to release
* Returns : nothing of any consequence
*/
-int acornscsi_release (struct Scsi_Host *instance)
+int acornscsi_release(struct Scsi_Host *instance)
{
AS_Host *host = (AS_Host *)instance->hostdata;
int i;
@@ -2701,30 +2950,30 @@
/*
* Put card into RESET state
*/
- outb (0x80, host->card.io_page);
+ outb(0x80, host->card.io_page);
if (host->scsi.irq != NO_IRQ)
- free_irq (host->scsi.irq, host);
+ free_irq(host->scsi.irq, host);
- release_region (instance->io_port + 0x800, 2);
- release_region (host->card.io_intr, 1);
- release_region (host->card.io_page, 1);
- release_region (host->dma.io_port, 256);
- release_region (instance->io_port, 2048);
+ release_region(instance->io_port + 0x800, 2);
+ release_region(host->card.io_intr, 1);
+ release_region(host->card.io_page, 1);
+ release_region(host->dma.io_port, 256);
+ release_region(instance->io_port, 2048);
for (i = 0; i < MAX_ECARDS; i++)
- if (ecs[i] && instance->io_port == ecard_address (ecs[i], ECARD_MEMC, 0))
- ecard_release (ecs[i]);
+ if (ecs[i] && instance->io_port == ecard_address(ecs[i], ECARD_MEMC, 0))
+ ecard_release(ecs[i]);
- msgqueue_free (&host->scsi.msgs);
- queue_free (&host->queues.disconnected);
- queue_free (&host->queues.issue);
+ msgqueue_free(&host->scsi.msgs);
+ queue_free(&host->queues.disconnected);
+ queue_free(&host->queues.issue);
return 0;
}
/*
- * Function: char *acornscsi_info (struct Scsi_Host *host)
+ * Function: char *acornscsi_info(struct Scsi_Host *host)
* Purpose : return a string describing this interface
* Params : host - host to give information on
* Returns : a constant string
@@ -2736,7 +2985,7 @@
p = string;
- p += sprintf (string, "%s at port %lX irq %d v%d.%d.%d"
+ p += sprintf(string, "%s at port %X irq %d v%d.%d.%d"
#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
" SYNC"
#endif
@@ -2772,7 +3021,7 @@
host = (AS_Host *)instance->hostdata;
- p += sprintf (p, "AcornSCSI driver v%d.%d.%d"
+ p += sprintf(p, "AcornSCSI driver v%d.%d.%d"
#ifdef CONFIG_SCSI_ACORNSCSI_SYNC
" SYNC"
#endif
@@ -2787,14 +3036,14 @@
#endif
"\n\n", VER_MAJOR, VER_MINOR, VER_PATCH);
- p += sprintf (p, "SBIC: WD33C93A Address: %08X IRQ : %d\n",
+ p += sprintf(p, "SBIC: WD33C93A Address: %08X IRQ : %d\n",
host->scsi.io_port, host->scsi.irq);
#ifdef USE_DMAC
- p += sprintf (p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n",
+ p += sprintf(p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n",
host->dma.io_port, host->scsi.irq);
#endif
- p += sprintf (p, "Statistics:\n"
+ p += sprintf(p, "Statistics:\n"
"Queued commands: %-10u Issued commands: %-10u\n"
"Done commands : %-10u Reads : %-10u\n"
"Writes : %-10u Others : %-10u\n"
@@ -2809,47 +3058,47 @@
for (devidx = 0; devidx < 9; devidx ++) {
unsigned int statptr, prev;
- p += sprintf (p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
- statptr = status_ptr[devidx] - 10;
+ p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx));
+ statptr = host->status_ptr[devidx] - 10;
if ((signed int)statptr < 0)
- statptr += 16;
+ statptr += STATUS_BUFFER_SIZE;
- prev = status[devidx][statptr].when;
+ prev = host->status[devidx][statptr].when;
- for (; statptr != status_ptr[devidx]; statptr = (statptr + 1) & 15) {
- if (status[devidx][statptr].when) {
- p += sprintf (p, "%c%02X:%02X+%2ld",
- status[devidx][statptr].irq ? '-' : ' ',
- status[devidx][statptr].ph,
- status[devidx][statptr].ssr,
- (status[devidx][statptr].when - prev) < 100 ?
- (status[devidx][statptr].when - prev) : 99);
- prev = status[devidx][statptr].when;
+ for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) {
+ if (host->status[devidx][statptr].when) {
+ p += sprintf(p, "%c%02X:%02X+%2ld",
+ host->status[devidx][statptr].irq ? '-' : ' ',
+ host->status[devidx][statptr].ph,
+ host->status[devidx][statptr].ssr,
+ (host->status[devidx][statptr].when - prev) < 100 ?
+ (host->status[devidx][statptr].when - prev) : 99);
+ prev = host->status[devidx][statptr].when;
}
}
}
- p += sprintf (p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none");
+ p += sprintf(p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none");
for (scd = instance->host_queue; scd; scd = scd->next) {
int len;
- proc_print_scsidevice (scd, p, &len, 0);
+ proc_print_scsidevice(scd, p, &len, 0);
p += len;
- p += sprintf (p, "Extensions: ");
+ p += sprintf(p, "Extensions: ");
if (scd->tagged_supported)
- p += sprintf (p, "TAG %sabled [%d] ",
+ p += sprintf(p, "TAG %sabled [%d] ",
scd->tagged_queue ? "en" : "dis", scd->current_tag);
- p += sprintf (p, "\nTransfers: ");
+ p += sprintf(p, "\nTransfers: ");
if (host->device[scd->id].sync_xfer & 15)
- p += sprintf (p, "sync, offset %d, %d ns\n",
+ p += sprintf(p, "sync, offset %d, %d ns\n",
host->device[scd->id].sync_xfer & 15,
- acornscsi_getperiod (host->device[scd->id].sync_xfer));
+ acornscsi_getperiod(host->device[scd->id].sync_xfer));
else
- p += sprintf (p, "async\n");
+ p += sprintf(p, "async\n");
pos = p - buffer;
if (pos + begin < offset) {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/acornscsi.h linux.ac/drivers/acorn/scsi/acornscsi.h
--- linux.vanilla/drivers/acorn/scsi/acornscsi.h Sun Nov 8 15:08:18 1998
+++ linux.ac/drivers/acorn/scsi/acornscsi.h Sun Jan 24 23:54:37 1999
@@ -291,6 +291,27 @@
#include "queue.h"
#include "msgqueue.h"
+#define STATUS_BUFFER_SIZE 32
+/*
+ * This is used to dump the previous states of the SBIC
+ */
+struct status_entry {
+ unsigned long when;
+ unsigned char ssr;
+ unsigned char ph;
+ unsigned char irq;
+ unsigned char unused;
+};
+
+#define ADD_STATUS(_q,_ssr,_ph,_irq) \
+({ \
+ host->status[(_q)][host->status_ptr[(_q)]].when = jiffies; \
+ host->status[(_q)][host->status_ptr[(_q)]].ssr = (_ssr); \
+ host->status[(_q)][host->status_ptr[(_q)]].ph = (_ph); \
+ host->status[(_q)][host->status_ptr[(_q)]].irq = (_irq); \
+ host->status_ptr[(_q)] = (host->status_ptr[(_q)] + 1) & (STATUS_BUFFER_SIZE - 1); \
+})
+
/*
* AcornSCSI host specific data
*/
@@ -361,6 +382,7 @@
char *xfer_ptr; /* pointer to area */
unsigned char xfer_required:1; /* set if we need to transfer something */
unsigned char xfer_setup:1; /* set if DMA is setup */
+ unsigned char xfer_done:1; /* set if DMA reached end of BH list */
} dma;
/* card info */
@@ -370,6 +392,9 @@
unsigned int io_ram; /* base address of RAM access */
unsigned char page_reg; /* current setting of page reg */
} card;
+
+ unsigned char status_ptr[9];
+ struct status_entry status[9][STATUS_BUFFER_SIZE];
} AS_Host;
#endif /* ndef HOSTS_C */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/cumana_2.c linux.ac/drivers/acorn/scsi/cumana_2.c
--- linux.vanilla/drivers/acorn/scsi/cumana_2.c Tue Dec 22 23:19:35 1998
+++ linux.ac/drivers/acorn/scsi/cumana_2.c Sun Jan 24 23:54:37 1999
@@ -4,12 +4,12 @@
* Copyright (C) 1997-1998 Russell King
*
* Changelog:
- * 30-08-1997 RMK 0.0.0 Created, READONLY version
- * 22-01-1998 RMK 0.0.1 Updated to 2.1.80
+ * 30-08-1997 RMK 0.0.0 Created, READONLY version.
+ * 22-01-1998 RMK 0.0.1 Updated to 2.1.80.
* 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it.
- * 02-05-1998 RMK 0.0.2 Updated & added DMA support
+ * 02-05-1998 RMK 0.0.2 Updated & added DMA support.
* 27-06-1998 RMK Changed asm/delay.h to linux/delay.h
- * 18-08-1998 RMK 0.0.3 Fixed synchronous transfer depth
+ * 18-08-1998 RMK 0.0.3 Fixed synchronous transfer depth.
*/
#include
@@ -117,6 +117,8 @@
cumanascsi_2_irqenable,
cumanascsi_2_irqdisable,
NULL,
+ NULL,
+ NULL,
NULL
};
@@ -364,6 +366,7 @@
info->info.ifcfg.sync_max_depth = CUMANASCSI2_SYNC_DEPTH;
info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
info->info.ifcfg.disconnect_ok = 1;
+ info->info.ifcfg.wide_max_size = 0;
info->info.dma.setup = cumanascsi_2_dma_setup;
info->info.dma.pseudo = cumanascsi_2_dma_pseudo;
info->info.dma.stop = cumanascsi_2_dma_stop;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/eesox.c linux.ac/drivers/acorn/scsi/eesox.c
--- linux.vanilla/drivers/acorn/scsi/eesox.c Tue Dec 22 23:19:35 1998
+++ linux.ac/drivers/acorn/scsi/eesox.c Sun Jan 24 23:54:37 1999
@@ -123,6 +123,8 @@
eesoxscsi_irqenable,
eesoxscsi_irqdisable,
NULL,
+ NULL,
+ NULL,
NULL
};
@@ -379,6 +381,7 @@
info->info.ifcfg.sync_max_depth = EESOX_SYNC_DEPTH;
info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
info->info.ifcfg.disconnect_ok = 1;
+ info->info.ifcfg.wide_max_size = 0;
info->info.dma.setup = eesoxscsi_dma_setup;
info->info.dma.pseudo = eesoxscsi_dma_pseudo;
info->info.dma.stop = eesoxscsi_dma_stop;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/fas216.c linux.ac/drivers/acorn/scsi/fas216.c
--- linux.vanilla/drivers/acorn/scsi/fas216.c Mon Dec 28 23:09:41 1998
+++ linux.ac/drivers/acorn/scsi/fas216.c Sun Jan 24 23:54:37 1999
@@ -24,9 +24,9 @@
* 02-05-1998 RMK Added extra checks in fas216_reset
* 24-05-1998 RMK Fixed synchronous transfers with period >= 200ns
* 27-06-1998 RMK Changed asm/delay.h to linux/delay.h
+ * 26-08-1998 RMK Improved message support wrt MESSAGE_REJECT
*
* Todo:
- * - tighten up the MESSAGE_REJECT support.
* - allow individual devices to enable sync xfers.
*/
@@ -57,7 +57,7 @@
#define VER_MAJOR 0
#define VER_MINOR 0
-#define VER_PATCH 4
+#define VER_PATCH 5
#define SCSI2_TAG
@@ -86,6 +86,8 @@
*/
#define SCSI2_SYNC
+#define SCSI2_WIDE
+
#undef DEBUG_CONNECT
#undef DEBUG_BUSSERVICE
#undef DEBUG_FUNCTIONDONE
@@ -132,8 +134,8 @@
printk(" SCp={ ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n",
info->scsi.SCp.ptr, info->scsi.SCp.this_residual,
info->scsi.SCp.buffer, info->scsi.SCp.buffers_residual);
- printk(" msgs async_stp=%X last_message=%X disconnectable=%d aborting=%d }\n",
- info->scsi.async_stp, info->scsi.last_message,
+ printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n",
+ info->scsi.async_stp,
info->scsi.disconnectable, info->scsi.aborting);
printk(" stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n"
" disconnects=%X aborts=%X resets=%X }\n",
@@ -144,10 +146,10 @@
info->ifcfg.clockrate, info->ifcfg.select_timeout,
info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth);
for (i = 0; i < 8; i++) {
- printk(" busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X negstate=%X }\n",
+ printk(" busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n",
i, info->busyluns[i], i,
info->device[i].disconnect_ok, info->device[i].stp,
- info->device[i].sof, info->device[i].negstate);
+ info->device[i].sof, info->device[i].sync_state);
}
printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n",
info->dma.transfer_type, info->dma.setup,
@@ -192,19 +194,19 @@
static const char *fas216_drv_phase(FAS216_Info *info)
{
switch (info->scsi.phase) {
- case PHASE_IDLE: return "idle";
- case PHASE_SELECTION: return "selection";
- case PHASE_MESSAGESENT: return "message sent";
- case PHASE_RECONNECTED: return "reconnected";
- case PHASE_DATAOUT: return "data out";
- case PHASE_DATAIN: return "data in";
- case PHASE_MSGOUT: return "message out";
- case PHASE_MSGIN: return "message in";
- case PHASE_AFTERMSGOUT: return "after message out";
- case PHASE_STATUS: return "status";
- case PHASE_DISCONNECT: return "disconnect";
- case PHASE_DONE: return "done";
- default: return "???";
+ case PHASE_IDLE: return "idle";
+ case PHASE_SELECTION: return "selection";
+ case PHASE_COMMAND: return "command";
+ case PHASE_RECONNECTED: return "reconnected";
+ case PHASE_DATAOUT: return "data out";
+ case PHASE_DATAIN: return "data in";
+ case PHASE_MSGIN: return "message in";
+ case PHASE_MSGIN_DISCONNECT: return "disconnect";
+ case PHASE_MSGOUT_EXPECT: return "expect message out";
+ case PHASE_MSGOUT: return "message out";
+ case PHASE_STATUS: return "status";
+ case PHASE_DONE: return "done";
+ default: return "???";
}
}
@@ -262,6 +264,37 @@
return clock;
}
+/* Function: unsigned short fas216_get_last_msg(FAS216_Info *info, int pos)
+ * Purpose : retrieve a last message from the list, using position in fifo
+ * Params : info - interface to search
+ * : pos - current fifo position
+ */
+static inline unsigned short
+fas216_get_last_msg(FAS216_Info *info, int pos)
+{
+ unsigned short packed_msg = NOP;
+ struct message *msg;
+ int msgnr = 0;
+
+ while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
+ if (pos >= msg->fifo)
+ break;
+ }
+
+ if (msg) {
+ if (msg->msg[0] == EXTENDED_MESSAGE)
+ packed_msg = EXTENDED_MESSAGE | msg->msg[2] << 8;
+ else
+ packed_msg = msg->msg[0];
+ }
+
+#ifdef DEBUG_MESSAGES
+ printk("Message: %04X found at position %02X\n",
+ packed_msg, pos);
+#endif
+ return packed_msg;
+}
+
/* Function: int fas216_syncperiod(FAS216_Info *info, int ns)
* Purpose : Calculate value to be loaded into the STP register
* for a given period in ns
@@ -303,6 +336,240 @@
outb(info->scsi.cfg[2], REG_CNTL3(info));
}
+/* Synchronous transfer support
+ *
+ * Note: The SCSI II r10 spec says (5.6.12):
+ *
+ * (2) Due to historical problems with early host adapters that could
+ * not accept an SDTR message, some targets may not initiate synchronous
+ * negotiation after a power cycle as required by this standard. Host
+ * adapters that support synchronous mode may avoid the ensuing failure
+ * modes when the target is independently power cycled by initiating a
+ * synchronous negotiation on each REQUEST SENSE and INQUIRY command.
+ * This approach increases the SCSI bus overhead and is not recommended
+ * for new implementations. The correct method is to respond to an
+ * SDTR message with a MESSAGE REJECT message if the either the
+ * initiator or target devices does not support synchronous transfers
+ * or does not want to negotiate for synchronous transfers at the time.
+ * Using the correct method assures compatibility with wide data
+ * transfers and future enhancements.
+ *
+ * We will always initiate a synchronous transfer negociation request on
+ * every INQUIRY or REQUEST SENSE message, unless the target itself has
+ * at some point performed a synchronous transfer negociation request, or
+ * we have synchronous transfers disabled for this device.
+ */
+
+/* Function: void fas216_handlesync(FAS216_Info *info, char *msg)
+ * Purpose : Handle a synchronous transfer message from the target
+ * Params : info - state structure for interface
+ * : msg - message from target
+ */
+static void
+fas216_handlesync(FAS216_Info *info, char *msg)
+{
+ struct fas216_device *dev = &info->device[info->SCpnt->target];
+ enum { sync, async, none, reject } res = none;
+
+#ifdef SCSI2_SYNC
+ switch (msg[0]) {
+ case MESSAGE_REJECT:
+ /* Synchronous transfer request failed.
+ * Note: SCSI II r10:
+ *
+ * SCSI devices that are capable of synchronous
+ * data transfers shall not respond to an SDTR
+ * message with a MESSAGE REJECT message.
+ *
+ * Hence, if we get this condition, we disable
+ * negociation for this device.
+ */
+ if (dev->sync_state == neg_inprogress) {
+ dev->sync_state = neg_invalid;
+ res = async;
+ }
+ break;
+
+ case EXTENDED_MESSAGE:
+ switch (dev->sync_state) {
+ /* We don't accept synchronous transfer requests.
+ * Respond with a MESSAGE_REJECT to prevent a
+ * synchronous transfer agreement from being reached.
+ */
+ case neg_invalid:
+ res = reject;
+ break;
+
+ /* We were not negociating a synchronous transfer,
+ * but the device sent us a negociation request.
+ * Honour the request by sending back a SDTR
+ * message containing our capability, limited by
+ * the targets capability.
+ */
+ default:
+ outb(CMD_SETATN, REG_CMD(info));
+ if (msg[4] > info->ifcfg.sync_max_depth)
+ msg[4] = info->ifcfg.sync_max_depth;
+ if (msg[3] < 1000 / info->ifcfg.clockrate)
+ msg[3] = 1000 / info->ifcfg.clockrate;
+
+ msgqueue_flush(&info->scsi.msgs);
+ msgqueue_addmsg(&info->scsi.msgs, 5,
+ EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
+ msg[3], msg[4]);
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
+
+ /* This is wrong. The agreement is not in effect
+ * until this message is accepted by the device
+ */
+ dev->sync_state = neg_targcomplete;
+ res = sync;
+ break;
+
+ /* We initiated the synchronous transfer negociation,
+ * and have successfully received a response from the
+ * target. The synchronous transfer agreement has been
+ * reached. Note: if the values returned are out of our
+ * bounds, we must reject the message.
+ */
+ case neg_inprogress:
+ res = reject;
+ if (msg[4] <= info->ifcfg.sync_max_depth &&
+ msg[3] >= 1000 / info->ifcfg.clockrate) {
+ dev->sync_state = neg_complete;
+ res = sync;
+ }
+ break;
+ }
+ }
+#else
+ res = reject;
+#endif
+
+ switch (res) {
+ case sync:
+ dev->period = msg[3];
+ dev->sof = msg[4];
+ dev->stp = fas216_syncperiod(info, msg[3] * 4);
+ fas216_set_sync(info, info->SCpnt->target);
+ break;
+
+ case reject:
+ outb(CMD_SETATN, REG_CMD(info));
+ msgqueue_flush(&info->scsi.msgs);
+ msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
+
+ case async:
+ dev->period = info->ifcfg.asyncperiod / 4;
+ dev->sof = 0;
+ dev->stp = info->scsi.async_stp;
+ fas216_set_sync(info, info->SCpnt->target);
+ break;
+
+ case none:
+ break;
+ }
+}
+
+/* Function: void fas216_handlewide(FAS216_Info *info, char *msg)
+ * Purpose : Handle a wide transfer message from the target
+ * Params : info - state structure for interface
+ * : msg - message from target
+ */
+static void
+fas216_handlewide(FAS216_Info *info, char *msg)
+{
+ struct fas216_device *dev = &info->device[info->SCpnt->target];
+ enum { wide, bit8, none, reject } res = none;
+
+#ifdef SCSI2_WIDE
+ switch (msg[0]) {
+ case MESSAGE_REJECT:
+ /* Wide transfer request failed.
+ * Note: SCSI II r10:
+ *
+ * SCSI devices that are capable of wide
+ * data transfers shall not respond to a
+ * WDTR message with a MESSAGE REJECT message.
+ *
+ * Hence, if we get this condition, we never
+ * reattempt negociation for this device.
+ */
+ if (dev->wide_state == neg_inprogress) {
+ dev->wide_state = neg_invalid;
+ res = bit8;
+ }
+ break;
+
+ case EXTENDED_MESSAGE:
+ switch (dev->wide_state) {
+ /* We don't accept wide data transfer requests.
+ * Respond with a MESSAGE REJECT to prevent a
+ * wide data transfer agreement from being reached.
+ */
+ case neg_invalid:
+ res = reject;
+ break;
+
+ /* We were not negociating a wide data transfer,
+ * but the device sent is a negociation request.
+ * Honour the request by sending back a WDTR
+ * message containing our capability, limited by
+ * the targets capability.
+ */
+ default:
+ outb(CMD_SETATN, REG_CMD(info));
+ if (msg[3] > info->ifcfg.wide_max_size)
+ msg[3] = info->ifcfg.wide_max_size;
+
+ msgqueue_flush(&info->scsi.msgs);
+ msgqueue_addmsg(&info->scsi.msgs, 4,
+ EXTENDED_MESSAGE, 2, EXTENDED_WDTR,
+ msg[3]);
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
+ res = wide;
+ break;
+
+ /* We initiated the wide data transfer negociation,
+ * and have successfully received a response from the
+ * target. The synchronous transfer agreement has been
+ * reached. Note: if the values returned are out of our
+ * bounds, we must reject the message.
+ */
+ case neg_inprogress:
+ res = reject;
+ if (msg[3] <= info->ifcfg.wide_max_size) {
+ dev->wide_state = neg_complete;
+ res = wide;
+ }
+ break;
+ }
+ }
+#else
+ res = reject;
+#endif
+
+ switch (res) {
+ case wide:
+ dev->wide_xfer = msg[3];
+ break;
+
+ case reject:
+ outb(CMD_SETATN, REG_CMD(info));
+ msgqueue_flush(&info->scsi.msgs);
+ msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
+
+ case bit8:
+ dev->wide_xfer = 0;
+ break;
+
+ case none:
+ break;
+ }
+}
+
/* Function: void fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
* Purpose : update data pointers after transfer suspended/paused
* Params : info - interface's local pointer to update
@@ -338,6 +605,9 @@
residual -= bytes_transferred;
ptr += bytes_transferred;
+ if (residual == 0)
+ ptr = NULL;
+
info->scsi.SCp.ptr = ptr;
info->scsi.SCp.this_residual = residual;
}
@@ -353,7 +623,7 @@
{
unsigned int residual;
char *ptr;
- int correction;
+ int correction = 0;
fas216_checkmagic(info, "fas216_pio");
@@ -361,23 +631,24 @@
ptr = info->scsi.SCp.ptr;
if (direction == DMA_OUT) {
- while (residual > 0) {
- if ((inb(REG_CFIS(info)) & CFIS_CF) < 8) {
+// while (residual > 0) {
+// if ((inb(REG_CFIS(info)) & CFIS_CF) < 8) {
outb(*ptr++, REG_FF(info));
residual -= 1;
- } else if (inb(REG_STAT(info)) & STAT_INT)
- break;
- }
- correction = inb(REG_CFIS(info)) & CFIS_CF;
+// }
+// if (inb(REG_STAT(info)) & STAT_INT)
+// break;
+// }
+// correction = inb(REG_CFIS(info)) & CFIS_CF;
} else {
- while (residual > 0) {
- if ((inb(REG_CFIS(info)) & CFIS_CF) != 0) {
+// while (residual > 0) {
+// if ((inb(REG_CFIS(info)) & CFIS_CF) != 0) {
*ptr++ = inb(REG_FF(info));
residual -= 1;
- } else if (inb(REG_STAT(info)) & STAT_INT)
- break;
- }
- correction = 0;
+// }
+// if (inb(REG_STAT(info)) & STAT_INT)
+// break;
+// }
}
ptr -= correction;
@@ -549,10 +820,11 @@
switch (info->scsi.phase) {
case PHASE_SELECTION: /* while selecting - no target */
+ case PHASE_SELSTEPS:
fas216_done(info, DID_NO_CONNECT);
break;
- case PHASE_DISCONNECT: /* message in - disconnecting */
+ case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */
outb(CMD_ENABLESEL, REG_CMD(info));
info->scsi.disconnectable = 1;
info->scsi.reconnected.tag = 0;
@@ -564,8 +836,8 @@
fas216_done(info, DID_OK);
break;
- case PHASE_AFTERMSGOUT: /* message out - possible ABORT message */
- if (info->scsi.last_message == ABORT) {
+ case PHASE_MSGOUT: /* message out - possible ABORT message */
+ if (fas216_get_last_msg(info, info->scsi.msgin_fifo) == ABORT) {
info->scsi.aborting = 0;
fas216_done(info, DID_ABORT);
break;
@@ -592,14 +864,17 @@
fas216_checkmagic(info, "fas216_reselected_intr");
- if (info->scsi.phase == PHASE_SELECTION && info->SCpnt) {
+ if ((info->scsi.phase == PHASE_SELECTION ||
+ info->scsi.phase == PHASE_SELSTEPS) && info->SCpnt) {
Scsi_Cmnd *SCpnt = info->SCpnt;
info->origSCpnt = SCpnt;
info->SCpnt = NULL;
- if (info->device[SCpnt->target].negstate == syncneg_sent)
- info->device[SCpnt->target].negstate = syncneg_start;
+ if (info->device[SCpnt->target].wide_state == neg_inprogress)
+ info->device[SCpnt->target].wide_state = neg_wait;
+ if (info->device[SCpnt->target].sync_state == neg_inprogress)
+ info->device[SCpnt->target].sync_state = neg_wait;
}
#ifdef DEBUG_CONNECT
@@ -607,15 +882,14 @@
fas216_target(info), info->scsi.phase);
#endif
- msgqueue_flush(&info->scsi.msgs);
-
if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) {
printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n",
info->host->host_no);
outb(CMD_SETATN, REG_CMD(info));
- msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
- info->scsi.phase = PHASE_MSGOUT;
outb(CMD_MSGACCEPTED, REG_CMD(info));
+ msgqueue_flush(&info->scsi.msgs);
+ msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
return;
}
@@ -636,13 +910,14 @@
if (!ok) {
/*
- * Something went wrong - abort the command on
- * the target. Should this be INITIATOR_ERROR ?
+ * Something went wrong - send an initiator error to
+ * the target.
*/
outb(CMD_SETATN, REG_CMD(info));
- msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
- info->scsi.phase = PHASE_MSGOUT;
outb(CMD_MSGACCEPTED, REG_CMD(info));
+ msgqueue_flush(&info->scsi.msgs);
+ msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
return;
}
@@ -672,17 +947,20 @@
if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg))
ok = 1;
+ msgqueue_flush(&info->scsi.msgs);
if (ok) {
info->scsi.phase = PHASE_RECONNECTED;
outb(target, REG_SDID(info));
} else {
/*
- * Our command structure not found - abort the command on the target
- * Should this be INITIATOR_ERROR ?
+ * Our command structure not found - abort the
+ * command on the target. Since we have no
+ * record of this command, we can't send
+ * an INITIATOR DETECTED ERROR message.
*/
outb(CMD_SETATN, REG_CMD(info));
msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
- info->scsi.phase = PHASE_MSGOUT;
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
}
outb(CMD_MSGACCEPTED, REG_CMD(info));
}
@@ -733,8 +1011,14 @@
}
if (!info->SCpnt) {
outb(CMD_SETATN, REG_CMD(info));
- msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
- info->scsi.phase = PHASE_MSGOUT;
+ msgqueue_flush(&info->scsi.msgs);
+#if 0
+ if (info->scsi.reconnected.tag)
+ msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag);
+ else
+#endif
+ msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
info->scsi.aborting = 1;
} else {
/*
@@ -751,6 +1035,28 @@
#endif
}
+static unsigned char fas216_get_msg_byte(FAS216_Info *info)
+{
+ int tout;
+
+ outb(CMD_MSGACCEPTED, REG_CMD(info));
+ for (tout = 1000000; tout; tout --)
+ if (inb(REG_STAT(info)) & STAT_INT)
+ break;
+
+ inb(REG_INST(info));
+
+ outb(CMD_TRANSFERINFO, REG_CMD(info));
+
+ for (tout = 1000000; tout; tout --)
+ if (inb(REG_STAT(info)) & STAT_INT)
+ break;
+
+ inb(REG_INST(info));
+
+ return inb(REG_FF(info));
+}
+
/* Function: void fas216_message(FAS216_Info *info)
* Purpose : handle a function done interrupt from FAS216 chip
* Params : info - interface which caused function done interrupt
@@ -765,34 +1071,10 @@
message[0] = inb(REG_FF(info));
if (message[0] == EXTENDED_MESSAGE) {
- int tout;
- outb(CMD_MSGACCEPTED, REG_CMD(info));
- for (tout = 1000000; tout; tout--)
- if (inb(REG_STAT(info)) & STAT_INT)
- break;
- inb(REG_INST(info));
- outb(CMD_TRANSFERINFO, REG_CMD(info));
- for (tout = 1000000; tout; tout--)
- if (inb(REG_STAT(info)) & STAT_INT)
- break;
- inb(REG_INST(info));
-
- message[1] = inb(REG_FF(info));
-
- for (msglen = 2; msglen < message[1] + 2; msglen++) {
- outb(CMD_MSGACCEPTED, REG_CMD(info));
- for (tout = 1000000; tout; tout--)
- if (inb(REG_STAT(info)) & STAT_INT)
- break;
- inb(REG_INST(info));
- outb(CMD_TRANSFERINFO, REG_CMD(info));
- for (tout = 1000000; tout; tout--)
- if (inb(REG_STAT(info)) & STAT_INT)
- break;
- inb(REG_INST(info));
+ message[1] = fas216_get_msg_byte(info);
- message[msglen] = inb(REG_FF(info));
- }
+ for (msglen = 2; msglen < message[1] + 2; msglen++)
+ message[msglen] = fas216_get_msg_byte(info);
}
#ifdef DEBUG_MESSAGES
@@ -806,6 +1088,7 @@
printk("\n");
}
#endif
+
if (info->scsi.phase == PHASE_RECONNECTED) {
if (message[0] == SIMPLE_QUEUE_TAG)
info->scsi.reconnected.tag = message[1];
@@ -815,14 +1098,22 @@
switch (message[0]) {
case COMMAND_COMPLETE:
- printk("fas216: command complete with no status in MESSAGE_IN?\n");
+ printk(KERN_ERR "scsi%d.%c: command complete with no "
+ "status in MESSAGE_IN?\n",
+ info->host->host_no, fas216_target(info));
break;
case SAVE_POINTERS:
/*
* Save current data pointer to SAVED data pointer
+ * SCSI II standard says that we must not acknowledge
+ * this until we have really saved pointers.
+ * NOTE: we DO NOT save the command nor status pointers
+ * as required by the SCSI II standard. These always
+ * point to the start of their respective areas.
*/
info->SCpnt->SCp = info->scsi.SCp;
+ info->SCpnt->SCp.sent_command = 0;
#if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT)
printk("scsi%d.%c: save data pointers: [%p, %X]\n",
info->host->host_no, fas216_target(info),
@@ -843,13 +1134,27 @@
break;
case DISCONNECT:
- info->scsi.phase = PHASE_DISCONNECT;
+ info->scsi.phase = PHASE_MSGIN_DISCONNECT;
break;
case MESSAGE_REJECT:
- printk("scsi%d.%c: reject, last message %04X\n",
- info->host->host_no, fas216_target(info),
- info->scsi.last_message);
+ switch (fas216_get_last_msg(info, info->scsi.msgin_fifo)) {
+ case EXTENDED_MESSAGE | EXTENDED_SDTR << 8:
+ fas216_handlesync(info, message);
+ break;
+
+ case EXTENDED_MESSAGE | EXTENDED_WDTR << 8:
+ fas216_handlewide(info, message);
+ break;
+
+ default:
+ printk("scsi%d.%c: reject, last message %04X\n",
+ info->host->host_no, fas216_target(info),
+ fas216_get_last_msg(info, info->scsi.msgin_fifo));
+ }
+ break;
+
+ case NOP:
break;
case SIMPLE_QUEUE_TAG:
@@ -862,49 +1167,18 @@
case EXTENDED_MESSAGE:
switch (message[2]) {
case EXTENDED_SDTR: /* Sync transfer negociation request/reply */
- switch (info->device[info->SCpnt->target].negstate) {
- case syncneg_invalid:
- msgqueue_flush(&info->scsi.msgs);
- outb(CMD_SETATN, REG_CMD(info));
- msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
- info->scsi.phase = PHASE_MSGOUT;
- break;
-
- default:
- if (message[4] > info->ifcfg.sync_max_depth)
- message[4] = info->ifcfg.sync_max_depth;
- if (message[3] < 1000 / info->ifcfg.clockrate)
- message[3] = 1000 / info->ifcfg.clockrate;
-
- outb(CMD_SETATN, REG_CMD(info));
- msgqueue_addmsg(&info->scsi.msgs, 5,
- EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
- message[3], message[4]);
- info->scsi.phase = PHASE_MSGOUT;
- case syncneg_sent:
- info->device[info->SCpnt->target].negstate = syncneg_complete;
- info->device[info->SCpnt->target].period = message[3];
- info->device[info->SCpnt->target].sof = message[4];
- info->device[info->SCpnt->target].stp =
- fas216_syncperiod(info, message[3] * 4);
- printk(KERN_NOTICE "scsi%d.%c: using synchronous transfer, offset %d, %d ns\n",
- info->host->host_no, fas216_target(info), message[4], message[3] * 4);
- fas216_set_sync(info, info->SCpnt->target);
- break;
- }
+ fas216_handlesync(info, message);
break;
case EXTENDED_WDTR: /* Wide transfer negociation request/reply */
- /* We don't do wide transfers - reject message */
+ fas216_handlewide(info, message);
+ break;
+
default:
printk("scsi%d.%c: unrecognised extended message %02X, rejecting\n",
info->host->host_no, fas216_target(info),
message[2]);
- msgqueue_flush(&info->scsi.msgs);
- outb(CMD_SETATN, REG_CMD(info));
- msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
- info->scsi.phase = PHASE_MSGOUT;
- break;
+ goto reject_message;
}
break;
@@ -912,13 +1186,17 @@
printk("scsi%d.%c: unrecognised message %02X, rejecting\n",
info->host->host_no, fas216_target(info),
message[0]);
- msgqueue_flush(&info->scsi.msgs);
- outb(CMD_SETATN, REG_CMD(info));
- msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
- info->scsi.phase = PHASE_MSGOUT;
- break;
+ goto reject_message;
}
outb(CMD_MSGACCEPTED, REG_CMD(info));
+ return;
+
+reject_message:
+ outb(CMD_SETATN, REG_CMD(info));
+ outb(CMD_MSGACCEPTED, REG_CMD(info));
+ msgqueue_flush(&info->scsi.msgs);
+ msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
}
/* Function: void fas216_send_command(FAS216_Info *info)
@@ -935,201 +1213,46 @@
outb(CMD_FLUSHFIFO, REG_CMD(info));
/* load command */
- for (i = 0; i < info->SCpnt->cmd_len; i++)
+ for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++)
outb(info->SCpnt->cmnd[i], REG_FF(info));
outb(CMD_TRANSFERINFO, REG_CMD(info));
-}
-
-/* Function: int fas216_busservice_selection(FAS216_Info *info, unsigned int stat)
- * Purpose : handle bus service in selection phase
- * Params : info - interface which caused bus service
- * Returns : 0 if unable to service this interrupt
- */
-static int fas216_busservice_selection(FAS216_Info *info, unsigned int stat)
-{
- fas216_checkmagic(info, "fas216_busservice_selection");
-
- switch (stat & STAT_BUSMASK) {
- case STAT_DATAOUT: /* data out phase */
- fas216_starttransfer(info, DMA_OUT, 1);
- return 1;
-
- case STAT_DATAIN: /* data in phase */
- fas216_starttransfer(info, DMA_IN, 0);
- return 1;
-
- case STAT_STATUS: /* status phase */
- info->scsi.phase = PHASE_STATUS;
- outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
- return 1;
- case STAT_MESGIN: /* message in phase */
- info->scsi.phase = PHASE_MSGIN;
- outb(CMD_TRANSFERINFO, REG_CMD(info));
- return 1;
-
- case STAT_MESGOUT:{ /* message out phase */
- char *msg;
- int start = 1, msglen;
-
- /* load message bytes, but don't forget to miss the first
- * byte!
- */
- while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) {
- int i;
-
- for (i = start; i < msglen; i++)
- outb(msg[i], REG_FF(info));
- start = 0;
- }
- outb(CMD_TRANSFERINFO, REG_CMD(info));
- info->scsi.phase = PHASE_MESSAGESENT;
- return 1;
- }
- default:
- return 0;
- }
+ info->scsi.phase = PHASE_COMMAND;
}
-/* Function: int fas216_busservice_messagesent(FAS216_Info *info, unsigned int stat)
- * Purpose : handle bus service after the IDENTIFY message has been sent
- * Params : info - interface which caused bus service
- * Returns : 0 if unable to service this interrupt
- */
-static int fas216_busservice_messagesent(FAS216_Info *info, unsigned int stat)
-{
- fas216_checkmagic(info, "fas216_busservice_messagesent");
-
- switch (stat & STAT_BUSMASK) {
- case STAT_MESGIN: /* message in phase */
- info->scsi.phase = PHASE_MSGIN;
- outb(CMD_FLUSHFIFO, REG_CMD(info));
- outb(CMD_TRANSFERINFO, REG_CMD(info));
- return 1;
-
- case STAT_COMMAND: /* command phase */
- fas216_send_command(info);
- return 1;
-
- default:
- return 0;
- }
-}
-
-/* Function: int fas216_busservice_dataphase(FAS216_Info *info, unsigned int stat)
- * Purpose : handle bus service in a data in/out phase.
- * Params : info - interface which caused bus service
- * Returns : 0 if unable to service this interrupt
- * Note : We do not allow the device to change the data direction!
- */
-static int fas216_busservice_dataphase(FAS216_Info *info, unsigned int stat)
-{
- fas216_checkmagic(info, "fas216_busservice_dataphase");
-
- switch (stat & STAT_BUSMASK) {
- case STAT_DATAIN: /* continue data in phase */
- if (info->scsi.phase == PHASE_DATAIN) {
- fas216_starttransfer(info, DMA_IN, 0);
- return 1;
- } else
- return 0;
-
- case STAT_DATAOUT: /* continue data out phase */
- if (info->scsi.phase == PHASE_DATAOUT) {
- fas216_starttransfer(info, DMA_OUT, 0);
- return 1;
- } else
- return 0;
-
- case STAT_STATUS: /* status in phase */
- fas216_stoptransfer(info);
- info->scsi.phase = PHASE_STATUS;
- outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
- return 1;
-
- case STAT_MESGIN: /* message in phase */
- fas216_stoptransfer(info);
- info->scsi.phase = PHASE_MSGIN;
- outb(CMD_TRANSFERINFO, REG_CMD(info));
- return 1;
-
- default:
- return 0;
- }
-}
-
-/* Function: int fas216_busservice_reconnected(FAS216_Info *info, unsigned int stat)
- * Purpose : handle bus service in after a reconnection
+/* Function: void fas216_send_messageout(FAS216_Info *info, int start)
+ * Purpose : handle bus service to send a message
* Params : info - interface which caused bus service
- * Returns : 0 if unable to service this interrupt
* Note : We do not allow the device to change the data direction!
*/
-static int fas216_busservice_reconnected(FAS216_Info *info, unsigned int stat)
+static void fas216_send_messageout(FAS216_Info *info, int start)
{
- fas216_checkmagic(info, "fas216_busservice_reconnected");
-
- switch (stat & STAT_BUSMASK) {
- case STAT_MESGIN:
- outb(CMD_TRANSFERINFO, REG_CMD(info));
- return 1;
+ unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs);
- case STAT_STATUS:
- fas216_finish_reconnect(info);
- info->scsi.phase = PHASE_STATUS;
- outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
- return 1;
-
- case STAT_DATAOUT: /* data out phase */
- fas216_finish_reconnect(info);
- fas216_starttransfer(info, DMA_OUT, 1);
- return 1;
+ fas216_checkmagic(info, "fas216_send_messageout");
- case STAT_DATAIN: /* data in phase */
- fas216_finish_reconnect(info);
- fas216_starttransfer(info, DMA_IN, 0);
- return 1;
+ outb(CMD_FLUSHFIFO, REG_CMD(info));
- default:
- return 0;
- }
-}
+ if (tot_msglen) {
+ struct message *msg;
+ int msgnr = 0;
-/* Function: int fas216_busservice_messageout(FAS216_Info *info, unsigned int stat)
- * Purpose : handle bus service to send a message
- * Params : info - interface which caused bus service
- * Returns : 0 if unable to service this interrupt
- * Note : We do not allow the device to change the data direction!
- */
-static int fas216_busservice_messageout(FAS216_Info *info, unsigned int stat)
-{
- fas216_checkmagic(info, "fas216_busservice_messageout");
-
- if ((stat & STAT_BUSMASK) != STAT_MESGOUT) {
- printk("scsi%d.%c: didn't manage MESSAGE OUT phase\n",
- info->host->host_no, fas216_target(info));
- return 0;
- } else {
- unsigned int msglen = msgqueue_msglength(&info->scsi.msgs);
+ while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
+ int i;
- outb(CMD_FLUSHFIFO, REG_CMD(info));
+ for (i = start; i < msg->length; i++)
+ outb(msg->msg[i], REG_FF(info));
- if (msglen == 0)
- outb(NOP, REG_FF(info));
- else {
- char *msg;
+ msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF);
+ start = 0;
+ }
+ } else
+ outb(NOP, REG_FF(info));
- while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) {
- int i;
+ outb(CMD_TRANSFERINFO, REG_CMD(info));
- for (i = 0; i < msglen; i++)
- outb(msg[i], REG_FF(info));
- }
- }
- outb(CMD_TRANSFERINFO, REG_CMD(info));
- info->scsi.phase = PHASE_AFTERMSGOUT;
- return 1;
- }
+ info->scsi.phase = PHASE_MSGOUT;
}
/* Function: void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
@@ -1151,91 +1274,150 @@
case IS_COMPLETE: /* last action completed */
outb(CMD_NOP, REG_CMD(info));
- switch (info->scsi.phase) {
- case PHASE_SELECTION: /* while selecting - selected target */
- if (!fas216_busservice_selection(info, stat))
- printk("scsi%d.%c: bus phase %s after connect?\n",
- info->host->host_no, fas216_target(info),
- fas216_bus_phase(stat));
- break;
-
- case PHASE_MESSAGESENT:
- if (!fas216_busservice_messagesent(info, stat))
- printk("scsi%d.%c: bus phase %s after message sent?\n",
- info->host->host_no, fas216_target(info),
- fas216_bus_phase(stat));
- break;
+#define STATE(st,ph) ((ph) << 3 | (st))
+ /* This table describes the legal SCSI state transitions,
+ * as described by the SCSI II spec.
+ */
+ switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) {
+ /* Reselmsgin -> Data In */
+ case STATE(STAT_DATAIN, PHASE_RECONNECTED):
+ fas216_finish_reconnect(info);
+ case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */
+ case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */
+ case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */
+ case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */
+ case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */
+ fas216_starttransfer(info, DMA_IN, 0);
+ return;
- case PHASE_DATAIN: /* while transfering data in */
- case PHASE_DATAOUT: /* while transfering data out */
- if (!fas216_busservice_dataphase(info, stat))
- printk("scsi%d.%c: bus phase %s after %s?\n",
- info->host->host_no, fas216_target(info),
- fas216_bus_phase(stat), fas216_drv_phase(info));
- break;
+ case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */
+ fas216_starttransfer(info, DMA_OUT, 0);
+ return;
- case PHASE_RECONNECTED: /* newly reconnected device */
- /*
- * Command reconnected - if MESGIN, get message - it may be
- * the tag. If not, get command out of the disconnected queue
- */
- if (!fas216_busservice_reconnected(info, stat))
- printk("scsi%d.%c: bus phase %s after reconnect?\n",
- info->host->host_no, fas216_target(info),
- fas216_bus_phase(stat));
- break;
+ /* Reselmsgin -> Data Out */
+ case STATE(STAT_DATAOUT, PHASE_RECONNECTED):
+ fas216_finish_reconnect(info);
+ case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */
+ case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */
+ case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */
+ case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */
+ fas216_starttransfer(info, DMA_OUT, 1);
+ return;
+
+ /* Reselmsgin -> Status */
+ case STATE(STAT_STATUS, PHASE_RECONNECTED):
+ fas216_finish_reconnect(info);
+ goto status;
+ case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */
+ case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */
+ fas216_stoptransfer(info);
+ case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */
+ case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */
+ case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */
+ case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */
+ status:
+ outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
+ info->scsi.phase = PHASE_STATUS;
+ return;
+
+ case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */
+ case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */
+ fas216_stoptransfer(info);
+ case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */
+ case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */
+ info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
+ outb(CMD_TRANSFERINFO, REG_CMD(info));
+ info->scsi.phase = PHASE_MSGIN;
+ return;
- case PHASE_MSGIN:
- case PHASE_AFTERMSGOUT:
- switch (stat & STAT_BUSMASK) {
- case STAT_MESGIN:
- info->scsi.phase = PHASE_MSGIN;
- outb(CMD_TRANSFERINFO, REG_CMD(info));
- break;
+ /* Reselmsgin -> Message In */
+ case STATE(STAT_MESGIN, PHASE_RECONNECTED):
+ case STATE(STAT_MESGIN, PHASE_MSGIN):
+ info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
+ outb(CMD_TRANSFERINFO, REG_CMD(info));
+ return;
- case STAT_COMMAND: /* command phase */
- fas216_send_command(info);
- info->scsi.phase = PHASE_SELECTION;
- break;
+ /* Reselmsgin -> Command */
+ case STATE(STAT_COMMAND, PHASE_RECONNECTED):
+ fas216_finish_reconnect(info);
+ case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */
+ case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */
+ fas216_send_command(info);
+ info->scsi.phase = PHASE_COMMAND;
+ return;
+ /* Selection -> Message Out */
+ case STATE(STAT_MESGOUT, PHASE_SELECTION):
+ fas216_send_messageout(info, 1);
+ return;
+ /* Any -> Message Out */
+ case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT):
+ fas216_send_messageout(info, 0);
+ return;
+
+ /* Error recovery rules.
+ * These either attempt to abort or retry the operation.
+ * TODO: we need more of these
+ */
+ case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command -> Command */
+ /* error - we've sent out all the command bytes
+ * we have.
+ * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS
+ * to include the command bytes sent for this to work
+ * correctly.
+ */
+ printk(KERN_ERR "scsi%d.%c: "
+ "target trying to receive more command bytes\n",
+ info->host->host_no, fas216_target(info));
+ outb(CMD_SETATN, REG_CMD(info));
+ outb(15, REG_STCL(info));
+ outb(0, REG_STCM(info));
+ outb(0, REG_STCH(info));
+ outb(CMD_PADBYTES | CMD_WITHDMA, REG_CMD(info));
+ msgqueue_flush(&info->scsi.msgs);
+ msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
+ return;
- default:
- printk("scsi%d.%c: bus phase %s after %s?\n",
- info->host->host_no, fas216_target(info),
- fas216_bus_phase(stat),
- fas216_drv_phase(info));
- }
- break;
+ /* Selection -> Message Out */
+ case STATE(STAT_MESGOUT, PHASE_SELSTEPS):
+ case STATE(STAT_MESGOUT, PHASE_MSGOUT): /* Message Out -> Message Out */
+ /* If we get another message out phase, this
+ * usually means some parity error occurred.
+ * Resend complete set of messages. If we have
+ * more than 1 byte to send, we need to assert
+ * ATN again.
+ */
+ if (msgqueue_msglength(&info->scsi.msgs) > 1)
+ outb(CMD_SETATN, REG_CMD(info));
- case PHASE_MSGOUT:
- if (!fas216_busservice_messageout(info, stat))
- printk("scsi%d.%c: bus phase %s instead of message out?\n",
- info->host->host_no, fas216_target(info),
- fas216_bus_phase(stat));
- break;
+ fas216_send_messageout(info, 0);
+ return;
+ }
- case PHASE_DISCONNECT:
- printk("scsi%d.%c: disconnect message received, but bus service %s?\n",
+ if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) {
+ printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n",
info->host->host_no, fas216_target(info),
fas216_bus_phase(stat));
+ msgqueue_flush(&info->scsi.msgs);
outb(CMD_SETATN, REG_CMD(info));
msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
- info->scsi.phase = PHASE_MSGOUT;
+ info->scsi.phase = PHASE_MSGOUT_EXPECT;
info->scsi.aborting = 1;
outb(CMD_TRANSFERINFO, REG_CMD(info));
- break;
-
- default:
- printk("scsi%d.%c: internal phase %s for bus service?"
- " What do I do with this?\n",
- info->host->host_no, fas216_target(info),
- fas216_drv_phase(info));
+ return;
}
- break;
+ printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n",
+ info->host->host_no, fas216_target(info),
+ fas216_bus_phase(stat),
+ fas216_drv_phase(info));
+ print_debug_list();
+ return;
default:
printk("scsi%d.%c: bus service at step %d?\n",
info->host->host_no, fas216_target(info),
ssr & IS_BITS);
+ print_debug_list();
}
}
@@ -1269,6 +1451,7 @@
case PHASE_MSGIN: /* message in phase */
case PHASE_RECONNECTED: /* reconnected command */
if ((stat & STAT_BUSMASK) == STAT_MESGIN) {
+ info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
fas216_message(info);
break;
}
@@ -1300,10 +1483,11 @@
if (stat & STAT_INT) {
if (isr & INST_BUSRESET)
- printk("scsi%d.H: fas216: bus reset detected\n", instance->host_no);
- else if (isr & INST_ILLEGALCMD)
+ printk("scsi%d.H: bus reset detected\n", instance->host_no);
+ else if (isr & INST_ILLEGALCMD) {
printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no);
- else if (isr & INST_DISCONNECT)
+ fas216_dumpstate(info);
+ } else if (isr & INST_DISCONNECT)
fas216_disconnect_intr(info);
else if (isr & INST_RESELECTED) /* reselected */
fas216_reselected_intr(info);
@@ -1327,7 +1511,7 @@
static void fas216_kick(FAS216_Info *info)
{
Scsi_Cmnd *SCpnt;
- int i, msglen, from_queue = 0;
+ int tot_msglen, from_queue = 0;
fas216_checkmagic(info, "fas216_kick");
@@ -1380,7 +1564,8 @@
if (from_queue) {
#ifdef SCSI2_TAG
- if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE) {
+ if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE &&
+ SCpnt->cmnd[0] != INQUIRY) {
SCpnt->device->current_tag += 1;
if (SCpnt->device->current_tag == 0)
SCpnt->device->current_tag = 1;
@@ -1409,6 +1594,7 @@
/* build outgoing message bytes */
msgqueue_flush(&info->scsi.msgs);
+
if (info->device[SCpnt->target].disconnect_ok)
msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(1, SCpnt->lun));
else
@@ -1418,15 +1604,29 @@
if (SCpnt->tag)
msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag);
- /* add synchronous negociation */
- if (SCpnt->cmnd[0] == REQUEST_SENSE &&
- info->device[SCpnt->target].negstate == syncneg_start) {
- info->device[SCpnt->target].negstate = syncneg_sent;
+#ifdef SCSI2_WIDE
+ if (info->device[SCpnt->target].wide_state == neg_wait) {
+ info->device[SCpnt->target].wide_state = neg_inprogress;
+ msgqueue_addmsg(&info->scsi.msgs, 4,
+ EXTENDED_MESSAGE, 2, EXTENDED_WDTR,
+ info->ifcfg.wide_max_size);
+ }
+#ifdef SCSI2_SYNC
+ else
+#endif
+#endif
+#ifdef SCSI2_SYNC
+ if ((info->device[SCpnt->target].sync_state == neg_wait ||
+ info->device[SCpnt->target].sync_state == neg_complete) &&
+ (SCpnt->cmnd[0] == REQUEST_SENSE ||
+ SCpnt->cmnd[0] == INQUIRY)) {
+ info->device[SCpnt->target].sync_state = neg_inprogress;
msgqueue_addmsg(&info->scsi.msgs, 5,
EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
1000 / info->ifcfg.clockrate,
info->ifcfg.sync_max_depth);
}
+#endif
/* following what the ESP driver says */
outb(0, REG_STCL(info));
@@ -1444,25 +1644,29 @@
/* synchronous transfers */
fas216_set_sync(info, SCpnt->target);
- msglen = msgqueue_msglength(&info->scsi.msgs);
+ tot_msglen = msgqueue_msglength(&info->scsi.msgs);
- if (msglen == 1 || msglen == 3) {
+ if (tot_msglen == 1 || tot_msglen == 3) {
/*
* We have an easy message length to send...
*/
- char *msg;
+ struct message *msg;
+ int msgnr = 0, i;
+
+ info->scsi.phase = PHASE_SELSTEPS;
/* load message bytes */
- while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) {
- for (i = 0; i < msglen; i++)
- outb(msg[i], REG_FF(info));
+ while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
+ for (i = 0; i < msg->length; i++)
+ outb(msg->msg[i], REG_FF(info));
+ msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF);
}
/* load command */
for (i = 0; i < SCpnt->cmd_len; i++)
outb(SCpnt->cmnd[i], REG_FF(info));
- if (msglen == 1)
+ if (tot_msglen == 1)
outb(CMD_SELECTATN, REG_CMD(info));
else
outb(CMD_SELECTATN3, REG_CMD(info));
@@ -1471,17 +1675,11 @@
* We have an unusual number of message bytes to send.
* Load first byte into fifo, and issue SELECT with ATN and
* stop steps.
- * Note: we only peek at t his message - we need the rest
- * later on!
*/
- int thismsg;
- char *msg = msgqueue_peeknextmsg(&info->scsi.msgs, &thismsg);
+ struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0);
- if (!msg || thismsg < 1)
- printk(KERN_CRIT "scsi%d.%c: no message to send, but %d bytes\n",
- info->host->host_no, fas216_target(info), msglen);
- else
- outb(msg[0], REG_FF(info));
+ outb(msg->msg[0], REG_FF(info));
+ msg->fifo = 1;
outb(CMD_SELECTATNSTOP, REG_CMD(info));
}
@@ -1525,11 +1723,15 @@
/*
* In theory, this should not happen, but just in case it does.
*/
- if (info->scsi.SCp.ptr && result == DID_OK) {
+ if (info->scsi.SCp.ptr &&
+ info->scsi.SCp.this_residual &&
+ result == DID_OK) {
switch (SCpnt->cmnd[0]) {
case INQUIRY:
case START_STOP:
case READ_CAPACITY:
+ case TEST_UNIT_READY:
+ case MODE_SENSE:
break;
default:
@@ -1819,7 +2021,7 @@
*/
static void fas216_reset_state(FAS216_Info *info)
{
- syncneg_t negstate;
+ neg_t sync_state, wide_state;
int i;
fas216_checkmagic(info, "fas216_reset_state");
@@ -1833,26 +2035,37 @@
info->scsi.reconnected.lun = 0;
info->scsi.reconnected.tag = 0;
info->scsi.disconnectable = 0;
- info->scsi.last_message = 0;
info->scsi.aborting = 0;
info->scsi.phase = PHASE_IDLE;
- info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod);
+ info->scsi.async_stp =
+ fas216_syncperiod(info, info->ifcfg.asyncperiod);
+
+ if (info->ifcfg.wide_max_size == 0)
+ wide_state = neg_invalid;
+ else
+#ifdef SCSI2_WIDE
+ wide_state = neg_wait;
+#else
+ wide_state = neg_invalid;
+#endif
if (info->host->dma_channel == NO_DMA || !info->dma.setup)
- negstate = syncneg_invalid;
+ sync_state = neg_invalid;
else
#ifdef SCSI2_SYNC
- negstate = syncneg_start;
+ sync_state = neg_wait;
#else
- negstate = syncneg_invalid;
+ sync_state = neg_invalid;
#endif
for (i = 0; i < 8; i++) {
- info->device[i].disconnect_ok = info->ifcfg.disconnect_ok;
- info->device[i].negstate = negstate;
- info->device[i].period = info->ifcfg.asyncperiod / 4;
- info->device[i].stp = info->scsi.async_stp;
- info->device[i].sof = 0;
+ info->device[i].disconnect_ok = info->ifcfg.disconnect_ok;
+ info->device[i].sync_state = sync_state;
+ info->device[i].wide_state = wide_state;
+ info->device[i].period = info->ifcfg.asyncperiod / 4;
+ info->device[i].stp = info->scsi.async_stp;
+ info->device[i].sof = 0;
+ info->device[i].wide_xfer = 0;
}
}
@@ -2083,6 +2296,49 @@
return 0;
}
+int fas216_print_stats(FAS216_Info *info, char *buffer)
+{
+ return sprintf(buffer,
+ "Queued commands: %-10u Issued commands: %-10u\n"
+ "Done commands : %-10u Reads : %-10u\n"
+ "Writes : %-10u Others : %-10u\n"
+ "Disconnects : %-10u Aborts : %-10u\n"
+ "Resets : %-10u\n",
+ info->stats.queues, info->stats.removes,
+ info->stats.fins, info->stats.reads,
+ info->stats.writes, info->stats.miscs,
+ info->stats.disconnects, info->stats.aborts,
+ info->stats.resets);
+}
+
+int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer)
+{
+ struct fas216_device *dev = &info->device[scd->id];
+ int len = 0;
+ char *p;
+
+ proc_print_scsidevice(scd, buffer, &len, 0);
+ p = buffer + len;
+
+ p += sprintf(p, " Extensions: ");
+
+ if (scd->tagged_supported)
+ p += sprintf(p, "TAG %sabled [%d] ",
+ scd->tagged_queue ? "en" : "dis",
+ scd->current_tag);
+
+ p += sprintf(p, "\n Transfers : %d-bit ",
+ 8 << dev->wide_xfer);
+
+ if (dev->sof)
+ p += sprintf(p, "sync offset %d, %d ns\n",
+ dev->sof, dev->period * 4);
+ else
+ p += sprintf(p, "async\n");
+
+ return p - buffer;
+}
+
EXPORT_SYMBOL(fas216_init);
EXPORT_SYMBOL(fas216_abort);
EXPORT_SYMBOL(fas216_reset);
@@ -2094,7 +2350,8 @@
EXPORT_SYMBOL(fas216_eh_device_reset);
EXPORT_SYMBOL(fas216_eh_bus_reset);
EXPORT_SYMBOL(fas216_eh_host_reset);
-
+EXPORT_SYMBOL(fas216_print_stats);
+EXPORT_SYMBOL(fas216_print_device);
#ifdef MODULE
int init_module(void)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/fas216.h linux.ac/drivers/acorn/scsi/fas216.h
--- linux.vanilla/drivers/acorn/scsi/fas216.h Sun Nov 8 15:08:19 1998
+++ linux.ac/drivers/acorn/scsi/fas216.h Sun Jan 24 23:54:37 1999
@@ -40,6 +40,7 @@
#define CMD_TRANSFERINFO 0x10
#define CMD_INITCMDCOMPLETE 0x11
#define CMD_MSGACCEPTED 0x12
+#define CMD_PADBYTES 0x18
#define CMD_SETATN 0x1a
#define CMD_RSETATN 0x1b
@@ -171,15 +172,17 @@
typedef enum {
PHASE_IDLE, /* we're not planning on doing anything */
PHASE_SELECTION, /* selecting a device */
+ PHASE_SELSTEPS, /* selection with command steps */
+ PHASE_COMMAND, /* command sent */
PHASE_MESSAGESENT, /* selected, and we're sending cmd */
PHASE_RECONNECTED, /* reconnected */
PHASE_DATAOUT, /* data out to device */
PHASE_DATAIN, /* data in from device */
PHASE_MSGIN, /* message in from device */
- PHASE_MSGOUT, /* message out to device */
- PHASE_AFTERMSGOUT, /* after message out phase */
+ PHASE_MSGIN_DISCONNECT, /* disconnecting from bus */
+ PHASE_MSGOUT, /* after message out phase */
+ PHASE_MSGOUT_EXPECT, /* expecting message out */
PHASE_STATUS, /* status from device */
- PHASE_DISCONNECT, /* disconnecting from bus */
PHASE_DONE /* Command complete */
} phase_t;
@@ -197,13 +200,15 @@
} fasdmatype_t;
typedef enum {
- syncneg_start, /* Negociate with device for Sync xfers */
- syncneg_sent, /* Sync Xfer negociation sent */
- syncneg_complete, /* Sync Xfer complete */
- syncneg_invalid /* Sync Xfer not supported */
-} syncneg_t;
+ neg_wait, /* Negociate with device */
+ neg_inprogress, /* Negociation sent */
+ neg_complete, /* Negociation complete */
+ neg_targcomplete, /* Target completed negociation */
+ neg_invalid /* Negociation not supported */
+} neg_t;
#define MAGIC 0x441296bdUL
+#define NR_MSGS 8
typedef struct {
unsigned long magic_start;
@@ -231,7 +236,7 @@
MsgQueue_t msgs; /* message queue for connected device */
unsigned int async_stp; /* Async transfer STP value */
- unsigned short last_message; /* last message to be sent */
+ unsigned char msgin_fifo; /* bytes in fifo at time of message in */
unsigned char disconnectable:1; /* this command can be disconnected */
unsigned char aborting:1; /* aborting command */
@@ -255,6 +260,7 @@
unsigned char clockrate; /* clock rate of FAS device (MHz) */
unsigned char select_timeout; /* timeout (R5) */
unsigned char sync_max_depth; /* Synchronous xfer max fifo depth */
+ unsigned char wide_max_size; /* Maximum wide transfer size */
unsigned char cntl3; /* Control Reg 3 */
unsigned int asyncperiod; /* Async transfer period (ns) */
unsigned int disconnect_ok:1; /* Disconnects allowed? */
@@ -267,12 +273,14 @@
} queues;
/* per-device info */
- struct {
+ struct fas216_device {
unsigned char disconnect_ok:1; /* device can disconnect */
- unsigned int period; /* sync xfer period (*4ns) */
+ unsigned char period; /* sync xfer period in (*4ns) */
unsigned char stp; /* synchronous transfer period */
unsigned char sof; /* synchronous offset register */
- syncneg_t negstate; /* synchronous transfer mode */
+ unsigned char wide_xfer; /* currently negociated wide transfer */
+ neg_t sync_state; /* synchronous transfer mode */
+ neg_t wide_state; /* wide transfer mode */
} device[8];
unsigned char busyluns[8]; /* array of bits indicating LUNs busy */
@@ -339,6 +347,9 @@
* Returns : 0 on success
*/
extern int fas216_release (struct Scsi_Host *instance);
+
+extern int fas216_print_stats(FAS216_Info *info, char *buffer);
+extern int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer);
/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt)
* Purpose : abort this command
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/msgqueue.c linux.ac/drivers/acorn/scsi/msgqueue.c
--- linux.vanilla/drivers/acorn/scsi/msgqueue.c Sun Nov 8 15:08:19 1998
+++ linux.ac/drivers/acorn/scsi/msgqueue.c Sun Jan 24 23:54:37 1999
@@ -83,45 +83,25 @@
int length = 0;
for (mq = msgq->qe; mq; mq = mq->next)
- length += mq->length;
+ length += mq->msg.length;
return length;
}
/*
- * Function: char *msgqueue_getnextmsg(MsgQueue_t *msgq, int *length)
- * Purpose : return a message & its length
+ * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno)
+ * Purpose : return a message
* Params : msgq - queue to obtain message from
- * length - pointer to int for message length
+ * : msgno - message number
* Returns : pointer to message string, or NULL
*/
-char *msgqueue_getnextmsg(MsgQueue_t *msgq, int *length)
+struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno)
{
struct msgqueue_entry *mq;
- if ((mq = msgq->qe) != NULL) {
- msgq->qe = mq->next;
- mqe_free(msgq, mq);
- *length = mq->length;
- }
-
- return mq ? mq->msg : NULL;
-}
-
-/*
- * Function: char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length)
- * Purpose : return next message & length without removing it from the list
- * Params : msgq - queue to obtain message from
- * : length - pointer to int for message length
- * Returns : pointer to message string, or NULL
- */
-char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length)
-{
- struct msgqueue_entry *mq = msgq->qe;
-
- *length = mq ? mq->length : 0;
+ for (mq = msgq->qe; mq && msgno; mq = mq->next, msgno--);
- return mq ? mq->msg : NULL;
+ return mq ? &mq->msg : NULL;
}
/*
@@ -143,10 +123,11 @@
va_start(ap, length);
for (i = 0; i < length; i++)
- mq->msg[i] = va_arg(ap, unsigned char);
+ mq->msg.msg[i] = va_arg(ap, unsigned char);
va_end(ap);
- mq->length = length;
+ mq->msg.length = length;
+ mq->msg.fifo = 0;
mq->next = NULL;
mqp = &msgq->qe;
@@ -178,8 +159,7 @@
EXPORT_SYMBOL(msgqueue_initialise);
EXPORT_SYMBOL(msgqueue_free);
EXPORT_SYMBOL(msgqueue_msglength);
-EXPORT_SYMBOL(msgqueue_getnextmsg);
-EXPORT_SYMBOL(msgqueue_peeknextmsg);
+EXPORT_SYMBOL(msgqueue_getmsg);
EXPORT_SYMBOL(msgqueue_addmsg);
EXPORT_SYMBOL(msgqueue_flush);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/msgqueue.h linux.ac/drivers/acorn/scsi/msgqueue.h
--- linux.vanilla/drivers/acorn/scsi/msgqueue.h Sun Nov 8 15:08:19 1998
+++ linux.ac/drivers/acorn/scsi/msgqueue.h Sun Jan 24 23:54:37 1999
@@ -6,9 +6,14 @@
#ifndef MSGQUEUE_H
#define MSGQUEUE_H
-struct msgqueue_entry {
+struct message {
char msg[8];
int length;
+ int fifo;
+};
+
+struct msgqueue_entry {
+ struct message msg;
struct msgqueue_entry *next;
};
@@ -21,60 +26,51 @@
} MsgQueue_t;
/*
- * Function: void msgqueue_initialise (MsgQueue_t *msgq)
+ * Function: void msgqueue_initialise(MsgQueue_t *msgq)
* Purpose : initialise a message queue
* Params : msgq - queue to initialise
*/
-extern void msgqueue_initialise (MsgQueue_t *msgq);
+extern void msgqueue_initialise(MsgQueue_t *msgq);
/*
- * Function: void msgqueue_free (MsgQueue_t *msgq)
+ * Function: void msgqueue_free(MsgQueue_t *msgq)
* Purpose : free a queue
* Params : msgq - queue to free
*/
-extern void msgqueue_free (MsgQueue_t *msgq);
+extern void msgqueue_free(MsgQueue_t *msgq);
/*
- * Function: int msgqueue_msglength (MsgQueue_t *msgq)
+ * Function: int msgqueue_msglength(MsgQueue_t *msgq)
* Purpose : calculate the total length of all messages on the message queue
* Params : msgq - queue to examine
* Returns : number of bytes of messages in queue
*/
-extern int msgqueue_msglength (MsgQueue_t *msgq);
+extern int msgqueue_msglength(MsgQueue_t *msgq);
/*
- * Function: char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length)
+ * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno)
* Purpose : return a message & its length
* Params : msgq - queue to obtain message from
- * length - pointer to int for message length
- * Returns : pointer to message string, or NULL
- */
-extern char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length);
-
-/*
- * Function: char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length)
- * Purpose : return next message & length without removing it from the list
- * Params : msgq - queue to obtain message from
- * : length - pointer to int for message length
+ * : msgno - message number
* Returns : pointer to message string, or NULL
*/
-extern char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length);
+extern struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno);
/*
- * Function: int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...)
+ * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...)
* Purpose : add a message onto a message queue
* Params : msgq - queue to add message on
* length - length of message
* ... - message bytes
* Returns : != 0 if successful
*/
-extern int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...);
+extern int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...);
/*
- * Function: void msgqueue_flush (MsgQueue_t *msgq)
+ * Function: void msgqueue_flush(MsgQueue_t *msgq)
* Purpose : flush all messages from message queue
* Params : msgq - queue to flush
*/
-extern void msgqueue_flush (MsgQueue_t *msgq);
+extern void msgqueue_flush(MsgQueue_t *msgq);
#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/powertec.c linux.ac/drivers/acorn/scsi/powertec.c
--- linux.vanilla/drivers/acorn/scsi/powertec.c Tue Dec 22 23:19:35 1998
+++ linux.ac/drivers/acorn/scsi/powertec.c Sun Jan 24 23:54:37 1999
@@ -114,6 +114,8 @@
powertecscsi_irqenable,
powertecscsi_irqdisable,
NULL,
+ NULL,
+ NULL,
NULL
};
@@ -271,8 +273,9 @@
info->info.ifcfg.select_timeout = 255;
info->info.ifcfg.asyncperiod = POWERTEC_ASYNC_PERIOD;
info->info.ifcfg.sync_max_depth = POWERTEC_SYNC_DEPTH;
- info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+ info->info.ifcfg.cntl3 = /*CNTL3_BS8 |*/ CNTL3_FASTSCSI | CNTL3_FASTCLK;
info->info.ifcfg.disconnect_ok = 1;
+ info->info.ifcfg.wide_max_size = 0;
info->info.dma.setup = powertecscsi_dma_setup;
info->info.dma.pseudo = NULL;
info->info.dma.stop = powertecscsi_dma_stop;
@@ -443,31 +446,12 @@
host->io_port, host->irq, host->dma_channel,
info->info.scsi.type, info->control.terms ? "on" : "off");
- pos += sprintf(buffer+pos,
- "Queued commands: %-10u Issued commands: %-10u\n"
- "Done commands : %-10u Reads : %-10u\n"
- "Writes : %-10u Others : %-10u\n"
- "Disconnects : %-10u Aborts : %-10u\n"
- "Resets : %-10u\n",
- info->info.stats.queues, info->info.stats.removes,
- info->info.stats.fins, info->info.stats.reads,
- info->info.stats.writes, info->info.stats.miscs,
- info->info.stats.disconnects, info->info.stats.aborts,
- info->info.stats.resets);
+ pos += fas216_print_stats(&info->info, buffer + pos);
- pos += sprintf (buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none");
+ pos += sprintf (buffer+pos, "\nAttached devices:\n");
for (scd = host->host_queue; scd; scd = scd->next) {
- int len;
-
- proc_print_scsidevice (scd, buffer, &len, pos);
- pos += len;
- pos += sprintf (buffer+pos, "Extensions: ");
- if (scd->tagged_supported)
- pos += sprintf (buffer+pos, "TAG %sabled [%d] ",
- scd->tagged_queue ? "en" : "dis",
- scd->current_tag);
- pos += sprintf (buffer+pos, "\n");
+ pos += fas216_print_device(&info->info, scd, buffer + pos);
if (pos + begin < offset) {
begin += pos;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/acorn/scsi/queue.c linux.ac/drivers/acorn/scsi/queue.c
--- linux.vanilla/drivers/acorn/scsi/queue.c Sun Nov 8 15:08:19 1998
+++ linux.ac/drivers/acorn/scsi/queue.c Sun Jan 24 23:54:37 1999
@@ -55,6 +55,7 @@
q->magic = QUEUE_MAGIC_FREE;
q->SCpnt = NULL;
}
+ q -= 1;
q->next = NULL;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/genhd.c linux.ac/drivers/block/genhd.c
--- linux.vanilla/drivers/block/genhd.c Tue Feb 23 14:21:32 1999
+++ linux.ac/drivers/block/genhd.c Sat Feb 20 01:06:46 1999
@@ -879,7 +879,7 @@
res = 0;
for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
- if(!(bh = bread(dev,blk,get_ptable_blocksize(dev)))) {
+ if(!(bh = bread(dev,blk,512))) {
printk("Dev %s: unable to read RDB block %d\n",
kdevname(dev),blk);
goto rdb_done;
@@ -896,7 +896,7 @@
blk = htonl(rdb->rdb_PartitionList);
brelse(bh);
for (part = 1; blk > 0 && part <= 16; part++) {
- if (!(bh = bread(dev,blk, get_ptable_blocksize(dev)))) {
+ if (!(bh = bread(dev,blk, 512))) {
printk("Dev %s: unable to read partition block %d\n",
kdevname(dev),blk);
goto rdb_done;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/hd.c linux.ac/drivers/block/hd.c
--- linux.vanilla/drivers/block/hd.c Tue Jan 19 02:57:23 1999
+++ linux.ac/drivers/block/hd.c Thu Feb 18 20:27:35 1999
@@ -744,11 +744,12 @@
*/
- if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
+ if ((cmos_disks = CMOS_READ(0x12)) & 0xf0) {
if (cmos_disks & 0x0f)
NR_HD = 2;
else
NR_HD = 1;
+ }
}
#endif /* __i386__ */
for (drive=0 ; drive < NR_HD ; drive++) {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-cd.c linux.ac/drivers/block/ide-cd.c
--- linux.vanilla/drivers/block/ide-cd.c Sun Jan 24 19:55:33 1999
+++ linux.ac/drivers/block/ide-cd.c Wed Feb 24 17:04:26 1999
@@ -33,6 +33,7 @@
* boot
* -Integrate DVD-ROM support in driver. Thanks to Merete Gotsæd-Petersen
* of Pioneer Denmark for providing me with a drive for testing.
+ * -Implement Features and Profiles.
*
*
* ----------------------------------
@@ -230,9 +231,23 @@
* 4.52 Jan 19, 1999 -- Jens Axboe
* - Detect DVD-ROM/RAM drives
*
+ * 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar
+ * drive in transfer size limit.
+ * - Fix the I/O error when doing eject without a medium
+ * loaded on some drives.
+ * - CDROMREADMODE2 is now implemented through
+ * CDROMREADRAW, since many drives don't support
+ * MODE2 (even though ATAPI 2.6 says they must).
+ * - Added ignore parameter to ide-cd (as a module), eg
+ * insmod ide-cd ignore='hda hdb'
+ * Useful when using ide-cd in conjunction with
+ * ide-scsi. TODO: non-modular way of doing the
+ * same.
+ *
+ *
*************************************************************************/
-#define IDECD_VERSION "4.52"
+#define IDECD_VERSION "4.53"
#include
#include
@@ -252,7 +267,6 @@
#include "ide.h"
#include "ide-cd.h"
-
/****************************************************************************
* Generic packet command support and error handling routines.
*/
@@ -1527,6 +1541,10 @@
CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
stat = 0;
}
+
+ /* no medium, that's alright. */
+ if (stat != 0 && reqbuf->sense_key == NOT_READY && reqbuf->asc == 0x3a)
+ stat = 0;
if (stat == 0)
CDROM_STATE_FLAGS (drive)->door_locked = lockflag;
@@ -1806,7 +1824,6 @@
return cdrom_queue_packet_command (drive, &pc);
}
-
/* ATAPI cdrom drives are free to select the speed you request or any slower
rate :-( Requesting too fast a speed will _not_ produce an error. */
static int
@@ -2092,22 +2109,17 @@
if (cmd == CDROMREADMODE1) {
blocksize = CD_FRAMESIZE;
format = 2;
- } else if (cmd == CDROMREADMODE2) {
- blocksize = CD_FRAMESIZE_RAW0;
- format = 3;
- } else {
+ } else { /* for RAW and MODE2. */
blocksize = CD_FRAMESIZE_RAW;
format = 0;
}
- stat = verify_area (VERIFY_WRITE, (char *)arg, blocksize);
- if (stat) return stat;
+
+ copy_from_user_ret(&msf, (void *)arg, sizeof (msf), -EFAULT);
- copy_from_user (&msf, (void *)arg, sizeof (msf));
+ lba = msf_to_lba(msf.cdmsf_min0,
+ msf.cdmsf_sec0,
+ msf.cdmsf_frame0);
- lba = msf_to_lba (msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0);
-
/* Make sure the TOC is up to date. */
stat = cdrom_read_toc (drive, NULL);
if (stat) return stat;
@@ -2117,14 +2129,21 @@
if (lba < 0 || lba >= toc->capacity)
return -EINVAL;
- buf = (char *) kmalloc (CD_FRAMESIZE_RAW, GFP_KERNEL);
+ buf = (char *) kmalloc (blocksize, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
stat = cdrom_read_block (drive, format, lba, 1, buf, blocksize,
NULL);
- if (stat == 0)
- copy_to_user ((char *)arg, buf, blocksize);
+
+ if (stat == 0) {
+ if (cmd == CDROMREADMODE2) {
+ /* For Mode2, skip the Sync, Header, and Subheader */
+ copy_to_user_ret((char *)arg, buf+16, CD_FRAMESIZE_RAW0, -EFAULT);
+ } else {
+ copy_to_user_ret((char *)arg, buf, blocksize, -EFAULT);
+ }
+ }
kfree (buf);
return stat;
@@ -2486,14 +2505,12 @@
static
int ide_cdrom_reset (struct cdrom_device_info *cdi)
{
-
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct request req;
ide_init_drive_cmd (&req);
req.cmd = RESET_DRIVE_COMMAND;
return ide_do_drive_cmd (drive, &req, ide_wait);
-
}
@@ -2501,9 +2518,10 @@
int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct atapi_request_sense rq;
if (position) {
- int stat = cdrom_lockdoor (drive, 0, NULL);
+ int stat = cdrom_lockdoor (drive, 0, &rq);
if (stat) return stat;
}
@@ -2980,12 +2998,17 @@
CDROM_CONFIG_FLAGS (drive)->no_eject = 1;
CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
- /* limit transfer size per interrupt. currently only one Samsung
- drive needs this. */
+ /* limit transfer size per interrupt. */
CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0;
- if (drive->id != NULL)
- if (strcmp (drive->id->model, "SAMSUNG CD-ROM SCR-2432") == 0)
+ if (drive->id != NULL) {
+ if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
+ CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
+ else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
+ else if (!strcmp (drive->id->model, "GCD-R580B"))
+ CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
+ /* 124/SECTORS_PER_FRAME; ? */
+ }
#if ! STANDARD_ATAPI
/* by default Sanyo 3 CD changer support is turned off and
@@ -3155,7 +3178,13 @@
NULL
};
+/* options */
+char *ignore = NULL;
+
#ifdef MODULE
+MODULE_PARM(ignore, "s");
+MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
+
int init_module (void)
{
return ide_cdrom_init();
@@ -3183,6 +3212,12 @@
MOD_INC_USE_COUNT;
while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) {
+ /* skip drives that we were told to ignore */
+ if (ignore != NULL)
+ if (strstr(ignore, drive->name)) {
+ printk("ide-cd: ignoring drive %s\n", drive->name);
+ continue;
+ }
info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
printk ("%s: Can't allocate a cdrom structure\n", drive->name);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-cd.h linux.ac/drivers/block/ide-cd.h
--- linux.vanilla/drivers/block/ide-cd.h Sun Jan 24 19:55:33 1999
+++ linux.ac/drivers/block/ide-cd.h Tue Feb 23 21:25:44 1999
@@ -85,6 +85,9 @@
#define MECHANISM_STATUS 0xbd
#define READ_CD 0xbe
+/* DVD Opcodes */
+#define DVD_GET_PERFORMANCE 0xac
+
/* Page codes for mode sense/set */
@@ -562,7 +565,7 @@
/* Sector buffer. If a read request wants only the first part
of a cdrom block, we cache the rest of the block here,
- in the expectation that that data is going to be wanted soon.
+ in the expectation that the data is going to be wanted soon.
SECTOR_BUFFERED is the number of the first buffered sector,
and NSECTORS_BUFFERED is the number of sectors in the buffer.
Before the buffer is allocated, we should have
@@ -656,6 +659,7 @@
{ PLAY_CD, "Play CD" },
{ MECHANISM_STATUS, "Mechanism Status" },
{ READ_CD, "Read CD" },
+ { DVD_GET_PERFORMANCE, "Get Performance" },
};
@@ -776,7 +780,8 @@
{ 0x6400, "Illegal mode for this track or incompatible medium" },
- { 0xb900, "Play operation oborted (sic)" },
+ /* Following error is misspelled in ATAPI 2.6 */
+ { 0xb900, "Play operation oborted [sic]" },
{ 0xbf00, "Loss of streaming" },
};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide.c linux.ac/drivers/block/ide.c
--- linux.vanilla/drivers/block/ide.c Tue Jan 19 02:57:24 1999
+++ linux.ac/drivers/block/ide.c Mon Feb 1 00:37:11 1999
@@ -2068,6 +2068,12 @@
(unsigned long *) &loc->start)) return -EFAULT;
return 0;
}
+ case BLKSSZGET:
+ /* Block size of media */
+ return put_user(blksize_size[HWIF(drive)->major]
+ [minor&PARTN_MASK],
+ (int *)arg);
+
case BLKFLSBUF:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
fsync_dev(inode->i_rdev);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/rd.c linux.ac/drivers/block/rd.c
--- linux.vanilla/drivers/block/rd.c Sun Nov 8 15:07:36 1998
+++ linux.ac/drivers/block/rd.c Mon Feb 1 00:39:15 1999
@@ -170,14 +170,12 @@
break;
case BLKGETSIZE: /* Return device size */
if (!arg) return -EINVAL;
- err = verify_area(VERIFY_WRITE, (long *) arg,
- sizeof(long));
- if (err)
- return err;
- put_user(rd_length[MINOR(inode->i_rdev)] / 512,
+ return put_user(rd_length[MINOR(inode->i_rdev)] / 512,
(long *) arg);
- return 0;
-
+ case BLKSSZGET:
+ /* Block size of media */
+ return put_user(rd_blocksizes[MINOR(inode->i_rdev)],
+ (int *)arg);
default:
break;
};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/cdrom/cdrom.c linux.ac/drivers/cdrom/cdrom.c
--- linux.vanilla/drivers/cdrom/cdrom.c Tue Jan 19 02:57:24 1999
+++ linux.ac/drivers/cdrom/cdrom.c Wed Feb 24 17:57:25 1999
@@ -24,8 +24,9 @@
-- Change the CDROMREADMODE1, CDROMREADMODE2, CDROMREADAUDIO, and
CDROMREADRAW ioctls so they go through the Uniform CD-ROM driver.
-
-
+
+ -- Sync options and capability flags.
+
Revision History
@@ -97,17 +98,27 @@
cdi->options in various ioctl.
-- Added version to proc entry.
- 2.52 Jan 16, 1998 - Jens Axboe
+ 2.52 Jan 16, 1999 - Jens Axboe
-- Fixed an error in open_for_data where we would sometimes not return
the correct error value. Thanks Huba Gaspar .
-- Fixed module usage count - usage was based on /proc/sys/dev
instead of /proc/sys/dev/cdrom. This could lead to an oops when other
- modules had entries in dev.
+ modules had entries in dev. Feb 02 - real bug was in sysctl.c where
+ dev would be removed even though it was used. cdrom.c just illuminated
+ that bug.
+
+ 2.53 Feb 22, 1999 - Jens Axboe
+ -- Fixup of several ioctl calls, in particular CDROM_SET_OPTIONS has
+ been "rewritten" because capabilities and options aren't in sync. They
+ should be...
+ -- Added CDROM_LOCKDOOR ioctl. Not useful until I add a lock flag,
+ since cdrom_release() unlocks the door when use count drops to zero.
+ -- Added CDROM_RESET ioctl.
-------------------------------------------------------------------------*/
-#define REVISION "Revision: 2.52"
-#define VERSION "Id: cdrom.c 2.52 1999/01/16"
+#define REVISION "Revision: 2.53"
+#define VERSION "Id: cdrom.c 2.52 1999/02/22"
/* I use an error-log mask to give fine grain control over the type of
messages dumped to the system logs. The available masks include: */
@@ -520,7 +531,7 @@
cdo->capability & CDC_LOCK) {
cdinfo(CD_CLOSE, "Unlocking door!\n");
cdo->lock_door(cdi, 0);
- }
+ }
opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
!(fp && fp->f_flags & O_NONBLOCK);
cdo->release(cdi);
@@ -716,18 +727,18 @@
cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n");
if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY))
return -ENOSYS;
- if (cdi->use_count != 1)
+ if (cdi->use_count != 1)
return -EBUSY;
- if (cdo->capability & ~cdi->mask & CDC_LOCK) {
+ if (cdo->capability & ~cdi->mask & CDC_LOCK)
if ((ret=cdo->lock_door(cdi, 0)))
return ret;
- }
+
return cdo->tray_move(cdi, 1);
}
case CDROMCLOSETRAY:
cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n");
- if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY))
+ if (!(cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY))
return -ENOSYS;
return cdo->tray_move(cdi, 0);
@@ -755,8 +766,19 @@
case CDROM_SET_OPTIONS:
cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n");
- if (cdo->capability & arg & ~cdi->mask)
- return -ENOSYS;
+ /* options need to be in sync with capability. too late for
+ that, so we have to check each one separately... */
+ switch (arg) {
+ case CDO_AUTO_CLOSE:
+ if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY)
+ return -ENOSYS;
+ case CDO_AUTO_EJECT:
+ if (cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)
+ return -ENOSYS;
+ case CDO_LOCK:
+ if (cdo->capability & ~cdi->mask & CDC_LOCK)
+ return -ENOSYS;
+ }
cdi->options |= (int) arg;
return cdi->options;
@@ -783,6 +805,21 @@
return cdo->select_disc(cdi, arg);
}
+ case CDROMRESET: {
+ cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n");
+ if (!(cdo->capability & ~cdi->mask & CDC_RESET))
+ return -ENOSYS;
+ return cdo->reset(cdi);
+ }
+
+ case CDROM_LOCKDOOR: {
+ cdinfo(CD_DO_IOCTL, "%socking door.\n",arg?"L":"Unl");
+ if (cdo->capability & ~cdi->mask & CDC_LOCK)
+ return cdo->lock_door(cdi, arg);
+ else
+ return -EDRIVE_CANT_DO_THIS;
+ }
+
/* The following function is implemented, although very few audio
* discs give Universal Product Code information, which should just be
* the Medium Catalog Number on the box. Note, that the way the code
@@ -1123,7 +1160,7 @@
return;
cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
- cdrom_root_table->de->fill_inode = &cdrom_procfs_modcount;
+ cdrom_root_table->child->de->fill_inode = &cdrom_procfs_modcount;
initialized = 1;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/Config.in linux.ac/drivers/char/Config.in
--- linux.vanilla/drivers/char/Config.in Mon Dec 28 23:09:42 1998
+++ linux.ac/drivers/char/Config.in Tue Feb 16 17:27:11 1999
@@ -139,6 +139,16 @@
if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
hex ' SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
fi
+ dep_tristate 'Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV
+ if [ "$CONFIG_PROC_FS" = "y" ]; then
+ if [ "$CONFIG_RADIO_TYPHOON" != "n" ]; then
+ bool ' Support for /proc/radio-typhoon' CONFIG_RADIO_TYPHOON_PROC_FS
+ fi
+ fi
+ if [ "$CONFIG_RADIO_TYPHOON" = "y" ]; then
+ hex ' Typhoon I/O port (0x316 or 0x336)' CONFIG_RADIO_TYPHOON_PORT 316
+ int ' Typhoon frequency set when muting the device (kHz)' CONFIG_RADIO_TYPHOON_MUTEFREQ 87500
+ fi
dep_tristate 'Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV
if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then
hex ' ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/Makefile linux.ac/drivers/char/Makefile
--- linux.vanilla/drivers/char/Makefile Mon Dec 28 23:09:42 1998
+++ linux.ac/drivers/char/Makefile Tue Feb 16 17:27:11 1999
@@ -44,12 +44,17 @@
ifdef CONFIG_VT
L_OBJS += keyboard.o
endif
-ifneq ($(ARCH),m68k)
-L_OBJS += pc_keyb.o defkeymap.o
+ ifneq ($(ARCH),m68k)
+ L_OBJS += pc_keyb.o defkeymap.o
+ endif
+else
+ifdef CONFIG_PCI
+L_OBJS += defkeymap.o keyboard.o
endif
-ifdef CONFIG_MAGIC_SYSRQ
-L_OBJS += sysrq.o
endif
+
+ifdef CONFIG_MAGIC_SYSRQ
+LX_OBJS += sysrq.o
endif
ifeq ($(CONFIG_ATARI_DSP56K),y)
@@ -361,6 +366,14 @@
else
ifeq ($(CONFIG_RADIO_RTRACK2),m)
M_OBJS += radio-rtrack2.o
+ endif
+endif
+
+ifeq ($(CONFIG_RADIO_TYPHOON),y)
+L_OBJS += radio-typhoon.o
+else
+ ifeq ($(CONFIG_RADIO_TYPHOON),m)
+ M_OBJS += radio-typhoon.o
endif
endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bttv.c linux.ac/drivers/char/bttv.c
--- linux.vanilla/drivers/char/bttv.c Tue Feb 23 14:21:33 1999
+++ linux.ac/drivers/char/bttv.c Sat Feb 27 02:13:55 1999
@@ -1558,12 +1558,33 @@
static void bttv_close(struct video_device *dev)
{
struct bttv *btv=(struct bttv *)dev;
-
+
btv->user--;
audio(btv, AUDIO_INTERN);
btv->cap&=~3;
bt848_set_risc_jmps(btv);
+ /*
+ * A word of warning. At this point the chip
+ * is still capturing because its FIFO hasn't emptied
+ * and the DMA control operations are posted PCI
+ * operations.
+ */
+
+ btread(BT848_I2C); /* This fixes the PCI posting delay */
+
+ /*
+ * This is sucky but right now I can't find a good way to
+ * be sure its safe to free the buffer. We wait 5-6 fields
+ * which is more than sufficient to be sure.
+ */
+
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ/10); /* Wait 1/10th of a second */
+
+ /*
+ * We have allowed it to drain.
+ */
if(btv->fbuffer)
rvfree((void *) btv->fbuffer, 2*BTTV_MAX_FBUF);
btv->fbuffer=0;
@@ -3037,7 +3058,7 @@
btv->risc_jmp[12]=BT848_RISC_JUMP;
btv->risc_jmp[13]=virt_to_bus(btv->risc_jmp);
- /* enable cpaturing and DMA */
+ /* enable capturing */
btaor(flags, ~0x0f, BT848_CAP_CTL);
if (flags&0x0f)
bt848_dma(btv, 3);
@@ -3242,7 +3263,7 @@
if (astat&BT848_INT_SCERR) {
IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr));
bt848_dma(btv, 0);
- bt848_dma(btv, 1);
+ bt848_dma(btv, 3);
wake_up_interruptible(&btv->vbiq);
wake_up_interruptible(&btv->capq);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bw-qcam.c linux.ac/drivers/char/bw-qcam.c
--- linux.vanilla/drivers/char/bw-qcam.c Sun Nov 8 15:10:11 1998
+++ linux.ac/drivers/char/bw-qcam.c Sun Jan 24 21:15:01 1999
@@ -5,6 +5,28 @@
*
* Video4Linux conversion work by Alan Cox.
* Parport compatibility by Phil Blundell.
+ * Busy loop avoidance by Mark Cooke.
+ *
+ * Module parameters:
+ *
+ * maxpoll=<1 - 5000>
+ *
+ * When polling the QuickCam for a response, busy-wait for a
+ * maximum of this many loops. The default of 250 gives little
+ * impact on interactive response.
+ *
+ * NOTE: If this parameter is set too high, the processor
+ * will busy wait until this loop times out, and then
+ * slowly poll for a further 5 seconds before failing
+ * the transaction. You have been warned.
+ *
+ * yieldlines=<1 - 250>
+ *
+ * When acquiring a frame from the camera, the data gathering
+ * loop will yield back to the scheduler after completing
+ * this many lines. The default of 4 provides a trade-off
+ * between increased frame acquisition time and impact on
+ * interactive response.
*/
/* qcam-lib.c -- Library for programming with the Connectix QuickCam.
@@ -58,6 +80,14 @@
#include "bw-qcam.h"
+#if LINUX_VERSION_CODE >= 0x020117
+MODULE_PARM(maxpoll,"i");
+MODULE_PARM(yieldlines,"i");
+#endif
+
+static unsigned int maxpoll=250; /* Maximum busy-loop count for qcam I/O */
+static unsigned int yieldlines=4; /* Yield after this many during capture */
+
extern __inline__ int read_lpstatus(struct qcam_device *q)
{
return parport_read_status(q->pport);
@@ -154,6 +184,7 @@
q->top = 1;
q->left = 14;
q->mode = -1;
+ q->status = QC_PARAM_CHANGE;
return q;
}
@@ -209,14 +240,17 @@
{
/* 1000 is enough spins on the I/O for all normal
cases, at that point we start to poll slowly
- until the camera wakes up */
+ until the camera wakes up. However, we are
+ busy blocked until the camera responds, so
+ setting it lower is much better for interactive
+ response. */
- if(runs++>1000)
+ if(runs++>maxpoll)
{
current->state=TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/10);
+ schedule_timeout(HZ/200);
}
- if(runs>1050)
+ if(runs>(maxpoll+1000)) /* 5 seconds */
return -1;
}
}
@@ -226,14 +260,17 @@
{
/* 1000 is enough spins on the I/O for all normal
cases, at that point we start to poll slowly
- until the camera wakes up */
+ until the camera wakes up. However, we are
+ busy blocked until the camera responds, so
+ setting it lower is much better for interactive
+ response. */
- if(runs++>1000)
+ if(runs++>maxpoll)
{
current->state=TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/10);
+ schedule_timeout(HZ/200);
}
- if(runs++>1050) /* 5 seconds */
+ if(runs++>(maxpoll+1000)) /* 5 seconds */
return -1;
}
}
@@ -256,14 +293,17 @@
status = read_lpdata(q);
/* 1000 is enough spins on the I/O for all normal
cases, at that point we start to poll slowly
- until the camera wakes up */
+ until the camera wakes up. However, we are
+ busy blocked until the camera responds, so
+ setting it lower is much better for interactive
+ response. */
- if(runs++>1000)
+ if(runs++>maxpoll)
{
current->state=TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/10);
+ schedule_timeout(HZ/200);
}
- if(runs++>1050) /* 5 seconds */
+ if(runs++>(maxpoll+1000)) /* 5 seconds */
return 0;
}
while ((status & 1) != val);
@@ -287,7 +327,7 @@
lastreg = reg = read_lpstatus(q) & 0xf0;
- for (i = 0; i < 300; i++)
+ for (i = 0; i < 500; i++)
{
reg = read_lpstatus(q) & 0xf0;
if (reg != lastreg)
@@ -296,9 +336,20 @@
mdelay(2);
}
- /* Be liberal in what you accept... */
- if (count > 30 && count < 200)
+#if 0
+ /* Force camera detection during testing. Sometimes the camera
+ won't be flashing these bits. Possibly unloading the module
+ in the middle of a grab? Or some timeout condition?
+ I've seen this parameter as low as 19 on my 450Mhz box - mpc */
+ printk("Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count);
+ return 1;
+#endif
+
+ /* Be (even more) liberal in what you accept... */
+
+/* if (count > 30 && count < 200) */
+ if (count > 20 && count < 300)
return 1; /* found */
else
return 0; /* not found */
@@ -352,6 +403,8 @@
static int qc_setscanmode(struct qcam_device *q)
{
+ int old_mode = q->mode;
+
switch (q->transfer_scale)
{
case 1:
@@ -383,6 +436,10 @@
case QC_UNIDIR:
break;
}
+
+ if (q->mode != old_mode)
+ q->status |= QC_PARAM_CHANGE;
+
return 0;
}
@@ -434,8 +491,11 @@
qc_command(q, q->contrast);
qc_command(q, 0x1f);
qc_command(q, q->whitebal);
-}
+ /* Clear flag that we must update the grabbing parameters on the camera
+ before we grab the next frame */
+ q->status &= (~QC_PARAM_CHANGE);
+}
/* Qc_readbytes reads some bytes from the QC and puts them in
the supplied buffer. It returns the number of bytes read,
@@ -539,7 +599,7 @@
long qc_capture(struct qcam_device * q, char *buf, unsigned long len)
{
- int i, j, k;
+ int i, j, k, yield;
int bytes;
int linestotrans, transperline;
int divisor;
@@ -575,7 +635,7 @@
q->transfer_scale;
transperline = (transperline + divisor - 1) / divisor;
- for (i = 0; i < linestotrans; i++)
+ for (i = 0, yield = yieldlines; i < linestotrans; i++)
{
for (pixels_read = j = 0; j < transperline; j++)
{
@@ -599,6 +659,18 @@
pixels_read += bytes;
}
(void) qc_readbytes(q, 0); /* reset state machine */
+
+ /* Grabbing an entire frame from the quickcam is a lengthy
+ process. We don't (usually) want to busy-block the
+ processor for the entire frame. yieldlines is a module
+ parameter. If we yield every line, the minimum frame
+ time will be 240 / 200 = 1.2 seconds. The compile-time
+ default is to yield every 4 lines. */
+ if (i >= yield) {
+ current->state=TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/200);
+ yield = i + yieldlines;
+ }
}
if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR)
@@ -745,9 +817,12 @@
qcam->bpp = p.depth;
qc_setscanmode(qcam);
- parport_claim_or_block(qcam->pdev);
+ qcam->status |= QC_PARAM_CHANGE;
+
+/* parport_claim_or_block(qcam->pdev);
qc_set(qcam);
parport_release(qcam->pdev);
+*/
return 0;
}
case VIDIOCSWIN:
@@ -779,6 +854,11 @@
qcam->transfer_scale = 1;
}
qc_setscanmode(qcam);
+
+ /* We must update the camera before we grab. We could
+ just have changed the grab size */
+ qcam->status |= QC_PARAM_CHANGE;
+
/* Ok we figured out what to use from our wide choice */
return 0;
}
@@ -824,11 +904,15 @@
parport_claim_or_block(qcam->pdev);
/* Probably should have a semaphore against multiple users */
qc_reset(qcam);
+
+ /* Update the camera parameters if we need to */
+ if (qcam->status & QC_PARAM_CHANGE)
+ qc_set(qcam);
+
len=qc_capture(qcam, buf,count);
parport_release(qcam->pdev);
return len;
}
-
static struct video_device qcam_template=
{
@@ -909,6 +993,17 @@
for (port = parport_enumerate(); port; port=port->next)
init_bwqcam(port);
+
+ /* Do some sanity checks on the module parameters. */
+ if (maxpoll > 5000) {
+ printk("Connectix Quickcam max-poll was above 5000. Using 5000.\n");
+ maxpoll = 5000;
+ }
+
+ if (yieldlines < 1) {
+ printk("Connectix Quickcam yieldlines was less than 1. Using 1.\n");
+ yieldlines = 1;
+ }
return (num_cams)?0:-ENODEV;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bw-qcam.h linux.ac/drivers/char/bw-qcam.h
--- linux.vanilla/drivers/char/bw-qcam.h Sun Nov 8 15:07:44 1998
+++ linux.ac/drivers/char/bw-qcam.h Sun Jan 24 21:15:01 1999
@@ -48,6 +48,9 @@
#define MAX_HEIGHT 243
#define MAX_WIDTH 336
+/* Bit fields for status flags */
+#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */
+
struct qcam_device {
struct video_device vdev;
struct pardevice *pdev;
@@ -59,6 +62,6 @@
int port_mode;
int transfer_scale;
int top, left;
+ int status;
unsigned int saved_bits;
};
-
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/console.c linux.ac/drivers/char/console.c
--- linux.vanilla/drivers/char/console.c Sun Jan 24 19:55:33 1999
+++ linux.ac/drivers/char/console.c Wed Jan 27 18:58:10 1999
@@ -2778,7 +2778,7 @@
set_cursor(currcons);
}
-u16 vcs_scr_readw(int currcons, u16 *org)
+u16 vcs_scr_readw(int currcons, const u16 *org)
{
if ((unsigned long)org == pos && softcursor_original != -1)
return softcursor_original;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/esp.c linux.ac/drivers/char/esp.c
--- linux.vanilla/drivers/char/esp.c Sun Nov 8 15:10:12 1998
+++ linux.ac/drivers/char/esp.c Sun Nov 8 14:58:21 1998
@@ -2186,7 +2186,7 @@
if (signal_pending(current))
break;
- if (timeout && ((orig_jiffies + timeout) < jiffies))
+ if (timeout && time_before(orig_jiffies + timeout, jiffies))
break;
serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/radio-aimslab.c linux.ac/drivers/char/radio-aimslab.c
--- linux.vanilla/drivers/char/radio-aimslab.c Thu Jan 14 01:25:21 1999
+++ linux.ac/drivers/char/radio-aimslab.c Fri Feb 26 01:47:18 1999
@@ -3,6 +3,11 @@
* Coverted to new API by Alan Cox
* Various bugfixes and enhancements by Russell Kroll
*
+ * History:
+ * 1999-02-24 Russell Kroll
+ * Fine tuning/VIDEO_TUNER_LOW
+ * Frequency range expanded to start at 87 MHz
+ *
* TODO: Allow for more than one of these foolish entities :-)
*
* Notes on the hardware (reverse engineered from other peoples'
@@ -156,14 +161,11 @@
/* adapted from radio-aztech.c */
- /* We want to compute x * 100 / 16 without overflow
- * So we compute x*6 + (x/100)*25 to give x*6.25
- */
-
- freq = freq * 6 + freq/4; /* massage the data a little */
- freq += 1070; /* IF = 10.7 MHz */
- freq /= 5; /* ref = 25 kHz */
+ /* now uses VIDEO_TUNER_LOW for fine tuning */
+ freq += 171200; /* Add 10.7 MHz IF */
+ freq /= 800; /* Convert to 50 kHz units */
+
send_0_byte (io, dev); /* 0: LSB of frequency */
for (i = 0; i < 13; i++) /* : frequency bits (1-13) */
@@ -229,9 +231,9 @@
return -EFAULT;
if(v.tuner) /* Only 1 tuner */
return -EINVAL;
- v.rangelow=(88*16);
- v.rangehigh=(108*16);
- v.flags=0;
+ v.rangelow=(87*16000);
+ v.rangehigh=(108*16000);
+ v.flags=VIDEO_TUNER_LOW;
v.mode=VIDEO_MODE_AUTO;
v.signal=0xFFFF*rt_getsigstr(rt);
if(copy_to_user(arg,&v, sizeof(v)))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/radio-aztech.c linux.ac/drivers/char/radio-aztech.c
--- linux.vanilla/drivers/char/radio-aztech.c Sun Nov 8 15:07:47 1998
+++ linux.ac/drivers/char/radio-aztech.c Fri Feb 26 01:47:18 1999
@@ -1,9 +1,7 @@
-/* aztech.c - Aztech radio card driver for Linux 2.1 by Russell Kroll
+/* radio-aztech.c - Aztech radio card driver for Linux 2.2
*
- * Heavily modified to support the new 2.1 radio card interfaces by
- * Russell Kroll (rkroll@exploits.org)
- *
- * Based on code by
+ * Adapted to support the Video for Linux API by
+ * Russell Kroll . Based on original tuner code by:
*
* Quay Ly
* Donald Song
@@ -14,6 +12,11 @@
* The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/
* along with more information on the card itself.
*
+ * History:
+ * 1999-02-24 Russell Kroll
+ * Fine tuning/VIDEO_TUNER_LOW
+ * Range expanded to 87-108 MHz (from 87.9-107.8)
+ *
* Notable changes from the original source:
* - includes stripped down to the essentials
* - for loops used as delays replaced with udelay()
@@ -113,11 +116,8 @@
{
int i;
- /* 6.25 * */
- frequency = frequency*6 + frequency/4; /* massage data a bit */
-
- frequency += 1070; /* tuning needs 24 data bits */
- frequency /= 5;
+ frequency += 171200; /* Add 10.7 MHz IF */
+ frequency /= 800; /* Convert to 50 kHz units */
send_0_byte (dev); /* 0: LSB of frequency */
@@ -179,9 +179,9 @@
return -EFAULT;
if(v.tuner) /* Only 1 tuner */
return -EINVAL;
- v.rangelow=(879*16)/10;
- v.rangehigh=(1078*16)/10;
- v.flags=0;
+ v.rangelow=(87*16000);
+ v.rangehigh=(108*16000);
+ v.flags=VIDEO_TUNER_LOW;
v.mode=VIDEO_MODE_AUTO;
v.signal=0xFFFF*az_getsigstr(az);
if(az_getstereo(az))
@@ -292,7 +292,7 @@
return -EINVAL;
request_region(io, 2, "aztech");
- printk(KERN_INFO "Aztech radio card driver v0.40/19980422 rkroll@exploits.org\n");
+ printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
/* mute card - prevents noisy bootups */
outb (0, io);
return 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/radio-typhoon.c linux.ac/drivers/char/radio-typhoon.c
--- linux.vanilla/drivers/char/radio-typhoon.c Thu Jan 1 01:00:00 1970
+++ linux.ac/drivers/char/radio-typhoon.c Tue Feb 16 17:27:11 1999
@@ -0,0 +1,428 @@
+/* Typhoon Radio Card driver for radio support
+ * (c) 1999 Dr. Henrik Seidel
+ *
+ * Card manufacturer:
+ * http://194.18.155.92/idc/prod2.idc?nr=50753&lang=e
+ *
+ * Notes on the hardware
+ *
+ * This card has two output sockets, one for speakers and one for line.
+ * The speaker output has volume control, but only in four discrete
+ * steps. The line output has neither volume control nor mute.
+ *
+ * The card has auto-stereo according to its manual, although it all
+ * sounds mono to me (even with the Win/DOS drivers). Maybe it's my
+ * antenna - I really don't know for sure.
+ *
+ * Frequency control is done digitally.
+ *
+ * Volume control is done digitally, but there are only four different
+ * possible values. So you should better always turn the volume up and
+ * use line control. I got the best results by connecting line output
+ * to the sound card microphone input. For such a configuration the
+ * volume control has no effect, since volume control only influences
+ * the speaker output.
+ *
+ * There is no explicit mute/unmute. So I set the radio frequency to a
+ * value where I do expect just noise and turn the speaker volume down.
+ * The frequency change is necessary since the card never seems to be
+ * completely silent.
+ */
+
+#include /* Modules */
+#include /* Initdata */
+#include /* check_region, request_region */
+#include /* radio card status report */
+#include /* outb, outb_p */
+#include /* copy to/from user */
+#include /* kernel radio structs */
+#include /* CONFIG_RADIO_TYPHOON_* */
+
+#define BANNER "Typhoon Radio Card driver v0.1\n"
+
+#ifndef CONFIG_RADIO_TYPHOON_PORT
+#define CONFIG_RADIO_TYPHOON_PORT -1
+#endif
+
+#ifndef CONFIG_RADIO_TYPHOON_MUTEFREQ
+#define CONFIG_RADIO_TYPHOON_MUTEFREQ 0
+#endif
+
+struct typhoon_device {
+ int users;
+ int iobase;
+ int curvol;
+ int muted;
+ unsigned long curfreq;
+ unsigned long mutefreq;
+};
+
+static void typhoon_setvol_generic(struct typhoon_device *dev, int vol);
+static int typhoon_setfreq_generic(struct typhoon_device *dev,
+ unsigned long frequency);
+static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
+static void typhoon_mute(struct typhoon_device *dev);
+static void typhoon_unmute(struct typhoon_device *dev);
+static int typhoon_setvol(struct typhoon_device *dev, int vol);
+static int typhoon_ioctl(struct video_device *dev, unsigned int cmd, void *arg);
+static int typhoon_open(struct video_device *dev, int flags);
+static void typhoon_close(struct video_device *dev);
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+static int typhoon_read_proc(char *buf, char **start, off_t offset, int len,
+ int unused);
+#endif
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
+int typhoon_init(struct video_init *v);
+#else
+int typhoon_init(struct video_init *v) __init;
+#endif
+
+static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
+{
+ vol >>= 14; /* Map 16 bit to 2 bit */
+ vol &= 3;
+ outb_p(vol / 2, dev->iobase); /* Set the volume, high bit. */
+ outb_p(vol % 2, dev->iobase + 2); /* Set the volume, low bit. */
+}
+
+static int typhoon_setfreq_generic(struct typhoon_device *dev,
+ unsigned long frequency)
+{
+ unsigned long outval;
+ unsigned long x;
+
+ /*
+ * The frequency transfer curve is not linear. The best fit I could
+ * get is
+ *
+ * outval = -155 + exp((f + 15.55) * 0.057))
+ *
+ * where frequency f is in MHz. Since we don't have exp in the kernel,
+ * I approximate this function by a third order polynomial.
+ *
+ */
+
+ x = frequency / 160;
+ outval = (x * x + 2500) / 5000;
+ outval = (outval * x + 5000) / 10000;
+ outval -= (10 * x * x + 10433) / 20866;
+ outval += 4 * x - 11505;
+
+ outb_p((outval >> 8) & 0x01, dev->iobase + 4);
+ outb_p(outval >> 9, dev->iobase + 6);
+ outb_p(outval & 0xff, dev->iobase + 8);
+
+ return 0;
+}
+
+static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency)
+{
+ typhoon_setfreq_generic(dev, frequency);
+ dev->curfreq = frequency;
+ return 0;
+}
+
+static void typhoon_mute(struct typhoon_device *dev)
+{
+ if (dev->muted == 1)
+ return;
+ typhoon_setvol_generic(dev, 0);
+ typhoon_setfreq_generic(dev, dev->mutefreq);
+ dev->muted = 1;
+}
+
+static void typhoon_unmute(struct typhoon_device *dev)
+{
+ if (dev->muted == 0)
+ return;
+ typhoon_setfreq_generic(dev, dev->curfreq);
+ typhoon_setvol_generic(dev, dev->curvol);
+ dev->muted = 0;
+}
+
+static int typhoon_setvol(struct typhoon_device *dev, int vol)
+{
+ if (dev->muted && vol != 0) { /* user is unmuting the card */
+ dev->curvol = vol;
+ typhoon_unmute(dev);
+ return 0;
+ }
+ if (vol == dev->curvol) /* requested volume == current */
+ return 0;
+
+ if (vol == 0) { /* volume == 0 means mute the card */
+ typhoon_mute(dev);
+ dev->curvol = vol;
+ return 0;
+ }
+ typhoon_setvol_generic(dev, vol);
+ dev->curvol = vol;
+ return 0;
+}
+
+
+static int typhoon_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+ struct typhoon_device *typhoon = dev->priv;
+
+ switch (cmd) {
+ case VIDIOCGCAP:
+ {
+ struct video_capability v;
+ v.type = VID_TYPE_TUNER;
+ v.channels = 1;
+ v.audios = 1;
+ /* No we don't do pictures */
+ v.maxwidth = 0;
+ v.maxheight = 0;
+ v.minwidth = 0;
+ v.minheight = 0;
+ strcpy(v.name, "Typhoon Radio");
+ if (copy_to_user(arg, &v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCGTUNER:
+ {
+ struct video_tuner v;
+ if (copy_from_user(&v, arg, sizeof(v)) != 0)
+ return -EFAULT;
+ if (v.tuner) /* Only 1 tuner */
+ return -EINVAL;
+ v.rangelow = 875 * 1600;
+ v.rangehigh = 1080 * 1600;
+ v.flags = VIDEO_TUNER_LOW;
+ v.mode = VIDEO_MODE_AUTO;
+ v.signal = 0; /* We can't get the signal strength */
+ if (copy_to_user(arg, &v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSTUNER:
+ {
+ struct video_tuner v;
+ if (copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if (v.tuner != 0)
+ return -EINVAL;
+ /* Only 1 tuner so no setting needed ! */
+ return 0;
+ }
+ case VIDIOCGFREQ:
+ if (copy_to_user(arg, &typhoon->curfreq,
+ sizeof(typhoon->curfreq)))
+ return -EFAULT;
+ return 0;
+ case VIDIOCSFREQ:
+ if (copy_from_user(&typhoon->curfreq, arg,
+ sizeof(typhoon->curfreq)))
+ return -EFAULT;
+ typhoon_setfreq(typhoon, typhoon->curfreq);
+ return 0;
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio v;
+ memset(&v, 0, sizeof(v));
+ v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
+ v.mode |= VIDEO_SOUND_MONO;
+ v.volume = typhoon->curvol;
+ v.step = 1 << 14;
+ strcpy(v.name, "Typhoon Radio");
+ if (copy_to_user(arg, &v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio v;
+ if (copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if (v.audio)
+ return -EINVAL;
+
+ if (v.flags & VIDEO_AUDIO_MUTE)
+ typhoon_mute(typhoon);
+ else
+ typhoon_unmute(typhoon);
+
+ if (v.flags & VIDEO_AUDIO_VOLUME)
+ typhoon_setvol(typhoon, v.volume);
+
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static int typhoon_open(struct video_device *dev, int flags)
+{
+ struct typhoon_device *typhoon = dev->priv;
+ if (typhoon->users)
+ return -EBUSY;
+ typhoon->users++;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static void typhoon_close(struct video_device *dev)
+{
+ struct typhoon_device *typhoon = dev->priv;
+ typhoon->users--;
+ MOD_DEC_USE_COUNT;
+}
+
+static struct typhoon_device typhoon_unit =
+{
+ 0, /* users */
+ CONFIG_RADIO_TYPHOON_PORT, /* iobase */
+ 0, /* curvol */
+ 0, /* muted */
+ CONFIG_RADIO_TYPHOON_MUTEFREQ, /* curfreq */
+ CONFIG_RADIO_TYPHOON_MUTEFREQ /* mutefreq */
+};
+
+static struct video_device typhoon_radio =
+{
+ "Typhoon Radio",
+ VID_TYPE_TUNER,
+ VID_HARDWARE_TYPHOON,
+ typhoon_open,
+ typhoon_close,
+ NULL, /* Can't read (no capture ability) */
+ NULL, /* Can't write */
+ NULL, /* Can't poll */
+ typhoon_ioctl,
+ NULL,
+ NULL
+};
+
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+
+static int typhoon_read_proc(char *buf, char **start, off_t offset, int len,
+ int unused)
+{
+ #ifdef MODULE
+ #define MODULEPROCSTRING "Driver loaded as a module"
+ #else
+ #define MODULEPROCSTRING "Driver compiled into kernel"
+ #endif
+
+ #define LIMIT (PAGE_SIZE - 80)
+
+ len = 0;
+ len += sprintf(buf + len, BANNER);
+ if (len > LIMIT) return len;
+ len += sprintf(buf + len, "Load type: " MODULEPROCSTRING "\n\n");
+ if (len > LIMIT) return len;
+ len += sprintf(buf + len, "frequency = %lu kHz\n",
+ typhoon_unit.curfreq >> 4);
+ if (len > LIMIT) return len;
+ len += sprintf(buf + len, "volume = %d\n", typhoon_unit.curvol);
+ if (len > LIMIT) return len;
+ len += sprintf(buf + len, "mute = %s\n", typhoon_unit.muted ?
+ "on" : "off");
+ if (len > LIMIT) return len;
+ len += sprintf(buf + len, "iobase = 0x%x\n", typhoon_unit.iobase);
+ if (len > LIMIT) return len;
+ len += sprintf(buf + len, "mute frequency = %lu kHz\n",
+ typhoon_unit.mutefreq >> 4);
+ return len;
+}
+
+static struct proc_dir_entry typhoon_proc_entry = {
+ 0, /* low_ino: inode is dynamic */
+ 13, "radio-typhoon", /* length of name and name */
+ S_IFREG | S_IRUGO, /* mode */
+ 1, 0, 0, /* nlinks, owner, group */
+ 0, /* size -- not used */
+ NULL, /* operations -- use default */
+ &typhoon_read_proc, /* function used to read data */
+ /* nothing more */
+};
+
+#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
+
+int typhoon_init(struct video_init *v)
+{
+ printk(KERN_INFO BANNER);
+ if (check_region(typhoon_unit.iobase, 8)) {
+ printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n",
+ typhoon_unit.iobase);
+ return -EBUSY;
+ }
+
+ typhoon_radio.priv = &typhoon_unit;
+ if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1)
+ return -EINVAL;
+
+ request_region(typhoon_unit.iobase, 8, "typhoon");
+ printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase);
+ printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n",
+ typhoon_unit.mutefreq);
+ typhoon_unit.mutefreq <<= 4;
+
+ /* mute card - prevents noisy bootups */
+ typhoon_mute(&typhoon_unit);
+
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+
+ if (proc_register(&proc_root, &typhoon_proc_entry))
+ printk(KERN_ERR "radio-typhoon: registering /proc/radio-typhoon failed\n");
+
+#endif
+
+ return 0;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dr. Henrik Seidel");
+MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
+MODULE_PARM(mutefreq, "i");
+MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
+
+EXPORT_NO_SYMBOLS;
+
+static int io = -1;
+static unsigned long mutefreq = 0;
+
+int init_module(void)
+{
+ if (io == -1) {
+ printk(KERN_ERR "radio-typhoon: You must set an I/O address with io=0x316 or io=0x336\n");
+ return -EINVAL;
+ }
+ typhoon_unit.iobase = io;
+
+ if (mutefreq < 87000 || mutefreq > 108500) {
+ printk(KERN_ERR "radio-typhoon: You must set a frequency (in kHz) used when muting the card,\n");
+ printk(KERN_ERR "radio-typhoon: e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");
+ return -EINVAL;
+ }
+ typhoon_unit.mutefreq = mutefreq;
+
+ return typhoon_init(NULL);
+}
+
+void cleanup_module(void)
+{
+
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+
+ if (proc_unregister(&proc_root, typhoon_proc_entry.low_ino))
+ printk(KERN_ERR "radio-typhoon: unregistering /proc/radio-typhoon failed\n");
+
+#endif
+
+ video_unregister_device(&typhoon_radio);
+ release_region(io, 8);
+}
+
+#endif
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/radio-zoltrix.c linux.ac/drivers/char/radio-zoltrix.c
--- linux.vanilla/drivers/char/radio-zoltrix.c Sat Jan 9 21:50:38 1999
+++ linux.ac/drivers/char/radio-zoltrix.c Fri Feb 19 10:50:13 1999
@@ -11,7 +11,8 @@
* at a low frequency, and it is not possible (at least I have not found)
* to get fine volume control over the low volume range.
*
- * Some code derived from code by Frans Brinkman
+ * Some code derived from code by Romolo Manfredini
+ * romolo@bicnet.it
*
* 1999-01-05 - (C. van Schaik)
* - Changed tuning to 1/160Mhz accuracy
@@ -285,10 +286,10 @@
if (v.flags & VIDEO_AUDIO_MUTE)
zol_mute(zol);
else
+ {
zol_unmute(zol);
-
- if (v.flags & VIDEO_AUDIO_VOLUME)
zol_setvol(zol, v.volume / 4096);
+ }
if (v.mode & VIDEO_SOUND_STEREO)
{
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/videodev.c linux.ac/drivers/char/videodev.c
--- linux.vanilla/drivers/char/videodev.c Sun Jan 24 19:55:34 1999
+++ linux.ac/drivers/char/videodev.c Tue Feb 16 17:27:11 1999
@@ -72,6 +72,9 @@
#ifdef CONFIG_RADIO_GEMTEK
extern int gemtek_init(struct video_init *);
#endif
+#ifdef CONFIG_RADIO_TYPHOON
+extern int typhoon_init(struct video_init *);
+#endif
#ifdef CONFIG_VIDEO_PMS
extern int init_pms_cards(struct video_init *);
#endif
@@ -101,7 +104,7 @@
#endif
#ifdef CONFIG_RADIO_RTRACK
{"RTrack", rtrack_init},
-#endif
+#endif
#ifdef CONFIG_RADIO_SF16FMI
{"SF16FMI", fmi_init},
#endif
@@ -110,6 +113,9 @@
#endif
#ifdef CONFIG_RADIO_GEMTEK
{"GemTek", gemtek_init},
+#endif
+#ifdef CONFIG_RADIO_TYPHOON
+ {"radio-typhoon", typhoon_init},
#endif
{"end", NULL}
};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/3c509.c linux.ac/drivers/net/3c509.c
--- linux.vanilla/drivers/net/3c509.c Tue Dec 22 23:19:40 1998
+++ linux.ac/drivers/net/3c509.c Sat Feb 27 02:10:16 1999
@@ -1,8 +1,8 @@
/* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
/*
- Written 1993-1997 by Donald Becker.
+ Written 1993-1998 by Donald Becker.
- Copyright 1994-1997 by Donald Becker.
+ Copyright 1994-1998 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
distributed according to the terms of the GNU Public License,
@@ -35,19 +35,24 @@
other cleanups. -djb
Andrea Arcangeli: Upgraded to Donald Becker's version 1.12.
Rick Payne: Fixed SMP race condition
+ v1.13 9/8/97 Made 'max_interrupt_work' an insmod-settable variable -djb
+ v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
+ v1.15 1/31/98 Faster recovery for Tx errors. -djb
+ v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
*/
-static char *version = "3c509.c:1.12 6/4/97 becker@cesdis.gsfc.nasa.gov\n";
+static char *version = "3c509.c:1.16 (2.2) 2/3/98 becker@cesdis.gsfc.nasa.gov.\n";
/* A few values that may be tweaked. */
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT (400*HZ/1000)
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-#define INTR_WORK 10
+static int max_interrupt_work = 10;
+#include
#include
-#include /* for CONFIG_MCA */
+#include
#include
#include
#include
@@ -129,12 +134,13 @@
/* skb send-queue */
int head, size;
struct sk_buff *queue[SKB_QUEUE_SIZE];
+ char mca_slot;
};
-static int id_port = 0x100;
+static int id_port = 0x110; /* Start with 0x110 to avoid new sound cards.*/
static struct device *el3_root_dev = NULL;
static ushort id_read_eeprom(int index);
-static ushort read_eeprom(short ioaddr, int index);
+static ushort read_eeprom(int ioaddr, int index);
static int el3_open(struct device *dev);
static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -144,13 +150,27 @@
static int el3_close(struct device *dev);
static void set_multicast_list(struct device *dev);
-
+#ifdef CONFIG_MCA
+struct el3_mca_adapters_struct {
+ char* name;
+ int id;
+};
+
+struct el3_mca_adapters_struct el3_mca_adapters[] = {
+ { "3Com 3c529 EtherLink III (10base2)", 0x627c },
+ { "3Com 3c529 EtherLink III (10baseT)", 0x627d },
+ { "3Com 3c529 EtherLink III (test mode)", 0x62db },
+ { "3Com 3c529 EtherLink III (TP or coax)", 0x62f6 },
+ { "3Com 3c529 EtherLink III (TP)", 0x62f7 },
+ { NULL, 0 },
+};
+#endif
int el3_probe(struct device *dev)
{
short lrs_state = 0xff, i;
- ushort ioaddr, irq, if_port;
- short phys_addr[3];
+ int ioaddr, irq, if_port;
+ u16 phys_addr[3];
static int current_tag = 0;
/* First check all slots of the EISA bus. The next slot address to
@@ -182,69 +202,70 @@
}
#ifdef CONFIG_MCA
-#define MCA_NUMBER_OF_SLOTS 8
-#define MCA_PORT_POS_SEL 0x096
-#define MCA_PORT_ID_REG_0 0x100
-#define MCA_PORT_ID_REG_1 0x101
-#define MCA_SELECT_BIT 0x08
- if (MCA_bus)
- {
- u_int mca_id;
- u_char posreg[4];
- int mca_slot;
-
- if (el3_debug > 2)
- printk("3c529: probing...\n");
- /* This should probably be done once early on and read into
- * a structure somewhere... */
- for (mca_slot = 0; mca_slot < MCA_NUMBER_OF_SLOTS; mca_slot++)
- {
- /* Select MCA slot i */
- outb_p(mca_slot | MCA_SELECT_BIT, MCA_PORT_POS_SEL);
- mca_id = ((inb_p(MCA_PORT_ID_REG_1)<<8)
- + inb_p(MCA_PORT_ID_REG_0));
- if (mca_id == 0x627C /* 10base2 */
- || mca_id == 0x627D /* 10baseT */
- || mca_id == 0x62DB /* Test mode */
- || mca_id == 0x62F6 /* TP or coax */
- || mca_id == 0x62F7) /* TP only */
- {
- if (el3_debug > 1)
- printk("3c529: Found with id 0x%x at slot %d\n",
- mca_id, mca_slot);
- posreg[0] = inb_p(0x102); posreg[1] = inb_p(0x103);
- posreg[2] = inb_p(0x104); posreg[3] = inb_p(0x105);
- break;
+ /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, heavily
+ * modified by Chris Beauregard (cpbeaure@csclub.uwaterloo.ca)
+ * to support standard MCA probing.
+ *
+ * redone for multi-card detection by ZP Gu (zpg@castle.net)
+ * now works as a module
+ */
+
+ if( MCA_bus ) {
+ int slot, j;
+ u_char pos4, pos5;
+
+ for( j = 0; el3_mca_adapters[j].name != NULL; j ++ ) {
+ slot = 0;
+ while( slot != MCA_NOTFOUND ) {
+ slot = mca_find_unused_adapter(
+ el3_mca_adapters[j].id, slot );
+ if( slot == MCA_NOTFOUND ) break;
+
+ /* if we get this far, an adapter has been
+ * detected and is enabled
+ */
+
+ printk("3c509: found %s at slot %d\n",
+ el3_mca_adapters[j].name, slot + 1 );
+
+ pos4 = mca_read_stored_pos( slot, 4 );
+ pos5 = mca_read_stored_pos( slot, 5 );
+
+ ioaddr = ((short)((pos4&0xfc)|0x02)) << 8;
+ irq = pos5 & 0x0f;
+
+ /* probing for a card at a particular IO/IRQ */
+ if(dev && ((dev->irq && dev->irq != irq) ||
+ (dev->base_addr && dev->base_addr != ioaddr))) {
+ slot++; /* probing next slot */
+ continue;
+ }
+
+ /* claim the slot */
+ mca_set_adapter_name(slot, el3_mca_adapters[j].name);
+ mca_mark_as_used(slot);
+
+ if_port = pos4 & 0x03;
+ if (el3_debug > 2) {
+ printk("3c529: irq %d ioaddr 0x%x ifport %d\n", irq, ioaddr, if_port);
+ }
+ for (i = 0; i < 3; i++) {
+ phys_addr[i] = htons(read_eeprom(ioaddr, i));
+ }
+ ((struct el3_private *)dev->priv)->mca_slot = slot;
+
+ goto found;
}
- mca_id = 0xFFFF;
- }
- /* Read values from POS registers so now disable */
- outb(0,MCA_PORT_POS_SEL);
- if (mca_id != 0xFFFF && !(posreg[0]&0x01))
- printk("3c529: Adapter found but disabled in slot %d\n", mca_slot);
- else if (mca_id != 0xFFFF && posreg[0]&0x01)
- {
- /* Found and adapter is enabled */
- if (el3_debug > 2)
- printk("3c529: pos registers 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
- posreg[0], posreg[1], posreg[2], posreg[3]);
- ioaddr = ((short)((posreg[2]&0xfc)|0x02)) << 8;
- irq = posreg[3] & 0x0f;
- if_port = posreg[2] & 0x03;
- if (el3_debug > 2)
- printk("3c529: irq %d ioaddr 0x%x ifport %d\n",
- irq, ioaddr, if_port);
- for (i = 0; i < 3; i++)
- phys_addr[i] = htons(read_eeprom(ioaddr, i));
- goto found;
}
+ /* if we get here, we didn't find an MCA adapter */
+ return -ENODEV;
}
#endif
/* Reset the ISA PnP mechanism on 3c509b. */
outb(0x02, 0x279); /* Select PnP config control register. */
outb(0x02, 0xA79); /* Return to WaitForKey state. */
/* Select an open I/O location at 0x1*0 to do contention select. */
- for (id_port = 0x100; id_port < 0x200; id_port += 0x10) {
+ for ( ; id_port < 0x200; id_port += 0x10) {
if (check_region(id_port, 1))
continue;
outb(0x00, id_port);
@@ -288,18 +309,23 @@
}
{
- unsigned short iobase = id_read_eeprom(8);
+ unsigned int iobase = id_read_eeprom(8);
if_port = iobase >> 14;
ioaddr = 0x200 + ((iobase & 0x1f) << 4);
}
- if (dev && dev->irq > 1 && dev->irq < 16)
- irq = dev->irq;
- else
- irq = id_read_eeprom(9) >> 12;
+ irq = id_read_eeprom(9) >> 12;
- if (dev && dev->base_addr != 0
- && dev->base_addr != (unsigned short)ioaddr) {
- return -ENODEV;
+ if (dev) { /* Set passed-in IRQ or I/O Addr. */
+ if (dev->irq > 1 && dev->irq < 16)
+ irq = dev->irq;
+
+ if (dev->base_addr) {
+ if (dev->mem_end == 0x3c509 /* Magic key */
+ && dev->base_addr >= 0x200 && dev->base_addr <= 0x3e0)
+ ioaddr = dev->base_addr & 0x3f0;
+ else if (dev->base_addr != ioaddr)
+ return -ENODEV;
+ }
}
/* Set the adaptor tag so that the next card can be found. */
@@ -364,7 +390,7 @@
/* Read a word from the EEPROM using the regular EEPROM access register.
Assume that we are in register window zero.
*/
-static ushort read_eeprom(short ioaddr, int index)
+static ushort read_eeprom(int ioaddr, int index)
{
outw(EEPROM_READ + index, ioaddr + 10);
/* Pause for at least 162 us. for the read to take place. */
@@ -394,7 +420,6 @@
}
-
static int
el3_open(struct device *dev)
{
@@ -464,7 +489,7 @@
/* Ack all pending events, and set active indicator mask. */
outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
ioaddr + EL3_CMD);
- outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull,
+ outw(SetIntrEnb | IntLatch|TxAvailable|TxComplete|RxComplete|StatsFull,
ioaddr + EL3_CMD);
if (el3_debug > 3)
@@ -589,7 +614,7 @@
struct device *dev = (struct device *)dev_id;
struct el3_private *lp;
int ioaddr, status;
- int i = INTR_WORK;
+ int i = max_interrupt_work;
if (dev == NULL) {
printk ("el3_interrupt(): irq %d for unknown device.\n", irq);
@@ -624,7 +649,7 @@
dev->tbusy = 0;
mark_bh(NET_BH);
}
- if (status & (AdapterFailure | RxEarly | StatsFull)) {
+ if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) {
/* Handle all uncommon interrupts. */
if (status & StatsFull) /* Empty statistics. */
update_stats(dev);
@@ -632,6 +657,18 @@
el3_rx(dev);
outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
}
+ if (status & TxComplete) { /* Really Tx error. */
+ struct el3_private *lp = (struct el3_private *)dev->priv;
+ short tx_status;
+ int i = 4;
+
+ while (--i>0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
+ if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
+ if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
+ if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
+ outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
+ }
+ }
if (status & AdapterFailure) {
/* Adapter failure requires Rx reset and reinit. */
outw(RxReset, ioaddr + EL3_CMD);
@@ -730,6 +767,8 @@
while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
if (rx_status & 0x4000) { /* Error, update stats. */
short error = rx_status & 0x3800;
+
+ outw(RxDiscard, ioaddr + EL3_CMD);
lp->stats.rx_errors++;
switch (error) {
case 0x0000: lp->stats.rx_over_errors++; break;
@@ -761,19 +800,21 @@
(pkt_len + 3) >> 2);
#endif
+ outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
- outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
lp->stats.rx_packets++;
continue;
- } else if (el3_debug)
+ }
+ outw(RxDiscard, ioaddr + EL3_CMD);
+ lp->stats.rx_dropped++;
+ if (el3_debug)
printk("%s: Couldn't allocate a sk_buff of size %d.\n",
dev->name, pkt_len);
}
- lp->stats.rx_dropped++;
- outw(RxDiscard, ioaddr + EL3_CMD);
+ inw(ioaddr + EL3_STATUS); /* Delay. */
while (inw(ioaddr + EL3_STATUS) & 0x1000)
- printk(" Waiting for 3c509 to discard packet, status %x.\n",
+ printk(KERN_DEBUG " Waiting for 3c509 to discard packet, status %x.\n",
inw(ioaddr + EL3_STATUS) );
}
@@ -786,7 +827,7 @@
static void
set_multicast_list(struct device *dev)
{
- short ioaddr = dev->base_addr;
+ int ioaddr = dev->base_addr;
if (el3_debug > 1) {
static int old = 0;
if (old != dev->mc_count) {
@@ -844,7 +885,7 @@
}
#ifdef MODULE
-/* Parameter that may be passed into the module. */
+/* Parameters that may be passed into the module. */
static int debug = -1;
static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1};
@@ -880,7 +921,9 @@
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (el3_root_dev) {
- next_dev = ((struct el3_private *)el3_root_dev->priv)->next_dev;
+ struct el3_private *lp = (struct el3_private *)el3_root_dev->priv;
+ mca_mark_as_unused(lp->mca_slot);
+ next_dev = lp->next_dev;
unregister_netdev(el3_root_dev);
release_region(el3_root_dev->base_addr, EL3_IO_EXTENT);
kfree(el3_root_dev);
@@ -888,7 +931,7 @@
}
}
#endif /* MODULE */
-
+
/*
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c509.c"
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/8390.c linux.ac/drivers/net/8390.c
--- linux.vanilla/drivers/net/8390.c Sat Jan 9 21:50:40 1999
+++ linux.ac/drivers/net/8390.c Thu Feb 18 20:30:14 1999
@@ -165,8 +165,10 @@
spin_lock_irqsave(&ei_local->page_lock, flags);
NS8390_init(dev, 1);
- spin_unlock_irqrestore(&ei_local->page_lock, flags);
+ /* Set the flag before we drop the lock, That way the IRQ arrives
+ after its set and we get no silly warnings */
dev->start = 1;
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
ei_local->irqlock = 0;
return 0;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/Config.in linux.ac/drivers/net/Config.in
--- linux.vanilla/drivers/net/Config.in Sun Jan 24 19:55:35 1999
+++ linux.ac/drivers/net/Config.in Fri Feb 26 14:20:14 1999
@@ -2,6 +2,9 @@
# Network device configuration
#
+mainmenu_option next_comment
+comment 'ARCnet devices'
+
tristate 'ARCnet support' CONFIG_ARCNET
if [ "$CONFIG_ARCNET" != "n" ]; then
bool ' Enable arc0e (ARCnet "Ether-Encap" packet format)' CONFIG_ARCNET_ETH
@@ -12,6 +15,8 @@
dep_tristate ' ARCnet COM20020 chipset driver' CONFIG_ARCNET_COM20020 $CONFIG_ARCNET
fi
+endmenu
+
tristate 'Dummy net driver support' CONFIG_DUMMY
tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -22,6 +27,10 @@
#
# Ethernet
#
+
+mainmenu_option next_comment
+comment 'Ethernet (10 or 100Mbit)'
+
bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
if [ "$CONFIG_ARM" = "y" ]; then
@@ -53,6 +62,7 @@
tristate '3c507 support' CONFIG_EL16
if [ "$CONFIG_MCA" = "y" ]; then
tristate '3c523 support' CONFIG_ELMC
+ #tristate '3c527 support' CONFIG_ELMC_II
fi
fi
tristate '3c509/3c579 support' CONFIG_EL3
@@ -81,18 +91,15 @@
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN
- tristate 'Alteon AceNIC & 3Com 3C985 Gigabit support' CONFIG_ACENIC
fi
bool 'Other ISA cards' CONFIG_NET_ISA
if [ "$CONFIG_NET_ISA" = "y" ]; then
- tristate 'AT1700/1720 support' CONFIG_AT1700
+ tristate 'AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700
tristate 'Cabletron E21xx support' CONFIG_E2100
tristate 'DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA
tristate 'EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
tristate 'EtherExpress 16 support' CONFIG_EEXPRESS
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
- fi
+ tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
tristate 'FMV-181/182/183/184 support' CONFIG_FMV18X
tristate 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS
tristate 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN
@@ -113,6 +120,7 @@
if [ "$CONFIG_NET_EISA" = "y" ]; then
tristate 'AMD PCnet32 (VLB and PCI) support' CONFIG_PCNET32
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Alteon AceNIC & 3Com 3C985 Gigabit support' CONFIG_ACENIC
tristate 'Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200
fi
@@ -143,6 +151,8 @@
fi
fi
+endmenu
+
bool 'FDDI driver support' CONFIG_FDDI
if [ "$CONFIG_FDDI" = "y" ]; then
bool 'Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX
@@ -151,7 +161,6 @@
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool 'HIPPI driver support (EXPERIMENTAL)' CONFIG_HIPPI
if [ "$CONFIG_HIPPI" = "y" ]; then
- bool 'CERN HIPPI PCI adapter support' CONFIG_CERN_HIPPI
bool 'Essential RoadRunner HIPPI PCI adapter support' CONFIG_ROADRUNNER
if [ "$CONFIG_ROADRUNNER" != "n" ]; then
bool ' Use large TX/RX rings' CONFIG_ROADRUNNER_LARGE_RINGS
@@ -159,17 +168,13 @@
fi
fi
-tristate 'Frame relay DLCI support' CONFIG_DLCI
-if [ "$CONFIG_DLCI" = "y" -o "$CONFIG_DLCI" = "m" ]; then
- int ' Max open DLCI' CONFIG_DLCI_COUNT 24
- int ' Max DLCI per device' CONFIG_DLCI_MAX 8
- dep_tristate ' SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI
-fi
-
#
# AppleTalk
#
+
if [ "$CONFIG_ATALK" != "n" ]; then
+ mainmenu_option next_comment
+ comment 'Appletalk devices'
dep_tristate 'Apple/Farallon LocalTalk PC support' CONFIG_LTPC $CONFIG_ATALK
dep_tristate 'COPS LocalTalk PC support' CONFIG_COPS $CONFIG_ATALK
if [ "$CONFIG_COPS" != "n" ]; then
@@ -181,6 +186,7 @@
bool 'IP to Appletalk-IP Encapsulation support' CONFIG_IPDDP_ENCAP
bool 'Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP
fi
+ endmenu
fi
if [ ! "$CONFIG_PARPORT" = "n" ]; then
@@ -201,10 +207,13 @@
bool 'Wireless LAN (non-hamradio)' CONFIG_NET_RADIO
if [ "$CONFIG_NET_RADIO" = "y" ]; then
- tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP
+ dep_tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP $CONFIG_INET
tristate 'AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN
fi
+mainmenu_option next_comment
+comment 'Token ring devices'
+
bool 'Token Ring driver support' CONFIG_TR
if [ "$CONFIG_TR" = "y" ]; then
tristate 'IBM Tropic chipset based adaptor support' CONFIG_IBMTR
@@ -212,12 +221,21 @@
tristate 'SysKonnect adapter support' CONFIG_SKTR
fi
+endmenu
+
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI
tristate 'Traffic Shaper (EXPERIMENTAL)' CONFIG_SHAPER
fi
+
#
# WAN drivers support
#
+
+mainmenu_option next_comment
+comment 'Wan interfaces'
+
+
# There is no way to detect a comtrol sv11 - force it modular for now.
#
dep_tristate 'Comtrol Hostess SV-11 support' CONFIG_HOSTESS_SV11 m
@@ -225,8 +243,22 @@
# The COSA/SRP driver has not been tested as non-modular yet.
#
dep_tristate 'COSA/SRP sync serial boards support' CONFIG_COSA m
-tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI
#
+# There is no way to detect a Sealevel board. Force it modular
+#
+dep_tristate 'Sealevel Systems 4021 support' CONFIG_SEALEVEL_4021 m
+
+tristate 'Frame relay DLCI support' CONFIG_DLCI
+if [ "$CONFIG_DLCI" != "n" ]; then
+ int ' Max open DLCI' CONFIG_DLCI_COUNT 24
+ int ' Max DLCI per device' CONFIG_DLCI_MAX 8
+ dep_tristate ' SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI
+fi
+
+#
+# Wan router core.
+#
+
if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
bool 'WAN drivers' CONFIG_WAN_DRIVERS
if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then
@@ -239,11 +271,14 @@
fi
fi
fi
+
+endmenu
+
#
# X.25 network drivers
#
if [ "$CONFIG_X25" != "n" ]; then
-if [ "$CONFIG_LAPB" != "n" ]; then
+if [ "$CONFIG_LAPB" = "y" -o "$CONFIG_LAPB" = "m" ]; then
dep_tristate 'LAPB over Ethernet driver' CONFIG_LAPBETHER $CONFIG_LAPB
dep_tristate 'X.25 async driver' CONFIG_X25_ASY $CONFIG_LAPB
fi
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/Makefile linux.ac/drivers/net/Makefile
--- linux.vanilla/drivers/net/Makefile Tue Jan 19 02:57:28 1999
+++ linux.ac/drivers/net/Makefile Thu Feb 18 17:35:52 1999
@@ -143,14 +143,6 @@
endif
endif
-ifeq ($(CONFIG_ETHERH),y)
-CONFIG_8390_BUILTIN = y
-else
- ifeq ($(CONFIG_ETHERH),m)
- CONFIG_8390_MODULE = y
- endif
-endif
-
ifeq ($(CONFIG_WD80x3),y)
L_OBJS += wd.o
CONFIG_8390_BUILTIN = y
@@ -171,14 +163,6 @@
endif
endif
-ifeq ($(CONFIG_ETHERH),y)
-CONFIG_8390_BUILTIN = y
-else
- ifeq ($(CONFIG_ETHERH),m)
- CONFIG_8390_MODULE = y
- endif
-endif
-
ifeq ($(CONFIG_NE2K_PCI),y)
L_OBJS += ne2k-pci.o
CONFIG_8390_BUILTIN = y
@@ -430,6 +414,14 @@
endif
endif
+ifeq ($(CONFIG_SUNBMAC),y)
+L_OBJS += sunbmac.o
+else
+ ifeq ($(CONFIG_SUNBMAC),m)
+ M_OBJS += sunbmac.o
+ endif
+endif
+
ifeq ($(CONFIG_MYRI_SBUS),y)
L_OBJS += myri_sbus.o
else
@@ -478,6 +470,14 @@
endif
endif
+ifeq ($(CONFIG_ELMC_II),y)
+L_OBJS += 3c527.o
+else
+ ifeq ($(CONFIG_ELMC_II),m)
+ M_OBJS += 3c527.o
+ endif
+endif
+
ifeq ($(CONFIG_EL3),y)
L_OBJS += 3c509.o
else
@@ -756,6 +756,19 @@
endif
endif
+ifeq ($(CONFIG_SEALEVEL_4021),y)
+L_OBJS += sealevel.o
+CONFIG_85230_BUILTIN = y
+CONFIG_SYNCPPP_BUILTIN = y
+else
+ ifeq ($(CONFIG_SEALEVEL_4021),m)
+ CONFIG_85230_MODULE = y
+ CONFIG_SYNCPPP_MODULE = y
+ M_OBJS += sealevel.o
+ endif
+endif
+
+
ifeq ($(CONFIG_COSA),y)
L_OBJS += cosa.o
CONFIG_SYNCPPP_BUILTIN = y
@@ -1046,6 +1059,7 @@
ifeq ($(CONFIG_IRDA),y)
SUB_DIRS += irda
+MOD_IN_SUB_DIRS += irda
else
ifeq ($(CONFIG_IRDA),m)
MOD_SUB_DIRS += irda
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/cosa.c linux.ac/drivers/net/cosa.c
--- linux.vanilla/drivers/net/cosa.c Mon Dec 28 23:09:42 1998
+++ linux.ac/drivers/net/cosa.c Tue Feb 16 17:29:53 1999
@@ -1,4 +1,4 @@
-/* $Id: cosa.c,v 1.11 1998/12/24 23:44:23 kas Exp $ */
+/* $Id: cosa.c,v 1.21 1999/02/06 19:49:18 kas Exp $ */
/*
* Copyright (C) 1995-1997 Jan "Yenya" Kasprzak
@@ -27,7 +27,7 @@
* Masaryk University (http://www.ics.muni.cz/). The hardware is
* developed by Jiri Novotny . More information
* and the photo of both cards is available at
- * http://www.kozakmartin.cz/cosa.html. The card documentation, firmwares
+ * http://www.pavoucek.cz/cosa.html. The card documentation, firmwares
* and other goods can be downloaded from ftp://ftp.ics.muni.cz/pub/cosa/.
* For Linux-specific utilities, see below in the "Software info" section.
* If you want to order the card, contact Jiri Novotny.
@@ -141,11 +141,13 @@
unsigned int datareg, statusreg; /* I/O ports */
unsigned short irq, dma; /* IRQ and DMA number */
unsigned short startaddr; /* Firmware start address */
+ unsigned short busmaster; /* Use busmastering? */
int nchannels; /* # of channels on this card */
int driver_status; /* For communicating with firware */
int firmware_status; /* Downloaded, reseted, etc. */
int rxbitmap, txbitmap; /* Bitmap of channels who are willing to send/receive data */
int rxtx; /* RX or TX in progress? */
+ int enabled;
int usage; /* usage count */
int txchan, txsize, rxsize;
struct channel_data *rxchan;
@@ -331,9 +333,8 @@
static int get_wait_data(struct cosa_data *cosa);
static int put_wait_data(struct cosa_data *cosa, int data);
static int puthexnumber(struct cosa_data *cosa, int number);
-static void put_driver_status_common(struct cosa_data *cosa, int nolock);
-#define put_driver_status(x) put_driver_status_common((x), 0)
-#define put_driver_status_nolock(x) put_driver_status_common((x), 1)
+static void put_driver_status(struct cosa_data *cosa);
+static void put_driver_status_nolock(struct cosa_data *cosa);
/* Interrupt handling */
static void cosa_interrupt(int irq, void *cosa, struct pt_regs *regs);
@@ -357,7 +358,7 @@
#endif
{
int i;
- printk(KERN_INFO "cosa v1.03 (c) 1997-8 Jan Kasprzak \n");
+ printk(KERN_INFO "cosa v1.04 (c) 1997-8 Jan Kasprzak \n");
#ifdef __SMP__
printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
#endif
@@ -630,9 +631,14 @@
if (dev->tbusy) {
if (time_before(jiffies, dev->trans_start+2*HZ))
return 1; /* Two seconds timeout */
+ if (test_bit(RXBIT, &chan->cosa->rxtx)) {
+ chan->stats.rx_errors++;
+ chan->stats.rx_missed_errors++;
+ } else {
+ chan->stats.tx_errors++;
+ chan->stats.tx_aborted_errors++;
+ }
cosa_kick(chan->cosa);
- chan->stats.tx_errors++;
- chan->stats.tx_aborted_errors++;
if (chan->tx_skb) {
dev_kfree_skb(chan->tx_skb);
chan->tx_skb = 0;
@@ -659,6 +665,14 @@
d->tbusy = 1;
cosa_disable_rx(chan);
spin_lock_irqsave(&chan->cosa->lock, flags);
+ if (chan->rx_skb) {
+ kfree_skb(chan->rx_skb);
+ chan->rx_skb = 0;
+ }
+ if (chan->tx_skb) {
+ kfree_skb(chan->tx_skb);
+ chan->tx_skb = 0;
+ }
chan->usage=0;
chan->cosa->usage--;
MOD_DEC_USE_COUNT;
@@ -1128,6 +1142,17 @@
return nr_cards;
case COSAIONRCHANS:
return cosa->nchannels;
+ case COSAIOBMSET:
+ if (!suser())
+ return -EACCES;
+ if (is_8bit(cosa))
+ return -EINVAL;
+ if (arg != COSA_BM_OFF && arg != COSA_BM_ON)
+ return -EINVAL;
+ cosa->busmaster = arg;
+ return 0;
+ case COSAIOBMGET:
+ return cosa->busmaster;
}
return -ENOIOCTLCMD;
}
@@ -1208,37 +1233,67 @@
return 0;
}
-static void put_driver_status_common(struct cosa_data *cosa, int nolock)
+static void put_driver_status(struct cosa_data *cosa)
{
unsigned flags=0;
int status;
- if (!nolock)
- spin_lock_irqsave(&cosa->lock, flags);
+ spin_lock_irqsave(&cosa->lock, flags);
status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
| (cosa->txbitmap ? DRIVER_TX_READY : 0)
| (cosa->txbitmap? ~(cosa->txbitmap<rxtx || nolock) {
-#ifdef DEBUG_IO
- debug_data_cmd(cosa, status);
-#endif
- cosa_putdata8(cosa, status);
+ if (!cosa->rxtx) {
if (cosa->rxbitmap|cosa->txbitmap) {
- cosa_putstatus(cosa, SR_RX_INT_ENA);
+ if (!cosa->enabled) {
+ cosa_putstatus(cosa, SR_RX_INT_ENA);
#ifdef DEBUG_IO
- debug_status_out(cosa, SR_RX_INT_ENA);
+ debug_status_out(cosa, SR_RX_INT_ENA);
#endif
- } else {
+ cosa->enabled = 1;
+ }
+ } else if (cosa->enabled) {
+ cosa->enabled = 0;
cosa_putstatus(cosa, 0);
#ifdef DEBUG_IO
debug_status_out(cosa, 0);
#endif
}
+ cosa_putdata8(cosa, status);
+#ifdef DEBUG_IO
+ debug_data_cmd(cosa, status);
+#endif
}
- if (!nolock)
- spin_unlock_irqrestore(&cosa->lock, flags);
+ spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static void put_driver_status_nolock(struct cosa_data *cosa)
+{
+ int status;
+
+ status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
+ | (cosa->txbitmap ? DRIVER_TX_READY : 0)
+ | (cosa->txbitmap? ~(cosa->txbitmap<rxbitmap|cosa->txbitmap) {
+ cosa_putstatus(cosa, SR_RX_INT_ENA);
+#ifdef DEBUG_IO
+ debug_status_out(cosa, SR_RX_INT_ENA);
+#endif
+ cosa->enabled = 1;
+ } else {
+ cosa_putstatus(cosa, 0);
+#ifdef DEBUG_IO
+ debug_status_out(cosa, 0);
+#endif
+ cosa->enabled = 0;
+ }
+ cosa_putdata8(cosa, status);
+#ifdef DEBUG_IO
+ debug_data_cmd(cosa, status);
+#endif
}
/*
@@ -1249,9 +1304,14 @@
static void cosa_kick(struct cosa_data *cosa)
{
unsigned flags, flags1;
+ char *s = "Unknown";
- printk(KERN_INFO "%s: DMA timeout - restarting.\n", cosa->name);
+ if (test_bit(RXBIT, &cosa->rxtx))
+ s = "RX";
+ if (test_bit(TXBIT, &cosa->rxtx))
+ s = "TX";
+ printk(KERN_INFO "%s: %s DMA timeout - restarting.\n", cosa->name, s);
spin_lock_irqsave(&cosa->lock, flags);
cosa->rxtx = 0;
@@ -1261,6 +1321,13 @@
release_dma_lock(flags1);
/* FIXME: Anything else? */
+ udelay(100);
+ cosa_putstatus(cosa, 0);
+ udelay(100);
+ (void) cosa_getdata8(cosa);
+ udelay(100);
+ cosa_putdata8(cosa, 0);
+ udelay(100);
put_driver_status_nolock(cosa);
spin_unlock_irqrestore(&cosa->lock, flags);
}
@@ -1556,6 +1623,10 @@
* COSA status byte. I have moved the rx/tx/eot interrupt handling into
* separate functions to make it more readable. These functions are inline,
* so there should be no overhead of function call.
+ *
+ * In the COSA bus-master mode, we need to tell the card the address of a
+ * buffer. Unfortunately, COSA may be too slow for us, so we must busy-wait.
+ * It's time to use the bottom half :-(
*/
/*
@@ -1606,13 +1677,13 @@
if (is_8bit(cosa)) {
if (!test_bit(IRQBIT, &cosa->rxtx)) {
+ cosa_putstatus(cosa, SR_TX_INT_ENA);
cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0)|
((cosa->txsize >> 8) & 0x1f));
- cosa_putstatus(cosa, SR_TX_INT_ENA);
#ifdef DEBUG_IO
+ debug_status_out(cosa, SR_TX_INT_ENA);
debug_data_out(cosa, ((cosa->txchan << 5) & 0xe0)|
((cosa->txsize >> 8) & 0x1f));
- debug_status_out(cosa, SR_TX_INT_ENA);
debug_data_in(cosa, cosa_getdata8(cosa));
#else
cosa_getdata8(cosa);
@@ -1630,27 +1701,57 @@
#endif
}
} else {
+ cosa_putstatus(cosa, SR_TX_INT_ENA);
cosa_putdata16(cosa, ((cosa->txchan<<13) & 0xe000)
| (cosa->txsize & 0x1fff));
- cosa_getdata16(cosa);
#ifdef DEBUG_IO
- debug_status_out(cosa, ((cosa->txchan<<13) & 0xe000)
+ debug_status_out(cosa, SR_TX_INT_ENA);
+ debug_data_out(cosa, ((cosa->txchan<<13) & 0xe000)
| (cosa->txsize & 0x1fff));
- debug_data_in(cosa, cosa_getdata16(cosa));
+ debug_data_in(cosa, cosa_getdata8(cosa));
+ debug_status_out(cosa, 0);
#else
- cosa_getdata16(cosa);
+ cosa_getdata8(cosa);
#endif
+ cosa_putstatus(cosa, 0);
}
- /* start the DMA */
- flags1 = claim_dma_lock();
- disable_dma(cosa->dma);
- clear_dma_ff(cosa->dma);
- set_dma_mode(cosa->dma, DMA_MODE_WRITE);
- set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
- set_dma_count(cosa->dma, cosa->txsize);
- enable_dma(cosa->dma);
- release_dma_lock(flags1);
+ if (cosa->busmaster) {
+ unsigned long addr = virt_to_bus(cosa->txbuf);
+ int count=0;
+ printk(KERN_INFO "busmaster IRQ\n");
+ while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
+ count++;
+ udelay(10);
+ if (count > 1000) break;
+ }
+ printk(KERN_INFO "status %x\n", cosa_getstatus(cosa));
+ printk(KERN_INFO "ready after %d loops\n", count);
+ cosa_putdata16(cosa, (addr >> 16)&0xffff);
+
+ count = 0;
+ while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
+ count++;
+ if (count > 1000) break;
+ udelay(10);
+ }
+ printk(KERN_INFO "ready after %d loops\n", count);
+ cosa_putdata16(cosa, addr &0xffff);
+ flags1 = claim_dma_lock();
+ set_dma_mode(cosa->dma, DMA_MODE_CASCADE);
+ enable_dma(cosa->dma);
+ release_dma_lock(flags1);
+ } else {
+ /* start the DMA */
+ flags1 = claim_dma_lock();
+ disable_dma(cosa->dma);
+ clear_dma_ff(cosa->dma);
+ set_dma_mode(cosa->dma, DMA_MODE_WRITE);
+ set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
+ set_dma_count(cosa->dma, cosa->txsize);
+ enable_dma(cosa->dma);
+ release_dma_lock(flags1);
+ }
cosa_putstatus(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
#ifdef DEBUG_IO
debug_status_out(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
@@ -1671,21 +1772,16 @@
if (is_8bit(cosa)) {
if (!test_bit(IRQBIT, &cosa->rxtx)) {
set_bit(IRQBIT, &cosa->rxtx);
- cosa_putstatus(cosa, 0);
cosa->rxsize = cosa_getdata8(cosa) <<8;
#ifdef DEBUG_IO
- debug_status_out(cosa, 0);
debug_data_in(cosa, cosa->rxsize >> 8);
#endif
- put_driver_status_nolock(cosa);
spin_unlock_irqrestore(&cosa->lock, flags);
return;
} else {
clear_bit(IRQBIT, &cosa->rxtx);
- cosa_putstatus(cosa, 0);
cosa->rxsize |= cosa_getdata8(cosa) & 0xff;
#ifdef DEBUG_IO
- debug_status_out(cosa, 0);
debug_data_in(cosa, cosa->rxsize & 0xff);
#endif
#if 0
@@ -1695,12 +1791,8 @@
}
} else {
cosa->rxsize = cosa_getdata16(cosa);
- cosa_putstatus(cosa, 0);
- cosa_putdata8(cosa, DRIVER_RX_READY);
#ifdef DEBUG_IO
debug_data_in(cosa, cosa->rxsize);
- debug_status_out(cosa, 0);
- debug_cmd_out(cosa, DRIVER_RX_READY);
#endif
#if 0
printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
@@ -1725,10 +1817,7 @@
reject: /* Reject the packet */
printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n",
cosa->num, cosa->rxchan->num);
- /* FIXME: This works for COSA only (not SRP) */
- cosa->rxtx = 0;
- put_driver_status(cosa);
- return;
+ cosa->rxbuf = cosa->bouncebuf;
}
/* start the DMA */
@@ -1746,8 +1835,12 @@
release_dma_lock(flags);
spin_lock_irqsave(&cosa->lock, flags);
cosa_putstatus(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+ if (!is_8bit(cosa) && (status & SR_TX_RDY))
+ cosa_putdata8(cosa, DRIVER_RX_READY);
#ifdef DEBUG_IO
debug_status_out(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+ if (!is_8bit(cosa) && (status & SR_TX_RDY))
+ debug_data_cmd(cosa, DRIVER_RX_READY);
#endif
spin_unlock_irqrestore(&cosa->lock, flags);
}
@@ -1756,11 +1849,12 @@
{
unsigned long flags, flags1;
spin_lock_irqsave(&cosa->lock, flags);
+ flags1 = claim_dma_lock();
+ disable_dma(cosa->dma);
+ clear_dma_ff(cosa->dma);
+ release_dma_lock(flags1);
if (test_bit(TXBIT, &cosa->rxtx)) {
struct channel_data *chan = cosa->chan+cosa->txchan;
-#ifdef DEBUG_IRQS
- printk(KERN_INFO "cosa%d: end of transfer.\n", cosa->num);
-#endif
if (chan->tx_done)
if (chan->tx_done(chan, cosa->txsize))
clear_bit(chan->num, &cosa->txbitmap);
@@ -1775,6 +1869,9 @@
printk("\n");
}
#endif
+ /* Packet for unknown channel? */
+ if (cosa->rxbuf == cosa->bouncebuf)
+ goto out;
if (!cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize))
memcpy(cosa->rxbuf, cosa->bouncebuf, cosa->rxsize);
if (cosa->rxchan->rx_done)
@@ -1786,12 +1883,11 @@
}
/*
* Clear the RXBIT, TXBIT and IRQBIT (the latest should be
- * cleared anyway).
+ * cleared anyway). We should do it as soon as possible
+ * so that we can tell the COSA we are done and to give it a time
+ * for recovery.
*/
- flags1 = claim_dma_lock();
- disable_dma(cosa->dma);
- clear_dma_ff(cosa->dma);
- release_dma_lock(flags1);
+out:
cosa->rxtx = 0;
put_driver_status_nolock(cosa);
spin_unlock_irqrestore(&cosa->lock, flags);
@@ -1799,7 +1895,7 @@
static void cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs)
{
- int status;
+ unsigned status;
int count = 0;
struct cosa_data *cosa = cosa_;
again:
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/cosa.h linux.ac/drivers/net/cosa.h
--- linux.vanilla/drivers/net/cosa.h Mon Dec 28 23:09:42 1998
+++ linux.ac/drivers/net/cosa.h Tue Feb 16 17:30:03 1999
@@ -1,4 +1,4 @@
-/* $Id: cosa.h,v 1.5 1998/12/24 12:40:18 kas Exp $ */
+/* $Id: cosa.h,v 1.6 1999/01/06 14:02:44 kas Exp $ */
/*
* Copyright (C) 1995-1997 Jan "Yenya" Kasprzak
@@ -98,5 +98,14 @@
/* Get the number of channels on this card */
#define COSAIONRCHANS _IO('C',0xf8)
+
+/* Set the driver for the bus-master operations */
+#define COSAIOBMSET _IOW('C', 0xf9, sizeof(unsigned short))
+
+#define COSA_BM_OFF 0 /* Bus-mastering off - use ISA DMA (default) */
+#define COSA_BM_ON 1 /* Bus-mastering on - faster but untested */
+
+/* Gets the busmaster status */
+#define COSAIOBMGET _IO('C', 0xfa)
#endif /* !COSA_H__ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/cs89x0.c linux.ac/drivers/net/cs89x0.c
--- linux.vanilla/drivers/net/cs89x0.c Sun Nov 8 15:10:16 1998
+++ linux.ac/drivers/net/cs89x0.c Thu Feb 4 20:22:31 1999
@@ -991,22 +991,26 @@
0, 0,
0, 0, 0, NULL, NULL };
-int io=0;
-int irq=0;
-#endif
-#ifdef MODULE
-int debug=1;
-char *media="auto";
-char *duplex="f";
+static int io=0;
+static int irq=0;
+static int debug=0;
+static char media[8];
+static int duplex=-1;
+
+MODULE_PARM(io, "i");
+MODULE_PARM(irq, "i");
+MODULE_PARM(debug, "i");
+MODULE_PARM(media, "s");
+MODULE_PARM(duplex, "i");
+
+EXPORT_NO_SYMBOLS;
/*
* media=t - specify media type
or media=2
or media=aui
or medai=auto
-* duplex=f - specify forced half/full/autonegotiate duplex
- or duplex=h
- or duplex=auto
+* duplex=0 - specify forced half/full/autonegotiate duplex
* debug=# - debug level
@@ -1044,12 +1048,14 @@
/* boy, they'd better get these right */
if (!strcmp(media, "rj45"))
lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
- if (!strcmp(media, "aui"))
+ else if (!strcmp(media, "aui"))
lp->adapter_cnf = A_CNF_MEDIA_AUI | A_CNF_AUI;
- if (!strcmp(media, "bnc"))
+ else if (!strcmp(media, "bnc"))
lp->adapter_cnf = A_CNF_MEDIA_10B_2 | A_CNF_10B_2;
+ else
+ lp->adapter_cnf = A_CNF_MEDIA_10B_T | A_CNF_10B_T;
- if (!strcmp(duplex, "auto"))
+ if (duplex==-1)
lp->auto_neg_cnf = AUTO_NEG_ENABLE;
if (io == 0) {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/ibmtr.c linux.ac/drivers/net/ibmtr.c
--- linux.vanilla/drivers/net/ibmtr.c Tue Jan 26 09:44:20 1999
+++ linux.ac/drivers/net/ibmtr.c Thu Jan 28 13:22:37 1999
@@ -1353,12 +1353,23 @@
static void tr_tx(struct device *dev)
{
struct tok_info *ti=(struct tok_info *) dev->priv;
- struct trh_hdr *trhdr=(struct trh_hdr *)ti->current_skb->data;
+ struct trh_hdr *trhdr;
unsigned int hdr_len;
__u32 dhb;
unsigned char xmit_command;
int i;
struct trllc *llc;
+
+ if(ti->current_skb==NULL)
+ {
+ printk(KERN_ERR "%s: tx request but no packet!\n",
+ dev->name);
+ dev->tbusy=0;
+ mark_bh(NET_BH);
+ return;
+ }
+
+ trhdr=(struct trh_hdr *)ti->current_skb->data;
if (readb(ti->asb + offsetof(struct asb_xmit_resp, ret_code))!=0xFF)
DPRINTK("ASB not free !!!\n");
@@ -1603,6 +1614,7 @@
writeb(XMIT_UI_FRAME, ti->srb + offsetof(struct srb_xmit, command));
writew(ti->exsap_station_id, ti->srb
+offsetof(struct srb_xmit, station_id));
+ wmb(); /* This must be written before the IRQ hits */
writeb(CMD_IN_SRB, (ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD));
dev->trans_start=jiffies;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/Config.in linux.ac/drivers/net/irda/Config.in
--- linux.vanilla/drivers/net/irda/Config.in Sun Jan 24 19:55:35 1999
+++ linux.ac/drivers/net/irda/Config.in Tue Feb 16 17:45:19 1999
@@ -9,6 +9,7 @@
dep_tristate ' ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRTTY_SIR
dep_tristate ' ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRTTY_SIR
dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRTTY_SIR
+ dep_tristate ' Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRTTY_SIR
fi
fi
dep_tristate ' NSC PC87108' CONFIG_NSC_FIR $CONFIG_IRDA
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/Makefile linux.ac/drivers/net/irda/Makefile
--- linux.vanilla/drivers/net/irda/Makefile Sun Jan 24 19:55:35 1999
+++ linux.ac/drivers/net/irda/Makefile Tue Feb 16 17:45:19 1999
@@ -68,6 +68,14 @@
endif
endif
+ifeq ($(CONFIG_GIRBIL_DONGLE),y)
+L_OBJS += girbil.o
+else
+ ifeq ($(CONFIG_GIRBIL_DONGLE),m)
+ M_OBJS += girbil.o
+ endif
+endif
+
include $(TOPDIR)/Rules.make
clean:
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/actisys.c linux.ac/drivers/net/irda/actisys.c
--- linux.vanilla/drivers/net/irda/actisys.c Sun Jan 24 19:55:35 1999
+++ linux.ac/drivers/net/irda/actisys.c Tue Feb 16 17:45:19 1999
@@ -1,13 +1,13 @@
/*********************************************************************
*
* Filename: actisys.c
- * Version: 0.4
+ * Version: 0.5
* Description: Implementation for the ACTiSYS IR-220L and IR-220L+
* dongles
* Status: Experimental.
* Author: Dag Brattli
* Created at: Wed Oct 21 20:02:35 1998
- * Modified at: Mon Jan 18 11:30:25 1999
+ * Modified at: Tue Feb 9 15:38:16 1999
* Modified by: Dag Brattli
*
* Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -70,9 +70,10 @@
static void actisys_open( struct irda_device *idev, int type)
{
- strcat( idev->name, " <-> actisys");
+ strcat(idev->description, " <-> actisys");
idev->io.dongle_id = type;
+ idev->flags |= IFF_DONGLE;
MOD_INC_USE_COUNT;
}
@@ -85,24 +86,20 @@
/*
* Function actisys_change_speed (tty, baud)
*
- * Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
- * To cycle through the available baud rates, pulse RTS low for a few ms.
- * To be compatible with the new IR-220L+, we have to reset the dongle
- * first since its not possible cycle around anymore and still be
- * compatible with both dongles :-(
+ * Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
+ * To cycle through the available baud rates, pulse RTS low for a few
+ * ms.
*/
static void actisys_change_speed( struct irda_device *idev, int baudrate)
{
struct irtty_cb *self;
struct tty_struct *tty;
- int arg;
struct termios old_termios;
int cflag;
int current_baudrate;
int index = 0;
- mm_segment_t fs;
- DEBUG( 0, __FUNCTION__ "()\n");
+ DEBUG( 4, __FUNCTION__ "()\n");
ASSERT( idev != NULL, return;);
ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -115,10 +112,10 @@
current_baudrate = idev->qos.baud_rate.value;
/* Find the correct baudrate index for the currently used baudrate */
- while ( current_baudrate != baud_rates[index])
+ while (current_baudrate != baud_rates[index])
index++;
- DEBUG( 0, __FUNCTION__ "(), index=%d\n", index);
+ DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
if ( !self->tty)
return;
@@ -127,38 +124,18 @@
/* Cycle through avaiable baudrates until we reach the correct one */
while ( current_baudrate != baudrate) {
- DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n",
+ DEBUG( 4, __FUNCTION__ "(), current baudrate = %d\n",
baud_rates[index]);
- DEBUG( 0, __FUNCTION__ "(), Clearing RTS\n");
/* Set DTR, clear RTS */
- arg = TIOCM_DTR|TIOCM_OUT2;
-
- fs = get_fs();
- set_fs( get_ds());
-
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
- (unsigned long) &arg)) {
- DEBUG( 0, __FUNCTION__
- "Error clearing RTS!\n");
- }
- set_fs(fs);
+ irtty_set_dtr_rts(tty, TRUE, FALSE);
/* Wait at a few ms */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(2);
/* Set DTR, Set RTS */
- arg = TIOCM_DTR | TIOCM_RTS |TIOCM_OUT2;
-
- fs = get_fs();
- set_fs( get_ds());
-
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
- (unsigned long) &arg)) {
- DEBUG( 0, __FUNCTION__ "Error setting RTS!\n");
- }
- set_fs(fs);
+ irtty_set_dtr_rts(tty, TRUE, TRUE);
/* Wait at a few ms again */
current->state = TASK_INTERRUPTIBLE;
@@ -172,8 +149,8 @@
current_baudrate = baud_rates[index];
}
- DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n",
- baud_rates[index]);
+ DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
+ baud_rates[index]);
/* Now change the speed of the serial port */
old_termios = *(tty->termios);
@@ -200,9 +177,8 @@
break;
}
+ /* Change speed of serial port */
tty->termios->c_cflag = cflag;
-
- DEBUG( 0, __FUNCTION__ "(), Setting the speed of the serial port\n");
tty->driver.set_termios( tty, &old_termios);
}
@@ -219,10 +195,6 @@
{
struct irtty_cb *self;
struct tty_struct *tty;
- int arg = 0;
- mm_segment_t fs;
-
- DEBUG( 4, __FUNCTION__ "()\n");
ASSERT( idev != NULL, return;);
ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -236,36 +208,16 @@
if ( !tty)
return;
- DEBUG( 0, __FUNCTION__ "(), Clearing DTR\n");
- arg = TIOCM_RTS | TIOCM_OUT2;
-
- fs = get_fs();
- set_fs( get_ds());
-
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
- (unsigned long) &arg))
- {
- DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
- }
- set_fs(fs);
+ /* Clear DTR */
+ irtty_set_dtr_rts(tty, FALSE, TRUE);
/* Sleep 10-20 ms*/
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(2);
- DEBUG( 0, __FUNCTION__ "(), Setting DTR\n");
- arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
-
- fs = get_fs();
- set_fs( get_ds());
+ /* Go back to normal mode */
+ irtty_set_dtr_rts(tty, TRUE, TRUE);
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
- (unsigned long) &arg))
- {
- DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
- }
- set_fs(fs);
-
idev->qos.baud_rate.value = 9600;
}
@@ -287,6 +239,9 @@
}
#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli ");
+MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");
/*
* Function init_module (void)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/esi.c linux.ac/drivers/net/irda/esi.c
--- linux.vanilla/drivers/net/irda/esi.c Sun Jan 24 19:55:35 1999
+++ linux.ac/drivers/net/irda/esi.c Tue Feb 16 17:45:19 1999
@@ -1,12 +1,12 @@
/*********************************************************************
*
* Filename: esi.c
- * Version: 1.1
- * Description: Driver for the Extended Systems JetEye PC
+ * Version: 1.2
+ * Description: Driver for the Extended Systems JetEye PC dongle
* Status: Experimental.
* Author: Thomas Davis,
* Created at: Sat Feb 21 18:54:38 1998
- * Modified at: Mon Jan 18 11:30:32 1999
+ * Modified at: Tue Feb 9 15:36:47 1999
* Modified by: Dag Brattli
* Sources: esi.c
*
@@ -71,6 +71,7 @@
strcat( idev->description, " <-> esi");
idev->io.dongle_id = type;
+ idev->flags |= IFF_DONGLE;
MOD_INC_USE_COUNT;
}
@@ -90,10 +91,9 @@
{
struct irtty_cb *self;
struct tty_struct *tty;
- int arg = TIOCM_OUT2;
+ int dtr, rts;
struct termios old_termios;
int cflag;
- mm_segment_t fs;
ASSERT( idev != NULL, return;);
ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -116,37 +116,25 @@
switch (baud) {
case 19200:
cflag |= B19200;
- arg |= TIOCM_DTR;
+ dtr = TRUE;
+ rts = FALSE;
break;
case 115200:
cflag |= B115200;
- arg |= TIOCM_RTS | TIOCM_DTR;
+ dtr = rts = TRUE;
break;
case 9600:
default:
cflag |= B9600;
- arg |= TIOCM_RTS;
+ dtr = FALSE;
+ rts = TRUE;
break;
}
-
+ /* Change speed of serial driver */
tty->termios->c_cflag = cflag;
tty->driver.set_termios( tty, &old_termios);
- /*
- * The ioctl function, or actually set_modem_info in serial.c
- * expects a pointer to the argument in user space. To hack us
- * around this we use the set_fs function to fool the routines
- * that check if they are called from user space. We also need
- * to send a pointer to the argument so get_user() gets happy.
- * DB.
- */
- fs = get_fs();
- set_fs( get_ds());
-
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) {
- DEBUG( 0, __FUNCTION__ "(), error setting ESI speed!\n");
- }
- set_fs(fs);
+ irtty_set_dtr_rts(tty, dtr, rts);
}
static void esi_reset( struct irda_device *idev, int unused)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/girbil.c linux.ac/drivers/net/irda/girbil.c
--- linux.vanilla/drivers/net/irda/girbil.c Thu Jan 1 01:00:00 1970
+++ linux.ac/drivers/net/irda/girbil.c Tue Feb 16 17:45:19 1999
@@ -0,0 +1,276 @@
+/*********************************************************************
+ *
+ * Filename: girbil.c
+ * Version: 1.0
+ * Description: Implementation for the Greenwich GIrBIL dongle
+ * Status: Experimental.
+ * Author: Dag Brattli
+ * Created at: Sat Feb 6 21:02:33 1999
+ * Modified at: Tue Feb 9 15:36:36 1999
+ * Modified by: Dag Brattli
+ *
+ * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *
+ * 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.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+static void girbil_reset(struct irda_device *dev, int unused);
+static void girbil_open(struct irda_device *dev, int type);
+static void girbil_close(struct irda_device *dev);
+static void girbil_change_speed(struct irda_device *dev, int baud);
+static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos);
+
+/* Control register 1 */
+#define GIRBIL_TXEN 0x01 /* Enable transmitter */
+#define GIRBIL_RXEN 0x02 /* Enable receiver */
+#define GIRBIL_ECAN 0x04 /* Cancel self emmited data */
+#define GIRBIL_ECHO 0x08 /* Echo control characters */
+
+/* LED Current Register (0x2) */
+#define GIRBIL_HIGH 0x20
+#define GIRBIL_MEDIUM 0x21
+#define GIRBIL_LOW 0x22
+
+/* Baud register (0x3) */
+#define GIRBIL_2400 0x30
+#define GIRBIL_4800 0x31
+#define GIRBIL_9600 0x32
+#define GIRBIL_19200 0x33
+#define GIRBIL_38400 0x34
+#define GIRBIL_57600 0x35
+#define GIRBIL_115200 0x36
+
+/* Mode register (0x4) */
+#define GIRBIL_IRDA 0x40
+#define GIRBIL_ASK 0x41
+
+/* Control register 2 (0x5) */
+#define GIRBIL_LOAD 0x51 /* Load the new baud rate value */
+
+static struct dongle dongle = {
+ GIRBIL_DONGLE,
+ girbil_open,
+ girbil_close,
+ girbil_reset,
+ girbil_change_speed,
+ girbil_init_qos,
+};
+
+__initfunc(void girbil_init(void))
+{
+ irtty_register_dongle(&dongle);
+}
+
+void girbil_cleanup(void)
+{
+ irtty_unregister_dongle(&dongle);
+}
+
+static void girbil_open(struct irda_device *idev, int type)
+{
+ strcat( idev->description, " <-> girbil");
+
+ idev->io.dongle_id = type;
+ idev->flags |= IFF_DONGLE;
+
+ MOD_INC_USE_COUNT;
+}
+
+static void girbil_close(struct irda_device *dev)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function girbil_change_speed (dev, speed)
+ *
+ * Set the speed for the Girbil type dongle. Warning, this
+ * function must be called with a process context!
+ *
+ */
+static void girbil_change_speed(struct irda_device *idev, int speed)
+{
+ struct irtty_cb *self;
+ struct tty_struct *tty;
+ struct termios old_termios;
+ int cflag;
+ __u8 control[2];
+
+ ASSERT(idev != NULL, return;);
+ ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = (struct irtty_cb *) idev->priv;
+
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == IRTTY_MAGIC, return;);
+
+ if (!self->tty)
+ return;
+
+ tty = self->tty;
+
+ old_termios = *(tty->termios);
+ cflag = tty->termios->c_cflag;
+
+ cflag &= ~CBAUD;
+
+ switch (speed) {
+ case 9600:
+ default:
+ cflag |= B9600;
+ control[0] = GIRBIL_9600;
+ break;
+ case 19200:
+ cflag |= B19200;
+ control[0] = GIRBIL_19200;
+ break;
+ case 34800:
+ cflag |= B38400;
+ control[0] = GIRBIL_38400;
+ break;
+ case 57600:
+ cflag |= B57600;
+ control[0] = GIRBIL_57600;
+ break;
+ case 115200:
+ cflag |= B115200;
+ control[0] = GIRBIL_115200;
+ break;
+ }
+ control[1] = GIRBIL_LOAD;
+
+ /* Set DTR and Clear RTS to enter command mode */
+ irtty_set_dtr_rts(tty, FALSE, TRUE);
+
+ /* Write control bytes */
+ if (tty->driver.write)
+ tty->driver.write(self->tty, 0, control, 2);
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(2);
+
+ /* Go back to normal mode */
+ irtty_set_dtr_rts(tty, TRUE, TRUE);
+
+ /* Now change the speed of the serial port */
+ tty->termios->c_cflag = cflag;
+ tty->driver.set_termios(tty, &old_termios);
+}
+
+/*
+ * Function girbil_reset (driver)
+ *
+ * This function resets the girbil dongle. Warning, this function
+ * must be called with a process context!!
+ *
+ * Algorithm:
+ * 0. set RTS, and wait at least 5 ms
+ * 1. clear RTS
+ */
+void girbil_reset(struct irda_device *idev, int unused)
+{
+ struct irtty_cb *self;
+ struct tty_struct *tty;
+ __u8 control = GIRBIL_TXEN | GIRBIL_RXEN /* | GIRBIL_ECAN */;
+
+ ASSERT(idev != NULL, return;);
+ ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = (struct irtty_cb *) idev->priv;
+
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == IRTTY_MAGIC, return;);
+
+ tty = self->tty;
+ if (!tty)
+ return;
+
+ /* Reset dongle */
+ irtty_set_dtr_rts(tty, TRUE, FALSE);
+
+ /* Sleep at least 5 ms */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(2);
+
+ /* Set DTR and clear RTS to enter command mode */
+ irtty_set_dtr_rts(tty, FALSE, TRUE);
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(2);
+
+ /* Write control byte */
+ if (tty->driver.write)
+ tty->driver.write(self->tty, 0, &control, 1);
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(2);
+
+ /* Go back to normal mode */
+ irtty_set_dtr_rts(tty, TRUE, TRUE);
+}
+
+/*
+ * Function girbil_init_qos (qos)
+ *
+ * Initialize QoS capabilities
+ *
+ */
+static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos)
+{
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli ");
+MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
+
+/*
+ * Function init_module (void)
+ *
+ * Initialize Girbil module
+ *
+ */
+int init_module(void)
+{
+ girbil_init();
+ return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ * Cleanup Girbil module
+ *
+ */
+void cleanup_module(void)
+{
+ girbil_cleanup();
+}
+
+#endif /* MODULE */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/irport.c linux.ac/drivers/net/irda/irport.c
--- linux.vanilla/drivers/net/irda/irport.c Tue Jan 26 09:44:20 1999
+++ linux.ac/drivers/net/irda/irport.c Wed Jan 27 19:06:11 1999
@@ -96,7 +96,7 @@
#ifdef MODULE
static void irport_cleanup(void)
{
- int i;
+/* int i; */
DEBUG( 4, __FUNCTION__ "()\n");
@@ -303,7 +303,6 @@
int irport_hard_xmit( struct sk_buff *skb, struct device *dev)
{
struct irda_device *idev;
- int xbofs;
int actual;
DEBUG( 4, __FUNCTION__ "()\n");
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/irtty.c linux.ac/drivers/net/irda/irtty.c
--- linux.vanilla/drivers/net/irda/irtty.c Sun Jan 24 19:55:35 1999
+++ linux.ac/drivers/net/irda/irtty.c Tue Feb 16 17:45:19 1999
@@ -1,12 +1,12 @@
/*********************************************************************
*
* Filename: irtty.c
- * Version: 1.0
+ * Version: 1.1
* Description: IrDA line discipline implementation
* Status: Experimental.
* Author: Dag Brattli
* Created at: Tue Dec 9 21:18:38 1997
- * Modified at: Mon Jan 18 15:32:03 1999
+ * Modified at: Tue Feb 9 13:08:25 1999
* Modified by: Dag Brattli
* Sources: slip.c by Laurence Culhane,
* Fred N. van Kempen,
@@ -206,6 +206,7 @@
self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200;
self->idev.qos.min_turn_time.bits = 0x03;
+ self->idev.flags = IFF_SIR | IFF_PIO;
irda_qos_bits_to_value( &self->idev.qos);
/* Specify which buffer allocation policy we need */
@@ -272,8 +273,6 @@
kfree( self);
MOD_DEC_USE_COUNT;
-
- DEBUG( 4, "IrTTY: close() -->\n");
}
/*
@@ -289,6 +288,8 @@
struct irtty_cb *self;
int cflag;
+ DEBUG(4,__FUNCTION__ "(), <%ld>\n", jiffies);
+
ASSERT( idev != NULL, return;);
ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -360,10 +361,15 @@
DEBUG( 0, __FUNCTION__ "(), Tekram dongle!\n");
request_module( "tekram");
break;
- case ACTISYS_DONGLE:
+ case ACTISYS_DONGLE: /* FALLTHROUGH */
+ case ACTISYS_PLUS_DONGLE:
DEBUG( 0, __FUNCTION__ "(), ACTiSYS dongle!\n");
request_module( "actisys");
break;
+ case GIRBIL_DONGLE:
+ DEBUG( 0, __FUNCTION__ "(), GIrBIL dongle!\n");
+ request_module( "girbil");
+ break;
default:
DEBUG( 0, __FUNCTION__ "(), Unknown dongle type!\n");
return;
@@ -373,8 +379,7 @@
node = hashbin_find( dongles, type, NULL);
if ( !node) {
- DEBUG( 0, __FUNCTION__
- "(), Unable to find requested dongle\n");
+ DEBUG(0, __FUNCTION__ "(), Unable to find requested dongle\n");
return;
}
self->dongle_q = node;
@@ -401,8 +406,7 @@
* The Swiss army knife of system calls :-)
*
*/
-static int irtty_ioctl( struct tty_struct *tty, void *file, int cmd,
- void *arg)
+static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
{
struct irtty_cb *self;
int err = 0;
@@ -444,8 +448,8 @@
* been received, which can now be decapsulated and delivered for
* further processing
*/
-static void irtty_receive_buf( struct tty_struct *tty, const unsigned
- char *cp, char *fp, int count)
+static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+ char *fp, int count)
{
struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
@@ -464,11 +468,8 @@
cp++;
continue;
}
- /*
- * Unwrap and destuff one byte
- */
+ /* Unwrap and destuff one byte */
async_unwrap_char( &self->idev, *cp++);
- /* self->rx_over_errors++; */
}
}
@@ -478,7 +479,7 @@
* Transmit skb
*
*/
-static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev)
+static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev)
{
struct irtty_cb *self;
struct irda_device *idev;
@@ -487,43 +488,40 @@
ASSERT( dev != NULL, return 0;);
ASSERT( skb != NULL, return 0;);
- if ( dev->tbusy) {
- DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-
- return -EBUSY;
- }
-
idev = (struct irda_device *) dev->priv;
- ASSERT( idev != NULL, return 0;);
- ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+ ASSERT(idev != NULL, return 0;);
+ ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
self = (struct irtty_cb *) idev->priv;
- ASSERT( self != NULL, return 0;);
- ASSERT( self->magic == IRTTY_MAGIC, return 0;);
+ ASSERT(self != NULL, return 0;);
+ ASSERT(self->magic == IRTTY_MAGIC, return 0;);
/* Lock transmit buffer */
- if ( irda_lock( (void *) &dev->tbusy) == FALSE)
- return 0;
+ if (irda_lock((void *) &dev->tbusy) == FALSE)
+ return -EBUSY;
/*
* Transfer skb to tx_buff while wrapping, stuffing and making CRC
*/
- idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data,
- idev->tx_buff.truesize);
+ idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data,
+ idev->tx_buff.truesize);
self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
dev->trans_start = jiffies;
if ( self->tty->driver.write)
- actual = self->tty->driver.write( self->tty, 0,
- idev->tx_buff.data,
- idev->tx_buff.len);
+ actual = self->tty->driver.write(self->tty, 0,
+ idev->tx_buff.data,
+ idev->tx_buff.len);
idev->tx_buff.offset = actual;
idev->tx_buff.head = idev->tx_buff.data + actual;
+
+ idev->stats.tx_packets++;
+ idev->stats.tx_bytes += idev->tx_buff.len;
#if 0
/*
* Did we transmit the whole frame? Commented out for now since
@@ -535,8 +533,7 @@
irda_unlock( &self->tbusy);
}
#endif
-
- dev_kfree_skb( skb);
+ dev_kfree_skb(skb);
return 0;
}
@@ -587,8 +584,6 @@
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
idev->netdev.tbusy = 0; /* Unlock */
- idev->stats.tx_packets++;
- idev->stats.tx_bytes += idev->tx_buff.len;
/* Tell network layer that we want more frames */
mark_bh( NET_BH);
@@ -602,8 +597,6 @@
actual = tty->driver.write( tty, 0, idev->tx_buff.head, count);
idev->tx_buff.offset += actual;
idev->tx_buff.head += actual;
-
- DEBUG( 4, "actual=%d, sent %d\n", actual, count);
}
/*
@@ -648,8 +641,7 @@
}
/* Make new IrDA dongle */
- new = (struct dongle_q *) kmalloc (sizeof (struct dongle_q),
- GFP_KERNEL);
+ new = (struct dongle_q *)kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
if (new == NULL) {
return 1;
@@ -675,6 +667,35 @@
kfree( node);
}
+
+void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts)
+{
+ mm_segment_t fs;
+ int arg = TIOCM_OUT2;
+
+ if (rts)
+ arg |= TIOCM_RTS;
+ if (dtr)
+ arg |= TIOCM_DTR;
+
+ /*
+ * The ioctl() function, or actually set_modem_info() in serial.c
+ * expects a pointer to the argument in user space. To hack us
+ * around this, we use the set_fs() function to fool the routines
+ * that check if they are called from user space. We also need
+ * to send a pointer to the argument so get_user() gets happy. DB.
+ */
+
+ fs = get_fs();
+ set_fs(get_ds());
+
+ if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) {
+ DEBUG(0, __FUNCTION__ "(), error!\n");
+ }
+ set_fs(fs);
+}
+
+
static int irtty_net_init( struct device *dev)
{
/* Set up to be a normal IrDA network device driver */
@@ -714,6 +735,9 @@
}
#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli ");
+MODULE_DESCRIPTION("IrDA TTY device driver");
/*
* Function init_module (void)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/pc87108.c linux.ac/drivers/net/irda/pc87108.c
--- linux.vanilla/drivers/net/irda/pc87108.c Sun Jan 24 19:55:35 1999
+++ linux.ac/drivers/net/irda/pc87108.c Tue Feb 16 17:45:19 1999
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli
* Created at: Sat Nov 7 21:43:15 1998
- * Modified at: Mon Dec 28 08:46:16 1998
+ * Modified at: Tue Feb 9 13:29:40 1999
* Modified by: Dag Brattli
*
* Copyright (c) 1998 Dag Brattli
@@ -100,7 +100,9 @@
/* Some prototypes */
static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr,
unsigned int irq, unsigned int dma);
+#ifdef MODULE
static int pc87108_close( struct irda_device *idev);
+#endif /* MODULE */
static int pc87108_probe( int iobase, int board_addr, int irq, int dma);
static void pc87108_pio_receive( struct irda_device *idev);
static int pc87108_dma_receive( struct irda_device *idev);
@@ -221,6 +223,8 @@
idev->qos.min_turn_time.bits = 0x07;
irda_qos_bits_to_value( &idev->qos);
+ idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
+
/* Specify which buffer allocation policy we need */
idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
@@ -250,6 +254,7 @@
return 0;
}
+#ifdef MODULE
/*
* Function pc87108_close (idev)
*
@@ -276,6 +281,7 @@
return 0;
}
+#endif /* MODULE */
/*
* Function pc87108_probe (iobase, board_addr, irq, dma)
@@ -720,12 +726,6 @@
iobase = idev->io.iobase;
DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-
- if ( dev->tbusy) {
- DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-
- return -EBUSY;
- }
/* Lock transmit buffer */
if ( irda_lock( (void *) &dev->tbusy) == FALSE)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/tekram.c linux.ac/drivers/net/irda/tekram.c
--- linux.vanilla/drivers/net/irda/tekram.c Sun Jan 24 19:55:35 1999
+++ linux.ac/drivers/net/irda/tekram.c Tue Feb 16 17:45:19 1999
@@ -1,12 +1,12 @@
/*********************************************************************
*
* Filename: tekram.c
- * Version: 0.4
+ * Version: 0.5
* Description: Implementation of the Tekram IrMate IR-210B dongle
* Status: Experimental.
* Author: Dag Brattli
* Created at: Wed Oct 21 20:02:35 1998
- * Modified at: Mon Jan 18 11:30:38 1999
+ * Modified at: Tue Feb 9 15:36:55 1999
* Modified by: Dag Brattli
*
* Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -63,9 +63,12 @@
irtty_unregister_dongle( &dongle);
}
-static void tekram_open( struct irda_device *dev, int type)
+static void tekram_open( struct irda_device *idev, int type)
{
- strcat( dev->name, " <-> tekram");
+ strcat(idev->description, " <-> tekram");
+
+ idev->io.dongle_id = type;
+ idev->flags |= IFF_DONGLE;
MOD_INC_USE_COUNT;
}
@@ -96,11 +99,8 @@
struct irtty_cb *self;
struct tty_struct *tty;
struct termios old_termios;
- int arg = 0;
int cflag;
__u8 byte;
- int actual;
- mm_segment_t fs;
DEBUG( 4, __FUNCTION__ "()\n");
@@ -147,44 +147,22 @@
}
/* Set DTR, Clear RTS */
- DEBUG( 0, __FUNCTION__ "(), Setting DTR, Clearing RTS\n");
- arg = TIOCM_DTR | TIOCM_OUT2;
-
- fs = get_fs();
- set_fs( get_ds());
-
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
- (unsigned long) &arg)) {
- DEBUG( 0, "error setting Tekram speed!\n");
- }
- set_fs(fs);
+ irtty_set_dtr_rts(tty, TRUE, FALSE);
/* Wait at least 7us */
udelay( 7);
- DEBUG( 0, __FUNCTION__ "(), Writing control byte\n");
/* Write control byte */
if ( tty->driver.write)
- actual = tty->driver.write( self->tty, 0, &byte, 1);
+ tty->driver.write( self->tty, 0, &byte, 1);
/* Wait at least 100 ms */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout( 10);
/* Set DTR, Set RTS */
- DEBUG( 0, __FUNCTION__ "(), Setting DTR, Setting RTS\n");
- arg = TIOCM_DTR | TIOCM_RTS | TIOCM_OUT2;
-
- fs = get_fs();
- set_fs( get_ds());
-
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
- (unsigned long) &arg)) {
- DEBUG( 0, "error setting Tekram speed!\n");
- }
- set_fs(fs);
+ irtty_set_dtr_rts(tty, TRUE, TRUE);
- DEBUG( 0, __FUNCTION__ "(), Setting new speed on serial port\n");
/* Now change the speed of the serial port */
tty->termios->c_cflag = cflag;
tty->driver.set_termios( tty, &old_termios);
@@ -208,8 +186,6 @@
{
struct irtty_cb *self;
struct tty_struct *tty;
- int arg = 0;
- mm_segment_t fs;
DEBUG( 4, __FUNCTION__ "()\n");
@@ -225,51 +201,22 @@
if ( !tty)
return;
- DEBUG( 0, __FUNCTION__ "(), Power off dongle\n");
- arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
-
- fs = get_fs();
- set_fs( get_ds());
-
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
- (unsigned long) &arg))
- {
- DEBUG(0, "error setting ESI speed!\n");
- }
- set_fs(fs);
+ /* Power off dongle */
+ irtty_set_dtr_rts(tty, FALSE, FALSE);
/* Sleep 50 ms */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(5);
-
- DEBUG( 0, __FUNCTION__ "(), Set DTR, clear RTS\n");
- /* Set DTR, clear RTS */
- arg = TIOCM_DTR | TIOCM_OUT2;
-
- fs = get_fs();
- set_fs( get_ds());
-
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
- (unsigned long) &arg)) {
- DEBUG( 0, "Error setting Tekram speed!\n");
- }
- set_fs(fs);
+
+ /* Clear DTR, Set RTS */
+ irtty_set_dtr_rts(tty, FALSE, TRUE);
/* Should sleep 1 ms, but 10-20 should not do any harm */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(2);
- DEBUG( 0, __FUNCTION__ "(), STATE3\n");
- /* Clear DTR, clear RTS */
- arg = TIOCM_OUT2;
-
- fs = get_fs();
- set_fs( get_ds());
-
- if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) {
- DEBUG( 0, "error setting Tekram speed!\n");
- }
- set_fs(fs);
+ /* Set DTR, Set RTS */
+ irtty_set_dtr_rts(tty, TRUE, TRUE);
/* Finished! */
}
@@ -287,6 +234,9 @@
}
#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli ");
+MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
/*
* Function init_module (void)
@@ -311,4 +261,4 @@
tekram_cleanup();
}
-#endif
+#endif /* MODULE */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/uircc.c linux.ac/drivers/net/irda/uircc.c
--- linux.vanilla/drivers/net/irda/uircc.c Tue Jan 26 09:44:21 1999
+++ linux.ac/drivers/net/irda/uircc.c Tue Feb 16 17:45:19 1999
@@ -7,7 +7,7 @@
* Status: Experimental.
* Author: Dag Brattli
* Created at: Sat Dec 26 10:59:03 1998
- * Modified at: Tue Jan 19 23:54:04 1999
+ * Modified at: Tue Feb 9 13:30:41 1999
* Modified by: Dag Brattli
*
* Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -196,6 +196,8 @@
idev->qos.min_turn_time.bits = 0x07;
irda_qos_bits_to_value( &idev->qos);
+
+ idev->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
/* Specify which buffer allocation policy we need */
idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
@@ -271,9 +273,11 @@
static int uircc_probe( int iobase, int iobase2, int irq, int dma)
{
int version;
+#if 0
int probe_irq=0;
unsigned long mask;
int i;
+#endif
DEBUG( 0, __FUNCTION__ "()\n");
@@ -442,20 +446,12 @@
DEBUG(0, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
/* Use irport for SIR speeds */
- if ( idev->io.baudrate <= 115200) {
- return irport_hard_xmit( skb, dev);
- }
-
- if ( dev->tbusy) {
- __u8 sr3;
-
- DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-
- return -EBUSY;
+ if (idev->io.baudrate <= 115200) {
+ return irport_hard_xmit(skb, dev);
}
/* Lock transmit buffer */
- if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+ if (irda_lock((void *) &dev->tbusy) == FALSE)
return -EBUSY;
memcpy( idev->tx_buff.data, skb->data, skb->len);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/w83977af_ir.c linux.ac/drivers/net/irda/w83977af_ir.c
--- linux.vanilla/drivers/net/irda/w83977af_ir.c Tue Dec 22 23:19:44 1998
+++ linux.ac/drivers/net/irda/w83977af_ir.c Tue Feb 16 17:45:19 1999
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Paul VanderSpek
* Created at: Wed Nov 4 11:46:16 1998
- * Modified at: Mon Dec 14 21:51:53 1998
+ * Modified at: Tue Feb 9 13:30:35 1999
* Modified by: Dag Brattli
*
* Copyright (c) 1998 Corel Computer Corp.
@@ -204,6 +204,8 @@
/* The HP HDLS-1100 needs 1 ms according to the specs */
idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */
irda_qos_bits_to_value( &idev->qos);
+
+ idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
/* Specify which buffer allocation policy we need */
idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
@@ -468,12 +470,6 @@
iobase = idev->io.iobase;
DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-
- if ( dev->tbusy) {
- DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-
- return -EBUSY;
- }
/* Lock transmit buffer */
if ( irda_lock( (void *) &dev->tbusy) == FALSE)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/myri_sbus.c linux.ac/drivers/net/myri_sbus.c
--- linux.vanilla/drivers/net/myri_sbus.c Sun Nov 8 15:07:29 1998
+++ linux.ac/drivers/net/myri_sbus.c Thu Jan 14 06:23:57 1999
@@ -278,7 +278,7 @@
mp->rx_skbs[i] = skb;
skb->dev = dev;
skb_put(skb, RX_ALLOC_SIZE);
- rxd[i].myri_scatters[0].addr = (u32) ((unsigned long)skb->data);
+ rxd[i].myri_scatters[0].addr = sbus_dvma_addr(skb->data);
rxd[i].myri_scatters[0].len = RX_ALLOC_SIZE;
rxd[i].ctx = i;
rxd[i].num_sg = 1;
@@ -340,12 +340,6 @@
dev_kfree_skb(skb);
mp->tx_skbs[entry] = NULL;
mp->enet_stats.tx_packets++;
-
-#ifdef NEED_DMA_SYNCHRONIZATION
- mmu_sync_dma(((u32)((unsigned long)skb->data)),
- skb->len, mp->myri_sbus_dev->my_bus);
-#endif
-
entry = NEXT_TX(entry);
}
mp->tx_old = entry;
@@ -437,8 +431,7 @@
drops++;
DRX(("DROP "));
mp->enet_stats.rx_dropped++;
- rxd->myri_scatters[0].addr =
- (u32) ((unsigned long)skb->data);
+ rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data);
rxd->myri_scatters[0].len = RX_ALLOC_SIZE;
rxd->ctx = index;
rxd->num_sg = 1;
@@ -447,7 +440,7 @@
}
#ifdef NEED_DMA_SYNCHRONIZATION
- mmu_sync_dma(((u32)((unsigned long)skb->data)),
+ mmu_sync_dma(sbus_dvma_addr(skb->data),
skb->len, mp->myri_sbus_dev->my_bus);
#endif
@@ -464,8 +457,7 @@
mp->rx_skbs[index] = new_skb;
new_skb->dev = dev;
skb_put(new_skb, RX_ALLOC_SIZE);
- rxd->myri_scatters[0].addr =
- (u32) ((unsigned long)new_skb->data);
+ rxd->myri_scatters[0].addr = sbus_dvma_addr(new_skb->data);
rxd->myri_scatters[0].len = RX_ALLOC_SIZE;
rxd->ctx = index;
rxd->num_sg = 1;
@@ -489,8 +481,7 @@
/* Reuse original ring buffer. */
DRX(("reuse "));
- rxd->myri_scatters[0].addr =
- (u32) ((unsigned long)skb->data);
+ rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data);
rxd->myri_scatters[0].len = RX_ALLOC_SIZE;
rxd->ctx = index;
rxd->num_sg = 1;
@@ -600,6 +591,12 @@
return 1;
}
+
+#ifdef NEED_DMA_SYNCHRONIZATION
+ mmu_sync_dma(sbus_dvma_addr(skb->data),
+ skb->len, mp->myri_sbus_dev->my_bus);
+#endif
+
/* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */
head = sq->head;
tail = sq->tail;
@@ -628,8 +625,7 @@
txd = &sq->myri_txd[entry];
mp->tx_skbs[entry] = skb;
- txd->myri_gathers[0].addr =
- (unsigned int) ((unsigned long)skb->data);
+ txd->myri_gathers[0].addr = sbus_dvma_addr(skb->data);
txd->myri_gathers[0].len = len;
txd->num_sg = 1;
txd->chan = KERNEL_CHANNEL;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/ne.c linux.ac/drivers/net/ne.c
--- linux.vanilla/drivers/net/ne.c Tue Dec 22 23:19:46 1998
+++ linux.ac/drivers/net/ne.c Fri Feb 26 01:51:53 1999
@@ -105,6 +105,7 @@
{"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
{"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
{"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
+ {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
{0,}
};
#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/plip.c linux.ac/drivers/net/plip.c
--- linux.vanilla/drivers/net/plip.c Wed Jan 6 23:02:22 1999
+++ linux.ac/drivers/net/plip.c Fri Feb 26 01:53:20 1999
@@ -1217,7 +1217,7 @@
plip_searchfor(int list[], int a)
{
int i;
- for (i = 0; i < 3 && list[i] != -1; i++) {
+ for (i = 0; i < PLIP_MAX && list[i] != -1; i++) {
if (list[i] == a) return 1;
}
return 0;
@@ -1240,7 +1240,7 @@
/* If the user feeds parameters, use them */
while (pb) {
if ((parport[0] == -1 && (!timid || !pb->devices)) ||
- plip_searchfor(parport, i)) {
+ plip_searchfor(parport, pb->number)) {
if (i == PLIP_MAX) {
printk(KERN_ERR "plip: too many devices\n");
break;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sealevel.c linux.ac/drivers/net/sealevel.c
--- linux.vanilla/drivers/net/sealevel.c Thu Jan 1 01:00:00 1970
+++ linux.ac/drivers/net/sealevel.c Thu Feb 18 19:10:37 1999
@@ -0,0 +1,471 @@
+#define LINUX_21
+
+/*
+ * Sealevel Systems 4021 driver.
+ *
+ * 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.
+ *
+ * (c) Copyright 1999 Building Number Three Ltd
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include "syncppp.h"
+#include "z85230.h"
+
+
+struct slvl_device
+{
+ struct z8530_channel *chan;
+ struct ppp_device netdev;
+ char name[16];
+ int channel;
+};
+
+
+struct slvl_board
+{
+ struct slvl_device dev[2];
+ struct z8530_dev board;
+ int iobase;
+};
+
+/*
+ * Network driver support routines
+ */
+
+/*
+ * Frame receive. Simple for our card as we do sync ppp and there
+ * is no funny garbage involved
+ */
+
+static void sealevel_input(struct z8530_channel *c, struct sk_buff *skb)
+{
+ /* Drop the CRC - its not a good idea to try and negotiate it ;) */
+ skb_trim(skb, skb->len-2);
+ skb->protocol=htons(ETH_P_WAN_PPP);
+ skb->mac.raw=skb->data;
+ skb->dev=c->netdevice;
+ /*
+ * Send it to the PPP layer. We dont have time to process
+ * it right now.
+ */
+ netif_rx(skb);
+}
+
+/*
+ * We've been placed in the UP state
+ */
+
+static int sealevel_open(struct device *d)
+{
+ struct slvl_device *slvl=d->priv;
+ int err = -1;
+ int unit = slvl->channel;
+
+ /*
+ * Link layer up.
+ */
+
+ switch(unit)
+ {
+ case 0:
+ err=z8530_sync_dma_open(d, slvl->chan);
+ break;
+ case 1:
+ err=z8530_sync_open(d, slvl->chan);
+ break;
+ }
+
+ if(err)
+ return err;
+ /*
+ * Begin PPP
+ */
+ err=sppp_open(d);
+ if(err)
+ {
+ switch(unit)
+ {
+ case 0:
+ z8530_sync_dma_close(d, slvl->chan);
+ break;
+ case 1:
+ z8530_sync_close(d, slvl->chan);
+ break;
+ }
+ return err;
+ }
+
+ slvl->chan->rx_function=sealevel_input;
+
+ /*
+ * Go go go
+ */
+ d->tbusy=0;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int sealevel_close(struct device *d)
+{
+ struct slvl_device *slvl=d->priv;
+ int unit = slvl->channel;
+
+ /*
+ * Discard new frames
+ */
+
+ slvl->chan->rx_function=z8530_null_rx;
+
+ /*
+ * PPP off
+ */
+ sppp_close(d);
+ /*
+ * Link layer down
+ */
+ d->tbusy=1;
+
+ switch(unit)
+ {
+ case 0:
+ z8530_sync_dma_close(d, slvl->chan);
+ break;
+ case 1:
+ z8530_sync_close(d, slvl->chan);
+ break;
+ }
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int sealevel_ioctl(struct device *d, struct ifreq *ifr, int cmd)
+{
+ /* struct slvl_device *slvl=d->priv;
+ z8530_ioctl(d,&slvl->sync.chanA,ifr,cmd) */
+ return sppp_do_ioctl(d, ifr,cmd);
+}
+
+static struct enet_statistics *sealevel_get_stats(struct device *d)
+{
+ struct slvl_device *slvl=d->priv;
+ if(slvl)
+ return z8530_get_stats(slvl->chan);
+ else
+ return NULL;
+}
+
+/*
+ * Passed PPP frames, fire them downwind.
+ */
+
+static int sealevel_queue_xmit(struct sk_buff *skb, struct device *d)
+{
+ struct slvl_device *slvl=d->priv;
+ return z8530_queue_xmit(slvl->chan, skb);
+}
+
+#ifdef LINUX_21
+static int sealevel_neigh_setup(struct neighbour *n)
+{
+ if (n->nud_state == NUD_NONE) {
+ n->ops = &arp_broken_ops;
+ n->output = n->ops->output;
+ }
+ return 0;
+}
+
+static int sealevel_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
+{
+ if (p->tbl->family == AF_INET) {
+ p->neigh_setup = sealevel_neigh_setup;
+ p->ucast_probes = 0;
+ p->mcast_probes = 0;
+ }
+ return 0;
+}
+
+#else
+
+static int return_0(struct device *d)
+{
+ return 0;
+}
+
+#endif
+
+/*
+ * Description block for a Comtrol Hostess SV11 card
+ */
+
+static struct slvl_board *slvl_init(int iobase, int irq, int txdma, int rxdma, int slow)
+{
+ struct z8530_dev *dev;
+ struct slvl_device *sv;
+ struct slvl_board *b;
+
+ int i;
+ unsigned long flags;
+ int u;
+
+ /*
+ * Get the needed I/O space
+ */
+
+ if(check_region(iobase, 8))
+ {
+ printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n", iobase);
+ return NULL;
+ }
+ request_region(iobase, 8, "Sealevel 4021");
+
+ b=(struct slvl_board *)kmalloc(sizeof(struct slvl_board), GFP_KERNEL);
+ if(!b)
+ goto fail3;
+
+ memset(b, 0, sizeof(*sv));
+
+ b->dev[0].chan = &b->board.chanA;
+ b->dev[1].chan = &b->board.chanB;
+
+ dev=&b->board;
+
+ /*
+ * Stuff in the I/O addressing
+ */
+
+ dev->active = 0;
+
+ b->iobase = iobase;
+
+ /*
+ * Select 8530 delays for the old board
+ */
+
+ if(slow)
+ iobase |= Z8530_PORT_SLEEP;
+
+ dev->chanA.ctrlio=iobase+1;
+ dev->chanA.dataio=iobase;
+ dev->chanB.ctrlio=iobase+3;
+ dev->chanB.dataio=iobase+2;
+
+ dev->chanA.irqs=&z8530_nop;
+ dev->chanB.irqs=&z8530_nop;
+
+ /*
+ * Assert DTR enable DMA
+ */
+
+ outb(3|(1<<7), b->iobase+4);
+
+
+ /* We want a fast IRQ for this device. Actually we'd like an even faster
+ IRQ ;) - This is one driver RtLinux is made for */
+
+ if(request_irq(irq, &z8530_interrupt, SA_INTERRUPT, "SeaLevel", dev)<0)
+ {
+ printk(KERN_WARNING "sealevel: IRQ %d already in use.\n", irq);
+ goto fail2;
+ }
+
+ dev->irq=irq;
+ dev->chanA.private=&b->dev[0];
+ dev->chanB.private=&b->dev[1];
+ dev->chanA.netdevice=&b->dev[0].netdev.dev;
+ dev->chanB.netdevice=&b->dev[1].netdev.dev;
+ dev->chanA.dev=dev;
+ dev->chanB.dev=dev;
+ dev->name=b->dev[0].name;
+
+ dev->chanA.txdma=3;
+ dev->chanA.rxdma=1;
+ if(request_dma(dev->chanA.txdma, "SeaLevel (TX)")!=0)
+ goto fail;
+
+ if(request_dma(dev->chanA.rxdma, "SeaLevel (RX)")!=0)
+ goto dmafail;
+
+ save_flags(flags);
+ cli();
+
+ /*
+ * Begin normal initialise
+ */
+
+ if(z8530_init(dev)!=0)
+ {
+ printk(KERN_ERR "Z8530 series device not found.\n");
+ goto dmafail2;
+ }
+ if(dev->type==Z85C30)
+ {
+ z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream);
+ z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream);
+ }
+ else
+ {
+ z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream_85230);
+ z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream_85230);
+ }
+
+ /*
+ * Now we can take the IRQ
+ */
+
+ restore_flags(flags);
+
+ for(u=0; u<2; u++)
+ {
+ sv=&b->dev[u];
+ sv->channel = u;
+
+ for(i=0;i<999;i++)
+ {
+ sprintf(sv->name,"hdlc%d", i);
+ if(dev_get(sv->name)==NULL)
+ {
+ struct device *d=sv->chan->netdevice;
+
+ /*
+ * Initialise the PPP components
+ */
+ sppp_attach(&sv->netdev);
+
+ /*
+ * Local fields
+ */
+ sprintf(sv->name,"hdlc%d", i);
+
+ d->name = sv->name;
+ d->base_addr = iobase;
+ d->irq = irq;
+ d->priv = sv;
+ d->init = NULL;
+
+ d->open = sealevel_open;
+ d->stop = sealevel_close;
+ d->hard_start_xmit = sealevel_queue_xmit;
+ d->get_stats = sealevel_get_stats;
+ d->set_multicast_list = NULL;
+ d->do_ioctl = sealevel_ioctl;
+#ifdef LINUX_21
+ d->neigh_setup = sealevel_neigh_setup_dev;
+ dev_init_buffers(d);
+#else
+ d->init = return_0;
+#endif
+ d->set_mac_address = NULL;
+
+ if(register_netdev(d)==-1)
+ {
+ printk(KERN_ERR "%s: unable to register device.\n",
+ sv->name);
+ goto fail_unit;
+ }
+
+ break;
+ }
+ }
+ }
+ z8530_describe(dev, "I/O", iobase);
+ dev->active=1;
+ return b;
+
+fail_unit:
+ if(u==1)
+ unregister_netdev(b->dev[0].chan->netdevice);
+
+dmafail2:
+ free_dma(dev->chanA.rxdma);
+dmafail:
+ free_dma(dev->chanA.txdma);
+fail:
+ free_irq(irq, dev);
+fail2:
+ kfree(b);
+fail3:
+ release_region(iobase,8);
+ return NULL;
+}
+
+static void slvl_shutdown(struct slvl_board *b)
+{
+ int u;
+
+ z8530_shutdown(&b->board);
+
+ for(u=0; u<2; u++)
+ {
+ sppp_detach(&b->dev[u].netdev.dev);
+ unregister_netdev(&b->dev[u].netdev.dev);
+ }
+
+ free_irq(b->board.irq, &b->board);
+ free_dma(b->board.chanA.rxdma);
+ free_dma(b->board.chanA.txdma);
+ /* DMA off on the card, drop DTR */
+ outb(0, b->iobase);
+ release_region(b->iobase, 8);
+}
+
+#ifdef MODULE
+
+static int io=0x238;
+static int txdma=1;
+static int rxdma=3;
+static int irq=5;
+static int slow=0;
+
+#ifdef LINUX_21
+MODULE_PARM(io,"i");
+MODULE_PARM_DESC(io, "The I/O base of the Sealevel card");
+MODULE_PARM(txdma,"i");
+MODULE_PARM_DESC(txdma, "Transmit DMA channel");
+MODULE_PARM(rxdma,"i");
+MODULE_PARM_DESC(rxdma, "Receive DMA channel");
+MODULE_PARM(irq,"i");
+MODULE_PARM_DESC(irq, "The interrupt line setting for the SeaLevel card");
+MODULE_PARM(slow,"i");
+MODULE_PARM_DESC(slow, "Set this for an older Sealevel card such as the 4012");
+
+MODULE_AUTHOR("Bulding Number Three Ltd");
+MODULE_DESCRIPTION("Modular driver for the SeaLevel 4021");
+#endif
+
+static struct slvl_board *slvl_unit;
+
+int init_module(void)
+{
+ printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.01.\n");
+ printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n");
+ if((slvl_unit=slvl_init(io,irq, txdma, rxdma, slow))==NULL)
+ return -ENODEV;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if(slvl_unit)
+ slvl_shutdown(slvl_unit);
+}
+
+#endif
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/shaper.c linux.ac/drivers/net/shaper.c
--- linux.vanilla/drivers/net/shaper.c Thu Nov 19 18:38:38 1998
+++ linux.ac/drivers/net/shaper.c Fri Feb 19 10:41:11 1999
@@ -53,6 +53,13 @@
* This will be fixed in BETA4
*/
+/*
+ * bh_atomic() SMP races fixes and rewritten the locking code to be SMP safe
+ * and irq-mask friendly. NOTE: we can't use start_bh_atomic() in kick_shaper()
+ * because it's going to be recalled from an irq handler, and synchronize_bh()
+ * is a nono if called from irq context.
+ * 1999 Andrea Arcangeli
+ */
#include
#include
@@ -83,21 +90,17 @@
static int shaper_lock(struct shaper *sh)
{
- unsigned long flags;
- save_flags(flags);
- cli();
/*
- * Lock in an interrupt may fail
+ * Lock in an interrupt must fail
*/
- if(sh->locked && in_interrupt())
+ while (test_and_set_bit(0, &sh->locked))
{
- restore_flags(flags);
- return 0;
+ if (!in_interrupt())
+ sleep_on(&sh->wait_queue);
+ else
+ return 0;
+
}
- while(sh->locked)
- sleep_on(&sh->wait_queue);
- sh->locked=1;
- restore_flags(flags);
return 1;
}
@@ -105,7 +108,7 @@
static void shaper_unlock(struct shaper *sh)
{
- sh->locked=0;
+ clear_bit(0, &sh->locked);
wake_up(&sh->wait_queue);
shaper_kick(sh);
}
@@ -240,7 +243,6 @@
dev_kfree_skb(ptr);
}
shaper_unlock(shaper);
- shaper_kick(shaper);
return 0;
}
@@ -285,24 +287,16 @@
static void shaper_kick(struct shaper *shaper)
{
struct sk_buff *skb;
- unsigned long flags;
- save_flags(flags);
- cli();
-
- del_timer(&shaper->timer);
-
/*
* Shaper unlock will kick
*/
- if(shaper->locked)
- {
+ if (test_and_set_bit(0, &shaper->locked))
+ {
if(sh_debug)
printk("Shaper locked.\n");
- shaper->timer.expires=jiffies+1;
- add_timer(&shaper->timer);
- restore_flags(flags);
+ mod_timer(&shaper->timer, jiffies);
return;
}
@@ -320,7 +314,7 @@
if(sh_debug)
printk("Clock = %d, jiffies = %ld\n", skb->shapeclock, jiffies);
- if(skb->shapeclock - jiffies <= SHAPER_BURST)
+ if(time_before_eq(skb->shapeclock - jiffies, SHAPER_BURST))
{
/*
* Pull the frame and get interrupts back on.
@@ -329,8 +323,6 @@
skb_unlink(skb);
if (shaper->recovery < skb->shapeclock + skb->shapelen)
shaper->recovery = skb->shapeclock + skb->shapelen;
- restore_flags(flags);
-
/*
* Pass on to the physical target device via
* our low level packet thrower.
@@ -338,7 +330,6 @@
skb->shapepend=0;
shaper_queue_xmit(shaper, skb); /* Fire */
- cli();
}
else
break;
@@ -349,17 +340,9 @@
*/
if(skb!=NULL)
- {
- del_timer(&shaper->timer);
- shaper->timer.expires=skb->shapeclock;
- add_timer(&shaper->timer);
- }
-
- /*
- * Interrupts on, mission complete
- */
-
- restore_flags(flags);
+ mod_timer(&shaper->timer, skb->shapeclock);
+
+ clear_bit(0, &shaper->locked);
}
@@ -370,8 +353,14 @@
static void shaper_flush(struct shaper *shaper)
{
struct sk_buff *skb;
+ if(!shaper_lock(shaper))
+ {
+ printk(KERN_ERR "shaper: shaper_flush() called by an irq!\n");
+ return;
+ }
while((skb=skb_dequeue(&shaper->sendq))!=NULL)
dev_kfree_skb(skb);
+ shaper_unlock(shaper);
}
/*
@@ -405,7 +394,9 @@
{
struct shaper *shaper=dev->priv;
shaper_flush(shaper);
+ start_bh_atomic();
del_timer(&shaper->timer);
+ end_bh_atomic();
MOD_DEC_USE_COUNT;
return 0;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/smc-ultra.c linux.ac/drivers/net/smc-ultra.c
--- linux.vanilla/drivers/net/smc-ultra.c Tue Feb 23 14:21:33 1999
+++ linux.ac/drivers/net/smc-ultra.c Tue Feb 16 17:38:29 1999
@@ -2,7 +2,7 @@
/*
This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards.
- Written 1993-1996 by Donald Becker.
+ Written 1993-1998 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
@@ -14,7 +14,7 @@
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
- This driver uses the cards in the 8390-compatible, shared memory mode.
+ This driver uses the cards in the 8390-compatible mode.
Most of the run-time complexity is handled by the generic code in
8390.c. The code in this file is responsible for
@@ -27,6 +27,8 @@
ultra_block_input() Routines for reading and writing blocks of
ultra_block_output() packet buffer memory.
+ ultra_pio_input()
+ ultra_pio_output()
This driver enables the shared memory only when doing the actual data
transfers to avoid a bug in early version of the card that corrupted
@@ -34,7 +36,7 @@
This driver now supports the programmed-I/O (PIO) data transfer mode of
the EtherEZ. It does not use the non-8390-compatible "Altego" mode.
- That support (if available) is smc-ez.c.
+ That support (if available) is in smc-ez.c.
Changelog:
@@ -44,8 +46,7 @@
*/
static const char *version =
- "smc-ultra.c:v2.00 6/6/96 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
+ "smc-ultra.c:v2.02 2/3/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
#include
@@ -75,13 +76,13 @@
static void ultra_block_input(struct device *dev, int count,
struct sk_buff *skb, int ring_offset);
static void ultra_block_output(struct device *dev, int count,
- const unsigned char *buf, int start_page);
+ const unsigned char *buf, const int start_page);
static void ultra_pio_get_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
static void ultra_pio_input(struct device *dev, int count,
struct sk_buff *skb, int ring_offset);
static void ultra_pio_output(struct device *dev, int count,
- const unsigned char *buf, int start_page);
+ const unsigned char *buf, const int start_page);
static int ultra_close_card(struct device *dev);
@@ -155,11 +156,8 @@
if (load_8390_module("smc-ultra.c"))
return -ENOSYS;
- /* We should have a "dev" from Space.c or the static module table. */
- if (dev == NULL) {
- printk("smc-ultra.c: Passed a NULL device.\n");
+ if (dev == NULL)
dev = init_etherdev(0, 0);
- }
if (ei_debug && version_printed++ == 0)
printk(version);
@@ -255,12 +253,19 @@
ultra_open(struct device *dev)
{
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+ unsigned char irq2reg[] = {0, 0, 0x04, 0x08, 0, 0x0C, 0, 0x40,
+ 0, 0x04, 0x44, 0x48, 0, 0, 0, 0x4C, };
if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, dev))
return -EAGAIN;
outb(0x00, ioaddr); /* Disable shared memory for safety. */
outb(0x80, ioaddr + 5);
+ /* Set the IRQ line. */
+ outb(inb(ioaddr + 4) | 0x80, ioaddr + 4);
+ outb((inb(ioaddr + 13) & ~0x4C) | irq2reg[dev->irq], ioaddr + 13);
+ outb(inb(ioaddr + 4) & 0x7f, ioaddr + 4);
+
if (ei_status.block_input == &ultra_pio_input) {
outb(0x11, ioaddr + 6); /* Enable interrupts and PIO. */
outb(0x01, ioaddr + 0x19); /* Enable ring read auto-wrap. */
@@ -358,7 +363,7 @@
byte-sequentially to IOPA, with no intervening I/O operations, and the
data is read or written to the IOPD data port.
The only potential complication is that the address register is shared
- must be always be rewritten between each read/write direction change.
+ and must be always be rewritten between each read/write direction change.
This is no problem for us, as the 8390 code ensures that we are single
threaded. */
static void ultra_pio_get_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
@@ -379,20 +384,17 @@
/* For now set the address again, although it should already be correct. */
outb(ring_offset, ioaddr + IOPA); /* Set the address, LSB first. */
outb(ring_offset >> 8, ioaddr + IOPA);
+ /* We know skbuffs are padded to at least word alignment. */
insw(ioaddr + IOPD, buf, (count+1)>>1);
-#ifdef notdef
- /* We don't need this -- skbuffs are padded to at least word alignment. */
- if (count & 0x01) {
- buf[count-1] = inb(ioaddr + IOPD);
-#endif
}
static void ultra_pio_output(struct device *dev, int count,
- const unsigned char *buf, int start_page)
+ const unsigned char *buf, const int start_page)
{
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
outb(0x00, ioaddr + IOPA); /* Set the address, LSB first. */
outb(start_page, ioaddr + IOPA);
+ /* An extra odd byte is OK here as well. */
outsw(ioaddr + IOPD, buf, (count+1)>>1);
}
@@ -461,15 +463,12 @@
}
if (register_netdev(dev) != 0) {
printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]);
- if (found != 0) { /* Got at least one. */
- lock_8390_module();
- return 0;
- }
+ if (found != 0) return 0; /* Got at least one. */
return -ENXIO;
}
found++;
}
- lock_8390_module();
+
return 0;
}
@@ -481,15 +480,14 @@
for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
struct device *dev = &dev_ultra[this_dev];
if (dev->priv != NULL) {
+ /* NB: ultra_close_card() does free_irq + irq2dev */
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
- void *priv = dev->priv;
- /* NB: ultra_close_card() does free_irq */
+ kfree(dev->priv);
+ dev->priv = NULL;
release_region(ioaddr, ULTRA_IO_EXTENT);
unregister_netdev(dev);
- kfree(priv);
}
}
- unlock_8390_module();
}
#endif /* MODULE */
@@ -500,6 +498,7 @@
* version-control: t
* kept-new-versions: 5
* c-indent-level: 4
+ * c-basic-offset: 4
* tab-width: 4
* End:
*/
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/wavelan.c linux.ac/drivers/net/wavelan.c
--- linux.vanilla/drivers/net/wavelan.c Sun Nov 8 15:07:22 1998
+++ linux.ac/drivers/net/wavelan.c Thu Feb 18 20:32:39 1999
@@ -290,24 +290,26 @@
wv_16_on(ioaddr, hacr);
} /* psa_write */
-#ifdef PSA_CRC
+#ifdef SET_PSA_CRC
/*------------------------------------------------------------------*/
/*
- * Calculate the PSA CRC (not tested yet)
- * As the WaveLAN drivers don't use the CRC, I won't use it either.
- * Thanks to Nico Valster for the code
+ * Calculate the PSA CRC
+ * Thanks to Valster, Nico for the code
* NOTE: By specifying a length including the CRC position the
- * returned value should be zero. (i.e. a correct checksum in the PSA).
+ * returned value should be zero. (i.e. a correct checksum in the PSA)
+ *
+ * The Windows drivers don't use the CRC, but the AP and the PtP tool
+ * depend on it.
*/
-static u_short
-psa_crc(u_short * psa, /* The PSA */
+static inline u_short
+psa_crc(u_char * psa, /* The PSA */
int size) /* Number of short for CRC */
{
int byte_cnt; /* Loop on the PSA */
u_short crc_bytes = 0; /* Data in the PSA */
int bit_cnt; /* Loop on the bits of the short */
- for(byte_cnt = 0; byte_cnt <= size; byte_cnt++ )
+ for(byte_cnt = 0; byte_cnt < size; byte_cnt++ )
{
crc_bytes ^= psa[byte_cnt]; /* Its an xor */
@@ -322,7 +324,47 @@
return crc_bytes;
} /* psa_crc */
-#endif /* PSA_CRC */
+
+/*------------------------------------------------------------------*/
+/*
+ * update the checksum field in the Wavelan's PSA
+ */
+static void
+update_psa_checksum(device * dev,
+ u_long ioaddr,
+ u_short hacr)
+{
+ psa_t psa;
+ u_short crc;
+
+ /* read the parameter storage area */
+ psa_read(ioaddr, hacr, 0, (unsigned char *) &psa, sizeof(psa));
+
+ /* update the checksum */
+ crc = psa_crc((unsigned char *) &psa,
+ sizeof(psa) - sizeof(psa.psa_crc[0]) - sizeof(psa.psa_crc[1])
+ - sizeof(psa.psa_crc_status));
+
+ psa.psa_crc[0] = crc & 0xFF;
+ psa.psa_crc[1] = (crc & 0xFF00) >> 8;
+
+ /* Write it ! */
+ psa_write(ioaddr, hacr, (char *)&psa.psa_crc - (char *)&psa,
+ (unsigned char *)&psa.psa_crc, 2);
+
+#ifdef DEBUG_IOCTL_INFO
+ printk (KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n",
+ dev->name, psa.psa_crc[0], psa.psa_crc[1]);
+
+ /* Check again (luxury !) */
+ crc = psa_crc ((unsigned char *) &psa,
+ sizeof(psa) - sizeof(psa.psa_crc_status));
+
+ if(crc != 0)
+ printk(KERN_WARNING "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", dev->name);
+#endif /* DEBUG_IOCTL_INFO */
+} /* update_psa_checksum */
+#endif /* SET_PSA_CRC */
/*------------------------------------------------------------------*/
/*
@@ -706,21 +748,21 @@
unsigned short ias_addr;
/* Check mc_config command */
- if(status & AC_SFLD_OK != 0)
+ if((status & AC_SFLD_OK) != 0)
printk(KERN_INFO "wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
dev->name, str, status);
/* check ia-config command */
ias_addr = mcs_addr - sizeof(ac_ias_t);
obram_read(ioaddr, acoff(ias_addr, ac_status), (unsigned char *)&status, sizeof(status));
- if(status & AC_SFLD_OK != 0)
+ if((status & AC_SFLD_OK) != 0)
printk(KERN_INFO "wv_config_complete(): set_MAC_address; status = 0x%x\n",
dev->name, str, status);
/* Check config command. */
cfg_addr = ias_addr - sizeof(ac_cfg_t);
obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status));
- if(status & AC_SFLD_OK != 0)
+ if((status & AC_SFLD_OK) != 0)
printk(KERN_INFO "wv_config_complete(): configure; status = 0x%x\n",
dev->name, str, status);
#endif /* DEBUG_CONFIG_ERROR */
@@ -1890,6 +1932,10 @@
/* Disable NWID in the mmc (no filtering). */
mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
}
+#ifdef SET_PSA_CRC
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+#endif
break;
case SIOCGIWNWID:
@@ -1946,6 +1992,10 @@
psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;
psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
(unsigned char *) &psa.psa_thr_pre_set, 1);
+#ifdef SET_PSA_CRC
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+#endif
mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set);
break;
@@ -1993,6 +2043,10 @@
mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
}
+#ifdef SET_PSA_CRC
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+#endif
break;
case SIOCGIWENCODE:
@@ -2206,6 +2260,10 @@
psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
(unsigned char *)&psa.psa_quality_thr, 1);
+#ifdef SET_PSA_CRC
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+#endif
mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr);
break;
@@ -2316,7 +2374,7 @@
mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
/* Copy data to wireless stuff. */
- wstats->status = m.mmr_dce_status;
+ wstats->status = m.mmr_dce_status & MMR_DCE_STATUS;
wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL;
wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL;
wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL;
@@ -2892,6 +2950,10 @@
(unsigned char *)&psa.psa_quality_thr, 1);
psa_write(ioaddr, lp->hacr, (char *)&psa.psa_conf_status - (char *)&psa,
(unsigned char *)&psa.psa_conf_status, 1);
+#ifdef SET_PSA_CRC
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+#endif
#endif
}
@@ -2918,21 +2980,18 @@
m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F;
m.mmw_quality_thr = psa.psa_quality_thr & 0x0F;
- /* Encryption stuff is missing. */
-
/*
* Set default modem control parameters.
* See NCR document 407-0024326 Rev. A.
*/
m.mmw_jabber_enable = 0x01;
+ m.mmw_freeze = 0;
m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN;
m.mmw_ifs = 0x20;
m.mmw_mod_delay = 0x04;
m.mmw_jam_time = 0x38;
- m.mmw_encr_enable = 0;
m.mmw_des_io_invert = 0;
- m.mmw_freeze = 0;
m.mmw_decay_prm = 0;
m.mmw_decay_updat_prm = 0;
@@ -3398,39 +3457,29 @@
/* Create a configure action. */
memset(&cfg, 0x00, sizeof(cfg));
-#if 0
- /*
- * The default board configuration
- */
- cfg.fifolim_bytecnt = 0x080c;
- cfg.addrlen_mode = 0x2600;
- cfg.linprio_interframe = 0x7820; /* IFS=120, ACS=2 */
- cfg.slot_time = 0xf00c; /* slottime=12 */
- cfg.hardware = 0x0008; /* tx even without CD */
- cfg.min_frame_len = 0x0040;
-#endif /* 0 */
-
/*
* For Linux we invert AC_CFG_ALOC() so as to conform
* to the way that net packets reach us from above.
* (See also ac_tx_t.)
+ *
+ * Updated from Wavelan Manual WCIN085B
*/
cfg.cfg_byte_cnt = AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t));
- cfg.cfg_fifolim = AC_CFG_FIFOLIM(8);
- cfg.cfg_byte8 = AC_CFG_SAV_BF(0) |
+ cfg.cfg_fifolim = AC_CFG_FIFOLIM(4);
+ cfg.cfg_byte8 = AC_CFG_SAV_BF(1) |
AC_CFG_SRDY(0);
cfg.cfg_byte9 = AC_CFG_ELPBCK(0) |
AC_CFG_ILPBCK(0) |
AC_CFG_PRELEN(AC_CFG_PLEN_2) |
AC_CFG_ALOC(1) |
AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE);
- cfg.cfg_byte10 = AC_CFG_BOFMET(0) |
- AC_CFG_ACR(0) |
+ cfg.cfg_byte10 = AC_CFG_BOFMET(1) |
+ AC_CFG_ACR(6) |
AC_CFG_LINPRIO(0);
- cfg.cfg_ifs = 32;
- cfg.cfg_slotl = 0;
+ cfg.cfg_ifs = 0x20;
+ cfg.cfg_slotl = 0x0C;
cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) |
- AC_CFG_SLTTMHI(2);
+ AC_CFG_SLTTMHI(0);
cfg.cfg_byte14 = AC_CFG_FLGPAD(0) |
AC_CFG_BTSTF(0) |
AC_CFG_CRC16(0) |
@@ -4016,6 +4065,10 @@
#endif
psa_write(ioaddr, HACR_DEFAULT,
psaoff(0, psa_int_req_no), &irq_mask, 1);
+#ifdef SET_PSA_CRC
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, HACR_DEFAULT);
+#endif
wv_hacr_reset(ioaddr);
}
}
@@ -4196,7 +4249,7 @@
init_module(void)
{
mac_addr mac; /* MAC address (check WaveLAN existence) */
- int ret = 0;
+ int ret = -EIO; /* Return error if no cards found */
int i;
#ifdef DEBUG_MODULE_TRACE
@@ -4241,7 +4294,11 @@
/* Deallocate everything. */
/* Note: if dev->priv is mallocated, there is no way to fail. */
kfree_s(dev, sizeof(struct device));
- ret = -EIO;
+ }
+ else
+ {
+ /* If at least one device OK, we do not fail */
+ ret = 0;
}
} /* if there is something at the address */
} /* Loop on all addresses. */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/wavelan.h linux.ac/drivers/net/wavelan.h
--- linux.vanilla/drivers/net/wavelan.h Sun Nov 8 15:07:24 1998
+++ linux.ac/drivers/net/wavelan.h Thu Feb 18 20:32:39 1999
@@ -28,6 +28,8 @@
{
{ 0x08, 0x00, 0x0E }, /* AT&T WaveLAN (standard) & DEC RoamAbout */
{ 0x08, 0x00, 0x6A }, /* AT&T WaveLAN (alternate) */
+ { 0x00, 0x00, 0xE1 }, /* Hitachi Wavelan */
+ { 0x00, 0x60, 0x1D } /* Lucent Wavelan (another one) */
/* Add your card here and send me the patch! */
};
@@ -293,6 +295,7 @@
#define MMR_DCE_STATUS_LOOPT_IND 0x02 /* loop test indicated */
#define MMR_DCE_STATUS_TX_BUSY 0x04 /* transmitter on */
#define MMR_DCE_STATUS_JBR_EXPIRED 0x08 /* jabber timer expired */
+#define MMR_DCE_STATUS 0x0F /* mask to get the bits */
unsigned char mmr_dsp_id; /* DSP ID (AA = Daedalus rev A) */
unsigned char mmr_unused2[2]; /* unused */
unsigned char mmr_correct_nwid_l; /* # of correct NWIDs rxd (low) */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/wavelan.p.h linux.ac/drivers/net/wavelan.p.h
--- linux.vanilla/drivers/net/wavelan.p.h Sun Nov 8 15:07:28 1998
+++ linux.ac/drivers/net/wavelan.p.h Fri Feb 26 20:11:50 1999
@@ -18,13 +18,7 @@
* This driver provides a Linux interface to the WaveLAN ISA hardware.
* The WaveLAN is a product of Lucent (http://www.wavelan.com/).
* This division was formerly part of NCR and then AT&T.
- * WaveLANs are also distributed by DEC (RoamAbout), Digital Ocean and
- * Aironet (Arlan). If you have one of those products, you will need to
- * make some changes below.
- *
- * This driver is still beta software. A lot of bugs have been corrected,
- * a lot of functionality is implemented, and the whole appears stable,
- * but there is still room for improvement (encryption, performance).
+ * WaveLANs are also distributed by DEC (RoamAbout DS) and Digital Ocean.
*
* To learn how to use this driver, read the NET3 HOWTO.
* If you want to exploit the many other functionalities, read the comments
@@ -35,12 +29,22 @@
/* ------------------------ SPECIFIC NOTES ------------------------ */
/*
+ * Web page
+ * --------
+ * I try to maintain a web page with the Wireless LAN Howto at :
+ * http://www-uk.hpl.hp.com/people/jt/Linux/Wavelan.html
+ *
* wavelan.o is too darned big
* ---------------------------
* That's true! There is a very simple way to reduce the driver
* object by 33%! Comment out the following line:
* #include
*
+ * Debugging and options
+ * ---------------------
+ * You will find below a set of '#define" allowing a very fine control
+ * on the driver behaviour and the debug messages printed.
+ *
* MAC address and hardware detection:
* -----------------------------------
* The detection code for the WaveLAN checks that the first three
@@ -60,23 +64,6 @@
* 3) Compile and verify
* 4) Send me the MAC code. I will include it in the next version.
*
- * "CU Inactive" message at boot up:
- * -----------------------------------
- * It seems that there is some weird timing problem with the
- * Intel microcontroller. In fact, this message is triggered by a
- * bad reading of the onboard RAM the first time we read the
- * control block. If you ignore this message, all is OK (but in
- * fact, currently, it resets the WaveLAN hardware).
- *
- * There are two ways to get rid of that problem. The first
- * is to add a dummy read of the scb at the end of
- * wv_82586_config. The second is to add the timers
- * wv_synchronous_cmd and wv_ack (the udelay just after the
- * waiting loops--it seems that the controller is not totally ready
- * when it says it is).
- *
- * In the current code, I use the second solution (to be
- * consistent with the original solution of Bruce Janson).
*/
/* --------------------- WIRELESS EXTENSIONS --------------------- */
@@ -273,6 +260,22 @@
* - encryption setting from Brent Elphick (thanks a lot!)
* - 'ioaddr' to 'u_long' for the Alpha (thanks to Stanislav Sinyagin)
*
+ * Other changes (not by me) :
+ * -------------------------
+ * - Spelling and gramar "rectification".
+ *
+ * Changes made for release in 2.0.37 & 2.2.2 :
+ * ------------------------------------------
+ * - Correct status in /proc/net/wireless
+ * - Set PSA CRC to make PtP diagnostic tool happy (Bob Gray)
+ * - Module init code don't fail if we found at least one card in
+ * the address list (Karlis Peisenieks)
+ * - Missing parenthesis (Christopher Peterson)
+ * - Correct i82586 configuration parameters
+ * - Encryption initialisation bug (Robert McCormack)
+ * - New mac addresses detected in the probe
+ * - Increase watchdog for busy envirnoments
+ *
* Wishes & dreams:
* ----------------
* - roaming
@@ -342,9 +345,9 @@
/* Options */
#define USE_PSA_CONFIG /* Use info from the PSA. */
+#define SET_PSA_CRC /* Calculate and set the CRC on PSA */
#define IGNORE_NORMAL_XMIT_ERRS /* Don't bother with normal conditions. */
#undef STRUCT_CHECK /* Verify padding of structures. */
-#undef PSA_CRC /* Check CRC in PSA. */
#undef OLDIES /* old code (to redo) */
#undef RECORD_SNR /* to redo */
#undef EEPROM_IS_PROTECTED /* doesn't seem to be necessary */
@@ -359,11 +362,11 @@
/************************ CONSTANTS & MACROS ************************/
#ifdef DEBUG_VERSION_SHOW
-static const char *version = "wavelan.c : v16 (wireless extensions) 17/4/97\n";
+static const char *version = "wavelan.c : v18 (wireless extensions) 18/2/99\n";
#endif
/* Watchdog temporisation */
-#define WATCHDOG_JIFFIES 32 /* TODO: express in HZ. */
+#define WATCHDOG_JIFFIES 256 /* TODO: express in HZ. */
/* Macro to get the number of elements in an array */
#define NELS(a) (sizeof(a) / sizeof(a[0]))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/53c7,8xx.c linux.ac/drivers/scsi/53c7,8xx.c
--- linux.vanilla/drivers/scsi/53c7,8xx.c Sun Nov 8 15:07:50 1998
+++ linux.ac/drivers/scsi/53c7,8xx.c Sun Nov 8 14:35:40 1998
@@ -1901,7 +1901,8 @@
*/
timeout = jiffies + 5 * HZ / 10;
- while ((hostdata->test_completed == -1) && jiffies < timeout)
+ while ((hostdata->test_completed == -1) &&
+ time_before(jiffies,timeout))
barrier();
failed = 1;
@@ -1986,7 +1987,8 @@
restore_flags(flags);
timeout = jiffies + 5 * HZ; /* arbitrary */
- while ((hostdata->test_completed == -1) && jiffies < timeout)
+ while ((hostdata->test_completed == -1) &&
+ time_before(jiffies, timeout))
barrier();
NCR53c7x0_write32 (DSA_REG, 0);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/53c7xx.c linux.ac/drivers/scsi/53c7xx.c
--- linux.vanilla/drivers/scsi/53c7xx.c Sun Nov 8 15:07:55 1998
+++ linux.ac/drivers/scsi/53c7xx.c Thu Dec 17 01:56:08 1998
@@ -298,6 +298,10 @@
*/
#undef inb
#undef outb
+#undef inw
+#undef outw
+#undef inl
+#undef outl
#define inb(x) 1
#define inw(x) 1
#define inl(x) 1
@@ -1612,7 +1616,8 @@
*/
timeout = jiffies + 5 * HZ / 10;
- while ((hostdata->test_completed == -1) && jiffies < timeout)
+ while ((hostdata->test_completed == -1) &&
+ time_before(jiffies, timeout))
barrier();
failed = 1;
@@ -1698,7 +1703,8 @@
restore_flags(flags);
timeout = jiffies + 5 * HZ; /* arbitrary */
- while ((hostdata->test_completed == -1) && jiffies < timeout)
+ while ((hostdata->test_completed == -1) &&
+ time_before(jiffies, timeout))
barrier();
NCR53c7x0_write32 (DSA_REG, 0);
@@ -1899,7 +1905,7 @@
if (left < 0)
printk("scsi%d: loop detected in ncr reconncect list\n",
host->host_no);
- else if (ncr_search)
+ else if (ncr_search) {
if (found)
printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n",
host->host_no, c->pid);
@@ -1910,6 +1916,7 @@
/* If we're at the tail end of the issue queue, update that pointer too. */
found = 1;
}
+ }
/*
* Traverse the host running list until we find this command or discover
@@ -2960,14 +2967,14 @@
NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM);
else
NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl);
-#if 0
- /* Following disables snooping - run with caches disabled at first */
+ /* Following disables snooping - snooping is not required, as non-
+ * cached pages are used for shared data, and appropriate use is
+ * made of cache_push/cache_clear. Indeed, for 68060
+ * enabling snooping causes disk corruption of ext2fs free block
+ * bitmaps and the like. If you have a 68060 with snooping hardwared
+ * on, then you need to enable CONFIG_060_WRITETHROUGH.
+ */
NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD);
-#else
- /* Setup CTEST7 for SC1=0, SC0=1 - sink/source data without invalidating
- * cache lines. */
- NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD|CTEST7_10_SC0);
-#endif
/* Actually burst of eight, according to my 53c710 databook */
NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2);
NCR53c7x0_write8(SCID_REG, 1 << host->this_id);
@@ -5947,11 +5954,12 @@
}
}
}
- if (!(istat & (ISTAT_SIP|ISTAT_DIP)))
+ if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {
if (stage == 0)
++stage;
else if (stage == 3)
break;
+ }
}
hostdata->state = STATE_HALTED;
restore_flags(flags);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/Config.in linux.ac/drivers/scsi/Config.in
--- linux.vanilla/drivers/scsi/Config.in Sun Jan 3 03:52:01 1999
+++ linux.ac/drivers/scsi/Config.in Wed Feb 3 21:55:04 1999
@@ -25,10 +25,8 @@
dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI
dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then
- bool ' Override driver defaults for commands per LUN' CONFIG_OVERRIDE_CMDS N
- if [ "$CONFIG_OVERRIDE_CMDS" != "n" ]; then
- int ' Maximum number of commands per LUN' CONFIG_AIC7XXX_CMDS_PER_LUN 24
- fi
+ bool ' Enable Tagged Command Queueing (TCQ) by default' CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+ int ' Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 8
bool ' Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS N
int ' Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5
fi
@@ -66,6 +64,7 @@
fi
if [ "$CONFIG_PCI" = "y" ]; then
dep_tristate 'Initio 9100U(W) support' CONFIG_SCSI_INITIO $CONFIG_SCSI
+ dep_tristate 'Initio INI-A100U2W support' CONFIG_SCSI_INIA100 $CONFIG_SCSI
fi
if [ "$CONFIG_PARPORT" != "n" ]; then
dep_tristate 'IOMEGA parallel port (ppa - older drives)' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
@@ -76,6 +75,7 @@
fi
fi
dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI
+dep_tristate 'symbios 53c416 SCSI support' CONFIG_SCSI_SYM53C416 $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" ]; then
dep_tristate 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI
if [ "$CONFIG_SCSI_NCR53C7xx" != "n" ]; then
@@ -117,7 +117,7 @@
dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" ]; then
dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
-# dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI
+ dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI
fi
dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" ]; then
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/Makefile linux.ac/drivers/scsi/Makefile
--- linux.vanilla/drivers/scsi/Makefile Sun Jan 3 03:52:01 1999
+++ linux.ac/drivers/scsi/Makefile Sat Jan 30 18:29:12 1999
@@ -298,6 +298,14 @@
endif
endif
+ifeq ($(CONFIG_SCSI_INIA100),y)
+L_OBJS += a100u2w.o
+else
+ ifeq ($(CONFIG_SCSI_INIA100),m)
+ M_OBJS += a100u2w.o
+ endif
+endif
+
ifeq ($(CONFIG_SCSI_QLOGIC_FC),y)
L_OBJS += qlogicfc.o
else
@@ -576,6 +584,14 @@
endif
endif
+ifeq ($(CONFIG_SCSI_SYM53C416),y)
+L_OBJS += sym53c416.o
+else
+ ifeq ($(CONFIG_SCSI_SYM53C416),m)
+ M_OBJS += sym53c416.o
+ endif
+endif
+
ifeq ($(CONFIG_BLK_DEV_IDESCSI),y)
L_OBJS += ide-scsi.o
else
@@ -616,6 +632,9 @@
$(CC) $(CFLAGS) -c i91uscsi.c -o i91uscsi.o
$(LD) -r -o initio.o ini9100u.o i91uscsi.o
rm -f ini9100u.o i91uscsi.o
+
+a100u2w.o: inia100.o i60uscsi.o
+ $(LD) -r -o a100u2w.o inia100.o i60uscsi.o
megaraid.o: megaraid.c
$(CC) $(CFLAGS) -c megaraid.c
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/README.aic7xxx linux.ac/drivers/scsi/README.aic7xxx
--- linux.vanilla/drivers/scsi/README.aic7xxx Wed Jan 6 23:02:22 1999
+++ linux.ac/drivers/scsi/README.aic7xxx Wed Feb 3 21:55:04 1999
@@ -17,6 +17,7 @@
AHA-274xT
AHA-2842
AHA-2910B
+ AHA-2920C
AHA-2940
AHA-2940W
AHA-2940U
@@ -77,8 +78,8 @@
Adaptec Cards
----------------------------
AHA-2920 (Only the cards that use the Future Domain chipset are not
- supported, any 2920 cards based on Adaptec AIC chipsets are
- supported)
+ supported, any 2920 cards based on Adaptec AIC chipsets,
+ such as the 2920C, are supported)
AAA-13x Raid Adapters
AAA-113x Raid Port Card
@@ -325,11 +326,12 @@
list and someone can help you out.
"aic7xxx=tag_info:{{8,8..},{8,8..},..}" - This option is used to disable
- tagged queueing on specific devices. As of driver version 5.1.8, we
- now globally enable tagged queueing by default. In order to
- disable tagged queueing for certian devices at boot time, a user may
- use this boot param. The driver will then parse this message out
- and disable the specific device entries that are present based upon
+ or enable Tagged Command Queueing (TCQ) on specific devices. As of
+ driver version 5.1.11, TCQ is now either on or off by default
+ according to the setting you choose during the make config process.
+ In order to en/disable TCQ for certian devices at boot time, a user
+ may use this boot param. The driver will then parse this message out
+ and en/disable the specific device entries that are present based upon
the value given. The param line is parsed in the following manner:
{ - first instance indicates the start of this parameter values
@@ -419,10 +421,10 @@
see this documentation, you need to use one of the advanced configuration
programs (menuconfig and xconfig). If you are using the "make menuconfig"
method of configuring your kernel, then you would simply highlight the
- option in question and hit the F1 key. If you are using the "make xconfig"
- method of configuring your kernel, then simply click on the help button next
- to the option you have questions about. The help information from the
- Configure.help file will then get automatically displayed.
+ option in question and hit the ? key. If you are using the "make xconfig"
+ method of configuring your kernel, then simply click on the help button
+ next to the option you have questions about. The help information from
+ the Configure.help file will then get automatically displayed.
/proc support
------------------------------
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx.c linux.ac/drivers/scsi/aic7xxx.c
--- linux.vanilla/drivers/scsi/aic7xxx.c Tue Jan 19 02:57:30 1999
+++ linux.ac/drivers/scsi/aic7xxx.c Wed Feb 3 21:55:05 1999
@@ -354,7 +354,7 @@
0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-#define AIC7XXX_C_VERSION "5.1.10"
+#define AIC7XXX_C_VERSION "5.1.11"
#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
@@ -447,10 +447,10 @@
* You can try raising me if tagged queueing is enabled, or lowering
* me if you only have 4 SCBs.
*/
-#ifdef CONFIG_AIC7XXX_CMDS_PER_LUN
-#define AIC7XXX_CMDS_PER_LUN CONFIG_AIC7XXX_CMDS_PER_LUN
+#ifdef CONFIG_AIC7XXX_CMDS_PER_DEVICE
+#define AIC7XXX_CMDS_PER_DEVICE CONFIG_AIC7XXX_CMDS_PER_DEVICE
#else
-#define AIC7XXX_CMDS_PER_LUN 24
+#define AIC7XXX_CMDS_PER_DEVICE 8
#endif
/* Set this to the delay in seconds after SCSI bus reset. */
@@ -495,7 +495,7 @@
*
* *** Determining commands per LUN ***
*
- * When AIC7XXX_CMDS_PER_LUN is not defined, the driver will use its
+ * When AIC7XXX_CMDS_PER_DEVICE is not defined, the driver will use its
* own algorithm to determine the commands/LUN. If SCB paging is
* enabled, which is always now, the default is 8 commands per lun
* that indicates it supports tagged queueing. All non-tagged devices
@@ -513,8 +513,13 @@
* Make a define that will tell the driver not to use tagged queueing
* by default.
*/
+#ifdef CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT
+#define DEFAULT_TAG_COMMANDS {0, 0, 0, 0, 0, 0, 0, 0,\
+ 0, 0, 0, 0, 0, 0, 0, 0}
+#else
#define DEFAULT_TAG_COMMANDS {255, 255, 255, 255, 255, 255, 255, 255,\
255, 255, 255, 255, 255, 255, 255, 255}
+#endif
/*
* Modify this as you see fit for your system. By setting tag_commands
@@ -553,6 +558,27 @@
};
*/
+static adapter_tag_info_t aic7xxx_tag_info[] =
+{
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS},
+ {DEFAULT_TAG_COMMANDS}
+};
+
+
/*
* Define an array of board names that can be indexed by aha_type.
* Don't forget to change this when changing the types!
@@ -1410,35 +1436,6 @@
#endif
-/*
- * See the comments earlier in the file for what this item is all about
- * If you have more than 4 controllers, you will need to increase the
- * the number of items in the array below. Additionally, if you don't
- * want to have lilo pass a humongous config line to the aic7xxx driver,
- * then you can get in and manually adjust these instead of leaving them
- * at the default. Pay attention to the comments earlier in this file
- * concerning this array if you are going to hand modify these values.
- */
-static adapter_tag_info_t aic7xxx_tag_info[] =
-{
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS},
- {DEFAULT_TAG_COMMANDS}
-};
-
#define VERBOSE_NORMAL 0x0000
#define VERBOSE_NEGOTIATION 0x0001
#define VERBOSE_SEQINT 0x0002
@@ -3625,7 +3622,7 @@
if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
printk(INFO_LEAD "Cleaning disconnected scbs "
"list.\n", p->host_no, channel, target, lun);
- if (p->features & AHC_PAGESCBS)
+ if (p->flags & AHC_PAGESCBS)
{
unsigned char next, prev, scb_index;
@@ -3677,7 +3674,7 @@
* Walk the free list making sure no entries on the free list have
* a valid SCB_TAG value or SCB_CONTROL byte.
*/
- if (p->features & AHC_PAGESCBS)
+ if (p->flags & AHC_PAGESCBS)
{
unsigned char next;
@@ -6368,7 +6365,7 @@
* Determines the queue depth for a given device. There are two ways
* a queue depth can be obtained for a tagged queueing device. One
* way is the default queue depth which is determined by whether
- * AIC7XXX_CMDS_PER_LUN is defined. If it is defined, then it is used
+ * AIC7XXX_CMDS_PER_DEVICE is defined. If it is defined, then it is used
* as the default queue depth. Otherwise, we use either 4 or 8 as the
* default queue depth (dependent on the number of hardware SCBs).
* The other way we determine queue depth is through the use of the
@@ -6396,7 +6393,7 @@
{
int tag_enabled = TRUE;
- default_depth = AIC7XXX_CMDS_PER_LUN;
+ default_depth = AIC7XXX_CMDS_PER_DEVICE;
if (!(p->discenable & target_mask))
{
@@ -8184,14 +8181,16 @@
{
printk("aic7xxx: Using leftover BIOS values.\n");
}
- if ( *sxfrctl1 & STPWEN )
+ if ( ((p->chip & ~AHC_CHIPID_MASK) == AHC_PCI) && (*sxfrctl1 & STPWEN) )
{
p->flags |= AHC_TERM_ENB_SE_LOW | AHC_TERM_ENB_SE_HIGH;
sc->adapter_control &= ~CFAUTOTERM;
sc->adapter_control |= CFSTERM | CFWSTERM | CFLVDSTERM;
}
if (aic7xxx_extended)
- p->flags |= AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B;
+ p->flags |= (AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B);
+ else
+ p->flags &= ~(AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B);
}
else
{
@@ -9212,20 +9211,9 @@
aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
CACHETHEN | MPARCKEN | USCBSIZE32 |
CIOPARCKEN) & ~DPARCKEN, DSCOMMAND0);
- /* FALLTHROUGH */
- default:
- /*
- * We attempt to read a SEEPROM on *everything*. If we fail,
- * then we fail, but this covers things like 2910c cards that
- * now have SEEPROMs with their 7856 chipset that we would
- * otherwise ignore. They still don't have a BIOS, but they
- * have a SEEPROM that the SCSISelect utility on the Adaptec
- * diskettes can configure.
- */
aic7xxx_load_seeprom(temp_p, &sxfrctl1);
break;
- case AHC_AIC7850:
- case AHC_AIC7860:
+ default:
/*
* Set the DSCOMMAND0 register on these cards different from
* on the 789x cards. Also, read the SEEPROM as well.
@@ -9233,27 +9221,7 @@
aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
CACHETHEN | MPARCKEN) & ~DPARCKEN,
DSCOMMAND0);
- aic7xxx_load_seeprom(temp_p, &sxfrctl1);
- break;
- case AHC_AIC7880:
- /*
- * Only set the DSCOMMAND0 register if this is a Rev B.
- * chipset. For those, we also enable Ultra mode by
- * force due to brain-damage on the part of some BIOSes
- * We overload the devconfig variable here since we can.
- */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
- pci_read_config_dword(pdev, DEVCONFIG, &devconfig);
-#else
- pcibios_read_config_dword(pci_bus, pci_devfn, DEVCONFIG,
- &devconfig);
-#endif
- if ((devconfig & 0xff) >= 1)
- {
- aic_outb(temp_p, (aic_inb(temp_p, DSCOMMAND0) |
- CACHETHEN | MPARCKEN) & ~DPARCKEN,
- DSCOMMAND0);
- }
+ case AHC_AIC7895:
aic7xxx_load_seeprom(temp_p, &sxfrctl1);
break;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/amiga7xx.c linux.ac/drivers/scsi/amiga7xx.c
--- linux.vanilla/drivers/scsi/amiga7xx.c Sun Nov 8 15:07:55 1998
+++ linux.ac/drivers/scsi/amiga7xx.c Thu Dec 17 01:56:25 1998
@@ -15,6 +15,7 @@
#include
#include
+#include