diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/CREDITS linux.ac/CREDITS
--- linux.vanilla/CREDITS Thu Jan 28 22:00:13 1999
+++ linux.ac/CREDITS Tue Feb 16 16:54:42 1999
@@ -1403,6 +1403,13 @@
S: FIN-00330 Helsingfors
S: Finland
+N: Trond Myklebust
+E: trond.myklebust@fys.uio.no
+D: current NFS client hacker.
+S: Dagaliveien 31e
+S: N-0391 Oslo
+S: Norway
+
N: Matija Nalis
E: mnalis@jagor.srce.hr
E: mnalis@voyager.hr
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/00-INDEX linux.ac/Documentation/00-INDEX
--- linux.vanilla/Documentation/00-INDEX Tue Dec 22 23:19:23 1998
+++ linux.ac/Documentation/00-INDEX Thu Feb 4 02:03:33 1999
@@ -57,6 +57,8 @@
- info on the in-kernel binary support for Java(tm)
joystick.txt
- info on using joystick devices (and driver) with linux.
+kbuild/
+ - directory with info about the kernel build process
kmod.txt
- - info on the kernel module loader/unloader (kerneld replacement)
locks.txt
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 Sun Jan 24 19:55:29 1999
+++ linux.ac/Documentation/Configure.help Tue Feb 16 18:09:33 1999
@@ -1749,6 +1749,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
@@ -1807,7 +1819,7 @@
This is the frame buffer device driver for generic VESA 2.0
compliant graphic cards. The older VESA 1.2 cards are not supported.
You will get a boot time penguin logo at no additional cost. Please
- read Documentation/fb/vesafb.txt and the . If unsure, say Y.
+ read Documentation/fb/vesafb.txt and the HOWTO. If unsure, say Y.
Backward compatibility mode for Xpmac
CONFIG_FB_COMPAT_XPMAC
@@ -2330,8 +2342,8 @@
IP: firewall packet netlink device
CONFIG_IP_FIREWALL_NETLINK
- If you say Y here, then the first 128 bytes of each packet that hit
- your Linux firewall and was blocked are passed on to optional user
+ If you say Y here, you can use the ipchains tool to copy all or part of
+ any packet you specify that hits your Linux firewall to optional user
space monitoring software that can then look for attacks and take
actions such as paging the administrator of the site.
@@ -2340,9 +2352,6 @@
and you need (to write) a program that reads from that device and
takes appropriate action.
- With the ipchains tool you can specify which packets you want to go
- to this device, as well as how many bytes from each packet.
-
IP: kernel level autoconfiguration
CONFIG_IP_PNP
This enables automatic configuration of IP addresses of devices and
@@ -2709,20 +2718,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
@@ -3675,34 +3670,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.
+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 unsure, say N.
-
-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).
+ 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.
- 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
@@ -4176,6 +4186,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
@@ -4189,6 +4210,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
@@ -4366,6 +4398,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
@@ -5206,27 +5255,6 @@
up to 256Kbits. It supports both PPP and Cisco HDLC
At this point, the driver can only be compiled as a module.
-COSA/SRP sync serial boards support
-CONFIG_COSA
- This is a driver for COSA and SRP synchronous serial boards.
- These boards enable to connect synchronous serial devices (for
- example base-band modems, or any other device with the X.21, V.24,
- V.35 or V.36 interface) to your Linux box. The cards can work
- as the character device, synchronous PPP network device, or the Cisco
- HDLC network device.
-
- To actually use the COSA or SRP board, you will need user-space
- utilities for downloading the firmware to the cards and to set
- them up. Look at the http://www.fi.muni.cz/~kas/cosa/ for more
- information about the cards (including the pointer to the user-space
- utilities). You can also read the comment at the top of the
- drivers/net/cosa.c for details about the cards and the driver itself.
-
- The driver will be compiled as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called cosa.o. For general information about
- modules read Documentation/modules.txt.
-
WAN Drivers
CONFIG_WAN_DRIVERS
Say Y to this option if your Linux box contains a WAN card and you
@@ -9353,6 +9381,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
@@ -10394,6 +10427,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 /dev/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
@@ -10626,27 +10697,12 @@
Say Y here if you want to build support for the IrLAN protocol. If
you want to compile it as a module, say M here and read
Documentation/modules.txt. IrLAN emulates an Ethernet and makes it
- possible to put up an wireless LAN using infrared beams.
+ possible to put up an infrared wireless LAN.
-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 ac-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 for 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
@@ -10758,6 +10814,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/fb/vesafb.txt linux.ac/Documentation/fb/vesafb.txt
--- linux.vanilla/Documentation/fb/vesafb.txt Tue Jan 19 02:57:22 1999
+++ linux.ac/Documentation/fb/vesafb.txt Tue Feb 16 16:55:12 1999
@@ -11,7 +11,7 @@
This means we decide at boot time whenever we want to run in text or
graphics mode. Switching mode later on (in protected mode) is
impossible; BIOS calls work in real mode only. VESA BIOS Extentions
-Version 2.0 are required, becauce we need a linear frame buffer.
+Version 2.0 are required, because we need a linear frame buffer.
Advantages:
@@ -75,7 +75,7 @@
1. Note: LILO cannot handle hex, for booting directly with
"vga=mode-number" you have to transform the numbers to decimal.
2. Note: Some newer versions of LILO appear to work with those hex values,
- if you set the 0x infront of the numbers.
+ if you set the 0x in front of the numbers.
X11
===
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/kbuild/00-INDEX linux.ac/Documentation/kbuild/00-INDEX
--- linux.vanilla/Documentation/kbuild/00-INDEX Thu Jan 1 01:00:00 1970
+++ linux.ac/Documentation/kbuild/00-INDEX Thu Feb 4 02:03:33 1999
@@ -0,0 +1,8 @@
+00-INDEX
+ - this file: info on the kernel build process
+bug-list.txt
+ - known bugs in kbuild programs
+commands.txt
+ - overview of kbuild commands
+config-language.txt
+ - specification of Config Language, the language in Config.in files
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/kbuild/bug-list.txt linux.ac/Documentation/kbuild/bug-list.txt
--- linux.vanilla/Documentation/kbuild/bug-list.txt Thu Jan 1 01:00:00 1970
+++ linux.ac/Documentation/kbuild/bug-list.txt Thu Feb 4 02:03:33 1999
@@ -0,0 +1,22 @@
+Bug List
+21 January 1999
+Michael Elizabeth Chastain,
+
+- If a variable has a value of "m" in the previous .config file,
+ and a type of bool in the Config script, then all the interpreters
+ get confused. This happens frequently when someone changes a
+ tristate option to a bool option and people in the field have
+ .config files with a value of 'm'. For example: CONFIG_PSMOUSE.
+
+- CONFIG_MODVERSIONS has incorrect dependencies. If you have a
+ problem building the kernel, and you have CONFIG_MODVERSIONS turned
+ on, do a 'make dep' followed by 'make clean' before you try anything
+ else.
+
+- 'make dep' uses multistage dependencies, so the .hdepend file contains
+ 'touch' commands. As a result, building a kernel often touches files
+ in include/linux/*.h. This messes up CVS and other systems which like
+ to rely on file dates.
+
+- 'make dep' fails for C files which include other C files, such as
+ drivers/cdrom/sbpcd2.c.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/kbuild/commands.txt linux.ac/Documentation/kbuild/commands.txt
--- linux.vanilla/Documentation/kbuild/commands.txt Thu Jan 1 01:00:00 1970
+++ linux.ac/Documentation/kbuild/commands.txt Thu Feb 4 02:03:33 1999
@@ -0,0 +1,113 @@
+Overview of Kbuild Commands
+24 January 1999
+Michael Elizabeth Chastain,
+
+
+
+=== Introduction
+
+Someday we'll get our arms around all this stuff and clean it up
+a little! Meanwhile, this file describes the system as it is today.
+
+
+
+=== Quick Start
+
+If you are building a kernel for the first time, here are the commands
+you need:
+
+ make config
+ make dep
+ make bzImage
+
+Instead of 'make config', you can run 'make menuconfig' for a full-screen
+text interface, or 'make xconfig' for an X interface using TCL/TK.
+
+'make bzImage' will leave your new kernel image in arch/i386/boot/bzImage.
+You can also use 'make bzdisk' or 'make bzlilo'.
+
+See the lilo documentation for more information on how to use lilo.
+You can also use the 'loadlin' program to boot Linux from MS-DOS.
+
+Some computers won't work with 'make bzImage', either due to hardware
+problems or very old versions of lilo or loadlin. If your kernel image
+is small, you may use 'make zImage', 'make zdisk', or 'make zlilo'
+on theses systems.
+
+If you find a file name 'vmlinux' in the top directory of the source tree,
+just ignore it. This is an intermediate file and you can't boot from it.
+
+Other architectures: the information above is oriented towards the
+i386. On other architectures, there are no 'bzImage' files; simply
+use 'zImage' or 'vmlinux' as appropriate for your architecture.
+
+Note: the difference between 'zImage' files and 'bzImage' files is that
+'bzImage' uses a different layout and a different loading algorithm,
+and thus has a larger capacity. Both files use gzip compression.
+The 'bz' in 'bzImage' stands for 'big zImage', not for 'bzip'!
+
+
+
+=== Top Level Makefile targets
+
+Here are the targets available at the top level:
+
+ make config, make oldconfig, make menuconfig, make xconfig
+
+ Configure the Linux kernel. You must do this before almost
+ anything else.
+
+ config line-oriented interface
+ oldconfig line-oriented interface, re-uses old values
+ menuconfig curses-based full-screen interface
+ xconfig X window system interface
+
+ make checkconfig
+
+ This runs a little perl script that checks the source tree for
+ missing instances of #include . Someone needs to
+ do this occasionally, because the C preprocessor will silently give
+ bad results if these symbols haven't been included (it treats
+ undefined symbols in preprocessor directives as defined to 0).
+ Superfluous uses of #include are also reported,
+ but you can ignore these, because smart CONFIG_* dependencies
+ make them harmless.
+
+ You can run 'make checkconfig' without configuring the kernel.
+ Also, 'make checkconfig' does not modify any files.
+
+ make checkhelp
+
+ This runs another little perl script that checks the source tree
+ for options that are in Config.in files but are not documented
+ in scripts/Configure.help. Again, someone needs to do this
+ occasionally. If you are adding configuration options, it's
+ nice if you do it before you publish your patch!
+
+ You can run 'make checkhelp' withoug configuring the kernel.
+ Also, 'make checkhelp' does not modify any files.
+
+ make dep, make depend
+
+ 'make dep' is a synonym for the long form, 'make depend'.
+
+ This command does two things. First, it computes dependency
+ information about which .o files depend on which .h files.
+ It records this information in a top-level file named .hdepend
+ and in one file per source directory named .depend.
+
+ Second, if you have CONFIG_MODVERSIONS enabled, 'make dep'
+ computes symbol version information for all of the files that
+ export symbols (note that both resident and modular files may
+ export symbols).
+
+ If you do not enable CONFIG_MODVERSIONS, you only have to run
+ 'make dep' once, right after the first time you configure
+ the kernel. The .hdepend files and the .depend file are
+ independent of your configuration.
+
+ If you do enable CONFIG_MODVERSIONS, you must run 'make dep'
+ every time you change your configuration, because the module
+ symbol version information depends on the configuration.
+
+[to be continued ...]
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/kbuild/config-language.txt linux.ac/Documentation/kbuild/config-language.txt
--- linux.vanilla/Documentation/kbuild/config-language.txt Thu Jan 1 01:00:00 1970
+++ linux.ac/Documentation/kbuild/config-language.txt Thu Feb 4 02:03:33 1999
@@ -0,0 +1,630 @@
+Config Language Specification
+21 January 1999
+Michael Elizabeth Chastain,
+
+
+
+=== Introduction
+
+Config Language is not 'bash'.
+
+This document describes Config Language, the Linux Kernel Configuration
+Language. config.in and Config.in files are written in this language.
+
+Although it looks, and usually acts, like a subset of the 'sh' language,
+Config Language has a restricted syntax and different semantics.
+
+Here is a basic guideline for Config Language programming: use only the
+programming idioms that you see in existing Config.in files. People often
+draw on their shell programming experience to invent idioms that look
+reasonable to shell programmers, but silently fail in Config Language.
+
+Config Language is not 'bash'.
+
+
+
+=== Interpreters
+
+Four different configuration programs read Config Language:
+
+ scripts/Configure make config, make oldconfig
+ scripts/Menuconfig make menuconfig
+ scripts/tkparse make xconfig
+ mconfig (in development)
+
+'Configure' is a bash script which interprets Config.in files by sourcing
+them. Some of the Config Language commands are native bash commands;
+simple bash functions implement the rest of the commands.
+
+'Menuconfig' is another bash script. It scans the input files with a
+small awk script, builds a shell function for each menu, sources the
+shell functions that it builds, and then executes the shell functions
+in a user-driven order. Menuconfig uses 'lxdialog', a back-end utility
+program, to perform actual screen output. 'lxdialog' is a C program
+which uses curses.
+
+'scripts/tkparse' is a C program with an ad hoc parser which translates
+a Config Language script to a huge TCL/TK program. 'make xconfig'
+then hands this TCL/TK program to 'wish', which executes it.
+
+'mconfig' is the next generation of Config Language interpreters. It is a
+C program with a bison parser which translates a Config Language script
+into an internal syntax tree and then hands the syntax tree to one of
+several user-interface front ends.
+
+This document describes the behaviour of all four interpreters, even though
+mconfig has not been released at the time of writing.
+
+
+
+=== Statements
+
+A Config Language script is a list of statements. There are 21 simple
+statements; an 'if' statement; menu blocks; and a 'source' statement.
+
+A '\' at the end of a line marks a line continuation.
+
+'#' usually introduces a comment, which continues to the end of the line.
+Lines of the form '# ... is not set', however, are not comments. They
+are semantically meaningful, and all four config interpreters implement
+this meaning.
+
+Newlines are significant. You may not substitute semicolons for newlines.
+The 'if' statement does accept a semicolon in one position; you may use
+a newline in that position instead.
+
+Here are the basic grammar elements.
+
+ A /prompt/ is a single-quoted string or a double-quoted string.
+ If the word is double-quoted, it may not have any $ substitutions.
+
+ A /word/ is a single unquoted word, a single-quoted string, or a
+ double-quoted string. If the word is unquoted or double quoted,
+ then $-substition will be performed on the word.
+
+ A /symbol/ is a single unquoted word.
+
+ A /dep/ is a dependency. Syntactically, it is a /word/. At run
+ time, a /dep/ must evaluate to "y", "m", "n", or "".
+
+ An /expr/ is a bash-like expression using the operators
+ '=', '!=', '-a', '-o', and '!'.
+
+Here are all the statements:
+
+ Text statements:
+
+ mainmenu_name /prompt/
+ comment /prompt/
+ text /prompt/
+
+ Ask statements:
+
+ bool /prompt/ /symbol/
+ hex /prompt/ /symbol/ /word/
+ int /prompt/ /symbol/ /word/
+ string /prompt/ /symbol/ /word/
+ tristate /prompt/ /symbol/
+
+ Define statements:
+
+ define_bool /symbol/ /word/
+ define_hex /symbol/ /word/
+ define_int /symbol/ /word/
+ define_string /symbol/ /word/
+ define_tristate /symbol/ /word/
+
+ Dependent statements:
+
+ dep_bool /prompt/ /symbol/ /dep/ ...
+ dep_hex /prompt/ /symbol/ /word/ /dep/ ...
+ dep_int /prompt/ /symbol/ /word/ /dep/ ...
+ dep_string /prompt/ /symbol/ /word/ /dep/ ...
+ dep_tristate /prompt/ /symbol/ /dep/ ...
+
+ Unset statement:
+
+ unset /symbol/ ...
+
+ Choice statements:
+
+ choice /prompt/ /word/ /word/
+ nchoice /prompt/ /symbol/ /prompt/ /symbol/ ...
+
+ If statements:
+
+ if [ /expr/ ] ; then
+ /statement/
+ ...
+ fi
+
+ if [ /expr/ ] ; then
+ /statement/
+ ...
+ else
+ /statement/
+ ...
+ fi
+
+ Menu block:
+
+ mainmenu_option next_comment
+ comment /prompt/
+ /statement/
+ ...
+ endmenu
+
+ Source statement:
+
+ source /word/
+
+
+
+=== mainmenu_name /prompt/
+
+This verb is a lot less important than it looks. It specifies the top-level
+name of this Config Language file.
+
+Configure: ignores this line
+Menuconfig: ignores this line
+Xconfig: uses /prompt/ for the label window.
+mconfig: ignores this line (mconfig does a better job without it).
+
+Example:
+
+ # arch/sparc/config.in
+ mainmenu_name "Linux/SPARC Kernel Configuration"
+
+
+
+=== comment /prompt/
+
+This verb displays its prompt to the user during the configuration process
+and also echoes it to the output files during output. Note that the
+prompt, like all prompts, is a quoted string with no dollar substitution.
+
+The 'comment' verb is not a Config Language comment. It causes the
+user interface to display text, and it causes output to appear in the
+output files.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: does not display, but writes to output files
+mconfig: implemented
+
+Example:
+
+ # drivers/net/Config.in
+ comment 'CCP compressors for PPP are only built as modules.'
+
+
+
+=== text /prompt/
+
+This verb displays the prompt to the user with no adornment whatsoever.
+It does not echo the prompt to the output file. mconfig uses this verb
+internally for its help facility.
+
+Configure: not implemented
+Menuconfig: not implemented
+Xconfig: not implemented
+mconfig: implemented
+
+Example:
+
+ # mconfig internal help text
+ text 'Here are all the mconfig command line options.'
+
+
+
+=== bool /prompt/ /symbol/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/. The legal input values are "n" and
+"y".
+
+Note that the bool verb does not have a default value. People keep
+trying to write Config Language scripts with a default value for bool,
+but *all* of the existing language interpreters discard additional values.
+Feel free to submit a multi-interpreter patch to linux-kbuild if you
+want to implement this as an enhancment.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: implemented
+mconfig: implemented
+
+Example:
+
+ # arch/i386/config.in
+ bool 'Symmetric multi-processing support' CONFIG_SMP
+
+
+
+=== hex /prompt/ /symbol/ /word/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/. Any hexadecimal number is a legal
+input value. /word/ is the default value.
+
+The hex verb does not accept range parameters.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: implemented
+mconfig: implemented
+
+Example:
+
+ # drivers/sound/Config.in
+ hex 'I/O base for SB Check from manual of the card' CONFIG_SB_BASE 220
+
+
+
+=== int /prompt/ /symbol/ /word/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/. /word/ is the default value.
+Any decimal number is a legal input value.
+
+The int verb does not accept range parameters.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: implemented
+mconfig: implemented
+
+Example:
+
+ # drivers/char/Config.in
+ int 'Maximum number of Unix98 PTYs in use (0-2048)' \
+ CONFIG_UNIX98_PTY_COUNT 256
+
+
+
+=== string /prompt/ /symbol/ /word/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/. /word/ is the default value. Legal
+input values are any ASCII string, except for the characters '"' and '\\'.
+
+The default value is mandatory.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: implemented
+mconfig: implemented
+
+Example:
+
+ # drivers/sound/Config.in
+ string ' Full pathname of DSPxxx.LD firmware file' \
+ CONFIG_PSS_BOOT_FILE /etc/sound/dsp001.ld
+
+
+
+=== tristate /prompt/ /symbol/
+
+This verb displays /prompt/ to the user, accepts a value from the user,
+and assigns that value to /symbol/. Legal values are "n", "m", or "y".
+
+The value "m" stands for "module"; it indicates that /symbol/ should
+be built as a kernel module. The value "m" is legal only if the symbol
+CONFIG_MODULES currently has the value "y".
+
+The tristate verb does not have a default value.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: implemented
+mconfig: implemented
+
+Example:
+
+ # fs/Config.in
+ tristate 'NFS filesystem support' CONFIG_NFS_FS
+
+
+
+=== define_bool /symbol/ /word/
+
+This verb the value of /word/ to /symbol/. Legal values are "n" or "y".
+
+For compatibility reasons, the value of "m" is also legal, because it
+will be a while before define_tristate is implemented everywhere.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: implemented
+mconfig: implemented
+
+Example:
+
+ # arch/alpha/config.in
+ if [ "$CONFIG_ALPHA_GENERIC" = "y" ]
+ then
+ define_bool CONFIG_PCI y
+ define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y
+ fi
+
+
+
+=== define_hex /symbol/ /word/
+
+This verb assigns the value of /word/ to /symbol/. Any hexadecimal
+number is a legal value.
+
+Configure: implemented
+Menuconfig: not implemented
+Xconfig: not implemented
+mconfig: implemented
+
+Example:
+
+ # Not from the corpus
+ bool 'Specify custom serial port' CONFIG_SERIAL_PORT_CUSTOM
+ if [ "$CONFIG_SERIAL_PORT_CUSTOM" = "y" ]; then
+ hex 'Serial port number' CONFIG_SERIAL_PORT
+ else
+ define_hex CONFIG_SERIAL_PORT 0x3F8
+ fi
+
+
+
+=== define_int /symbol/ /word/
+
+This verb assigns /symbol/ the value /word/. Any decimal number is a
+legal value.
+
+Configure: implemented
+Menuconfig: not implemented
+Xconfig: not implemented
+mconfig: implemented
+
+Example:
+
+ # Not from the corpus
+ define_int CONFIG_UID_TORVALDS 2026
+
+
+
+=== define_string /symbol/ /word/
+
+This verb assigns the value of /word/ to /symbol/. Legal input values
+are any ASCII string, except for the characters '"' and '\\'.
+
+Configure: implemented
+Menuconfig: not implemented
+Xconfig: not implemented
+mconfig: implemented
+
+Example
+
+ # Not from the corpus
+ define_string CONFIG_VERSION "2.2.0"
+
+
+
+=== define_tristate /symbol/ /word/
+
+This verb assigns the value of /word/ to /symbol/. Legal input values
+are "n", "m", and "y".
+
+As soon as this verb is implemented in all interpreters, please use it
+instead of define_bool to define tristate values. This aids in static
+type checking.
+
+Configure: not implemented
+Menuconfig: not implemented
+Xconfig: not implemented
+mconfig: implemented
+
+Example:
+
+ # not from the corpus
+ if [ "$CONFIG_ZFTAPE" != "n" ]; then
+ comment 'The compressor will be built as a module only!'
+ define_tristate CONFIG_ZFT_COMPRESSOR m
+ fi
+
+
+
+=== dep_bool /prompt/ /symbol/ /dep/ ...
+
+This verb evaluates all of the dependencies in the dependency list.
+Any dependency which has a value of "y" does not restrict the input
+range. Any dependency which has a value of "n", or which has some
+other value, restricts the input range to "n".
+
+If the input range is restricted to the single choice "n", dep_bool
+silently assigns "n" to /symbol/. If the input range has more than
+one choice, dep_bool displays /prompt/ to the user, accepts a value
+from the user, and assigns that value to /symbol/.
+
+Configure: not implemented
+Menuconfig: not implemented
+XConfig: not implemented
+mconfig: implemented
+
+ # not from the corpus
+ dep_bool 'RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_PCI
+
+
+
+=== dep_hex /prompt/ /symbol/ /word/ /dep/ ...
+=== dep_int /prompt/ /symbol/ /word/ /dep/ ...
+=== dep_string /prompt/ /symbol/ /word/ /dep/ ...
+
+I am still thinking about the semantics of these verbs.
+
+Configure: not implemented
+Menuconfig: not implemented
+XConfig: not implemented
+mconfig: not implemented
+
+
+
+=== dep_tristate /prompt/ /symbol /dep/ ...
+
+This verb evaluates all of the dependencies in the dependency list.
+Any dependency which as a value of "y" does not restrict the input range.
+Any dependency which has a value of "m" restricts the input range to
+"m" or "n". Any dependency which has a value of "n", or which has some
+other value, restricts the input range to "n".
+
+If the input range is restricted to the single choice "n", dep_tristate
+silently assigns "n" to /symbol/. If the input range has more than
+one choice, dep_tristate displays /prompt/ to the user, accepts a value
+from the user, and assigns that value to /symbol/.
+
+Configure: implemented
+Menuconfig: implemented (but silently ignores dependencies after the first)
+Xconfig: implemented (but silently ignores dependencies after the first)
+mconfig: implemented
+
+
+
+=== unset /symbol/ ...
+
+This verb assigns the value "" to /symbol/, but does not cause /symbol/
+to appear in the output. The existence of this verb is a hack; it covers
+up deeper problems with variable semantics in a random-execution language.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: not implemented
+mconfig: implemented
+
+
+
+=== choice /prompt/ /word/ /word/
+
+This verb implements a choice list or "radio button list" selection.
+It displays /prompt/ to the user, as well as a group of sub-prompts
+which have corresponding symbols.
+
+When the user selects a value, the choice verb sets the corresponding
+symbol to "y" and sets all the other symbols in the choice list to "n".
+
+The second argument is a single-quoted or double-quoted word that
+describes a series of sub-prompts and symbol names. The interpreter
+breaks up the word at white space boundaries into a list of sub-words.
+The first sub-word is the first prompt; the second sub-word is the
+first symbol. The third sub-word is the second prompt; the fourth
+sub-word is the second symbol. And so on, for all the sub-words.
+
+The third word is a literal word. Its value must be a unique abbreviation
+for exactly one of the prompts. The symbol corresponding to this prompt
+is the default enabled symbol.
+
+Note that because of the syntax of the choice verb, the sub-prompts
+may not have spaces in them.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: implemented
+mconfig: implemented
+
+
+
+=== nchoice /prompt/ /symbol/ /prompt/ /symbol/ ...
+
+This verb has the same semantics as the choice verb, but with a sensible
+syntax.
+
+The first /prompt/ is the master prompt for the entire choice list.
+
+The first /symbol/ is the default symbol to enable (notice that this
+is a symbol, not a unique prompt abbreviation).
+
+The subsequent /prompt/ and /symbol/ pairs are the prompts and symbols
+for the choice list.
+
+Configure: not implemented
+Menuconfig: not implemented
+XConfig: not implemented
+mconfig: implemented
+
+
+
+=== if [ /expr/ ] ; then
+
+This is a conditional statement, with an optional 'else' clause. You may
+substitute a newline for the semicolon if you choose.
+
+/expr/ may contain the following atoms and operators. Note that, unlike
+shell, you must use double quotes around every atom.
+
+ "..." a literal
+ "$..." a variable
+
+ /atom/ = /atom/ true if atoms have identical value
+ /atom/ != /atom/ true if atoms have different value
+
+ /expr/ -o /expr/ true if either expression is true
+ /expr/ -a /expr/ true if both expressions are true
+ ! /expr/ true if expression is not true
+
+Configure: implemented
+Menuconfig: implemented
+XConfig: implemented, with bugs
+mconfig: implemented
+
+Xconfig has several known bugs, and probably some unknown bugs too:
+
+- In a comparison, if the left-hand atom is a variable and that variable
+ is from a choice list, the right-hand atom must be "y".
+
+- In a comparison, if the right-hand atom is a variable and that variable
+ is from a choice list, you lose. tkparse will throw a segmentation
+ violation, silently generate bizarre TCL code, or something else.
+
+- tkparse gives the wrong precedence to -o, -a, and !. Don't use both
+ -o and -a in an expression. Don't use ! at all.
+
+
+
+=== mainmenu_option next_comment
+
+This verb introduces a new menu. The next statement must have a comment
+verb. The /prompt/ of that comment verb becomes the title of the menu.
+(I have no idea why the original designer didn't create a 'menu ...' verb).
+
+Statements outside the scope of any menu are in the implicit top menu.
+The title of the top menu comes from a variety of sources, depending on
+the interpreter.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: implemented
+mconfig: implemented
+
+
+
+=== endmenu
+
+This verb closes the scope of a menu.
+
+Configure: implemented
+Menuconfig: implemented
+Xconfig: implemented
+mconfig: implemented
+
+
+
+=== source /word/
+
+This verb interprets the literal /word/ as a filename, and interpolates
+the contents of that file. The word must be a single unquoted literal
+word.
+
+Some interpreters interpret this verb at run time; some interpreters
+interpret it at parse time.
+
+Inclusion is textual inclusion, like the C preprocessor #include facility.
+The source verb does not imply a submenu or any kind of block nesting.
+
+Configure: implemented (run time)
+Menuconfig: implemented (parse time)
+Xconfig: implemented (parse time)
+mconfig: implemented (parse time)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/proc.txt linux.ac/Documentation/proc.txt
--- linux.vanilla/Documentation/proc.txt Thu Jan 28 22:00:13 1999
+++ linux.ac/Documentation/proc.txt Tue Feb 16 16:55:23 1999
@@ -50,7 +50,7 @@
the work back to the Linux community. This work is based on the
2.1.132 and 2.2.0-pre-kernel versions. I'm afraid it's still far from
complete, but we hope it will be useful. As far as we know, it is the
-first 'all-in-one’ document about the /proc file system. It is
+first 'all-in-one' document about the /proc file system. It is
focused on the Intel x86 hardware, so if you are looking for PPC, ARM,
SPARC, APX, etc., features, you probably won't find what you are
looking for. It also only covers IPv4 networking, not IPv6 nor other
@@ -657,7 +657,7 @@
sg-big-buff
This file shows the size of the generic SCSI (sg) buffer. At this
- point, you can’t tune it yet, but you can change it at compile time
+ point, you can't tune it yet, but you can change it at compile time
by editing include/scsi/sg.h and changing the value of
SG_BIG_BUFF.
@@ -794,9 +794,9 @@
swap_cluster
This is probably the greatest influence on system
performance. swap_cluster is the number of pages kswapd writes in
- one turn. You’ll want this value to be large so that kswapd does
- its I/O in large chunks and the disk doesn’t have to seek as
- often., but you don’t want it to be too large since that would
+ one turn. You'll want this value to be large so that kswapd does
+ its I/O in large chunks and the disk doesn't have to seek as
+ often., but you don't want it to be too large since that would
flood the request queue.
overcommit_memory
@@ -1140,7 +1140,7 @@
accept_source_route
Should source routed packages be accepted or declined. The
default is dependent on the kernel configuration. It's 'yes' for
- routers and 'np' for hosts.
+ routers and 'no' for hosts.
bootp_relay
Accept packets with source address 0.b.c.d destined not to this
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sound/ESS linux.ac/Documentation/sound/ESS
--- linux.vanilla/Documentation/sound/ESS Thu Jan 1 01:00:00 1970
+++ linux.ac/Documentation/sound/ESS Sat Jan 30 18:26:08 1999
@@ -0,0 +1,33 @@
+Documentation for the ESS AudioDrive chips
+
+In 2.2 kernels the SoundBlaster driver not only tries to detect an ESS chip, it
+tries to detect the type of ESS chip too. The correct detection of the chip
+doesn't always succeed however, so the default behaviour is 2.0 behaviour
+which means: only detect ES688 and ES1688.
+
+All ESS chips now have a recording level setting. This is a need-to-have for
+people who want to use their ESS for recording sound.
+
+Every chip that's detected as a later-than-es1688 chip has a 6 bits logarithmic
+master volume control.
+
+Every chip that's detected as a ES1887 now has Full Duplex support. Made a
+little testprogram that showes that is works, haven't seen a real program that
+needs this however.
+
+For ESS chips an additional parameter "esstype" can be specified. This controls
+the (auto) detection of the ESS chips. It can have 3 kinds of values:
+
+-1 Act like 2.0 kernels: only detect ES688 or ES1688.
+0 Try to auto-detect the chip (may fail for ES1688)
+688 The chip will be treated as ES688
+1688 ,, ,, ,, ,, ,, ,, ES1688
+1868 ,, ,, ,, ,, ,, ,, ES1868
+1869 ,, ,, ,, ,, ,, ,, ES1869
+1788 ,, ,, ,, ,, ,, ,, ES1788
+1887 ,, ,, ,, ,, ,, ,, ES1887
+1888 ,, ,, ,, ,, ,, ,, ES1888
+
+Because Full Duplex is supported for ES1887 you can specify a second DMA
+channel by specifying module parameter dma16. It can be one of: 0, 1, 3 or 5.
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sound/OPL3-SA linux.ac/Documentation/sound/OPL3-SA
--- linux.vanilla/Documentation/sound/OPL3-SA Sun Nov 8 15:08:50 1998
+++ linux.ac/Documentation/sound/OPL3-SA Tue Jan 26 10:06:26 1999
@@ -2,8 +2,7 @@
---
Note: This howto only describes how to setup the OPL3-SA1 chip; this info
-does not apply to the SA2, SA3, or SA4. Contact hannu@opensound.com for
-the support details of these other SAx chips.
+does not apply to the SA2, SA3, or SA4.
---
The Yamaha OPL3-SA1 sound chip is usually found built into motherboards, and
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/video4linux/bttv/INSTALL linux.ac/Documentation/video4linux/bttv/INSTALL
--- linux.vanilla/Documentation/video4linux/bttv/INSTALL Fri Nov 13 01:37:09 1998
+++ linux.ac/Documentation/video4linux/bttv/INSTALL Tue Feb 16 16:55:31 1999
@@ -41,6 +41,9 @@
10: Newer Hauppage (Bt878)
11: Miro PCTV Pro
12: ADS Tech Channel Surfer TV (and maybe TV+FM)
+ 13: AVerMedia TVCapture 98
+ 14: Aimslab VHX
+ 15: Zoltrix TV-Max
- You may have to adjust BTTV_MAJOR to a different number depending on your
kernel version. The official number 81 does not work on some setups.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/video4linux/bttv/README.FIRST linux.ac/Documentation/video4linux/bttv/README.FIRST
--- linux.vanilla/Documentation/video4linux/bttv/README.FIRST Sun Nov 8 15:08:51 1998
+++ linux.ac/Documentation/video4linux/bttv/README.FIRST Tue Feb 16 16:55:38 1999
@@ -1,4 +1,4 @@
o Please direct queries about the in kernel version of this driver to
Alan Cox first not to Ralph, or better yet join the video4linux mailing
- list (mail majordomo@phunk.org with "subscribe video4linux")
+ list (mail video4linux-list-request@redhat.com with "subscribe")
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/MAINTAINERS linux.ac/MAINTAINERS
--- linux.vanilla/MAINTAINERS Sun Jan 24 19:55:29 1999
+++ linux.ac/MAINTAINERS Tue Feb 16 16:55:44 1999
@@ -530,6 +530,12 @@
L: netdev@roxanne.nuclecu.unam.mx
S: Maintained
+NFS CLIENT
+P: Trond Myklebust
+M: trond.myklebust@fys.uio.no
+L: linux-kernel@vger.rutgers.edu
+S: Maintained
+
NI5010 NETWORK DRIVER
P: Jan-Pascal van Best and Andreas Mohr
M: jvbest@qv3pluto.leidenuniv.nl (Best)
@@ -672,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 Thu Jan 28 22:00:13 1999
+++ linux.ac/Makefile Tue Feb 16 20:20:40 1999
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 1
-EXTRAVERSION =
+EXTRAVERSION = -ac6
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -221,35 +221,27 @@
mkdir include/linux/modules; \
fi
-oldconfig: symlinks scripts/split-include
+oldconfig: symlinks
$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
- if [ -r include/linux/autoconf.h ]; then \
- scripts/split-include include/linux/autoconf.h include/config; \
- fi
-xconfig: symlinks scripts/split-include
+xconfig: symlinks
$(MAKE) -C scripts kconfig.tk
wish -f scripts/kconfig.tk
- if [ -r include/linux/autoconf.h ]; then \
- scripts/split-include include/linux/autoconf.h include/config; \
- fi
-menuconfig: include/linux/version.h symlinks scripts/split-include
+menuconfig: include/linux/version.h symlinks
$(MAKE) -C scripts/lxdialog all
$(CONFIG_SHELL) scripts/Menuconfig arch/$(ARCH)/config.in
- if [ -r include/linux/autoconf.h ]; then \
- scripts/split-include include/linux/autoconf.h include/config; \
- fi
-config: symlinks scripts/split-include
+config: symlinks
$(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in
- if [ -r include/linux/autoconf.h ]; then \
- scripts/split-include include/linux/autoconf.h include/config; \
- fi
+
+include/config/MARKER: scripts/split-include include/linux/autoconf.h
+ scripts/split-include include/linux/autoconf.h include/config
+ @ touch include/config/MARKER
linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS))
-$(patsubst %, _dir_%, $(SUBDIRS)) : dummy
+$(patsubst %, _dir_%, $(SUBDIRS)) : dummy include/config/MARKER
$(MAKE) -C $(patsubst _dir_%, %, $@)
$(TOPDIR)/include/linux/version.h: include/linux/version.h
@@ -286,10 +278,10 @@
@echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver
@mv -f .ver $@
-init/version.o: init/version.c include/linux/compile.h
+init/version.o: init/version.c include/linux/compile.h include/config/MARKER
$(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c
-init/main.o: init/main.c
+init/main.o: init/main.c include/config/MARKER
$(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $<
fs lib mm ipc kernel drivers net: dummy
@@ -351,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
@@ -375,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
@@ -387,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
@@ -397,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
@@ -407,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/config.in linux.ac/arch/alpha/config.in
--- linux.vanilla/arch/alpha/config.in Tue Jan 19 02:57:22 1999
+++ linux.ac/arch/alpha/config.in Thu Feb 4 02:03:59 1999
@@ -243,7 +243,7 @@
endmenu
mainmenu_option next_comment
-comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+comment 'Old CD-ROM drivers (not SCSI, not IDE)'
bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
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 Tue Feb 16 17:11:41 1999
@@ -108,7 +108,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/entry.S linux.ac/arch/alpha/kernel/entry.S
--- linux.vanilla/arch/alpha/kernel/entry.S Tue Jan 26 09:44:20 1999
+++ linux.ac/arch/alpha/kernel/entry.S Thu Feb 4 02:03:59 1999
@@ -186,6 +186,18 @@
jsr $31,do_entIF
.end entIF
+.align 3
+.globl entDbg
+.ent entDbg
+entDbg:
+ SAVE_ALL
+ lda $8,0x3fff
+ bic $30,$8,$8
+ lda $26,ret_from_sys_call
+ jsr $31,do_entDbg
+.end entDbg
+
+
/*
* Fork() is one of the special system calls: it needs to
* save the callee-saved regs so that the regs can be found
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/proto.h linux.ac/arch/alpha/kernel/proto.h
--- linux.vanilla/arch/alpha/kernel/proto.h Thu Jan 14 01:25:21 1999
+++ linux.ac/arch/alpha/kernel/proto.h Thu Feb 4 02:03:59 1999
@@ -187,6 +187,7 @@
extern void entMM(void);
extern void entSys(void);
extern void entUna(void);
+extern void entDbg(void);
/* process.c */
extern void generic_kill_arch (int mode, char *reboot_cmd);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/traps.c linux.ac/arch/alpha/kernel/traps.c
--- linux.vanilla/arch/alpha/kernel/traps.c Sun Nov 8 15:08:24 1998
+++ linux.ac/arch/alpha/kernel/traps.c Thu Feb 4 02:03:59 1999
@@ -121,9 +121,9 @@
#endif
asmlinkage void
-do_entArith(unsigned long summary, unsigned long write_mask, unsigned long a2,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct pt_regs regs)
+do_entArith(unsigned long summary, unsigned long write_mask,
+ unsigned long a2, unsigned long a3, unsigned long a4,
+ unsigned long a5, struct pt_regs regs)
{
if ((summary & 1)) {
/*
@@ -145,9 +145,10 @@
unlock_kernel();
}
-asmlinkage void do_entIF(unsigned long type, unsigned long a1,
- unsigned long a2, unsigned long a3, unsigned long a4,
- unsigned long a5, struct pt_regs regs)
+asmlinkage void
+do_entIF(unsigned long type, unsigned long a1,
+ unsigned long a2, unsigned long a3, unsigned long a4,
+ unsigned long a5, struct pt_regs regs)
{
lock_kernel();
die_if_kernel("Instruction fault", ®s, type, 0);
@@ -230,6 +231,25 @@
unlock_kernel();
}
+/* There is an ifdef in the PALcode in MILO that enables a
+ "kernel debugging entry point" as an unprivilaged call_pal.
+
+ We don't want to have anything to do with it, but unfortunately
+ several versions of MILO included in distributions have it enabled,
+ and if we don't put something on the entry point we'll oops. */
+
+asmlinkage void
+do_entDbg(unsigned long type, unsigned long a1,
+ unsigned long a2, unsigned long a3, unsigned long a4,
+ unsigned long a5, struct pt_regs regs)
+{
+ lock_kernel();
+ die_if_kernel("Instruction fault", ®s, type, 0);
+ force_sig(SIGILL, current);
+ unlock_kernel();
+}
+
+
/*
* entUna has a different register layout to be reasonably simple. It
* needs access to all the integer registers (the kernel doesn't use
@@ -895,4 +915,5 @@
wrent(entIF, 3);
wrent(entUna, 4);
wrent(entSys, 5);
+ wrent(entDbg, 6);
}
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 Tue Feb 16 17:11:41 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 Sun Jan 24 19:55:30 1999
+++ linux.ac/arch/i386/defconfig Tue Feb 16 17:11:41 1999
@@ -121,7 +121,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/io_apic.c linux.ac/arch/i386/kernel/io_apic.c
--- linux.vanilla/arch/i386/kernel/io_apic.c Mon Dec 28 23:09:40 1998
+++ linux.ac/arch/i386/kernel/io_apic.c Fri Feb 5 19:12:26 1999
@@ -202,7 +202,7 @@
DO_ACTION( mask, 0, |= 0x00010000, io_apic_sync()) /* mask = 1 */
DO_ACTION( unmask, 0, &= 0xfffeffff, ) /* mask = 0 */
-static void __init clear_IO_APIC_pin(unsigned int pin)
+static void clear_IO_APIC_pin(unsigned int pin)
{
struct IO_APIC_route_entry entry;
@@ -215,6 +215,13 @@
io_apic_write(0x11 + 2 * pin, *(((int *)&entry) + 1));
}
+static void clear_IO_APIC (void)
+{
+ int pin;
+
+ for (pin = 0; pin < nr_ioapic_registers; pin++)
+ clear_IO_APIC_pin(pin);
+}
/*
* support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
@@ -625,7 +632,7 @@
/*
* Set up a certain pin as ExtINT delivered interrupt
*/
-void __init setup_ExtINT_pin(unsigned int pin)
+void __init setup_ExtINT_pin(unsigned int pin, int irq)
{
struct IO_APIC_route_entry entry;
@@ -635,11 +642,16 @@
memset(&entry,0,sizeof(entry));
entry.delivery_mode = dest_ExtINT;
- entry.dest_mode = 1; /* logical delivery */
+ entry.dest_mode = 0; /* physical delivery */
entry.mask = 0; /* unmask IRQ now */
- entry.dest.logical.logical_dest = 0x01; /* logical CPU #0 */
+ /*
+ * We use physical delivery to get the timer IRQ
+ * to the boot CPU. 'boot_cpu_id' is the physical
+ * APIC ID of the boot CPU.
+ */
+ entry.dest.physical.physical_dest = boot_cpu_id;
- entry.vector = 0; /* it's ignored */
+ entry.vector = assign_irq_vector(irq);
entry.polarity = 0;
entry.trigger = 0;
@@ -754,7 +766,7 @@
static void __init init_sym_mode(void)
{
- int i, pin;
+ int i;
for (i = 0; i < PIN_MAP_SIZE; i++) {
irq_2_pin[i].pin = -1;
@@ -784,8 +796,7 @@
/*
* Do not trust the IO-APIC being empty at bootup
*/
- for (pin = 0; pin < nr_ioapic_registers; pin++)
- clear_IO_APIC_pin(pin);
+ clear_IO_APIC();
}
/*
@@ -793,6 +804,15 @@
*/
void init_pic_mode(void)
{
+ /*
+ * Clear the IO-APIC before rebooting:
+ */
+ clear_IO_APIC();
+
+ /*
+ * Put it back into PIC mode (has an effect only on
+ * certain boards)
+ */
printk("disabling symmetric IO mode... ");
outb_p(0x70, 0x22);
outb_p(0x00, 0x23);
@@ -1178,7 +1198,7 @@
if (pin2 != -1) {
printk(".. (found pin %d) ...", pin2);
- setup_ExtINT_pin(pin2);
+ setup_ExtINT_pin(pin2, 0);
make_8259A_irq(0);
}
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 Jan 26 09:44:20 1999
+++ linux.ac/arch/i386/kernel/setup.c Wed Feb 3 22:18:39 1999
@@ -807,7 +807,7 @@
c->x86_model,
c->x86_model_id[0] ? c->x86_model_id : "unknown");
- if (c->x86_mask)
+ if (c->x86_mask || c->cpuid_level >= 0)
p += sprintf(p, "stepping\t: %d\n", c->x86_mask);
else
p += sprintf(p, "stepping\t: unknown\n");
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/smp.c linux.ac/arch/i386/kernel/smp.c
--- linux.vanilla/arch/i386/kernel/smp.c Tue Jan 26 09:44:20 1999
+++ linux.ac/arch/i386/kernel/smp.c Thu Feb 4 02:04:15 1999
@@ -147,6 +147,17 @@
#define APIC_DEFAULT_PHYS_BASE 0xfee00000
/*
+ * Reads and clears the Pentium Timestamp-Counter
+ */
+#define READ_TSC(x) __asm__ __volatile__ ( "rdtsc" \
+ :"=a" (((unsigned long*)&(x))[0]), \
+ "=d" (((unsigned long*)&(x))[1]))
+
+#define CLEAR_TSC \
+ __asm__ __volatile__ ("\t.byte 0x0f, 0x30;\n"::\
+ "a"(0x00001000), "d"(0x00001000), "c"(0x10):"memory")
+
+/*
* Setup routine for controlling SMP activation
*
* Command-line option of "nosmp" or "maxcpus=0" will disable SMP
@@ -710,24 +721,19 @@
value |= 0xff; /* Set spurious IRQ vector to 0xff */
apic_write(APIC_SPIV,value);
- value = apic_read(APIC_TASKPRI);
- value &= ~APIC_TPRI_MASK; /* Set Task Priority to 'accept all' */
- apic_write(APIC_TASKPRI,value);
-
/*
- * Set arbitrarion priority to 0
+ * Set Task Priority to 'accept all'
*/
- value = apic_read(APIC_ARBPRI);
- value &= ~APIC_ARBPRI_MASK;
- apic_write(APIC_ARBPRI, value);
+ value = apic_read(APIC_TASKPRI);
+ value &= ~APIC_TPRI_MASK;
+ apic_write(APIC_TASKPRI,value);
/*
- * Set the logical destination ID to 'all', just to be safe.
+ * Clear the logical destination ID, just to be safe.
* also, put the APIC into flat delivery mode.
*/
value = apic_read(APIC_LDR);
value &= ~APIC_LDR_MASK;
- value |= SET_APIC_LOGICAL_ID(0xff);
apic_write(APIC_LDR,value);
value = apic_read(APIC_DFR);
@@ -735,8 +741,6 @@
apic_write(APIC_DFR, value);
udelay(100); /* B safe */
- ack_APIC_irq();
- udelay(100);
}
unsigned long __init init_smp_mappings(unsigned long memory_start)
@@ -1815,10 +1819,6 @@
* closely follows bus clocks.
*/
-#define RDTSC(x) __asm__ __volatile__ ( "rdtsc" \
- :"=a" (((unsigned long*)&x)[0]), \
- "=d" (((unsigned long*)&x)[1]))
-
/*
* The timer chip is already set up at HZ interrupts per second here,
* but we do not accept timer interrupts yet. We only allow the BP
@@ -1937,7 +1937,7 @@
/*
* We wrapped around just now. Let's start:
*/
- RDTSC(t1);
+ READ_TSC(t1);
tt1=apic_read(APIC_TMCCT);
#define LOOPS (HZ/10)
@@ -1948,7 +1948,7 @@
wait_8254_wraparound ();
tt2=apic_read(APIC_TMCCT);
- RDTSC(t2);
+ READ_TSC(t2);
/*
* The APIC bus clock counter is 32 bits only, it
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/time.c linux.ac/arch/i386/kernel/time.c
--- linux.vanilla/arch/i386/kernel/time.c Sun Jan 24 19:55:30 1999
+++ linux.ac/arch/i386/kernel/time.c Wed Feb 3 22:17:20 1999
@@ -86,7 +86,7 @@
* Equal to 2^32 * (1 / (clocks per usec) ).
* Initialized in time_init.
*/
-static unsigned long fast_gettimeoffset_quotient=0;
+unsigned long fast_gettimeoffset_quotient=0;
extern rwlock_t xtime_lock;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/traps.c linux.ac/arch/i386/kernel/traps.c
--- linux.vanilla/arch/i386/kernel/traps.c Sun Jan 24 19:55:30 1999
+++ linux.ac/arch/i386/kernel/traps.c Thu Feb 4 18:01:28 1999
@@ -45,6 +45,8 @@
asmlinkage int system_call(void);
asmlinkage void lcall7(void);
+extern void init_unexpected_irq(void);
+
struct desc_struct default_ldt = { 0, 0 };
/*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/m68k/config.in linux.ac/arch/m68k/config.in
--- linux.vanilla/arch/m68k/config.in Sun Jan 24 19:55:30 1999
+++ linux.ac/arch/m68k/config.in Thu Feb 4 02:04:15 1999
@@ -346,13 +346,13 @@
source fs/Config.in
if [ "$CONFIG_VME" = "n" ]; then
+ mainmenu_option next_comment
+ comment 'Console drivers'
if [ "$CONFIG_HP300" = "y" ]; then
bool 'Frame buffer support' CONFIG_FB
else
define_bool CONFIG_FB y
fi
- mainmenu_option next_comment
- comment 'Console drivers'
source drivers/video/Config.in
endmenu
fi
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 Tue Feb 16 17:11:41 1999
@@ -95,7 +95,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/config.in linux.ac/arch/mips/config.in
--- linux.vanilla/arch/mips/config.in Tue Jan 19 02:57:23 1999
+++ linux.ac/arch/mips/config.in Thu Feb 4 02:04:23 1999
@@ -179,7 +179,7 @@
endmenu
mainmenu_option next_comment
- comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+ comment 'Old CD-ROM drivers (not SCSI, not IDE)'
bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
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 Tue Feb 16 17:11:41 1999
@@ -107,7 +107,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 Tue Feb 16 17:11:41 1999
@@ -118,7 +118,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 Tue Feb 16 17:11:41 1999
@@ -99,7 +99,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 Tue Feb 16 17:11:41 1999
@@ -100,7 +100,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/config.in linux.ac/arch/ppc/config.in
--- linux.vanilla/arch/ppc/config.in Tue Jan 19 02:57:23 1999
+++ linux.ac/arch/ppc/config.in Thu Feb 4 02:04:23 1999
@@ -152,7 +152,7 @@
endmenu
mainmenu_option next_comment
-comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+comment 'Old CD-ROM drivers (not SCSI, not IDE)'
bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
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 Tue Feb 16 17:11:41 1999
@@ -120,7 +120,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 Tue Feb 16 17:11:41 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
@@ -90,7 +89,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 Tue Feb 16 17:11:41 1999
@@ -120,7 +120,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 Tue Feb 16 17:11:41 1999
@@ -97,7 +97,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 Tue Feb 16 17:11:41 1999
@@ -118,7 +118,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 Tue Feb 16 17:11:41 1999
@@ -145,7 +145,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 Thu Jan 14 01:25:21 1999
+++ linux.ac/drivers/block/genhd.c Mon Feb 1 22:06:27 1999
@@ -130,6 +130,14 @@
SYS_IND(p) == LINUX_EXTENDED_PARTITION);
}
+static int sector_partition_scale(kdev_t dev)
+{
+ if (hardsect_size[MAJOR(dev)] != NULL)
+ return (hardsect_size[MAJOR(dev)][MINOR(dev)]/512);
+ else
+ return (1);
+}
+
static unsigned int get_ptable_blocksize(kdev_t dev)
{
int ret = 1024;
@@ -149,6 +157,7 @@
* the natural blocksize for the device so that we don't have to try
* and read partial sectors. Anything smaller should be just fine.
*/
+
switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
{
case 2048:
@@ -196,6 +205,7 @@
struct partition *p;
unsigned long first_sector, first_size, this_sector, this_size;
int mask = (1 << hd->minor_shift) - 1;
+ int sector_size = sector_partition_scale(dev);
int i;
first_sector = hd->part[MINOR(dev)].start_sect;
@@ -233,22 +243,22 @@
* First process the data partition(s)
*/
for (i=0; i<4; i++, p++) {
- if (!NR_SECTS(p) || is_extended_partition(p))
- continue;
+ if (!NR_SECTS(p) || is_extended_partition(p))
+ continue;
- /* Check the 3rd and 4th entries -
- these sometimes contain random garbage */
- if (i >= 2
- && START_SECT(p) + NR_SECTS(p) > this_size
- && (this_sector + START_SECT(p) < first_sector ||
- this_sector + START_SECT(p) + NR_SECTS(p) >
- first_sector + first_size))
- continue;
-
- add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
- current_minor++;
- if ((current_minor & mask) == 0)
- goto done;
+ /* Check the 3rd and 4th entries -
+ these sometimes contain random garbage */
+ if (i >= 2
+ && START_SECT(p) + NR_SECTS(p) > this_size
+ && (this_sector + START_SECT(p) < first_sector ||
+ this_sector + START_SECT(p) + NR_SECTS(p) >
+ first_sector + first_size))
+ continue;
+
+ add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
+ current_minor++;
+ if ((current_minor & mask) == 0)
+ goto done;
}
/*
* Next, process the (first) extended partition, if present.
@@ -262,20 +272,21 @@
*/
p -= 4;
for (i=0; i<4; i++, p++)
- if(NR_SECTS(p) && is_extended_partition(p))
- break;
+ if(NR_SECTS(p) && is_extended_partition(p))
+ break;
if (i == 4)
- goto done; /* nothing left to do */
+ goto done; /* nothing left to do */
- hd->part[current_minor].nr_sects = NR_SECTS(p);
- hd->part[current_minor].start_sect = first_sector + START_SECT(p);
- this_sector = first_sector + START_SECT(p);
+ hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
+ hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
+ this_sector = first_sector + START_SECT(p) * sector_size;
dev = MKDEV(hd->major, current_minor);
brelse(bh);
}
done:
brelse(bh);
}
+
#ifdef CONFIG_SOLARIS_X86_PARTITION
static void
solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
@@ -317,11 +328,13 @@
#endif
#ifdef CONFIG_BSD_DISKLABEL
-static void check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p)
+static void check_and_add_bsd_partition(struct gendisk *hd,
+ struct bsd_partition *bsd_p, kdev_t dev)
{
struct hd_struct *lin_p;
/* check relative position of partitions. */
- for (lin_p = hd->part + 1; lin_p - hd->part < current_minor; lin_p++) {
+ for (lin_p = hd->part + 1 + MINOR(dev);
+ lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) {
/* no relationship -> try again */
if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset
|| lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
@@ -383,7 +396,7 @@
break;
if (p->p_fstype != BSD_FS_UNUSED)
- check_and_add_bsd_partition(hd, p);
+ check_and_add_bsd_partition(hd, p, dev);
}
brelse(bh);
@@ -436,6 +449,7 @@
struct partition *p;
unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
+ int sector_size = sector_partition_scale(dev);
#ifdef CONFIG_BSD_DISKLABEL
/* no bsd disklabel as a default */
kdev_t bsd_kdev = 0;
@@ -538,7 +552,7 @@
for (i=1 ; i<=4 ; minor++,i++,p++) {
if (!NR_SECTS(p))
continue;
- add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
+ add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
if (is_extended_partition(p)) {
printk(" <");
/*
@@ -790,7 +804,7 @@
struct sgi_partition *p;
#define SGI_LABEL_MAGIC 0x0be5a941
- if(!(bh = bread(dev, 0, 1024))) {
+ if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
printk("Dev %s: unable to read partition table\n", kdevname(dev));
return -1;
}
@@ -854,11 +868,18 @@
int blk;
int part, res;
+ /*
+ * Don't bother touching M/O 2K media.
+ */
+
+ if (get_ptable_blocksize(dev) != 1024)
+ return 0;
+
set_blocksize(dev,512);
res = 0;
for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
- if(!(bh = bread(dev,blk,512))) {
+ if(!(bh = bread(dev,blk,get_ptable_blocksize(dev)))) {
printk("Dev %s: unable to read RDB block %d\n",
kdevname(dev),blk);
goto rdb_done;
@@ -875,7 +896,7 @@
blk = htonl(rdb->rdb_PartitionList);
brelse(bh);
for (part = 1; blk > 0 && part <= 16; part++) {
- if (!(bh = bread(dev,blk,512))) {
+ if (!(bh = bread(dev,blk, get_ptable_blocksize(dev)))) {
printk("Dev %s: unable to read partition block %d\n",
kdevname(dev),blk);
goto rdb_done;
@@ -908,6 +929,10 @@
}
rdb_done:
+ /*
+ * FIXME: should restore the original size. Then we could clean
+ * up the M/O skip. Amiga people ?
+ */
set_blocksize(dev,BLOCK_SIZE);
return res;
}
@@ -1089,7 +1114,7 @@
partsect = extensect = pi->st;
while (1)
{
- xbh = bread (dev, partsect / 2, 1024);
+ xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev));
if (!xbh)
{
printk (" block %ld read failed\n", partsect);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-disk.c linux.ac/drivers/block/ide-disk.c
--- linux.vanilla/drivers/block/ide-disk.c Tue Jan 19 02:57:24 1999
+++ linux.ac/drivers/block/ide-disk.c Thu Feb 4 02:04:44 1999
@@ -101,20 +101,6 @@
id->cyls = lba_sects / (16 * 63); /* correct cyls */
return 1; /* lba_capacity is our only option */
}
- /*
- * This is a split test for drives less than 8 Gig only.
- * Drives less than 8GB sometimes declare that they have 15 heads.
- * This is an accounting trick (0-15) == (1-16), just an initial
- * zero point difference.
- */
- if ((id->lba_capacity < 16514064) && (lba_sects > chs_sects) &&
- ((id->heads == 15) || (id->heads == 16)) && (id->sectors == 63)) {
- if (id->heads == 15)
- id->cyls = lba_sects / (15 * 63); /* correct cyls */
- if (id->heads == 16)
- id->cyls = lba_sects / (16 * 63); /* correct cyls */
- return 1; /* lba_capacity is our only option */
- }
/* perform a rough sanity check on lba_sects: within 10% is "okay" */
if ((lba_sects - chs_sects) < _10_percent) {
return 1; /* lba_capacity is good */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-probe.c linux.ac/drivers/block/ide-probe.c
--- linux.vanilla/drivers/block/ide-probe.c Wed Jan 6 23:02:18 1999
+++ linux.ac/drivers/block/ide-probe.c Tue Feb 16 16:55:52 1999
@@ -124,6 +124,10 @@
case ide_tape:
printk ("TAPE");
break;
+ case ide_optical:
+ printk ("OPTICAL");
+ drive->removable = 1;
+ break;
default:
printk("UNKNOWN (type %d)", type);
break;
@@ -720,17 +724,39 @@
}
if (register_blkdev (hwif->major, hwif->name, ide_fops)) {
printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major);
- } else if (init_irq (hwif)) {
- printk("%s: UNABLE TO GET IRQ %d\n", hwif->name, hwif->irq);
- (void) unregister_blkdev (hwif->major, hwif->name);
- } else {
- init_gendisk(hwif);
- blk_dev[hwif->major].data = hwif;
- blk_dev[hwif->major].request_fn = rfn;
- blk_dev[hwif->major].queue = ide_get_queue;
- read_ahead[hwif->major] = 8; /* (4kB) */
- hwif->present = 1; /* success */
+ return (hwif->present = 0);
}
+
+ if (init_irq (hwif)) {
+ int i = hwif->irq;
+ /*
+ * It failed to initialise. Find the default IRQ for
+ * this port and try that.
+ */
+ if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
+ {
+ printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i);
+ (void) unregister_blkdev (hwif->major, hwif->name);
+ return (hwif->present = 0);
+ }
+ if(init_irq (hwif))
+ {
+ printk("%s: probed IRQ %d and default IRQ %d failed.\n",
+ hwif->name, i, hwif->irq);
+ (void) unregister_blkdev (hwif->major, hwif->name);
+ return (hwif->present = 0);
+ }
+ printk("%s: probed IRQ %d failed, using default.\n",
+ hwif->name, hwif->irq);
+ }
+
+ init_gendisk(hwif);
+ blk_dev[hwif->major].data = hwif;
+ blk_dev[hwif->major].request_fn = rfn;
+ blk_dev[hwif->major].queue = ide_get_queue;
+ read_ahead[hwif->major] = 8; /* (4kB) */
+ hwif->present = 1; /* success */
+
#if (DEBUG_SPINLOCK > 0)
{
static int done = 0;
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/ide.h linux.ac/drivers/block/ide.h
--- linux.vanilla/drivers/block/ide.h Thu Dec 31 18:10:40 1998
+++ linux.ac/drivers/block/ide.h Tue Feb 16 16:55:59 1999
@@ -182,6 +182,7 @@
#define ide_scsi 0x21
#define ide_disk 0x20
+#define ide_optical 0x7
#define ide_cdrom 0x5
#define ide_tape 0x1
#define ide_floppy 0x0
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/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 Jan 26 09:44:20 1999
+++ linux.ac/drivers/char/bttv.c Tue Feb 16 16:56:07 1999
@@ -537,6 +537,8 @@
{ 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
/* Aimslab VHX */
{ 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
+ /* Zoltrix TV-Max */
+ { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
};
#define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
@@ -2880,9 +2882,6 @@
} else if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) {
btv->type=BTTV_STB;
- } else
- if (I2CRead(&(btv->i2c), I2C_VHX)>=0) {
- btv->type=BTTV_VHX;
} else {
if (I2CRead(&(btv->i2c), 0x80)>=0) /* check for msp34xx */
btv->type = BTTV_MIROPRO;
@@ -2907,8 +2906,8 @@
}
if(btv->type==BTTV_AVERMEDIA98)
{
- btv->pll.pll_ifreq=28636363;
- btv->pll.pll_crystal=BT848_IFORM_XT0;
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
}
if (btv->have_tuner && btv->tuner_type != -1)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bttv.h linux.ac/drivers/char/bttv.h
--- linux.vanilla/drivers/char/bttv.h Tue Jan 26 09:44:20 1999
+++ linux.ac/drivers/char/bttv.h Tue Feb 16 20:25:38 1999
@@ -206,7 +206,8 @@
#define BTTV_MIROPRO 0x0b
#define BTTV_ADSTECH_TV 0x0c
#define BTTV_AVERMEDIA98 0x0d
-#define BTTV_VHX 0x0e
+#define BTTV_VHX 0x0e
+#define BTTV_ZOLTRIX 0x0f
#define AUDIO_TUNER 0x00
#define AUDIO_RADIO 0x01
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/pc_keyb.c linux.ac/drivers/char/pc_keyb.c
--- linux.vanilla/drivers/char/pc_keyb.c Tue Jan 26 09:44:20 1999
+++ linux.ac/drivers/char/pc_keyb.c Tue Feb 16 17:05:18 1999
@@ -10,6 +10,9 @@
* because they share the same hardware.
* Johan Myreen 1998-10-08.
*
+ * Code fixes to handle mouse ACKs properly.
+ * C. Scott Ananian 1999-01-29.
+ *
*/
#include
@@ -74,6 +77,8 @@
static struct aux_queue *queue; /* Mouse data buffer. */
static int aux_count = 0;
+/* used when we send commands to the mouse that expect an ACK. */
+static unsigned char mouse_reply_expected = 0;
#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
#define AUX_INTS_ON (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
@@ -99,7 +104,7 @@
* Controller Status register are set 0."
*/
-static inline void kb_wait(void)
+static void kb_wait(void)
{
unsigned long timeout = KBC_TIMEOUT;
@@ -400,6 +405,33 @@
return 0200;
}
+static inline void handle_mouse_event(unsigned char scancode)
+{
+#ifdef CONFIG_PSMOUSE
+ if (mouse_reply_expected) {
+ if (scancode == AUX_ACK) {
+ mouse_reply_expected--;
+ return;
+ }
+ mouse_reply_expected = 0;
+ }
+
+ add_mouse_randomness(scancode);
+ if (aux_count) {
+ int head = queue->head;
+
+ queue->buf[head] = scancode;
+ head = (head + 1) & (AUX_BUF_SIZE-1);
+ if (head != queue->tail) {
+ queue->head = head;
+ if (queue->fasync)
+ kill_fasync(queue->fasync, SIGIO);
+ wake_up_interruptible(&queue->proc_list);
+ }
+ }
+#endif
+}
+
/*
* This reads the keyboard status port, and does the
* appropriate action.
@@ -417,21 +449,7 @@
scancode = inb(KBD_DATA_REG);
if (status & KBD_STAT_MOUSE_OBF) {
-#ifdef CONFIG_PSMOUSE
- /* Mouse data. */
- if (aux_count) {
- int head = queue->head;
- queue->buf[head] = scancode;
- add_mouse_randomness(scancode);
- head = (head + 1) & (AUX_BUF_SIZE-1);
- if (head != queue->tail) {
- queue->head = head;
- if (queue->fasync)
- kill_fasync(queue->fasync, SIGIO);
- wake_up_interruptible(&queue->proc_list);
- }
- }
-#endif
+ handle_mouse_event(scancode);
} else {
if (do_acknowledge(scancode))
handle_scancode(scancode);
@@ -716,9 +734,7 @@
static int __init detect_auxiliary_port(void)
{
unsigned long flags;
- unsigned char status;
- unsigned char val;
- int loops = 5;
+ int loops = 10;
int retval = 0;
spin_lock_irqsave(&kbd_controller_lock, flags);
@@ -736,20 +752,19 @@
kb_wait();
outb(0x5a, KBD_DATA_REG); /* 0x5a is a random dummy value. */
- status = inb(KBD_STATUS_REG);
- while (!(status & KBD_STAT_OBF) && loops--) {
- mdelay(1);
- status = inb(KBD_STATUS_REG);
- }
+ do {
+ unsigned char status = inb(KBD_STATUS_REG);
- if (status & KBD_STAT_OBF) {
- val = inb(KBD_DATA_REG);
- if (status & KBD_STAT_MOUSE_OBF) {
- printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
- retval = 1;
+ if (status & KBD_STAT_OBF) {
+ (void) inb(KBD_DATA_REG);
+ if (status & KBD_STAT_MOUSE_OBF) {
+ printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
+ retval = 1;
+ }
+ break;
}
- }
-
+ mdelay(1);
+ } while (--loops);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
return retval;
@@ -770,16 +785,33 @@
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
-static unsigned int get_from_queue(void)
+/*
+ * Send a byte to the mouse & handle returned ack
+ */
+static void aux_write_ack(int val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_controller_lock, flags);
+ kb_wait();
+ outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);
+ kb_wait();
+ outb(val, KBD_DATA_REG);
+ /* we expect an ACK in response. */
+ mouse_reply_expected++;
+ kb_wait();
+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+
+static unsigned char get_from_queue(void)
{
- unsigned int result;
+ unsigned char result;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&kbd_controller_lock, flags);
result = queue->buf[queue->tail];
queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
- restore_flags(flags);
+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
return result;
}
@@ -834,7 +866,7 @@
kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE); /* Enable the
auxiliary port on
controller. */
- aux_write_dev(AUX_ENABLE_DEV); /* Enable aux device */
+ aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
return 0;
@@ -951,11 +983,11 @@
#ifdef INITIALIZE_MOUSE
kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
- aux_write_dev(AUX_SET_SAMPLE);
- aux_write_dev(100); /* 100 samples/sec */
- aux_write_dev(AUX_SET_RES);
- aux_write_dev(3); /* 8 counts per mm */
- aux_write_dev(AUX_SET_SCALE21); /* 2:1 scaling */
+ aux_write_ack(AUX_SET_SAMPLE);
+ aux_write_ack(100); /* 100 samples/sec */
+ aux_write_ack(AUX_SET_RES);
+ aux_write_ack(3); /* 8 counts per mm */
+ aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */
#endif /* INITIALIZE_MOUSE */
kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/pc_keyb.h linux.ac/drivers/char/pc_keyb.h
--- linux.vanilla/drivers/char/pc_keyb.h Tue Jan 19 02:57:26 1999
+++ linux.ac/drivers/char/pc_keyb.h Tue Feb 16 16:56:38 1999
@@ -114,8 +114,12 @@
#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
#define AUX_RESET 0xFF /* Reset aux device */
+#define AUX_ACK 0xFA /* Command byte ACK. */
-#define AUX_BUF_SIZE 2048
+#define AUX_BUF_SIZE 2048 /* This might be better divisible by
+ three to make overruns stay in sync
+ but then the read function would need
+ a lock etc - ick */
struct aux_queue {
unsigned long head;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/pty.c linux.ac/drivers/char/pty.c
--- linux.vanilla/drivers/char/pty.c Sun Nov 8 15:07:40 1998
+++ linux.ac/drivers/char/pty.c Tue Feb 16 16:56:50 1999
@@ -84,7 +84,6 @@
wake_up_interruptible(&tty->link->write_wait);
set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
if (tty->driver.subtype == PTY_TYPE_MASTER) {
- tty_hangup(tty->link);
set_bit(TTY_OTHER_CLOSED, &tty->flags);
#ifdef CONFIG_UNIX98_PTYS
{
@@ -95,6 +94,7 @@
}
}
#endif
+ tty_vhangup(tty->link);
}
}
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/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/char/vt.c linux.ac/drivers/char/vt.c
--- linux.vanilla/drivers/char/vt.c Thu Jan 14 01:25:21 1999
+++ linux.ac/drivers/char/vt.c Fri Feb 5 19:12:26 1999
@@ -165,7 +165,7 @@
val = K_HOLE;
} else
val = (i ? K_HOLE : K_NOSUCHMAP);
- return __put_user(val, &user_kbe->kb_value);
+ return put_user(val, &user_kbe->kb_value);
case KDSKBENT:
if (!perm)
return -EPERM;
@@ -244,7 +244,7 @@
case KDGETKEYCODE:
kc = getkeycode(tmp.scancode);
if (kc >= 0)
- kc = __put_user(kc, &user_kbkc->keycode);
+ kc = put_user(kc, &user_kbkc->keycode);
break;
case KDSETKEYCODE:
if (!perm)
@@ -282,8 +282,8 @@
p = func_table[i];
if(p)
for ( ; *p && sz; p++, sz--)
- __put_user(*p, q++);
- __put_user('\0', q);
+ put_user(*p, q++);
+ put_user('\0', q);
return ((p && *p) ? -EOVERFLOW : 0);
case KDSKBSENT:
if (!perm)
@@ -603,12 +603,10 @@
{
struct kbdiacrs *a = (struct kbdiacrs *)arg;
- i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
- if (i)
- return i;
- __put_user(accent_table_size, &a->kb_cnt);
- __copy_to_user(a->kbdiacr, accent_table,
- accent_table_size*sizeof(struct kbdiacr));
+ if (put_user(accent_table_size, &a->kb_cnt))
+ return -EFAULT;
+ if (copy_to_user(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr)))
+ return -EFAULT;
return 0;
}
@@ -619,14 +617,13 @@
if (!perm)
return -EPERM;
- i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
- if (i)
- return i;
- __get_user(ct,&a->kb_cnt);
+ if (get_user(ct,&a->kb_cnt))
+ return -EFAULT;
if (ct >= MAX_DIACR)
return -EINVAL;
accent_table_size = ct;
- __copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
+ if (copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr)))
+ return -EFAULT;
return 0;
}
@@ -717,12 +714,12 @@
i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
if (i)
return i;
- __put_user(fg_console + 1, &vtstat->v_active);
+ put_user(fg_console + 1, &vtstat->v_active);
state = 1; /* /dev/tty0 is always open */
for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
if (VT_IS_IN_USE(i))
state |= mask;
- return __put_user(state, &vtstat->v_state);
+ return put_user(state, &vtstat->v_state);
}
/*
@@ -856,8 +853,8 @@
i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
if (i)
return i;
- __get_user(ll, &vtsizes->v_rows);
- __get_user(cc, &vtsizes->v_cols);
+ get_user(ll, &vtsizes->v_rows);
+ get_user(cc, &vtsizes->v_cols);
return vc_resize_all(ll, cc);
}
@@ -870,12 +867,12 @@
i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
if (i)
return i;
- __get_user(ll, &vtconsize->v_rows);
- __get_user(cc, &vtconsize->v_cols);
- __get_user(vlin, &vtconsize->v_vlin);
- __get_user(clin, &vtconsize->v_clin);
- __get_user(vcol, &vtconsize->v_vcol);
- __get_user(ccol, &vtconsize->v_ccol);
+ get_user(ll, &vtconsize->v_rows);
+ get_user(cc, &vtconsize->v_cols);
+ get_user(vlin, &vtconsize->v_vlin);
+ get_user(clin, &vtconsize->v_clin);
+ get_user(vcol, &vtconsize->v_vcol);
+ get_user(ccol, &vtconsize->v_ccol);
vlin = vlin ? vlin : video_scan_lines;
if ( clin )
{
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 Thu Feb 4 18:01:28 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,11 +91,10 @@
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
@@ -113,6 +122,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 +153,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 +163,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 +170,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 +188,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 +209,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 +223,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 +245,19 @@
# 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
#
+
+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 +270,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 Tue Feb 16 17:45:19 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
@@ -1046,6 +1046,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/Space.c linux.ac/drivers/net/Space.c
--- linux.vanilla/drivers/net/Space.c Tue Jan 19 02:57:28 1999
+++ linux.ac/drivers/net/Space.c Tue Jan 26 11:33:18 1999
@@ -518,7 +518,7 @@
&& dfx_probe(dev)
#endif
#ifdef CONFIG_APFDDI
- && apfddi_init(dev);
+ && apfddi_init(dev)
#endif
&& 1 ) {
return 1; /* -ENODEV or -EAGAIN would be more accurate. */
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/defxx.c linux.ac/drivers/net/defxx.c
--- linux.vanilla/drivers/net/defxx.c Sun Nov 8 15:07:29 1998
+++ linux.ac/drivers/net/defxx.c Tue Feb 16 16:56:57 1999
@@ -2881,6 +2881,22 @@
return(DFX_K_SUCCESS);
}
+
+/*
+ * Align an sk_buff to a boundary power of 2
+ *
+ */
+
+void my_skb_align(struct sk_buff *skb, int n)
+{
+ u32 x=(u32)skb->data; /* We only want the low bits .. */
+ u32 v;
+
+ v=(x+n-1)&~(n-1); /* Where we want to be */
+
+ skb_reserve(skb, v-x);
+}
+
/*
* ================
@@ -2950,8 +2966,8 @@
* align to 128 bytes for compatibility with
* the old EISA boards.
*/
- newskb->data = (char *)((unsigned long)
- (newskb->data+127) & ~127);
+
+ my_skb_align(newskb,128);
bp->descr_block_virt->rcv_data[i+j].long_1 = virt_to_bus(newskb->data);
/*
* p_rcv_buff_va is only used inside the
@@ -3062,10 +3078,10 @@
newskb = dev_alloc_skb(NEW_SKB_SIZE);
if (newskb){
rx_in_place = 1;
-
- newskb->data = (char *)((unsigned long)(newskb->data+127) & ~127);
+
+ my_skb_align(newskb, 128);
skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
- skb->data += RCV_BUFF_K_PADDING;
+ skb_reserve(skb, RCV_BUFF_K_PADDING);
bp->p_rcv_buff_va[entry] = (char *)newskb;
bp->descr_block_virt->rcv_data[entry].long_1 = virt_to_bus(newskb->data);
} else
@@ -3088,9 +3104,9 @@
memcpy(skb->data, p_buff + RCV_BUFF_K_PADDING, pkt_len+3);
}
-
- skb->data += 3; /* adjust data field so that it points to FC byte */
- skb->len = pkt_len; /* pass up packet length, NOT including CRC */
+
+ skb_reserve(skb,3); /* adjust data field so that it points to FC byte */
+ skb_put(skb, pkt_len); /* pass up packet length, NOT including CRC */
skb->dev = bp->dev; /* pass up device pointer */
skb->protocol = fddi_type_trans(skb, bp->dev);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/eepro100.c linux.ac/drivers/net/eepro100.c
--- linux.vanilla/drivers/net/eepro100.c Tue Jan 19 02:57:28 1999
+++ linux.ac/drivers/net/eepro100.c Tue Feb 16 16:57:05 1999
@@ -842,9 +842,6 @@
wait_for_cmd_done(ioaddr + SCBCmd);
outw(CU_DUMPSTATS, ioaddr + SCBCmd);
- /* No need to wait for the command unit to accept here. */
- if ((sp->phy[0] & 0x8000) == 0)
- mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);
/*
* Request the IRQ last, after we have set up all data structures.
@@ -854,6 +851,10 @@
"Intel EtherExpress Pro 10/100 Ethernet", dev)) {
return -EAGAIN;
}
+
+ /* No need to wait for the command unit to accept here. */
+ if ((sp->phy[0] & 0x8000) == 0)
+ mdio_read(ioaddr, sp->phy[0] & 0x1f, 0);
MOD_INC_USE_COUNT;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/baycom_epp.c linux.ac/drivers/net/hamradio/baycom_epp.c
--- linux.vanilla/drivers/net/hamradio/baycom_epp.c Thu Dec 3 13:48:35 1998
+++ linux.ac/drivers/net/hamradio/baycom_epp.c Wed Jan 27 19:08:52 1999
@@ -1075,6 +1075,7 @@
if (!(pp->modes & (PARPORT_MODE_PCECPEPP|PARPORT_MODE_PCEPP))) {
printk(KERN_ERR "%s: parport at 0x%lx does not support any EPP mode\n",
bc_drvname, pp->base);
+ parport_release(bc->pdev);
parport_unregister_device(bc->pdev);
return -EIO;
}
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/ppp.c linux.ac/drivers/net/ppp.c
--- linux.vanilla/drivers/net/ppp.c Tue Jan 19 02:57:28 1999
+++ linux.ac/drivers/net/ppp.c Tue Feb 16 19:18:15 1999
@@ -2062,7 +2062,11 @@
"ppp: error in VJ decompression\n");
return 0;
}
- skb_put(skb, new_count + PPP_HDRLEN - skb->len);
+ new_count += PPP_HDRLEN;
+ if (new_count > skb->len)
+ skb_put(skb, new_count - skb->len);
+ else
+ skb_trim(skb, new_count);
return rcv_proto_ip(ppp, skb);
}
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 Dec 22 23:19:47 1998
+++ 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);
}
@@ -440,6 +442,8 @@
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRA_CARDS) "i");
+EXPORT_NO_SYMBOLS;
+
/* This is set up so that only a single autoprobe takes place per call.
ISA device autoprobes on a running machine are not recommended. */
int
@@ -459,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;
}
@@ -479,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 */
@@ -498,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/syncppp.c linux.ac/drivers/net/syncppp.c
--- linux.vanilla/drivers/net/syncppp.c Thu Dec 3 13:48:36 1998
+++ linux.ac/drivers/net/syncppp.c Tue Feb 16 17:40:04 1999
@@ -51,7 +51,7 @@
#include
#include "syncppp.h"
-#define MAXALIVECNT 3 /* max. alive packets */
+#define MAXALIVECNT 6 /* max. alive packets */
#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
#define PPP_UI 0x03 /* Unnumbered Information */
@@ -380,6 +380,7 @@
if_down (dev);
if (! (sp->pp_flags & PP_CISCO)) {
/* Shut down the PPP link. */
+ sp->lcp.magic = jiffies;
sp->lcp.state = LCP_STATE_CLOSED;
sp->ipcp.state = IPCP_STATE_CLOSED;
sppp_clear_timeout (sp);
@@ -841,6 +842,25 @@
}
EXPORT_SYMBOL(sppp_open);
+
+int sppp_reopen (struct device *dev)
+{
+ struct sppp *sp = &((struct ppp_device *)dev)->sppp;
+ sppp_close(dev);
+ dev->flags |= IFF_RUNNING;
+ if (!(sp->pp_flags & PP_CISCO))
+ {
+ sp->lcp.magic = jiffies;
+ ++sp->pp_seq;
+ sp->lcp.state = LCP_STATE_CLOSED;
+ sp->ipcp.state = IPCP_STATE_CLOSED;
+ /* Give it a moment for the line to settle then go */
+ sppp_set_timeout (sp, 1);
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL(sppp_reopen);
int sppp_change_mtu(struct device *dev, int new_mtu)
{
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/syncppp.h linux.ac/drivers/net/syncppp.h
--- linux.vanilla/drivers/net/syncppp.h Sun Nov 8 15:07:36 1998
+++ linux.ac/drivers/net/syncppp.h Tue Feb 16 16:57:20 1999
@@ -80,6 +80,7 @@
int sppp_isempty (struct device *dev);
void sppp_flush (struct device *dev);
int sppp_open (struct device *dev);
+int sppp_reopen (struct device *dev);
int sppp_close (struct device *dev);
#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/tlan.c linux.ac/drivers/net/tlan.c
--- linux.vanilla/drivers/net/tlan.c Sat Jan 9 21:50:43 1999
+++ linux.ac/drivers/net/tlan.c Tue Feb 16 16:57:30 1999
@@ -29,6 +29,8 @@
*
* Tigran Aivazian : TLan_PciProbe() now uses
* new PCI BIOS interface.
+ * Alan Cox : Fixed the out of memory
+ * handling.
*
********************************************************************/
@@ -1250,28 +1252,36 @@
netif_rx( skb );
}
} else {
- skb = (struct sk_buff *) head_list->buffer[9].address;
- head_list->buffer[9].address = 0;
- skb_trim( skb, head_list->frameSize );
-
+ struct sk_buff *new_skb;
+
+ /*
+ * I changed the algorithm here. What we now do
+ * is allocate the new frame. If this fails we
+ * simply recycle the frame.
+ */
+
+ new_skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 );
+ if ( new_skb != NULL ) {
+ /* If this ever happened it would be a problem */
+ /* not any more - ac */
+ skb = (struct sk_buff *) head_list->buffer[9].address;
+ head_list->buffer[9].address = 0;
+ skb_trim( skb, head_list->frameSize );
#if LINUX_KERNEL_VERSION > 0x20100
priv->stats->rx_bytes += head_list->frameSize;
#endif
- skb->protocol = eth_type_trans( skb, dev );
- netif_rx( skb );
-
- skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 );
- if ( skb == NULL ) {
- printk( "TLAN: Couldn't allocate memory for received data.\n" );
- /* If this ever happened it would be a problem */
- } else {
- skb->dev = dev;
- skb_reserve( skb, 2 );
- t = (void *) skb_put( skb, TLAN_MAX_FRAME_SIZE );
+ skb->protocol = eth_type_trans( skb, dev );
+ netif_rx( skb );
+
+ new_skb->dev = dev;
+ skb_reserve( new_skb, 2 );
+ t = (void *) skb_put( new_skb, TLAN_MAX_FRAME_SIZE );
head_list->buffer[0].address = virt_to_bus( t );
- head_list->buffer[9].address = (u32) skb;
+ head_list->buffer[9].address = (u32) new_skb;
}
+ else
+ printk(KERN_WARNING "TLAN: Couldn't allocate memory for received data.\n" );
}
head_list->forward = 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/z85230.c linux.ac/drivers/net/z85230.c
--- linux.vanilla/drivers/net/z85230.c Sat Jan 9 21:50:43 1999
+++ linux.ac/drivers/net/z85230.c Tue Feb 16 16:57:30 1999
@@ -349,6 +349,7 @@
if(status&TxEOM)
{
/* printk("%s: Tx underrun.\n", chan->dev->name); */
+ chan->stats.tx_fifo_errors++;
write_zsctrl(chan, ERR_RES);
z8530_tx_done(chan);
}
@@ -359,6 +360,8 @@
{
printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3]|RxENABLE);
+ if(chan->netdevice)
+ sppp_reopen(chan->netdevice);
}
else
{
@@ -450,6 +453,8 @@
{
printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
write_zsreg(chan, R3, chan->regs[3]|RxENABLE);
+ if(chan->netdevice)
+ sppp_reopen(chan->netdevice);
}
else
{
@@ -1107,6 +1112,14 @@
{
flags=claim_dma_lock();
disable_dma(c->txdma);
+ /*
+ * Check if we crapped out.
+ */
+ if(get_dma_residue(c->txdma))
+ {
+ c->stats.tx_dropped++;
+ c->stats.tx_fifo_errors++;
+ }
release_dma_lock(flags);
}
c->txcount=0;
@@ -1133,6 +1146,7 @@
set_dma_count(c->txdma, c->txcount);
enable_dma(c->txdma);
release_dma_lock(flags);
+ write_zsctrl(c, RES_EOM_L);
write_zsreg(c, R5, c->regs[R5]|TxENAB);
}
else
@@ -1173,6 +1187,8 @@
c->tx_skb=NULL;
z8530_tx_begin(c);
spin_unlock_irqrestore(&z8530_buffer_lock, flags);
+ c->stats.tx_packets++;
+ c->stats.tx_bytes+=skb->len;
dev_kfree_skb(skb);
}
@@ -1255,11 +1271,16 @@
skb=dev_alloc_skb(ct);
if(skb==NULL)
- printk("%s: Memory squeeze.\n", c->netdevice->name);
+ {
+ c->stats.rx_dropped++;
+ printk(KERN_WARNING "%s: Memory squeeze.\n", c->netdevice->name);
+ }
else
{
skb_put(skb, ct);
memcpy(skb->data, rxb, ct);
+ c->stats.rx_packets++;
+ c->stats.rx_bytes+=ct;
}
c->dma_ready=1;
}
@@ -1305,6 +1326,9 @@
{
skb_put(c->skb2,c->mtu);
}
+ c->stats.rx_packets++;
+ c->stats.rx_bytes+=ct;
+
}
/*
* If we received a frame we must now process it.
@@ -1315,7 +1339,10 @@
c->rx_function(c,skb);
}
else
- printk("Lost a frame\n");
+ {
+ c->stats.rx_dropped++;
+ printk(KERN_ERR "%s: Lost a frame\n", c->netdevice->name);
+ }
}
/*
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
#include
#include
#include
@@ -33,9 +34,9 @@
S_IFDIR | S_IRUGO | S_IXUGO, 2
};
-extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip,
- u32 base, int io_port, int irq, int dma,
- long long options, int clock);
+extern int ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip,
+ u32 base, int io_port, int irq, int dma,
+ long long options, int clock);
int amiga7xx_detect(Scsi_Host_Template *tpnt)
{
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/atari_NCR5380.c linux.ac/drivers/scsi/atari_NCR5380.c
--- linux.vanilla/drivers/scsi/atari_NCR5380.c Sun Nov 8 15:07:54 1998
+++ linux.ac/drivers/scsi/atari_NCR5380.c Sun Nov 8 14:35:42 1998
@@ -1459,9 +1459,9 @@
unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
- && jiffies < timeout && !hostdata->connected)
+ && time_before(jiffies, timeout) && !hostdata->connected)
;
- if (jiffies >= timeout)
+ if (time_after_eq(jiffies, timeout))
{
printk("scsi : arbitration timeout at %d\n", __LINE__);
NCR5380_write(MODE_REG, MR_BASE);
@@ -1616,7 +1616,7 @@
* only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
*/
- while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) &
+ while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) &
(SR_BSY | SR_IO)));
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) ==
@@ -1629,7 +1629,7 @@
return -1;
}
#else
- while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
+ while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
#endif
/*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/atari_scsi.c linux.ac/drivers/scsi/atari_scsi.c
--- linux.vanilla/drivers/scsi/atari_scsi.c Sun Nov 8 15:07:50 1998
+++ linux.ac/drivers/scsi/atari_scsi.c Thu Dec 17 01:56:31 1998
@@ -132,51 +132,51 @@
} while(0)
#define SCSI_DMA_READ_P(elt) \
- (((unsigned long)tt_scsi_dma.elt##_hi << 24) | \
- ((unsigned long)tt_scsi_dma.elt##_hmd << 16) | \
- ((unsigned long)tt_scsi_dma.elt##_lmd << 8) | \
- (unsigned long)tt_scsi_dma.elt##_lo)
-
-
-#define SCSI_DMA_SETADR(adr) \
- do { \
- unsigned long __adr = (adr); \
- st_dma.dma_lo = (unsigned char)__adr; \
- MFPDELAY(); \
- __adr >>= 8; \
- st_dma.dma_md = (unsigned char)__adr; \
- MFPDELAY(); \
- __adr >>= 8; \
- st_dma.dma_hi = (unsigned char)__adr; \
- MFPDELAY(); \
- } while(0)
-
-#define SCSI_DMA_GETADR() ({ \
- unsigned long __adr; \
- __adr = st_dma.dma_lo; \
- MFPDELAY(); \
- __adr |= (st_dma.dma_md & 0xff) << 8; \
- MFPDELAY(); \
- __adr |= (st_dma.dma_hi & 0xff) << 16; \
- MFPDELAY(); \
- __adr; \
-})
-
-#define ENABLE_IRQ() \
- do { \
- if (IS_A_TT()) \
- atari_enable_irq( IRQ_TT_MFP_SCSI ); \
- else \
- atari_enable_irq( IRQ_MFP_FSCSI ); \
- } while(0)
-
-#define DISABLE_IRQ() \
- do { \
- if (IS_A_TT()) \
- atari_disable_irq( IRQ_TT_MFP_SCSI ); \
- else \
- atari_disable_irq( IRQ_MFP_FSCSI ); \
- } while(0)
+ (((((((unsigned long)tt_scsi_dma.elt##_hi << 8) | \
+ (unsigned long)tt_scsi_dma.elt##_hmd) << 8) | \
+ (unsigned long)tt_scsi_dma.elt##_lmd) << 8) | \
+ (unsigned long)tt_scsi_dma.elt##_lo)
+
+
+static inline void SCSI_DMA_SETADR(unsigned long adr)
+{
+ st_dma.dma_lo = (unsigned char)adr;
+ MFPDELAY();
+ adr >>= 8;
+ st_dma.dma_md = (unsigned char)adr;
+ MFPDELAY();
+ adr >>= 8;
+ st_dma.dma_hi = (unsigned char)adr;
+ MFPDELAY();
+}
+
+static inline unsigned long SCSI_DMA_GETADR(void)
+{
+ unsigned long adr;
+ adr = st_dma.dma_lo;
+ MFPDELAY();
+ adr |= (st_dma.dma_md & 0xff) << 8;
+ MFPDELAY();
+ adr |= (st_dma.dma_hi & 0xff) << 16;
+ MFPDELAY();
+ return adr;
+}
+
+static inline void ENABLE_IRQ(void)
+{
+ if (IS_A_TT())
+ atari_enable_irq(IRQ_TT_MFP_SCSI);
+ else
+ atari_enable_irq(IRQ_MFP_FSCSI);
+}
+
+static inline void DISABLE_IRQ(void)
+{
+ if (IS_A_TT())
+ atari_disable_irq(IRQ_TT_MFP_SCSI);
+ else
+ atari_disable_irq(IRQ_MFP_FSCSI);
+}
#define HOSTDATA_DMALEN (((struct NCR5380_hostdata *) \
@@ -480,16 +480,17 @@
/* fetch rest bytes in the DMA register */
dst = (char *)SCSI_DMA_READ_P( dma_addr );
- if ((nr = ((long)dst & 3))) {
+ nr = ((long)dst & 3);
+ if (nr) {
/* there are 'nr' bytes left for the last long address before the
DMA pointer */
- dst = (char *)( (unsigned long)dst & ~3 );
+ dst = (char *)((unsigned long)dst ^ nr);
DMA_PRINTK("SCSI DMA: there are %d rest bytes for phys addr 0x%08lx",
nr, (long)dst);
dst = (char *)PTOV(dst); /* The content of the DMA pointer
* is a physical address! */
DMA_PRINTK(" = virt addr 0x%08lx\n", (long)dst);
- for( src = (char *)&tt_scsi_dma.dma_restdata; nr > 0; --nr )
+ for (src = (char *)&tt_scsi_dma.dma_restdata; nr != 0; --nr)
*dst++ = *src++;
}
}
@@ -764,7 +765,7 @@
}
#endif
-__initfunc(void atari_scsi_setup( char *str, int *ints ))
+void __init atari_scsi_setup(char *str, int *ints)
{
/* Format of atascsi parameter is:
* atascsi=,,,,
@@ -772,23 +773,6 @@
* Negative values mean don't change.
*/
- /* Grmbl... the standard parameter parsing can't handle negative numbers
- * :-( So let's do it ourselves!
- */
-
- int i = ints[0]+1, fact;
-
- while( str && (isdigit(*str) || *str == '-') && i <= 10) {
- if (*str == '-')
- fact = -1, ++str;
- else
- fact = 1;
- ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
- if ((str = strchr( str, ',' )) != NULL)
- ++str;
- }
- ints[0] = i-1;
-
if (ints[0] < 1) {
printk( "atari_scsi_setup: no arguments!\n" );
return;
@@ -869,7 +853,7 @@
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
-__initfunc(static void atari_scsi_reset_boot( void ))
+static void __init atari_scsi_reset_boot(void)
{
unsigned long end;
@@ -892,7 +876,7 @@
NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
NCR5380_read( RESET_PARITY_INTERRUPT_REG );
- for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; )
+ for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies,end); )
barrier();
printk( " done\n" );
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/atp870u.c linux.ac/drivers/scsi/atp870u.c
--- linux.vanilla/drivers/scsi/atp870u.c Tue Dec 22 23:19:49 1998
+++ linux.ac/drivers/scsi/atp870u.c Tue Feb 16 17:41:52 1999
@@ -1684,7 +1684,7 @@
struct Scsi_Host * shpnt = NULL;
int count = 0;
static unsigned short devid[7]={0x8002,0x8010,0x8020,0x8030,0x8040,0x8050,0};
- static struct pci_dev *pdev = NULL;
+ static struct pci_dev *pdev = NULL, *acard_pdev[3];
printk("aec671x_detect: \n");
if (!pci_present())
@@ -1720,8 +1720,8 @@
h=0;
while ( devid[h] != 0 )
{
- pci_find_device(0x1191,devid[h],pdev);
- if (pdev == NULL); {
+ pdev = pci_find_device(0x1191,devid[h],pdev);
+ if (pdev == NULL) {
h++;
index=0;
continue;
@@ -1729,6 +1729,7 @@
chip_ver[2]=0;
/* To avoid messing with the things below... */
+ acard_pdev[2] = pdev;
pci_device_fn[2] = pdev->devfn;
pci_bus[2] = pdev->bus->number;
@@ -1746,15 +1747,18 @@
}
if ( pci_device_fn[2] < pci_device_fn[0] )
{
+ acard_pdev[1]=acard_pdev[0];
pci_bus[1]=pci_bus[0];
pci_device_fn[1]=pci_device_fn[0];
chip_ver[1]=chip_ver[0];
+ acard_pdev[0]=acard_pdev[2];
pci_bus[0]=pci_bus[2];
pci_device_fn[0]=pci_device_fn[2];
chip_ver[0]=chip_ver[2];
}
else if ( pci_device_fn[2] < pci_device_fn[1] )
{
+ acard_pdev[1]=acard_pdev[2];
pci_bus[1]=pci_bus[2];
pci_device_fn[1]=pci_device_fn[2];
chip_ver[1]=chip_ver[2];
@@ -1774,6 +1778,7 @@
return count;
}
+ pdev = acard_pdev[h];
pdev->devfn = pci_device_fn[h];
pdev->bus->number = pci_bus[h];
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/gdth_proc.c linux.ac/drivers/scsi/gdth_proc.c
--- linux.vanilla/drivers/scsi/gdth_proc.c Thu Jan 14 01:25:25 1999
+++ linux.ac/drivers/scsi/gdth_proc.c Sat Jan 16 21:35:28 1999
@@ -3,6 +3,7 @@
*/
#include "gdth_ioctl.h"
+#include
int gdth_proc_info(char *buffer,char **start,off_t offset,int length,
int hostno,int inout)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/hosts.c linux.ac/drivers/scsi/hosts.c
--- linux.vanilla/drivers/scsi/hosts.c Tue Jan 19 02:57:31 1999
+++ linux.ac/drivers/scsi/hosts.c Tue Feb 16 17:43:48 1999
@@ -223,6 +223,10 @@
#include "NCR53c406a.h"
#endif
+#ifdef CONFIG_SCSI_SYM53C416
+#include "sym53c416.h"
+#endif
+
#ifdef CONFIG_SCSI_DC390T
#include "dc390.h"
#endif
@@ -283,6 +287,10 @@
#include "ini9100u.h"
#endif
+#ifdef CONFIG_SCSI_INIA100
+#include "inia100.h"
+#endif
+
#ifdef CONFIG_SCSI_DEBUG
#include "scsi_debug.h"
#endif
@@ -452,7 +460,7 @@
#ifdef CONFIG_SCSI_AIC7XXX
AIC7XXX,
#endif
-#ifdef CONFIG_FD_MCS
+#ifdef CONFIG_SCSI_FD_MCS
FD_MCS,
#endif
#ifdef CONFIG_SCSI_FUTURE_DOMAIN
@@ -467,6 +475,9 @@
#ifdef CONFIG_SCSI_NCR53C406A /* 53C406A should come before QLOGIC */
NCR53c406a,
#endif
+#ifdef CONFIG_SCSI_SYM53C416
+ SYM53C416,
+#endif
#ifdef CONFIG_SCSI_QLOGIC_FAS
QLOGICFAS,
#endif
@@ -532,6 +543,9 @@
#endif
#ifdef CONFIG_SCSI_INITIO
INI9100U,
+#endif
+#ifdef CONFIG_SCSI_INIA100
+ INIA100,
#endif
#ifdef CONFIG_SCSI_QLOGICPTI
QLOGICPTI,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/i60uscsi.c linux.ac/drivers/scsi/i60uscsi.c
--- linux.vanilla/drivers/scsi/i60uscsi.c Thu Jan 1 01:00:00 1970
+++ linux.ac/drivers/scsi/i60uscsi.c Sat Jan 30 18:29:12 1999
@@ -0,0 +1,956 @@
+/**************************************************************************
+ * Initio A100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *************************************************************************
+ *
+ * module: i60uscsi.c
+ * DESCRIPTION:
+ * This is the Linux low-level SCSI driver for Initio INIA100 SCSI host
+ * adapters
+ *
+ * 07/02/98 hl - v.91n Initial drivers.
+ * 09/14/98 hl - v1.01 Support new Kernel.
+ * 09/22/98 hl - v1.01a Support reset.
+ * 09/24/98 hl - v1.01b Fixed reset.
+ * 10/05/98 hl - v1.02 split the source code and release.
+ * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up
+ **************************************************************************/
+
+#ifndef CVT_LINUX_VERSION
+#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
+#endif
+
+#include
+#include
+#include "i60uscsi.h"
+
+
+/* ---- INTERNAL FUNCTIONS ---- */
+static UCHAR waitChipReady(ORC_HCS * hcsp);
+static UCHAR waitFWReady(ORC_HCS * hcsp);
+static UCHAR waitFWReady(ORC_HCS * hcsp);
+static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp);
+static UCHAR waitHDOoff(ORC_HCS * hcsp);
+static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData);
+static unsigned short get_FW_version(ORC_HCS * hcsp);
+static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value);
+static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn);
+static int se2_rd_all(ORC_HCS * hcsp);
+static void se2_update_all(ORC_HCS * hcsp); /* setup default pattern */
+static void read_eeprom(ORC_HCS * hcsp);
+static UCHAR load_FW(ORC_HCS * hcsp);
+static void setup_SCBs(ORC_HCS * hcsp);
+static void initAFlag(ORC_HCS * hcsp);
+ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
+
+/* ---- EXTERNAL FUNCTIONS ---- */
+extern void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
+
+/* ---- INTERNAL VARIABLES ---- */
+ORC_HCS orc_hcs[MAX_SUPPORTED_ADAPTERS];
+static INIA100_ADPT_STRUCT inia100_adpt[MAX_SUPPORTED_ADAPTERS];
+/* set by inia100_setup according to the command line */
+int orc_num_scb;
+
+NVRAM nvram, *nvramp = &nvram;
+static UCHAR dftNvRam[64] =
+{
+/*----------header -------------*/
+ 0x01, /* 0x00: Sub System Vendor ID 0 */
+ 0x11, /* 0x01: Sub System Vendor ID 1 */
+ 0x60, /* 0x02: Sub System ID 0 */
+ 0x10, /* 0x03: Sub System ID 1 */
+ 0x00, /* 0x04: SubClass */
+ 0x01, /* 0x05: Vendor ID 0 */
+ 0x11, /* 0x06: Vendor ID 1 */
+ 0x60, /* 0x07: Device ID 0 */
+ 0x10, /* 0x08: Device ID 1 */
+ 0x00, /* 0x09: Reserved */
+ 0x00, /* 0x0A: Reserved */
+ 0x01, /* 0x0B: Revision of Data Structure */
+ /* -- Host Adapter Structure --- */
+ 0x01, /* 0x0C: Number Of SCSI Channel */
+ 0x01, /* 0x0D: BIOS Configuration 1 */
+ 0x00, /* 0x0E: BIOS Configuration 2 */
+ 0x00, /* 0x0F: BIOS Configuration 3 */
+ /* --- SCSI Channel 0 Configuration --- */
+ 0x07, /* 0x10: H/A ID */
+ 0x83, /* 0x11: Channel Configuration */
+ 0x20, /* 0x12: MAX TAG per target */
+ 0x0A, /* 0x13: SCSI Reset Recovering time */
+ 0x00, /* 0x14: Channel Configuration4 */
+ 0x00, /* 0x15: Channel Configuration5 */
+ /* SCSI Channel 0 Target Configuration */
+ /* 0x16-0x25 */
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ /* --- SCSI Channel 1 Configuration --- */
+ 0x07, /* 0x26: H/A ID */
+ 0x83, /* 0x27: Channel Configuration */
+ 0x20, /* 0x28: MAX TAG per target */
+ 0x0A, /* 0x29: SCSI Reset Recovering time */
+ 0x00, /* 0x2A: Channel Configuration4 */
+ 0x00, /* 0x2B: Channel Configuration5 */
+ /* SCSI Channel 1 Target Configuration */
+ /* 0x2C-0x3B */
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8,
+ 0x00, /* 0x3C: Reserved */
+ 0x00, /* 0x3D: Reserved */
+ 0x00, /* 0x3E: Reserved */
+ 0x00 /* 0x3F: Checksum */
+};
+
+
+/***************************************************************************/
+static void waitForPause(unsigned amount)
+{
+ ULONG the_time = jiffies + amount; /* 0.01 seconds per jiffy */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ while (time_before_eq(jiffies, the_time));
+#else
+ while (jiffies < the_time);
+#endif
+}
+
+/***************************************************************************/
+UCHAR waitChipReady(ORC_HCS * hcsp)
+{
+ int i;
+
+ for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */
+ if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP) /* Wait HOSTSTOP set */
+ return (TRUE);
+ waitForPause(5); /* wait 500ms before try again */
+ }
+ return (FALSE);
+}
+
+/***************************************************************************/
+UCHAR waitFWReady(ORC_HCS * hcsp)
+{
+ int i;
+
+ for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */
+ if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) /* Wait READY set */
+ return (TRUE);
+ waitForPause(5); /* wait 500ms before try again */
+ }
+ return (FALSE);
+}
+
+/***************************************************************************/
+UCHAR waitSCSIRSTdone(ORC_HCS * hcsp)
+{
+ int i;
+
+ for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */
+ if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST)) /* Wait SCSIRST done */
+ return (TRUE);
+ waitForPause(5); /* wait 500ms before try again */
+ }
+ return (FALSE);
+}
+
+/***************************************************************************/
+UCHAR waitHDOoff(ORC_HCS * hcsp)
+{
+ int i;
+
+ for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */
+ if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO)) /* Wait HDO off */
+ return (TRUE);
+ waitForPause(5); /* wait 500ms before try again */
+ }
+ return (FALSE);
+}
+
+/***************************************************************************/
+UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData)
+{
+ int i;
+
+ for (i = 0; i < 2000; i++) { /* Wait 1 second for report timeout */
+ if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI)
+ return (TRUE); /* Wait HDI set */
+ waitForPause(5); /* wait 500ms before try again */
+ }
+ return (FALSE);
+}
+
+/***************************************************************************/
+unsigned short get_FW_version(ORC_HCS * hcsp)
+{
+ UCHAR bData;
+ union {
+ unsigned short sVersion;
+ unsigned char cVersion[2];
+ } Version;
+
+ ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION);
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+ if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
+ return (FALSE);
+
+ if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */
+ return (FALSE);
+ Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
+ ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */
+
+ if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */
+ return (FALSE);
+ Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
+ ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */
+
+ return (Version.sVersion);
+}
+
+/***************************************************************************/
+UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value)
+{
+ ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM); /* Write command */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+ if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
+ return (FALSE);
+
+ ORC_WR(hcsp->HCS_Base + ORC_HDATA, address); /* Write address */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+ if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
+ return (FALSE);
+
+ ORC_WR(hcsp->HCS_Base + ORC_HDATA, value); /* Write value */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+ if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
+ return (FALSE);
+
+ return (TRUE);
+}
+
+/***************************************************************************/
+UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
+{
+ unsigned char bData;
+
+ ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM); /* Write command */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+ if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
+ return (FALSE);
+
+ ORC_WR(hcsp->HCS_Base + ORC_HDATA, address); /* Write address */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+ if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
+ return (FALSE);
+
+ if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */
+ return (FALSE);
+ *pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
+ ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */
+
+ return (TRUE);
+}
+
+/***************************************************************************/
+void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
+{
+ scbp->SCB_Status = SCB_POST;
+ ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx);
+ return;
+}
+
+
+/***********************************************************************
+ Read SCSI H/A configuration parameters from serial EEPROM
+************************************************************************/
+int se2_rd_all(ORC_HCS * hcsp)
+{
+ int i;
+ UCHAR *np, chksum = 0;
+
+ np = (UCHAR *) nvramp;
+ for (i = 0; i < 64; i++, np++) { /* <01> */
+ if (get_NVRAM(hcsp, (unsigned char) i, np) == FALSE)
+ return -1;
+// *np++ = get_NVRAM(hcsp, (unsigned char ) i);
+ }
+
+/*------ Is ckecksum ok ? ------*/
+ np = (UCHAR *) nvramp;
+ for (i = 0; i < 63; i++)
+ chksum += *np++;
+
+ if (nvramp->CheckSum != (UCHAR) chksum)
+ return -1;
+ return 1;
+}
+
+/************************************************************************
+ Update SCSI H/A configuration parameters from serial EEPROM
+*************************************************************************/
+void se2_update_all(ORC_HCS * hcsp)
+{ /* setup default pattern */
+ int i;
+ UCHAR *np, *np1, chksum = 0;
+
+ /* Calculate checksum first */
+ np = (UCHAR *) dftNvRam;
+ for (i = 0; i < 63; i++)
+ chksum += *np++;
+ *np = chksum;
+
+ np = (UCHAR *) dftNvRam;
+ np1 = (UCHAR *) nvramp;
+ for (i = 0; i < 64; i++, np++, np1++) {
+ if (*np != *np1) {
+ set_NVRAM(hcsp, (unsigned char) i, *np);
+ }
+ }
+ return;
+}
+
+/*************************************************************************
+ Function name : read_eeprom
+**************************************************************************/
+void read_eeprom(ORC_HCS * hcsp)
+{
+ if (se2_rd_all(hcsp) != 1) {
+ se2_update_all(hcsp); /* setup default pattern */
+ se2_rd_all(hcsp); /* load again */
+ }
+}
+
+
+/***************************************************************************/
+UCHAR load_FW(ORC_HCS * hcsp)
+{
+ U32 dData;
+ USHORT wBIOSAddress;
+ USHORT i;
+ UCHAR *pData, bData;
+
+
+ bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG);
+ ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG); /* Enable EEPROM programming */
+ ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00);
+ ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00);
+ if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) {
+ ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */
+ return (FALSE);
+ }
+ ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01);
+ if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) {
+ ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */
+ return (FALSE);
+ }
+ ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD); /* Enable SRAM programming */
+ pData = (UCHAR *) & dData;
+ dData = 0; /* Initial FW address to 0 */
+ ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10);
+ *pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
+ ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11);
+ *(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
+ ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12);
+ *(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
+ ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2));
+ ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData); /* Write FW address */
+
+ wBIOSAddress = (USHORT) dData; /* FW code locate at BIOS address + ? */
+ for (i = 0, pData = (UCHAR *) & dData; /* Download the code */
+ i < 0x1000; /* Firmware code size = 4K */
+ i++, wBIOSAddress++) {
+ ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
+ *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
+ if ((i % 4) == 3) {
+ ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData); /* Write every 4 bytes */
+ pData = (UCHAR *) & dData;
+ }
+ }
+
+ ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD); /* Reset program count 0 */
+ wBIOSAddress -= 0x1000; /* Reset the BIOS adddress */
+ for (i = 0, pData = (UCHAR *) & dData; /* Check the code */
+ i < 0x1000; /* Firmware code size = 4K */
+ i++, wBIOSAddress++) {
+ ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress);
+ *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */
+ if ((i % 4) == 3) {
+ if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) {
+ ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST); /* Reset program to 0 */
+ ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /*Disable EEPROM programming */
+ return (FALSE);
+ }
+ pData = (UCHAR *) & dData;
+ }
+ }
+ ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST); /* Reset program to 0 */
+ ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */
+ return (TRUE);
+}
+
+/***************************************************************************/
+void setup_SCBs(ORC_HCS * hcsp)
+{
+ ORC_SCB *pVirScb;
+ int i;
+ UCHAR j;
+ ESCB *pVirEscb;
+ PVOID pPhysEscb;
+ PVOID tPhysEscb;
+
+ j = 0;
+ pVirScb = NULL;
+ tPhysEscb = (PVOID) NULL;
+ pPhysEscb = (PVOID) NULL;
+ /* Setup SCB HCS_Base and SCB Size registers */
+ ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, orc_num_scb); /* Total number of SCBs */
+ /* SCB HCS_Base address 0 */
+ ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray);
+ /* SCB HCS_Base address 1 */
+ ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray);
+
+ /* setup scatter list address with one buffer */
+ pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
+ pVirEscb = (ESCB *) hcsp->HCS_virEscbArray;
+
+ for (i = 0; i < orc_num_scb; i++) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ pPhysEscb = (PVOID) ((ULONG) hcsp->HCS_virEscbArray + (sizeof(ESCB) * i));
+ pVirScb->SCB_SGPAddr = (U32) VIRT_TO_BUS(pPhysEscb);
+ pVirScb->SCB_SensePAddr = (U32) VIRT_TO_BUS(pPhysEscb);
+#else
+ pPhysEscb = (PVOID) (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i));
+ pVirScb->SCB_SGPAddr = (U32) pPhysEscb;
+ pVirScb->SCB_SensePAddr = (U32) pPhysEscb;
+#endif
+ pVirScb->SCB_EScb = pVirEscb;
+ pVirScb->SCB_ScbIdx = i;
+ pVirScb++;
+ pVirEscb++;
+ }
+
+ return;
+}
+
+/***************************************************************************/
+static void initAFlag(ORC_HCS * hcsp)
+{
+ UCHAR i, j;
+
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ for (j = 0; j < 8; j++) {
+ hcsp->BitAllocFlag[i][j] = 0xffffffff;
+ }
+ }
+}
+
+/***************************************************************************/
+int init_orchid(ORC_HCS * hcsp)
+{
+ UBYTE *readBytep;
+ USHORT revision;
+ UCHAR i;
+
+ initAFlag(hcsp);
+ ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF); /* Disable all interrupt */
+ if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) { /* Orchid is ready */
+ revision = get_FW_version(hcsp);
+ if (revision == 0xFFFF) {
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST); /* Reset Host Adapter */
+ if (waitChipReady(hcsp) == FALSE)
+ return (-1);
+ load_FW(hcsp); /* Download FW */
+ setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0); /* clear HOSTSTOP */
+ if (waitFWReady(hcsp) == FALSE)
+ return (-1);
+ /* Wait for firmware ready */
+ } else {
+ setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */
+ }
+ } else { /* Orchid is not Ready */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST); /* Reset Host Adapter */
+ if (waitChipReady(hcsp) == FALSE)
+ return (-1);
+ load_FW(hcsp); /* Download FW */
+ setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); /* Do Hardware Reset & */
+
+ /* clear HOSTSTOP */
+ if (waitFWReady(hcsp) == FALSE) /* Wait for firmware ready */
+ return (-1);
+ }
+
+/*------------- get serial EEProm settting -------*/
+
+ read_eeprom(hcsp);
+
+ if (nvramp->Revision != 1)
+ return (-1);
+
+ hcsp->HCS_SCSI_ID = nvramp->SCSI0Id;
+ hcsp->HCS_BIOS = nvramp->BIOSConfig1;
+ hcsp->HCS_MaxTar = MAX_TARGETS;
+ readBytep = (UCHAR *) & (nvramp->Target00Config);
+ for (i = 0; i < 16; readBytep++, i++) {
+ hcsp->TargetFlag[i] = *readBytep;
+ hcsp->MaximumTags[i] = orc_num_scb;
+ } /* for */
+
+ if (nvramp->SCSI0Config & NCC_BUSRESET) { /* Reset SCSI bus */
+ hcsp->HCS_Flags |= HCF_SCSI_RESET;
+ }
+ ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB); /* enable RP FIFO interrupt */
+ return (0);
+}
+
+/*****************************************************************************
+ Function name : orc_reset_scsi_bus
+ Description : Reset registers, reset a hanging bus and
+ kill active and disconnected commands for target w/o soft reset
+ Input : pHCB - Pointer to host adapter structure
+ Output : None.
+ Return : pSRB - Pointer to SCSI request block.
+*****************************************************************************/
+int orc_reset_scsi_bus(ORC_HCS * pHCB)
+{ /* I need Host Control Block Information */
+ ULONG flags;
+
+#if 0
+ printk("inia100: enter inia100_reset\n");
+#endif
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
+#endif
+
+ initAFlag(pHCB);
+ /* reset scsi bus */
+ ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST);
+ if (waitSCSIRSTdone(pHCB) == FALSE) {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+ return (SCSI_RESET_ERROR);
+ } else {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+ return (SCSI_RESET_SUCCESS);
+ }
+}
+
+/*****************************************************************************
+ Function name : orc_device_reset
+ Description : Reset registers, reset a hanging bus and
+ kill active and disconnected commands for target w/o soft reset
+ Input : pHCB - Pointer to host adapter structure
+ Output : None.
+ Return : pSRB - Pointer to SCSI request block.
+*****************************************************************************/
+int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned int ResetFlags)
+{ /* I need Host Control Block Information */
+ ORC_SCB *pScb;
+ ESCB *pVirEscb;
+ ORC_SCB *pVirScb;
+ UCHAR i;
+ ULONG flags;
+
+#if 0
+ printk("inia100: enter inia100_reset\n");
+#endif
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags);
+#endif
+ pScb = (ORC_SCB *) NULL;
+ pVirEscb = (ESCB *) NULL;
+
+ /* setup scatter list address with one buffer */
+ pVirScb = (ORC_SCB *) pHCB->HCS_virScbArray;
+
+ initAFlag(pHCB);
+ /* device reset */
+ for (i = 0; i < orc_num_scb; i++) {
+ pVirEscb = pVirScb->SCB_EScb;
+ if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt))
+ break;
+ pVirScb++;
+ }
+
+ if (i == orc_num_scb) {
+ printk("Unable to Reset - No SCB Found\n");
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+ return (SCSI_RESET_NOT_RUNNING);
+ }
+ if ((pScb = orc_alloc_scb(pHCB)) == NULL) {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+ return (SCSI_RESET_NOT_RUNNING);
+ }
+ pScb->SCB_Opcode = ORC_BUSDEVRST;
+ pScb->SCB_Target = target;
+ pScb->SCB_HaStat = 0;
+ pScb->SCB_TaStat = 0;
+ pScb->SCB_Status = 0x0;
+ pScb->SCB_Link = 0xFF;
+ pScb->SCB_Reserved0 = 0;
+ pScb->SCB_Reserved1 = 0;
+ pScb->SCB_XferLen = 0;
+ pScb->SCB_SGLen = 0;
+
+ pVirEscb->SCB_Srb = 0;
+ if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
+ pVirEscb->SCB_Srb = (unsigned char *) SCpnt;
+ }
+ orc_exec_scb(pHCB, pScb); /* Start execute SCB */
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags);
+#endif
+ return SCSI_RESET_PENDING;
+}
+
+
+/***************************************************************************/
+ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp)
+{
+ ORC_SCB *pTmpScb;
+ UCHAR Ch;
+ ULONG idx;
+ UCHAR index;
+ UCHAR i;
+ ULONG flags;
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
+#endif
+ Ch = hcsp->HCS_Index;
+ for (i = 0; i < 8; i++) {
+ for (index = 0; index < 32; index++) {
+ if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) {
+ hcsp->BitAllocFlag[Ch][i] &= ~(1 << index);
+ break;
+ }
+ }
+ idx = index + 32 * i;
+ pTmpScb = (PVOID) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB)));
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+ return (pTmpScb);
+ }
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+ return (NULL);
+}
+
+
+/***************************************************************************/
+void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
+{
+ ULONG flags;
+ UCHAR Index;
+ UCHAR i;
+ UCHAR Ch;
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
+#endif
+ Ch = hcsp->HCS_Index;
+ Index = scbp->SCB_ScbIdx;
+ i = Index / 32;
+ Index %= 32;
+ hcsp->BitAllocFlag[Ch][i] |= (1 << Index);
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+}
+
+
+/*****************************************************************************
+ Function name : Addinia100_into_Adapter_table
+ Description : This function will scan PCI bus to get all Orchid card
+ Input : None.
+ Output : None.
+ Return : SUCCESSFUL - Successful scan
+ ohterwise - No drives founded
+*****************************************************************************/
+int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
+ BYTE bBus, BYTE bDevice)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
+ if (inia100_adpt[i].ADPT_BIOS < wBIOS)
+ continue;
+ if (inia100_adpt[i].ADPT_BIOS == wBIOS) {
+ if (inia100_adpt[i].ADPT_BASE == wBASE)
+ if (inia100_adpt[i].ADPT_Bus != 0xFF)
+ return (FAILURE);
+ else if (inia100_adpt[i].ADPT_BASE < wBASE)
+ continue;
+ }
+ for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
+ inia100_adpt[j].ADPT_BASE = inia100_adpt[j - 1].ADPT_BASE;
+ inia100_adpt[j].ADPT_INTR = inia100_adpt[j - 1].ADPT_INTR;
+ inia100_adpt[j].ADPT_BIOS = inia100_adpt[j - 1].ADPT_BIOS;
+ inia100_adpt[j].ADPT_Bus = inia100_adpt[j - 1].ADPT_Bus;
+ inia100_adpt[j].ADPT_Device = inia100_adpt[j - 1].ADPT_Device;
+ }
+ inia100_adpt[i].ADPT_BASE = wBASE;
+ inia100_adpt[i].ADPT_INTR = bInterrupt;
+ inia100_adpt[i].ADPT_BIOS = wBIOS;
+ inia100_adpt[i].ADPT_Bus = bBus;
+ inia100_adpt[i].ADPT_Device = bDevice;
+ return (SUCCESSFUL);
+ }
+ return (FAILURE);
+}
+
+
+/*****************************************************************************
+ Function name : init_inia100Adapter_table
+ Description : This function will scan PCI bus to get all Orchid card
+ Input : None.
+ Output : None.
+ Return : SUCCESSFUL - Successful scan
+ ohterwise - No drives founded
+*****************************************************************************/
+void init_inia100Adapter_table(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { /* Initialize adapter structure */
+ inia100_adpt[i].ADPT_BIOS = 0xffff;
+ inia100_adpt[i].ADPT_BASE = 0xffff;
+ inia100_adpt[i].ADPT_INTR = 0xff;
+ inia100_adpt[i].ADPT_Bus = 0xff;
+ inia100_adpt[i].ADPT_Device = 0xff;
+ }
+}
+
+/*****************************************************************************
+ Function name : get_orcPCIConfig
+ Description :
+ Input : pHCB - Pointer to host adapter structure
+ Output : None.
+ Return : pSRB - Pointer to SCSI request block.
+*****************************************************************************/
+void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx)
+{
+ pCurHcb->HCS_Base = inia100_adpt[ch_idx].ADPT_BASE; /* Supply base address */
+ pCurHcb->HCS_BIOS = inia100_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */
+ pCurHcb->HCS_Intr = inia100_adpt[ch_idx].ADPT_INTR; /* Supply interrupt line */
+ return;
+}
+
+
+/*****************************************************************************
+ Function name : abort_SCB
+ Description : Abort a queued command.
+ (commands that are on the bus can't be aborted easily)
+ Input : pHCB - Pointer to host adapter structure
+ Output : None.
+ Return : pSRB - Pointer to SCSI request block.
+*****************************************************************************/
+int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
+{
+ unsigned char bData, bStatus;
+
+ ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB); /* Write command */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+ if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
+ return (FALSE);
+
+ ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx); /* Write address */
+ ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO);
+ if (waitHDOoff(hcsp) == FALSE) /* Wait HDO off */
+ return (FALSE);
+
+ if (waitHDIset(hcsp, &bData) == FALSE) /* Wait HDI set */
+ return (FALSE);
+ bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA);
+ ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */
+
+ if (bStatus == 1) /* 0 - Successfully */
+ return (FALSE); /* 1 - Fail */
+ return (TRUE);
+}
+
+/*****************************************************************************
+ Function name : inia100_abort
+ Description : Abort a queued command.
+ (commands that are on the bus can't be aborted easily)
+ Input : pHCB - Pointer to host adapter structure
+ Output : None.
+ Return : pSRB - Pointer to SCSI request block.
+*****************************************************************************/
+int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt)
+{
+ ESCB *pVirEscb;
+ ORC_SCB *pVirScb;
+ UCHAR i;
+ ULONG flags;
+
+#if 0
+ printk("inia100: abort SRB \n");
+#endif
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags);
+#endif
+
+ pVirScb = (ORC_SCB *) hcsp->HCS_virScbArray;
+
+ for (i = 0; i < orc_num_scb; i++, pVirScb++) {
+ pVirEscb = pVirScb->SCB_EScb;
+ if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == (unsigned char *) SCpnt)) {
+ if (pVirScb->SCB_TagMsg == 0) {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+ return (SCSI_ABORT_BUSY);
+ } else {
+ if (abort_SCB(hcsp, pVirScb)) {
+ pVirEscb->SCB_Srb = NULL;
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+ return (SCSI_ABORT_SUCCESS);
+ } else {
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+ return (SCSI_ABORT_NOT_RUNNING);
+ }
+ }
+ }
+ }
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2,1,95)
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags);
+#endif
+ return (SCSI_ABORT_NOT_RUNNING);
+}
+
+/***********************************************************************
+ Routine Description:
+ This is the interrupt service routine for the Orchid SCSI adapter.
+ It reads the interrupt register to determine if the adapter is indeed
+ the source of the interrupt and clears the interrupt at the device.
+ Arguments:
+ HwDeviceExtension - HBA miniport driver's adapter data storage
+ Return Value:
+***********************************************************************/
+void orc_interrupt(
+ ORC_HCS * hcsp
+)
+{
+ BYTE bScbIdx;
+ ORC_SCB *pScb;
+
+ if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) {
+ return; // (FALSE);
+
+ }
+ do {
+ bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE);
+
+ pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx));
+ pScb->SCB_Status = 0x0;
+
+ inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb);
+ } while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT));
+ return; //(TRUE);
+
+} /* End of I1060Interrupt() */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/i60uscsi.h linux.ac/drivers/scsi/i60uscsi.h
--- linux.vanilla/drivers/scsi/i60uscsi.h Thu Jan 1 01:00:00 1970
+++ linux.ac/drivers/scsi/i60uscsi.h Wed Feb 3 21:57:36 1999
@@ -0,0 +1,574 @@
+/**************************************************************************
+ * Initio A100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ **************************************************************************
+ *
+ * Module: inia100.h
+ * Description: INI-A100U2W LINUX device driver header
+ * Revision History:
+ * 06/18/98 HL, Initial Version 1.02
+ * 12/19/98 bv, v1.02a Use spinlocks for 2.1.95 and up.
+ **************************************************************************/
+
+#include
+
+#define ULONG unsigned long
+#define PVOID void *
+#define USHORT unsigned short
+#define UCHAR unsigned char
+#define BYTE unsigned char
+#define WORD unsigned short
+#define DWORD unsigned long
+#define UBYTE unsigned char
+#define UWORD unsigned short
+#define UDWORD unsigned long
+#ifdef ALPHA
+#define U32 unsigned int
+#else
+#define U32 unsigned long
+#endif
+
+#ifndef NULL
+#define NULL 0 /* zero */
+#endif
+#ifndef TRUE
+#define TRUE (1) /* boolean true */
+#endif
+#ifndef FALSE
+#define FALSE (0) /* boolean false */
+#endif
+#ifndef FAILURE
+#define FAILURE (-1)
+#endif
+#if 1
+#define ORC_MAXQUEUE 245
+#else
+#define ORC_MAXQUEUE 25
+#endif
+
+#define TOTAL_SG_ENTRY 32
+#define MAX_TARGETS 16
+#define IMAX_CDB 15
+#define SENSE_SIZE 14
+#define MAX_SUPPORTED_ADAPTERS 4
+#define SUCCESSFUL 0x00
+
+#define I920_DEVICE_ID 0x0002 /* Initio's inic-950 product ID */
+
+/************************************************************************/
+/* Scatter-Gather Element Structure */
+/************************************************************************/
+typedef struct ORC_SG_Struc {
+ U32 SG_Ptr; /* Data Pointer */
+ U32 SG_Len; /* Data Length */
+} ORC_SG;
+
+typedef struct inia100_Adpt_Struc {
+ UWORD ADPT_BIOS; /* 0 */
+ UWORD ADPT_BASE; /* 1 */
+ UBYTE ADPT_Bus; /* 2 */
+ UBYTE ADPT_Device; /* 3 */
+ UBYTE ADPT_INTR; /* 4 */
+} INIA100_ADPT_STRUCT;
+
+
+/* SCSI related definition */
+#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */
+#define DISC_ALLOW 0xC0 /* Disconnect is allowed */
+
+
+#define ORC_OFFSET_SCB 16
+#define ORC_MAX_SCBS 250
+#define MAX_CHANNELS 2
+#define MAX_ESCB_ELE 64
+#define TCF_DRV_255_63 0x0400
+
+/********************************************************/
+/* Orchid Configuration Register Set */
+/********************************************************/
+#define ORC_PVID 0x00 /* Vendor ID */
+#define ORC_VENDOR_ID 0x1101 /* Orchid vendor ID */
+#define ORC_PDID 0x02 /* Device ID */
+#define ORC_DEVICE_ID 0x1060 /* Orchid device ID */
+#define ORC_COMMAND 0x04 /* Command */
+#define BUSMS 0x04 /* BUS MASTER Enable */
+#define IOSPA 0x01 /* IO Space Enable */
+#define ORC_STATUS 0x06 /* Status register */
+#define ORC_REVISION 0x08 /* Revision number */
+#define ORC_BASE 0x10 /* Base address */
+#define ORC_BIOS 0x50 /* Expansion ROM base address */
+#define ORC_INT_NUM 0x3C /* Interrupt line */
+#define ORC_INT_PIN 0x3D /* Interrupt pin */
+
+
+/********************************************************/
+/* Orchid Host Command Set */
+/********************************************************/
+#define ORC_CMD_NOP 0x00 /* Host command - NOP */
+#define ORC_CMD_VERSION 0x01 /* Host command - Get F/W version */
+#define ORC_CMD_ECHO 0x02 /* Host command - ECHO */
+#define ORC_CMD_SET_NVM 0x03 /* Host command - Set NVRAM */
+#define ORC_CMD_GET_NVM 0x04 /* Host command - Get NVRAM */
+#define ORC_CMD_GET_BUS_STATUS 0x05 /* Host command - Get SCSI bus status */
+#define ORC_CMD_ABORT_SCB 0x06 /* Host command - Abort SCB */
+#define ORC_CMD_ISSUE_SCB 0x07 /* Host command - Issue SCB */
+
+/********************************************************/
+/* Orchid Register Set */
+/********************************************************/
+#define ORC_GINTS 0xA0 /* Global Interrupt Status */
+#define QINT 0x04 /* Reply Queue Interrupt */
+#define ORC_GIMSK 0xA1 /* Global Interrupt MASK */
+#define MQINT 0x04 /* Mask Reply Queue Interrupt */
+#define ORC_GCFG 0xA2 /* Global Configure */
+#define EEPRG 0x01 /* Enable EEPROM programming */
+#define ORC_GSTAT 0xA3 /* Global status */
+#define WIDEBUS 0x10 /* Wide SCSI Devices connected */
+#define ORC_HDATA 0xA4 /* Host Data */
+#define ORC_HCTRL 0xA5 /* Host Control */
+#define SCSIRST 0x80 /* SCSI bus reset */
+#define HDO 0x40 /* Host data out */
+#define HOSTSTOP 0x02 /* Host stop RISC engine */
+#define DEVRST 0x01 /* Device reset */
+#define ORC_HSTUS 0xA6 /* Host Status */
+#define HDI 0x02 /* Host data in */
+#define RREADY 0x01 /* RISC engine is ready to receive */
+#define ORC_NVRAM 0xA7 /* Nvram port address */
+#define SE2CS 0x008
+#define SE2CLK 0x004
+#define SE2DO 0x002
+#define SE2DI 0x001
+#define ORC_PQUEUE 0xA8 /* Posting queue FIFO */
+#define ORC_PQCNT 0xA9 /* Posting queue FIFO Cnt */
+#define ORC_RQUEUE 0xAA /* Reply queue FIFO */
+#define ORC_RQUEUECNT 0xAB /* Reply queue FIFO Cnt */
+#define ORC_FWBASEADR 0xAC /* Firmware base address */
+
+#define ORC_EBIOSADR0 0xB0 /* External Bios address */
+#define ORC_EBIOSADR1 0xB1 /* External Bios address */
+#define ORC_EBIOSADR2 0xB2 /* External Bios address */
+#define ORC_EBIOSDATA 0xB3 /* External Bios address */
+
+#define ORC_SCBSIZE 0xB7 /* SCB size register */
+#define ORC_SCBBASE0 0xB8 /* SCB base address 0 */
+#define ORC_SCBBASE1 0xBC /* SCB base address 1 */
+
+#define ORC_RISCCTL 0xE0 /* RISC Control */
+#define PRGMRST 0x002
+#define DOWNLOAD 0x001
+#define ORC_PRGMCTR0 0xE2 /* RISC program counter */
+#define ORC_PRGMCTR1 0xE3 /* RISC program counter */
+#define ORC_RISCRAM 0xEC /* RISC RAM data port 4 bytes */
+
+typedef struct orc_extended_scb { /* Extended SCB */
+ ORC_SG ESCB_SGList[TOTAL_SG_ENTRY]; /*0 Start of SG list */
+ unsigned char *SCB_Srb; /*50 SRB Pointer */
+// Scsi_Cmnd *SCB_Srb; /*50 SRB Pointer */
+} ESCB;
+
+/***********************************************************************
+ SCSI Control Block
+************************************************************************/
+typedef struct orc_scb { /* Scsi_Ctrl_Blk */
+ UBYTE SCB_Opcode; /*00 SCB command code&residual */
+ UBYTE SCB_Flags; /*01 SCB Flags */
+ UBYTE SCB_Target; /*02 Target Id */
+ UBYTE SCB_Lun; /*03 Lun */
+ U32 SCB_Reserved0; /*04 Reserved for ORCHID must 0 */
+ U32 SCB_XferLen; /*08 Data Transfer Length */
+ U32 SCB_Reserved1; /*0C Reserved for ORCHID must 0 */
+ U32 SCB_SGLen; /*10 SG list # * 8 */
+ U32 SCB_SGPAddr; /*14 SG List Buf physical Addr */
+ U32 SCB_SGPAddrHigh; /*18 SG Buffer high physical Addr */
+ UBYTE SCB_HaStat; /*1C Host Status */
+ UBYTE SCB_TaStat; /*1D Target Status */
+ UBYTE SCB_Status; /*1E SCB status */
+ UBYTE SCB_Link; /*1F Link pointer, default 0xFF */
+ UBYTE SCB_SenseLen; /*20 Sense Allocation Length */
+ UBYTE SCB_CDBLen; /*21 CDB Length */
+ UBYTE SCB_Ident; /*22 Identify */
+ UBYTE SCB_TagMsg; /*23 Tag Message */
+ UBYTE SCB_CDB[IMAX_CDB]; /*24 SCSI CDBs */
+ UBYTE SCB_ScbIdx; /*3C Index for this ORCSCB */
+ U32 SCB_SensePAddr; /*34 Sense Buffer physical Addr */
+
+ ESCB *SCB_EScb; /*38 Extended SCB Pointer */
+#ifndef ALPHA
+ UBYTE SCB_Reserved2[4]; /*3E Reserved for Driver use */
+#endif
+} ORC_SCB;
+
+/* Opcodes of ORCSCB_Opcode */
+#define ORC_EXECSCSI 0x00 /* SCSI initiator command with residual */
+#define ORC_BUSDEVRST 0x01 /* SCSI Bus Device Reset */
+
+/* Status of ORCSCB_Status */
+#define SCB_COMPLETE 0x00 /* SCB request completed */
+#define SCB_POST 0x01 /* SCB is posted by the HOST */
+
+/* Bit Definition for ORCSCB_Flags */
+#define SCF_DISINT 0x01 /* Disable HOST interrupt */
+#define SCF_DIR 0x18 /* Direction bits */
+#define SCF_NO_DCHK 0x00 /* Direction determined by SCSI */
+#define SCF_DIN 0x08 /* From Target to Initiator */
+#define SCF_DOUT 0x10 /* From Initiator to Target */
+#define SCF_NO_XF 0x18 /* No data transfer */
+#define SCF_POLL 0x40
+
+/* Error Codes for ORCSCB_HaStat */
+#define HOST_SEL_TOUT 0x11
+#define HOST_DO_DU 0x12
+#define HOST_BUS_FREE 0x13
+#define HOST_BAD_PHAS 0x14
+#define HOST_INV_CMD 0x16
+#define HOST_SCSI_RST 0x1B
+#define HOST_DEV_RST 0x1C
+
+
+/* Error Codes for ORCSCB_TaStat */
+#define TARGET_CHK_COND 0x02
+#define TARGET_BUSY 0x08
+#define TARGET_TAG_FULL 0x28
+
+
+/* Queue tag msg: Simple_quque_tag, Head_of_queue_tag, Ordered_queue_tag */
+#define MSG_STAG 0x20
+#define MSG_HTAG 0x21
+#define MSG_OTAG 0x22
+
+#define MSG_IGNOREWIDE 0x23
+
+#define MSG_IDENT 0x80
+#define MSG_DISC 0x40 /* Disconnect allowed */
+
+
+/* SCSI MESSAGE */
+#define MSG_EXTEND 0x01
+#define MSG_SDP 0x02
+#define MSG_ABORT 0x06
+#define MSG_REJ 0x07
+#define MSG_NOP 0x08
+#define MSG_PARITY 0x09
+#define MSG_DEVRST 0x0C
+#define MSG_STAG 0x20
+
+/***********************************************************************
+ Target Device Control Structure
+**********************************************************************/
+
+typedef struct ORC_Tar_Ctrl_Struc {
+ UBYTE TCS_DrvDASD; /* 6 */
+ UBYTE TCS_DrvSCSI; /* 7 */
+ UBYTE TCS_DrvHead; /* 8 */
+ UWORD TCS_DrvFlags; /* 4 */
+ UBYTE TCS_DrvSector; /* 7 */
+} ORC_TCS, *PORC_TCS;
+
+/* Bit Definition for TCF_DrvFlags */
+#define TCS_DF_NODASD_SUPT 0x20 /* Suppress OS/2 DASD Mgr support */
+#define TCS_DF_NOSCSI_SUPT 0x40 /* Suppress OS/2 SCSI Mgr support */
+
+
+/***********************************************************************
+ Host Adapter Control Structure
+************************************************************************/
+typedef struct ORC_Ha_Ctrl_Struc {
+ USHORT HCS_Base; /* 00 */
+ UBYTE HCS_Index; /* 02 */
+ UBYTE HCS_Intr; /* 04 */
+ UBYTE HCS_SCSI_ID; /* 06 H/A SCSI ID */
+ UBYTE HCS_BIOS; /* 07 BIOS configuration */
+
+ UBYTE HCS_Flags; /* 0B */
+ UBYTE HCS_HAConfig1; /* 1B SCSI0MAXTags */
+ UBYTE HCS_MaxTar; /* 1B SCSI0MAXTags */
+
+ USHORT HCS_Units; /* Number of units this adapter */
+ USHORT HCS_AFlags; /* Adapter info. defined flags */
+ ULONG HCS_Timeout; /* Adapter timeout value */
+ PVOID HCS_virScbArray; /* 28 Virtual Pointer to SCB array */
+ U32 HCS_physScbArray; /* Scb Physical address */
+ PVOID HCS_virEscbArray; /* Virtual pointer to ESCB Scatter list */
+ U32 HCS_physEscbArray; /* scatter list Physical address */
+ UBYTE TargetFlag[16]; /* 30 target configuration, TCF_EN_TAG */
+ UBYTE MaximumTags[16]; /* 40 ORC_MAX_SCBS */
+ UBYTE ActiveTags[16][16]; /* 50 */
+ ORC_TCS HCS_Tcs[16]; /* 28 */
+ U32 BitAllocFlag[MAX_CHANNELS][8]; /* Max STB is 256, So 256/32 */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spinlock_t BitAllocFlagLock;
+#endif
+ ULONG pSRB_head;
+ ULONG pSRB_tail;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spinlock_t pSRB_lock;
+#endif
+} ORC_HCS;
+
+/* Bit Definition for HCS_Flags */
+
+#define HCF_SCSI_RESET 0x01 /* SCSI BUS RESET */
+#define HCF_PARITY 0x02 /* parity card */
+#define HCF_LVDS 0x10 /* parity card */
+
+/* Bit Definition for TargetFlag */
+
+#define TCF_EN_255 0x08
+#define TCF_EN_TAG 0x10
+#define TCF_BUSY 0x20
+#define TCF_DISCONNECT 0x40
+#define TCF_SPIN_UP 0x80
+
+/* Bit Definition for HCS_AFlags */
+#define HCS_AF_IGNORE 0x01 /* Adapter ignore */
+#define HCS_AF_DISABLE_RESET 0x10 /* Adapter disable reset */
+#define HCS_AF_DISABLE_ADPT 0x80 /* Adapter disable */
+
+
+/*---------------------------------------*/
+/* TimeOut for RESET to complete (30s) */
+/* */
+/* After a RESET the drive is checked */
+/* every 200ms. */
+/*---------------------------------------*/
+#define DELAYED_RESET_MAX (30*1000L)
+#define DELAYED_RESET_INTERVAL 200L
+
+/*----------------------------------------------*/
+/* TimeOut for IRQ from last interrupt (5s) */
+/*----------------------------------------------*/
+#define IRQ_TIMEOUT_INTERVAL (5*1000L)
+
+/*----------------------------------------------*/
+/* Retry Delay interval (200ms) */
+/*----------------------------------------------*/
+#define DELAYED_RETRY_INTERVAL 200L
+
+#define INQUIRY_SIZE 36
+#define CAPACITY_SIZE 8
+#define DEFAULT_SENSE_LEN 14
+
+#define DEVICE_NOT_FOUND 0x86
+
+/*----------------------------------------------*/
+/* Definition for PCI device */
+/*----------------------------------------------*/
+#define MAX_PCI_DEVICES 21
+#define MAX_PCI_BUSES 8
+
+typedef struct Adpt_Struc {
+ USHORT ADPT_BIOS; /* 0 */
+ UBYTE ADPT_BASE; /* 1 */
+ UBYTE ADPT_Bus; /* 2 */
+ UBYTE ADPT_Device; /* 3 */
+ UBYTE ADPT_Reserved[3];
+} JACS, *PJACS;
+
+typedef struct _NVRAM {
+/*----------header ---------------*/
+ UCHAR SubVendorID0; /* 00 - Sub Vendor ID */
+ UCHAR SubVendorID1; /* 00 - Sub Vendor ID */
+ UCHAR SubSysID0; /* 02 - Sub System ID */
+ UCHAR SubSysID1; /* 02 - Sub System ID */
+ UCHAR SubClass; /* 04 - Sub Class */
+ UCHAR VendorID0; /* 05 - Vendor ID */
+ UCHAR VendorID1; /* 05 - Vendor ID */
+ UCHAR DeviceID0; /* 07 - Device ID */
+ UCHAR DeviceID1; /* 07 - Device ID */
+ UCHAR Reserved0[2]; /* 09 - Reserved */
+ UCHAR Revision; /* 0B - Revision of data structure */
+ /* ----Host Adapter Structure ---- */
+ UCHAR NumOfCh; /* 0C - Number of SCSI channel */
+ UCHAR BIOSConfig1; /* 0D - BIOS configuration 1 */
+ UCHAR BIOSConfig2; /* 0E - BIOS boot channel&target ID */
+ UCHAR BIOSConfig3; /* 0F - BIOS configuration 3 */
+ /* ----SCSI channel Structure ---- */
+ /* from "CTRL-I SCSI Host Adapter SetUp menu " */
+ UCHAR SCSI0Id; /* 10 - Channel 0 SCSI ID */
+ UCHAR SCSI0Config; /* 11 - Channel 0 SCSI configuration */
+ UCHAR SCSI0MaxTags; /* 12 - Channel 0 Maximum tags */
+ UCHAR SCSI0ResetTime; /* 13 - Channel 0 Reset recovering time */
+ UCHAR ReservedforChannel0[2]; /* 14 - Reserved */
+
+ /* ----SCSI target Structure ---- */
+ /* from "CTRL-I SCSI device SetUp menu " */
+ UCHAR Target00Config; /* 16 - Channel 0 Target 0 config */
+ UCHAR Target01Config; /* 17 - Channel 0 Target 1 config */
+ UCHAR Target02Config; /* 18 - Channel 0 Target 2 config */
+ UCHAR Target03Config; /* 19 - Channel 0 Target 3 config */
+ UCHAR Target04Config; /* 1A - Channel 0 Target 4 config */
+ UCHAR Target05Config; /* 1B - Channel 0 Target 5 config */
+ UCHAR Target06Config; /* 1C - Channel 0 Target 6 config */
+ UCHAR Target07Config; /* 1D - Channel 0 Target 7 config */
+ UCHAR Target08Config; /* 1E - Channel 0 Target 8 config */
+ UCHAR Target09Config; /* 1F - Channel 0 Target 9 config */
+ UCHAR Target0AConfig; /* 20 - Channel 0 Target A config */
+ UCHAR Target0BConfig; /* 21 - Channel 0 Target B config */
+ UCHAR Target0CConfig; /* 22 - Channel 0 Target C config */
+ UCHAR Target0DConfig; /* 23 - Channel 0 Target D config */
+ UCHAR Target0EConfig; /* 24 - Channel 0 Target E config */
+ UCHAR Target0FConfig; /* 25 - Channel 0 Target F config */
+
+ UCHAR SCSI1Id; /* 26 - Channel 1 SCSI ID */
+ UCHAR SCSI1Config; /* 27 - Channel 1 SCSI configuration */
+ UCHAR SCSI1MaxTags; /* 28 - Channel 1 Maximum tags */
+ UCHAR SCSI1ResetTime; /* 29 - Channel 1 Reset recovering time */
+ UCHAR ReservedforChannel1[2]; /* 2A - Reserved */
+
+ /* ----SCSI target Structure ---- */
+ /* from "CTRL-I SCSI device SetUp menu " */
+ UCHAR Target10Config; /* 2C - Channel 1 Target 0 config */
+ UCHAR Target11Config; /* 2D - Channel 1 Target 1 config */
+ UCHAR Target12Config; /* 2E - Channel 1 Target 2 config */
+ UCHAR Target13Config; /* 2F - Channel 1 Target 3 config */
+ UCHAR Target14Config; /* 30 - Channel 1 Target 4 config */
+ UCHAR Target15Config; /* 31 - Channel 1 Target 5 config */
+ UCHAR Target16Config; /* 32 - Channel 1 Target 6 config */
+ UCHAR Target17Config; /* 33 - Channel 1 Target 7 config */
+ UCHAR Target18Config; /* 34 - Channel 1 Target 8 config */
+ UCHAR Target19Config; /* 35 - Channel 1 Target 9 config */
+ UCHAR Target1AConfig; /* 36 - Channel 1 Target A config */
+ UCHAR Target1BConfig; /* 37 - Channel 1 Target B config */
+ UCHAR Target1CConfig; /* 38 - Channel 1 Target C config */
+ UCHAR Target1DConfig; /* 39 - Channel 1 Target D config */
+ UCHAR Target1EConfig; /* 3A - Channel 1 Target E config */
+ UCHAR Target1FConfig; /* 3B - Channel 1 Target F config */
+ UCHAR reserved[3]; /* 3C - Reserved */
+ /* ---------- CheckSum ---------- */
+ UCHAR CheckSum; /* 3F - Checksum of NVRam */
+} NVRAM, *PNVRAM;
+
+/* Bios Configuration for nvram->BIOSConfig1 */
+#define NBC_BIOSENABLE 0x01 /* BIOS enable */
+#define NBC_CDROM 0x02 /* Support bootable CDROM */
+#define NBC_REMOVABLE 0x04 /* Support removable drive */
+
+/* Bios Configuration for nvram->BIOSConfig2 */
+#define NBB_TARGET_MASK 0x0F /* Boot SCSI target ID number */
+#define NBB_CHANL_MASK 0xF0 /* Boot SCSI channel number */
+
+/* Bit definition for nvram->SCSIConfig */
+#define NCC_BUSRESET 0x01 /* Reset SCSI bus at power up */
+#define NCC_PARITYCHK 0x02 /* SCSI parity enable */
+#define NCC_LVDS 0x10 /* Enable LVDS */
+#define NCC_ACTTERM1 0x20 /* Enable active terminator 1 */
+#define NCC_ACTTERM2 0x40 /* Enable active terminator 2 */
+#define NCC_AUTOTERM 0x80 /* Enable auto termination */
+
+/* Bit definition for nvram->TargetxConfig */
+#define NTC_PERIOD 0x07 /* Maximum Sync. Speed */
+#define NTC_1GIGA 0x08 /* 255 head / 63 sectors (64/32) */
+#define NTC_NO_SYNC 0x10 /* NO SYNC. NEGO */
+#define NTC_NO_WIDESYNC 0x20 /* NO WIDE SYNC. NEGO */
+#define NTC_DISC_ENABLE 0x40 /* Enable SCSI disconnect */
+#define NTC_SPINUP 0x80 /* Start disk drive */
+
+/* Default NVRam values */
+#define NBC_DEFAULT (NBC_ENABLE)
+#define NCC_DEFAULT (NCC_BUSRESET | NCC_AUTOTERM | NCC_PARITYCHK)
+#define NCC_MAX_TAGS 0x20 /* Maximum tags per target */
+#define NCC_RESET_TIME 0x0A /* SCSI RESET recovering time */
+#define NTC_DEFAULT (NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE)
+
+typedef union { /* Union define for mechanism 1 */
+ struct {
+ unsigned char RegNum;
+ unsigned char FcnNum:3;
+ unsigned char DeviceNum:5;
+ unsigned char BusNum;
+ unsigned char Reserved:7;
+ unsigned char Enable:1;
+ } sConfigAdr;
+ unsigned long lConfigAdr;
+} CONFIG_ADR;
+
+typedef union { /* Union define for mechanism 2 */
+ struct {
+ unsigned char RegNum;
+ unsigned char DeviceNum;
+ unsigned short Reserved;
+ } sHostAdr;
+ unsigned long lHostAdr;
+} HOST_ADR;
+
+#define ORC_RD(x,y) (UCHAR)(inb( (int)((ULONG)((ULONG)x+(UCHAR)y)) ))
+#define ORC_RDLONG(x,y) (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
+
+#define ORC_WR( adr,data) outb( (UCHAR)(data), (int)(adr))
+#define ORC_WRSHORT(adr,data) outw( (UWORD)(data), (int)(adr))
+#define ORC_WRLONG( adr,data) outl( (ULONG)(data), (int)(adr))
+
+
+#define SCSI_ABORT_SNOOZE 0
+#define SCSI_ABORT_SUCCESS 1
+#define SCSI_ABORT_PENDING 2
+#define SCSI_ABORT_BUSY 3
+#define SCSI_ABORT_NOT_RUNNING 4
+#define SCSI_ABORT_ERROR 5
+
+#define SCSI_RESET_SNOOZE 0
+#define SCSI_RESET_PUNT 1
+#define SCSI_RESET_SUCCESS 2
+#define SCSI_RESET_PENDING 3
+#define SCSI_RESET_WAKEUP 4
+#define SCSI_RESET_NOT_RUNNING 5
+#define SCSI_RESET_ERROR 6
+
+#define SCSI_RESET_SYNCHRONOUS 0x01
+#define SCSI_RESET_ASYNCHRONOUS 0x02
+#define SCSI_RESET_SUGGEST_BUS_RESET 0x04
+#define SCSI_RESET_SUGGEST_HOST_RESET 0x08
+
+#define SCSI_RESET_BUS_RESET 0x100
+#define SCSI_RESET_HOST_RESET 0x200
+#define SCSI_RESET_ACTION 0xff
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/ide-scsi.c linux.ac/drivers/scsi/ide-scsi.c
--- linux.vanilla/drivers/scsi/ide-scsi.c Tue Jan 19 02:57:31 1999
+++ linux.ac/drivers/scsi/ide-scsi.c Tue Feb 16 17:21:46 1999
@@ -23,8 +23,9 @@
* Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer
* for access through /dev/sg.
* Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
- * Ver 0.7 Dev 04 98 Ignore commands where lun != 0 to avoid multiple
+ * Ver 0.7 Dec 04 98 Ignore commands where lun != 0 to avoid multiple
* detection of devices with CONFIG_SCSI_MULTI_LUN
+ * Ver 0.8 Feb 05 99 Optical media need translation too.
*/
#define IDESCSI_VERSION "0.6"
@@ -178,7 +179,7 @@
if (!test_bit(PC_TRANSFORM, &pc->flags))
return;
- if (drive->media == ide_cdrom) {
+ if (drive->media == ide_cdrom || drive->media == ide_optical) {
if (c[0] == READ_6 || c[0] == WRITE_6) {
c[8] = c[4]; c[5] = c[3]; c[4] = c[2];
c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0;
@@ -217,7 +218,7 @@
if (!test_bit(PC_TRANSFORM, &pc->flags))
return;
- if (drive->media == ide_cdrom) {
+ if (drive->media == ide_cdrom || drive->media == ide_optical) {
if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) {
scsi_buf[0] = atapi_buf[1]; /* Mode data length */
scsi_buf[1] = atapi_buf[2]; /* Medium type */
@@ -605,6 +606,8 @@
host = scsi_register(host_template, 0);
for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++);
host->max_id = id;
+ host->max_lun = 1; /* We should query the drive for multilun
+ support ? */
host->can_queue = host->cmd_per_lun * id;
return 1;
}
@@ -794,7 +797,7 @@
int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags)
{
- return SCSI_RESET_PUNT;
+ return SCSI_RESET_SUCCESS;
}
int idescsi_bios (Disk *disk, kdev_t dev, int *parm)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/imm.c linux.ac/drivers/scsi/imm.c
--- linux.vanilla/drivers/scsi/imm.c Thu Jan 14 01:25:25 1999
+++ linux.ac/drivers/scsi/imm.c Tue Feb 16 16:58:33 1999
@@ -1204,19 +1204,16 @@
status = imm_out(host_no, &cmd[l << 1], 2);
if (!status) {
- imm_disconnect(host_no);
- imm_connect(host_no, CONNECT_EPP_MAYBE);
- w_dtr(ppb, 0x40);
- w_ctr(ppb, 0x08);
- udelay(30);
- w_ctr(ppb, 0x0c);
- udelay(1000);
- imm_disconnect(host_no);
- udelay(1000);
- if (imm_hosts[host_no].mode == IMM_EPP_32) {
- imm_hosts[host_no].mode = old_mode;
- goto second_pass;
- }
+ imm_disconnect(host_no);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
+ imm_reset_pulse(IMM_BASE(host_no));
+ udelay(1000);
+ imm_disconnect(host_no);
+ udelay(1000);
+ if (imm_hosts[host_no].mode == IMM_EPP_32) {
+ imm_hosts[host_no].mode = old_mode;
+ goto second_pass;
+ }
printk("imm: Unable to establish communication, aborting driver load.\n");
return 1;
}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/inia100.c linux.ac/drivers/scsi/inia100.c
--- linux.vanilla/drivers/scsi/inia100.c Thu Jan 1 01:00:00 1970
+++ linux.ac/drivers/scsi/inia100.c Wed Feb 3 21:57:36 1999
@@ -0,0 +1,952 @@
+/**************************************************************************
+ * Initio A100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ **************************************************************************
+ *
+ * module: inia100.c
+ * DESCRIPTION:
+ * This is the Linux low-level SCSI driver for Initio INIA100 SCSI host
+ * adapters
+ * 09/24/98 hl - v1.02 initial production release.
+ * 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up.
+ **************************************************************************/
+
+#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
+
+#ifndef LINUX_VERSION_CODE
+#include
+#endif
+
+#ifdef MODULE
+#include
+#endif
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92)
+#include
+#endif
+#include
+#include
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23)
+#include
+#endif
+#include
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+#include