Commit 1a4049dd authored by Paul Gortmaker's avatar Paul Gortmaker Committed by James Bottomley

[SCSI] aci7xxx_old: delete decade+ obsolete driver

After getting warnings in an allyesconfig build[1] from this
driver, I decided to remind myself just how old it was, and
whether it warranted fixing.  In the Kconfig help text, I found:

  "This driver will eventually be phased out entirely"

Going back to the history archive, I see the line was added[2]
in Feb 2002, when we moved from v2.4.2.1 ---> v2.4.2.2

So, with over a decade of notification, and multiple major releases
since then, I think we can justify removing this.  Currently we have
people wasting time building it during routine testing, and then
wasting more time re-researching the known reported warnings, only to
find that nobody really is willing to integrate the fixes[3] for it.

A quick search didn't seem to indicate any active user base for it.
If someone happens to have a quirky _old_ card that the eleven year
old "new" driver doesn't work with, then it is entirely reasonable
that they stick with a kernel version that predates this removal.

[1] drivers/scsi/aic7xxx_old.c: In function ‘aic7xxx_register’:
    drivers/scsi/aic7xxx_old.c:7901:5: warning: case value ‘257’ not in enumerated type ‘ahc_chip’ [-Wswitch]
    drivers/scsi/aic7xxx_old.c:7898:5: warning: case value ‘513’ not in enumerated type ‘ahc_chip’ [-Wswitch]
    drivers/scsi/aic7xxx_old.c: In function ‘aic7xxx_load_seeprom’:
    drivers/scsi/aic7xxx_old.c:8517:5: warning: case value ‘257’ not in enumerated type ‘ahc_chip’ [-Wswitch]
    drivers/scsi/aic7xxx_old.c:8510:5: warning: case value ‘513’ not in enumerated type ‘ahc_chip’ [-Wswitch]

[2] http://git.kernel.org/cgit/linux/kernel/git/tglx/history.git commit 44e8778c

[3] https://lkml.org/lkml/2012/10/29/215Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
Acked-by: default avatarHannes Reinecke <hare@suse.de>
Acked-by: default avatarDoug Ledford <dledford@redhat.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 59ab3c93
......@@ -42,8 +42,6 @@ aic79xx.txt
- Adaptec Ultra320 SCSI host adapters
aic7xxx.txt
- info on driver for Adaptec controllers
aic7xxx_old.txt
- info on driver for Adaptec controllers, old generation
arcmsr_spec.txt
- ARECA FIRMWARE SPEC (for IOP331 adapter)
dc395x.txt
......
AIC7xxx Driver for Linux
Introduction
----------------------------
The AIC7xxx SCSI driver adds support for Adaptec (http://www.adaptec.com)
SCSI controllers and chipsets. Major portions of the driver and driver
development are shared between both Linux and FreeBSD. Support for the
AIC-7xxx chipsets have been in the default Linux kernel since approximately
linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
2.1.0 or later.
Supported cards/chipsets
----------------------------
Adaptec Cards
----------------------------
AHA-274x
AHA-274xT
AHA-2842
AHA-2910B
AHA-2920C
AHA-2930
AHA-2930U
AHA-2930CU
AHA-2930U2
AHA-2940
AHA-2940W
AHA-2940U
AHA-2940UW
AHA-2940UW-PRO
AHA-2940AU
AHA-2940U2W
AHA-2940U2
AHA-2940U2B
AHA-2940U2BOEM
AHA-2944D
AHA-2944WD
AHA-2944UD
AHA-2944UWD
AHA-2950U2
AHA-2950U2W
AHA-2950U2B
AHA-29160M
AHA-3940
AHA-3940U
AHA-3940W
AHA-3940UW
AHA-3940AUW
AHA-3940U2W
AHA-3950U2B
AHA-3950U2D
AHA-3960D
AHA-39160M
AHA-3985
AHA-3985U
AHA-3985W
AHA-3985UW
Motherboard Chipsets
----------------------------
AIC-777x
AIC-785x
AIC-786x
AIC-787x
AIC-788x
AIC-789x
AIC-3860
Bus Types
----------------------------
W - Wide SCSI, SCSI-3, 16bit bus, 68pin connector, will also support
SCSI-1/SCSI-2 50pin devices, transfer rates up to 20MB/s.
U - Ultra SCSI, transfer rates up to 40MB/s.
U2- Ultra 2 SCSI, transfer rates up to 80MB/s.
D - Differential SCSI.
T - Twin Channel SCSI. Up to 14 SCSI devices.
AHA-274x - EISA SCSI controller
AHA-284x - VLB SCSI controller
AHA-29xx - PCI SCSI controller
AHA-394x - PCI controllers with two separate SCSI controllers on-board.
AHA-398x - PCI RAID controllers with three separate SCSI controllers
on-board.
Not Supported Devices
------------------------------
Adaptec Cards
----------------------------
AHA-2920 (Only the cards that use the Future Domain chipset are not
supported, any 2920 cards based on Adaptec AIC chipsets,
such as the 2920C, are supported)
AAA-13x Raid Adapters
AAA-113x Raid Port Card
Motherboard Chipsets
----------------------------
AIC-7810
Bus Types
----------------------------
R - Raid Port busses are not supported.
The hardware RAID devices sold by Adaptec are *NOT* supported by this
driver (and will people please stop emailing me about them, they are
a totally separate beast from the bare SCSI controllers and this driver
cannot be retrofitted in any sane manner to support the hardware RAID
features on those cards - Doug Ledford).
People
------------------------------
Justin T Gibbs gibbs@plutotech.com
(BSD Driver Author)
Dan Eischen deischen@iworks.InterWorks.org
(Original Linux Driver Co-maintainer)
Dean Gehnert deang@teleport.com
(Original Linux FTP/patch maintainer)
Jess Johnson jester@frenzy.com
(AIC7xxx FAQ author)
Doug Ledford dledford@redhat.com
(Current Linux aic7xxx-5.x.x Driver/Patch/FTP maintainer)
Special thanks go to John Aycock (aycock@cpsc.ucalgary.ca), the original
author of the driver. John has since retired from the project. Thanks
again for all his work!
Mailing list
------------------------------
There is a mailing list available for users who want to track development
and converse with other users and developers. This list is for both
FreeBSD and Linux support of the AIC7xxx chipsets.
To subscribe to the AIC7xxx mailing list send mail to the list server,
with "subscribe AIC7xxx" in the body (no Subject: required):
To: majordomo@FreeBSD.ORG
---
subscribe AIC7xxx
To unsubscribe from the list, send mail to the list server with:
To: majordomo@FreeBSD.ORG
---
unsubscribe AIC7xxx
Send regular messages and replies to: AIC7xxx@FreeBSD.ORG
Boot Command line options
------------------------------
"aic7xxx=no_reset" - Eliminate the SCSI bus reset during startup.
Some SCSI devices need the initial reset that this option disables
in order to work. If you have problems at bootup, please make sure
you aren't using this option.
"aic7xxx=reverse_scan" - Certain PCI motherboards scan for devices at
bootup by scanning from the highest numbered PCI device to the
lowest numbered PCI device, others do just the opposite and scan
from lowest to highest numbered PCI device. There is no reliable
way to autodetect this ordering. So, we default to the most common
order, which is lowest to highest. Then, in case your motherboard
scans from highest to lowest, we have this option. If your BIOS
finds the drives on controller A before controller B but the linux
kernel finds your drives on controller B before A, then you should
use this option.
"aic7xxx=extended" - Force the driver to detect extended drive translation
on your controller. This helps those people who have cards without
a SEEPROM make sure that linux and all other operating systems think
the same way about your hard drives.
"aic7xxx=scbram" - Some cards have external SCB RAM that can be used to
give the card more hardware SCB slots. This allows the driver to use
that SCB RAM. Without this option, the driver won't touch the SCB
RAM because it is known to cause problems on a few cards out there
(such as 3985 class cards).
"aic7xxx=irq_trigger:x" - Replace x with either 0 or 1 to force the kernel
to use the correct IRQ type for your card. This only applies to EISA
based controllers. On these controllers, 0 is for Edge triggered
interrupts, and 1 is for Level triggered interrupts. If you aren't
sure or don't know which IRQ trigger type your EISA card uses, then
let the kernel autodetect the trigger type.
"aic7xxx=verbose" - This option can be used in one of two ways. If you
simply specify aic7xxx=verbose, then the kernel will automatically
pick the default set of verbose messages for you to see.
Alternatively, you can specify the command as
"aic7xxx=verbose:0xXXXX" where the X entries are replaced with
hexadecimal digits. This option is a bit field type option. For
a full listing of the available options, search for the
#define VERBOSE_xxxxxx lines in the aic7xxx.c file. If you want
verbose messages, then it is recommended that you simply use the
aic7xxx=verbose variant of this command.
"aic7xxx=pci_parity:x" - This option controls whether or not the driver
enables PCI parity error checking on the PCI bus. By default, this
checking is disabled. To enable the checks, simply specify pci_parity
with no value afterwords. To reverse the parity from even to odd,
supply any number other than 0 or 255. In short:
pci_parity - Even parity checking (even is the normal PCI parity)
pci_parity:x - Where x > 0, Odd parity checking
pci_parity:0 - No check (default)
NOTE: In order to get Even PCI parity checking, you must use the
version of the option that does not include the : and a number at
the end (unless you want to enter exactly 2^32 - 1 as the number).
"aic7xxx=no_probe" - This option will disable the probing for any VLB
based 2842 controllers and any EISA based controllers. This is
needed on certain newer motherboards where the normal EISA I/O ranges
have been claimed by other PCI devices. Probing on those machines
will often result in the machine crashing or spontaneously rebooting
during startup. Examples of machines that need this are the
Dell PowerEdge 6300 machines.
"aic7xxx=seltime:2" - This option controls how long the card waits
during a device selection sequence for the device to respond.
The original SCSI spec says that this "should be" 256ms. This
is generally not required with modern devices. However, some
very old SCSI I devices need the full 256ms. Most modern devices
can run fine with only 64ms. The default for this option is
64ms. If you need to change this option, then use the following
table to set the proper value in the example above:
0 - 256ms
1 - 128ms
2 - 64ms
3 - 32ms
"aic7xxx=panic_on_abort" - This option is for debugging and will cause
the driver to panic the linux kernel and freeze the system the first
time the drivers abort or reset routines are called. This is most
helpful when some problem causes infinite reset loops that scroll too
fast to see. By using this option, you can write down what the errors
actually are and send that information to me so it can be fixed.
"aic7xxx=dump_card" - This option will print out the *entire* set of
configuration registers on the card during the init sequence. This
is a debugging aid used to see exactly what state the card is in
when we finally finish our initialization routines. If you don't
have documentation on the chipsets, this will do you absolutely
no good unless you are simply trying to write all the information
down in order to send it to me.
"aic7xxx=dump_sequencer" - This is the same as the above options except
that instead of dumping the register contents on the card, this
option dumps the contents of the sequencer program RAM. This gives
the ability to verify that the instructions downloaded to the
card's sequencer are indeed what they are supposed to be. Again,
unless you have documentation to tell you how to interpret these
numbers, then it is totally useless.
"aic7xxx=override_term:0xffffffff" - This option is used to force the
termination on your SCSI controllers to a particular setting. This
is a bit mask variable that applies for up to 8 aic7xxx SCSI channels.
Each channel gets 4 bits, divided as follows:
bit 3 2 1 0
| | | Enable/Disable Single Ended Low Byte Termination
| | En/Disable Single Ended High Byte Termination
| En/Disable Low Byte LVD Termination
En/Disable High Byte LVD Termination
The upper 2 bits that deal with LVD termination only apply to Ultra2
controllers. Furthermore, due to the current Ultra2 controller
designs, these bits are tied together such that setting either bit
enables both low and high byte LVD termination. It is not possible
to only set high or low byte LVD termination in this manner. This is
an artifact of the BIOS definition on Ultra2 controllers. For other
controllers, the only important bits are the two lowest bits. Setting
the higher bits on non-Ultra2 controllers has no effect. A few
examples of how to use this option:
Enable low and high byte termination on a non-ultra2 controller that
is the first aic7xxx controller (the correct bits are 0011),
aic7xxx=override_term:0x3
Enable all termination on the third aic7xxx controller, high byte
termination on the second aic7xxx controller, and low and high byte
SE termination on the first aic7xxx controller
(bits are 1111 0010 0011),
aic7xxx=override_term:0xf23
No attempt has been made to make this option non-cryptic. It really
shouldn't be used except in dire circumstances, and if that happens,
I'm probably going to be telling you what to set this to anyway :)
"aic7xxx=stpwlev:0xffffffff" - This option is used to control the STPWLEV
bit in the DEVCONFIG PCI register. Currently, this is one of the
very few registers that we have absolutely *no* way of detecting
what the variable should be. It depends entirely on how the chipset
and external terminators were coupled by the card/motherboard maker.
Further, a chip reset (at power up) always sets this bit to 0. If
there is no BIOS to run on the chipset/card (such as with a 2910C
or a motherboard controller with the BIOS totally disabled) then
the variable may not get set properly. Of course, if the proper
setting was 0, then that's what it would be after the reset, but if
the proper setting is actually 1.....you get the picture. Now, since
we can't detect this at all, I've added this option to force the
setting. If you have a BIOS on your controller then you should never
need to use this option. However, if you are having lots of SCSI
reset problems and can't seem to get them knocked out, this may help.
Here's a test to know for certain if you need this option. Make
a boot floppy that you can use to boot your computer up and that
will detect the aic7xxx controller. Next, power down your computer.
While it's down, unplug all SCSI cables from your Adaptec SCSI
controller. Boot the system back up to the Adaptec EZ-SCSI BIOS
and then make sure that termination is enabled on your adapter (if
you have an Adaptec BIOS of course). Next, boot up the floppy you
made and wait for it to detect the aic7xxx controller. If the kernel
finds the controller fine, says scsi : x hosts and then tries to
detect your devices like normal, up to the point where it fails to
mount your root file system and panics, then you're fine. If, on
the other hand, the system goes into an infinite reset loop, then
you need to use this option and/or the previous option to force the
proper termination settings on your controller. If this happens,
then you next need to figure out what your settings should be.
To find the correct settings, power your machine back down, connect
back up the SCSI cables, and boot back into your machine like normal.
However, boot with the aic7xxx=verbose:0x39 option. Record the
initial DEVCONFIG values for each of your aic7xxx controllers as
they are listed, and also record what the machine is detecting as
the proper termination on your controllers. NOTE: the order in
which the initial DEVCONFIG values are printed out is not guaranteed
to be the same order as the SCSI controllers are registered. The
above option and this option both work on the order of the SCSI
controllers as they are registered, so make sure you match the right
DEVCONFIG values with the right controllers if you have more than
one aic7xxx controller.
Once you have the detected termination settings and the initial
DEVCONFIG values for each controller, then figure out what the
termination on each of the controllers *should* be. Hopefully, that
part is correct, but it could possibly be wrong if there is
bogus cable detection logic on your controller or something similar.
If all the controllers have the correct termination settings, then
don't set the aic7xxx=override_term variable at all, leave it alone.
Next, on any controllers that go into an infinite reset loop when
you unplug all the SCSI cables, get the starting DEVCONFIG value.
If the initial DEVCONFIG value is divisible by 2, then the correct
setting for that controller is 0. If it's an odd number, then
the correct setting for that controller is 1. For any other
controllers that didn't have an infinite reset problem, then reverse
the above options. If DEVCONFIG was even, then the correct setting
is 1, if not then the correct setting is 0.
Now that you know what the correct setting was for each controller,
we need to encode that into the aic7xxx=stpwlev:0x... variable.
This variable is a bit field encoded variable. Bit 0 is for the first
aic7xxx controller, bit 1 for the next, etc. Put all these bits
together and you get a number. For example, if the third aic7xxx
needed a 1, but the second and first both needed a 0, then the bits
would be 100 in binary. This then translates to 0x04. You would
therefore set aic7xxx=stpwlev:0x04. This is fairly standard binary
to hexadecimal conversions here. If you aren't up to speed on the
binary->hex conversion then send an email to the aic7xxx mailing
list and someone can help you out.
"aic7xxx=tag_info:{{8,8..},{8,8..},..}" - This option is used to disable
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 certain 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
second instance is the start of entries for a particular
device entry
} - end the entries for a particular host adapter, or end the entire
set of parameter entries
, - move to next entry. Inside of a set of device entries, this
moves us to the next device on the list. Outside of device
entries, this moves us to the next host adapter
. - Same effect as , but is safe to use with insmod.
x - the number to enter into the array at this position.
0 = Enable tagged queueing on this device and use the default
queue depth
1-254 = Enable tagged queueing on this device and use this
number as the queue depth
255 = Disable tagged queueing on this device.
Note: anything above 32 for an actual queue depth is wasteful
and not recommended.
A few examples of how this can be used:
tag_info:{{8,12,,0,,255,4}}
This line will only effect the first aic7xxx card registered. It
will set scsi id 0 to a queue depth of 8, id 1 to 12, leave id 2
at the default, set id 3 to tagged queueing enabled and use the
default queue depth, id 4 default, id 5 disabled, and id 6 to 4.
Any not specified entries stay at the default value, repeated
commas with no value specified will simply increment to the next id
without changing anything for the missing values.
tag_info:{,,,{,,,255}}
First, second, and third adapters at default values. Fourth
adapter, id 3 is disabled. Notice that leading commas simply
increment what the first number effects, and there are no need
for trailing commas. When you close out an adapter, or the
entire entry, anything not explicitly set stays at the default
value.
A final note on this option. The scanner I used for this isn't
perfect or highly robust. If you mess the line up, the worst that
should happen is that the line will get ignored. If you don't
close out the entire entry with the final bracket, then any other
aic7xxx options after this will get ignored. So, in general, be
sure of what you are entering, and after you have it right, just
add it to the lilo.conf file so there won't be any mistakes. As
a means of checking this parser, the entire tag_info array for
each card is now printed out in the /proc/scsi/aic7xxx/x file. You
can use that to verify that your options were parsed correctly.
Boot command line options may be combined to form the proper set of options
a user might need. For example, the following is valid:
aic7xxx=verbose,extended,irq_trigger:1
The only requirement is that individual options be separated by a comma or
a period on the command line.
Module Loading command options
------------------------------
When loading the aic7xxx driver as a module, the exact same options are
available to the user. However, the syntax to specify the options changes
slightly. For insmod, you need to wrap the aic7xxx= argument in quotes
and replace all ',' with '.'. So, for example, a valid insmod line
would be:
insmod aic7xxx aic7xxx='verbose.irq_trigger:1.extended'
This line should result in the *exact* same behaviour as if you typed
it in at the lilo prompt and the driver was compiled into the kernel
instead of being a module. The reason for the single quote is so that
the shell won't try to interpret anything in the line, such as {.
Insmod assumes any options starting with a letter instead of a number
is a character string (which is what we want) and by switching all of
the commas to periods, insmod won't interpret this as more than one
string and write junk into our binary image. I consider it a bug in
the insmod program that even if you wrap your string in quotes (quotes
that pass the shell mind you and that insmod sees) it still treats
a comma inside of those quotes as starting a new variable, resulting
in memory scribbles if you don't switch the commas to periods.
Kernel Compile options
------------------------------
The various kernel compile time options for this driver are now fairly
well documented in the file drivers/scsi/Kconfig. In order to
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 ? 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
------------------------------
The /proc support for the AIC7xxx can be found in the /proc/scsi/aic7xxx/
directory. That directory contains a file for each SCSI controller in
the system. Each file presents the current configuration and transfer
statistics (enabled with #define in aic7xxx.c) for each controller.
Thanks to Michael Neuffer for his upper-level SCSI help, and
Matthew Jacob for statistics support.
Debugging the driver
------------------------------
Should you have problems with this driver, and would like some help in
getting them solved, there are a couple debugging items built into
the driver to facilitate getting the needed information from the system.
In general, I need a complete description of the problem, with as many
logs as possible concerning what happens. To help with this, there is
a command option aic7xxx=panic_on_abort. This option, when set, forces
the driver to panic the kernel on the first SCSI abort issued by the
mid level SCSI code. If your system is going to reset loops and you
can't read the screen, then this is what you need. Not only will it
stop the system, but it also prints out a large amount of state
information in the process. Second, if you specify the option
"aic7xxx=verbose:0x1ffff", the system will print out *SOOOO* much
information as it runs that you won't be able to see anything.
However, this can actually be very useful if your machine simply
locks up when trying to boot, since it will pin-point what was last
happening (in regards to the aic7xxx driver) immediately prior to
the lockup. This is really only useful if your machine simply can
not boot up successfully. If you can get your machine to run, then
this will produce far too much information.
FTP sites
------------------------------
ftp://ftp.redhat.com/pub/aic/
- Out of date. I used to keep stuff here, but too many people
complained about having a hard time getting into Red Hat's ftp
server. So use the web site below instead.
ftp://ftp.pcnet.com/users/eischen/Linux/
- Dan Eischen's driver distribution area
ftp://ekf2.vsb.cz/pub/linux/kernel/aic7xxx/ftp.teleport.com/
- European Linux mirror of Teleport site
Web sites
------------------------------
http://people.redhat.com/dledford/
- My web site, also the primary aic7xxx site with several related
pages.
Dean W. Gehnert
deang@teleport.com
$Revision: 3.0 $
Modified by Doug Ledford 1998-2000
......@@ -484,7 +484,6 @@ M: Hannes Reinecke <hare@suse.de>
L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/aic7xxx/
F: drivers/scsi/aic7xxx_old/
AIMSLAB FM RADIO RECEIVER DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
......
......@@ -499,47 +499,6 @@ config SCSI_AACRAID
source "drivers/scsi/aic7xxx/Kconfig.aic7xxx"
config SCSI_AIC7XXX_OLD
tristate "Adaptec AIC7xxx support (old driver)"
depends on (ISA || EISA || PCI ) && SCSI
help
WARNING This driver is an older aic7xxx driver and is no longer
under active development. Adaptec, Inc. is writing a new driver to
take the place of this one, and it is recommended that whenever
possible, people should use the new Adaptec written driver instead
of this one. This driver will eventually be phased out entirely.
This is support for the various aic7xxx based Adaptec SCSI
controllers. These include the 274x EISA cards; 284x VLB cards;
2902, 2910, 293x, 294x, 394x, 3985 and several other PCI and
motherboard based SCSI controllers from Adaptec. It does not support
the AAA-13x RAID controllers from Adaptec, nor will it likely ever
support them. It does not support the 2920 cards from Adaptec that
use the Future Domain SCSI controller chip. For those cards, you
need the "Future Domain 16xx SCSI support" driver.
In general, if the controller is based on an Adaptec SCSI controller
chip from the aic777x series or the aic78xx series, this driver
should work. The only exception is the 7810 which is specifically
not supported (that's the RAID controller chip on the AAA-13x
cards).
Note that the AHA2920 SCSI host adapter is *not* supported by this
driver; choose "Future Domain 16xx SCSI support" instead if you have
one of those.
Information on the configuration options for this controller can be
found by checking the help file for each of the available
configuration options. You should read
<file:Documentation/scsi/aic7xxx_old.txt> at a minimum before
contacting the maintainer with any questions. The SCSI-HOWTO,
available from <http://www.tldp.org/docs.html#howto>, can also
be of great help.
To compile this driver as a module, choose M here: the
module will be called aic7xxx_old.
source "drivers/scsi/aic7xxx/Kconfig.aic79xx"
source "drivers/scsi/aic94xx/Kconfig"
source "drivers/scsi/mvsas/Kconfig"
......
......@@ -70,7 +70,6 @@ obj-$(CONFIG_SCSI_AHA1740) += aha1740.o
obj-$(CONFIG_SCSI_AIC7XXX) += aic7xxx/
obj-$(CONFIG_SCSI_AIC79XX) += aic7xxx/
obj-$(CONFIG_SCSI_AACRAID) += aacraid/
obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o
obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/
obj-$(CONFIG_SCSI_PM8001) += pm8001/
obj-$(CONFIG_SCSI_ISCI) += isci/
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/*+M*************************************************************************
* Adaptec AIC7xxx device driver for Linux.
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
*
* 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.
*
* $Id: aic7xxx.h,v 3.2 1996/07/23 03:37:26 deang Exp $
*-M*************************************************************************/
#ifndef _aic7xxx_h
#define _aic7xxx_h
#define AIC7XXX_H_VERSION "5.2.0"
#endif /* _aic7xxx_h */
/*
* Aic7xxx register and scratch ram definitions.
*
* Copyright (c) 1994-1998 Justin Gibbs.
* All rights reserved.
*
* 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. 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 General 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.
*
* $Id: aic7xxx.reg,v 1.4 1997/06/27 19:38:39 gibbs Exp $
*/
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
* firmware for the aic7xxx family of SCSI host adapters as well as to generate
* a C header file for use in the kernel portion of the Aic7xxx driver.
*
* All page numbers refer to the Adaptec AIC-7770 Data Book available from
* Adaptec's Technical Documents Department 1-800-934-2766
*/
/*
* SCSI Sequence Control (p. 3-11).
* Each bit, when set starts a specific SCSI sequence on the bus
*/
register SCSISEQ {
address 0x000
access_mode RW
bit TEMODE 0x80
bit ENSELO 0x40
bit ENSELI 0x20
bit ENRSELI 0x10
bit ENAUTOATNO 0x08
bit ENAUTOATNI 0x04
bit ENAUTOATNP 0x02
bit SCSIRSTO 0x01
}
/*
* SCSI Transfer Control 0 Register (pp. 3-13).
* Controls the SCSI module data path.
*/
register SXFRCTL0 {
address 0x001
access_mode RW
bit DFON 0x80
bit DFPEXP 0x40
bit FAST20 0x20
bit CLRSTCNT 0x10
bit SPIOEN 0x08
bit SCAMEN 0x04
bit CLRCHN 0x02
}
/*
* SCSI Transfer Control 1 Register (pp. 3-14,15).
* Controls the SCSI module data path.
*/
register SXFRCTL1 {
address 0x002
access_mode RW
bit BITBUCKET 0x80
bit SWRAPEN 0x40
bit ENSPCHK 0x20
mask STIMESEL 0x18
bit ENSTIMER 0x04
bit ACTNEGEN 0x02
bit STPWEN 0x01 /* Powered Termination */
}
/*
* SCSI Control Signal Read Register (p. 3-15).
* Reads the actual state of the SCSI bus pins
*/
register SCSISIGI {
address 0x003
access_mode RO
bit CDI 0x80
bit IOI 0x40
bit MSGI 0x20
bit ATNI 0x10
bit SELI 0x08
bit BSYI 0x04
bit REQI 0x02
bit ACKI 0x01
/*
* Possible phases in SCSISIGI
*/
mask PHASE_MASK CDI|IOI|MSGI
mask P_DATAOUT 0x00
mask P_DATAIN IOI
mask P_COMMAND CDI
mask P_MESGOUT CDI|MSGI
mask P_STATUS CDI|IOI
mask P_MESGIN CDI|IOI|MSGI
}
/*
* SCSI Control Signal Write Register (p. 3-16).
* Writing to this register modifies the control signals on the bus. Only
* those signals that are allowed in the current mode (Initiator/Target) are
* asserted.
*/
register SCSISIGO {
address 0x003
access_mode WO
bit CDO 0x80
bit IOO 0x40
bit MSGO 0x20
bit ATNO 0x10
bit SELO 0x08
bit BSYO 0x04
bit REQO 0x02
bit ACKO 0x01
/*
* Possible phases to write into SCSISIG0
*/
mask PHASE_MASK CDI|IOI|MSGI
mask P_DATAOUT 0x00
mask P_DATAIN IOI
mask P_COMMAND CDI
mask P_MESGOUT CDI|MSGI
mask P_STATUS CDI|IOI
mask P_MESGIN CDI|IOI|MSGI
}
/*
* SCSI Rate Control (p. 3-17).
* Contents of this register determine the Synchronous SCSI data transfer
* rate and the maximum synchronous Req/Ack offset. An offset of 0 in the
* SOFS (3:0) bits disables synchronous data transfers. Any offset value
* greater than 0 enables synchronous transfers.
*/
register SCSIRATE {
address 0x004
access_mode RW
bit WIDEXFER 0x80 /* Wide transfer control */
mask SXFR 0x70 /* Sync transfer rate */
mask SXFR_ULTRA2 0x7f /* Sync transfer rate */
mask SOFS 0x0f /* Sync offset */
}
/*
* SCSI ID (p. 3-18).
* Contains the ID of the board and the current target on the
* selected channel.
*/
register SCSIID {
address 0x005
access_mode RW
mask TID 0xf0 /* Target ID mask */
mask OID 0x0f /* Our ID mask */
/*
* SCSI Maximum Offset (p. 4-61 aic7890/91 Data Book)
* The aic7890/91 allow an offset of up to 127 transfers in both wide
* and narrow mode.
*/
alias SCSIOFFSET
mask SOFS_ULTRA2 0x7f /* Sync offset U2 chips */
}
/*
* SCSI Latched Data (p. 3-19).
* Read/Write latches used to transfer data on the SCSI bus during
* Automatic or Manual PIO mode. SCSIDATH can be used for the
* upper byte of a 16bit wide asynchronouse data phase transfer.
*/
register SCSIDATL {
address 0x006
access_mode RW
}
register SCSIDATH {
address 0x007
access_mode RW
}
/*
* SCSI Transfer Count (pp. 3-19,20)
* These registers count down the number of bytes transferred
* across the SCSI bus. The counter is decremented only once
* the data has been safely transferred. SDONE in SSTAT0 is
* set when STCNT goes to 0
*/
register STCNT {
address 0x008
size 3
access_mode RW
}
/*
* Option Mode Register (Alternate Mode) (p. 5-198)
* This register is used to set certain options on Ultra3 based chips.
* The chip must be in alternate mode (bit ALT_MODE in SFUNCT must be set)
*/
register OPTIONMODE {
address 0x008
access_mode RW
bit AUTORATEEN 0x80
bit AUTOACKEN 0x40
bit ATNMGMNTEN 0x20
bit BUSFREEREV 0x10
bit EXPPHASEDIS 0x08
bit SCSIDATL_IMGEN 0x04
bit AUTO_MSGOUT_DE 0x02
bit DIS_MSGIN_DUALEDGE 0x01
}
/*
* Clear SCSI Interrupt 0 (p. 3-20)
* Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT0.
*/
register CLRSINT0 {
address 0x00b
access_mode WO
bit CLRSELDO 0x40
bit CLRSELDI 0x20
bit CLRSELINGO 0x10
bit CLRSWRAP 0x08
bit CLRSPIORDY 0x02
}
/*
* SCSI Status 0 (p. 3-21)
* Contains one set of SCSI Interrupt codes
* These are most likely of interest to the sequencer
*/
register SSTAT0 {
address 0x00b
access_mode RO
bit TARGET 0x80 /* Board acting as target */
bit SELDO 0x40 /* Selection Done */
bit SELDI 0x20 /* Board has been selected */
bit SELINGO 0x10 /* Selection In Progress */
bit SWRAP 0x08 /* 24bit counter wrap */
bit IOERR 0x08 /* LVD Tranceiver mode changed */
bit SDONE 0x04 /* STCNT = 0x000000 */
bit SPIORDY 0x02 /* SCSI PIO Ready */
bit DMADONE 0x01 /* DMA transfer completed */
}
/*
* Clear SCSI Interrupt 1 (p. 3-23)
* Writing a 1 to a bit clears the associated SCSI Interrupt in SSTAT1.
*/
register CLRSINT1 {
address 0x00c
access_mode WO
bit CLRSELTIMEO 0x80
bit CLRATNO 0x40
bit CLRSCSIRSTI 0x20
bit CLRBUSFREE 0x08
bit CLRSCSIPERR 0x04
bit CLRPHASECHG 0x02
bit CLRREQINIT 0x01
}
/*
* SCSI Status 1 (p. 3-24)
*/
register SSTAT1 {
address 0x00c
access_mode RO
bit SELTO 0x80
bit ATNTARG 0x40
bit SCSIRSTI 0x20
bit PHASEMIS 0x10
bit BUSFREE 0x08
bit SCSIPERR 0x04
bit PHASECHG 0x02
bit REQINIT 0x01
}
/*
* SCSI Status 2 (pp. 3-25,26)
*/
register SSTAT2 {
address 0x00d
access_mode RO
bit OVERRUN 0x80
bit SHVALID 0x40
bit WIDE_RES 0x20
bit EXP_ACTIVE 0x10 /* SCSI Expander Active */
bit CRCVALERR 0x08 /* CRC Value Error */
bit CRCENDERR 0x04 /* CRC End Error */
bit CRCREQERR 0x02 /* CRC REQ Error */
bit DUAL_EDGE_ERROR 0x01 /* Invalid pins for Dual Edge phase */
mask SFCNT 0x1f
}
/*
* SCSI Status 3 (p. 3-26)
*/
register SSTAT3 {
address 0x00e
access_mode RO
mask SCSICNT 0xf0
mask OFFCNT 0x0f
}
/*
* SCSI ID for the aic7890/91 chips
*/
register SCSIID_ULTRA2 {
address 0x00f
access_mode RW
mask TID 0xf0 /* Target ID mask */
mask OID 0x0f /* Our ID mask */
}
/*
* SCSI Interrupt Mode 1 (p. 3-28)
* Setting any bit will enable the corresponding function
* in SIMODE0 to interrupt via the IRQ pin.
*/
register SIMODE0 {
address 0x010
access_mode RW
bit ENSELDO 0x40
bit ENSELDI 0x20
bit ENSELINGO 0x10
bit ENSWRAP 0x08
bit ENIOERR 0x08 /* LVD Tranceiver mode changes */
bit ENSDONE 0x04
bit ENSPIORDY 0x02
bit ENDMADONE 0x01
}
/*
* SCSI Interrupt Mode 1 (pp. 3-28,29)
* Setting any bit will enable the corresponding function
* in SIMODE1 to interrupt via the IRQ pin.
*/
register SIMODE1 {
address 0x011
access_mode RW
bit ENSELTIMO 0x80
bit ENATNTARG 0x40
bit ENSCSIRST 0x20
bit ENPHASEMIS 0x10
bit ENBUSFREE 0x08
bit ENSCSIPERR 0x04
bit ENPHASECHG 0x02
bit ENREQINIT 0x01
}
/*
* SCSI Data Bus (High) (p. 3-29)
* This register reads data on the SCSI Data bus directly.
*/
register SCSIBUSL {
address 0x012
access_mode RO
}
register SCSIBUSH {
address 0x013
access_mode RO
}
/*
* SCSI/Host Address (p. 3-30)
* These registers hold the host address for the byte about to be
* transferred on the SCSI bus. They are counted up in the same
* manner as STCNT is counted down. SHADDR should always be used
* to determine the address of the last byte transferred since HADDR
* can be skewed by write ahead.
*/
register SHADDR {
address 0x014
size 4
access_mode RO
}
/*
* Selection Timeout Timer (p. 3-30)
*/
register SELTIMER {
address 0x018
access_mode RW
bit STAGE6 0x20
bit STAGE5 0x10
bit STAGE4 0x08
bit STAGE3 0x04
bit STAGE2 0x02
bit STAGE1 0x01
}
/*
* Selection/Reselection ID (p. 3-31)
* Upper four bits are the device id. The ONEBIT is set when the re/selecting
* device did not set its own ID.
*/
register SELID {
address 0x019
access_mode RW
mask SELID_MASK 0xf0
bit ONEBIT 0x08
}
/*
* Serial Port I/O Cabability register (p. 4-95 aic7860 Data Book)
* Indicates if external logic has been attached to the chip to
* perform the tasks of accessing a serial eeprom, testing termination
* strength, and performing cable detection. On the aic7860, most of
* these features are handled on chip, but on the aic7855 an attached
* aic3800 does the grunt work.
*/
register SPIOCAP {
address 0x01b
access_mode RW
bit SOFT1 0x80
bit SOFT0 0x40
bit SOFTCMDEN 0x20
bit HAS_BRDCTL 0x10 /* External Board control */
bit SEEPROM 0x08 /* External serial eeprom logic */
bit EEPROM 0x04 /* Writable external BIOS ROM */
bit ROM 0x02 /* Logic for accessing external ROM */
bit SSPIOCPS 0x01 /* Termination and cable detection */
}
/*
* SCSI Block Control (p. 3-32)
* Controls Bus type and channel selection. In a twin channel configuration
* addresses 0x00-0x1e are gated to the appropriate channel based on this
* register. SELWIDE allows for the coexistence of 8bit and 16bit devices
* on a wide bus.
*/
register SBLKCTL {
address 0x01f
access_mode RW
bit DIAGLEDEN 0x80 /* Aic78X0 only */
bit DIAGLEDON 0x40 /* Aic78X0 only */
bit AUTOFLUSHDIS 0x20
bit SELBUSB 0x08
bit ENAB40 0x08 /* LVD transceiver active */
bit ENAB20 0x04 /* SE/HVD transceiver active */
bit SELWIDE 0x02
bit XCVR 0x01 /* External transceiver active */
}
/*
* Sequencer Control (p. 3-33)
* Error detection mode and speed configuration
*/
register SEQCTL {
address 0x060
access_mode RW
bit PERRORDIS 0x80
bit PAUSEDIS 0x40
bit FAILDIS 0x20
bit FASTMODE 0x10
bit BRKADRINTEN 0x08
bit STEP 0x04
bit SEQRESET 0x02
bit LOADRAM 0x01
}
/*
* Sequencer RAM Data (p. 3-34)
* Single byte window into the Scratch Ram area starting at the address
* specified by SEQADDR0 and SEQADDR1. To write a full word, simply write
* four bytes in succession. The SEQADDRs will increment after the most
* significant byte is written
*/
register SEQRAM {
address 0x061
access_mode RW
}
/*
* Sequencer Address Registers (p. 3-35)
* Only the first bit of SEQADDR1 holds addressing information
*/
register SEQADDR0 {
address 0x062
access_mode RW
}
register SEQADDR1 {
address 0x063
access_mode RW
mask SEQADDR1_MASK 0x01
}
/*
* Accumulator
* We cheat by passing arguments in the Accumulator up to the kernel driver
*/
register ACCUM {
address 0x064
access_mode RW
accumulator
}
register SINDEX {
address 0x065
access_mode RW
sindex
}
register DINDEX {
address 0x066
access_mode RW
}
register ALLONES {
address 0x069
access_mode RO
allones
}
register ALLZEROS {
address 0x06a
access_mode RO
allzeros
}
register NONE {
address 0x06a
access_mode WO
none
}
register FLAGS {
address 0x06b
access_mode RO
bit ZERO 0x02
bit CARRY 0x01
}
register SINDIR {
address 0x06c
access_mode RO
}
register DINDIR {
address 0x06d
access_mode WO
}
register FUNCTION1 {
address 0x06e
access_mode RW
}
register STACK {
address 0x06f
access_mode RO
}
/*
* Board Control (p. 3-43)
*/
register BCTL {
address 0x084
access_mode RW
bit ACE 0x08
bit ENABLE 0x01
}
register DSCOMMAND0 {
address 0x084
access_mode RW
bit CACHETHEN 0x80
bit DPARCKEN 0x40
bit MPARCKEN 0x20
bit EXTREQLCK 0x10
bit INTSCBRAMSEL 0x08
bit RAMPS 0x04
bit USCBSIZE32 0x02
bit CIOPARCKEN 0x01
}
/*
* On the aic78X0 chips, Board Control is replaced by the DSCommand
* register (p. 4-64)
*/
register DSCOMMAND {
address 0x084
access_mode RW
bit CACHETHEN 0x80 /* Cache Threshold enable */
bit DPARCKEN 0x40 /* Data Parity Check Enable */
bit MPARCKEN 0x20 /* Memory Parity Check Enable */
bit EXTREQLCK 0x10 /* External Request Lock */
}
/*
* Bus On/Off Time (p. 3-44)
*/
register BUSTIME {
address 0x085
access_mode RW
mask BOFF 0xf0
mask BON 0x0f
}
/*
* Bus Speed (p. 3-45)
*/
register BUSSPD {
address 0x086
access_mode RW
mask DFTHRSH 0xc0
mask STBOFF 0x38
mask STBON 0x07
mask DFTHRSH_100 0xc0
}
/*
* Host Control (p. 3-47) R/W
* Overall host control of the device.
*/
register HCNTRL {
address 0x087
access_mode RW
bit POWRDN 0x40
bit SWINT 0x10
bit IRQMS 0x08
bit PAUSE 0x04
bit INTEN 0x02
bit CHIPRST 0x01
bit CHIPRSTACK 0x01
}
/*
* Host Address (p. 3-48)
* This register contains the address of the byte about
* to be transferred across the host bus.
*/
register HADDR {
address 0x088
size 4
access_mode RW
}
register HCNT {
address 0x08c
size 3
access_mode RW
}
/*
* SCB Pointer (p. 3-49)
* Gate one of the four SCBs into the SCBARRAY window.
*/
register SCBPTR {
address 0x090
access_mode RW
}
/*
* Interrupt Status (p. 3-50)
* Status for system interrupts
*/
register INTSTAT {
address 0x091
access_mode RW
bit BRKADRINT 0x08
bit SCSIINT 0x04
bit CMDCMPLT 0x02
bit SEQINT 0x01
mask BAD_PHASE SEQINT /* unknown scsi bus phase */
mask SEND_REJECT 0x10|SEQINT /* sending a message reject */
mask NO_IDENT 0x20|SEQINT /* no IDENTIFY after reconnect*/
mask NO_MATCH 0x30|SEQINT /* no cmd match for reconnect */
mask EXTENDED_MSG 0x40|SEQINT /* Extended message received */
mask WIDE_RESIDUE 0x50|SEQINT /* need kernel to back up */
/* the SG array for us */
mask REJECT_MSG 0x60|SEQINT /* Reject message received */
mask BAD_STATUS 0x70|SEQINT /* Bad status from target */
mask RESIDUAL 0x80|SEQINT /* Residual byte count != 0 */
mask AWAITING_MSG 0xa0|SEQINT /*
* Kernel requested to specify
* a message to this target
* (command was null), so tell
* it that it can fill the
* message buffer.
*/
mask SEQ_SG_FIXUP 0xb0|SEQINT /* need help with fixing up
* the sg array pointer after
* a phasemis with no valid
* sg elements in the shadow
* pipeline.
*/
mask TRACEPOINT2 0xc0|SEQINT
mask MSGIN_PHASEMIS 0xd0|SEQINT /*
* Target changed phase on us
* when we were expecting
* another msgin byte.
*/
mask DATA_OVERRUN 0xe0|SEQINT /*
* Target attempted to write
* beyond the bounds of its
* command.
*/
mask SEQINT_MASK 0xf0|SEQINT /* SEQINT Status Codes */
mask INT_PEND (BRKADRINT|SEQINT|SCSIINT|CMDCMPLT)
}
/*
* Hard Error (p. 3-53)
* Reporting of catastrophic errors. You usually cannot recover from
* these without a full board reset.
*/
register ERROR {
address 0x092
access_mode RO
bit CIOPARERR 0x80 /* Ultra2 only */
bit PCIERRSTAT 0x40 /* PCI only */
bit MPARERR 0x20 /* PCI only */
bit DPARERR 0x10 /* PCI only */
bit SQPARERR 0x08
bit ILLOPCODE 0x04
bit ILLSADDR 0x02
bit DSCTMOUT 0x02 /* Ultra3 only */
bit ILLHADDR 0x01
}
/*
* Clear Interrupt Status (p. 3-52)
*/
register CLRINT {
address 0x092
access_mode WO
bit CLRPARERR 0x10 /* PCI only */
bit CLRBRKADRINT 0x08
bit CLRSCSIINT 0x04
bit CLRCMDINT 0x02
bit CLRSEQINT 0x01
}
register DFCNTRL {
address 0x093
access_mode RW
bit PRELOADEN 0x80 /* aic7890 only */
bit WIDEODD 0x40
bit SCSIEN 0x20
bit SDMAEN 0x10
bit SDMAENACK 0x10
bit HDMAEN 0x08
bit HDMAENACK 0x08
bit DIRECTION 0x04
bit FIFOFLUSH 0x02
bit FIFORESET 0x01
}
register DFSTATUS {
address 0x094
access_mode RO
bit PRELOAD_AVAIL 0x80
bit DWORDEMP 0x20
bit MREQPEND 0x10
bit HDONE 0x08
bit DFTHRESH 0x04
bit FIFOFULL 0x02
bit FIFOEMP 0x01
}
register DFDAT {
address 0x099
access_mode RW
}
/*
* SCB Auto Increment (p. 3-59)
* Byte offset into the SCB Array and an optional bit to allow auto
* incrementing of the address during download and upload operations
*/
register SCBCNT {
address 0x09a
access_mode RW
bit SCBAUTO 0x80
mask SCBCNT_MASK 0x1f
}
/*
* Queue In FIFO (p. 3-60)
* Input queue for queued SCBs (commands that the seqencer has yet to start)
*/
register QINFIFO {
address 0x09b
access_mode RW
}
/*
* Queue In Count (p. 3-60)
* Number of queued SCBs
*/
register QINCNT {
address 0x09c
access_mode RO
}
/*
* SCSIDATL IMAGE Register (p. 5-104)
* Write to this register also go to SCSIDATL but this register will preserve
* the data for later reading as long as the SCSIDATL_IMGEN bit in the
* OPTIONMODE register is set.
*/
register SCSIDATL_IMG {
address 0x09c
access_mode RW
}
/*
* Queue Out FIFO (p. 3-61)
* Queue of SCBs that have completed and await the host
*/
register QOUTFIFO {
address 0x09d
access_mode WO
}
/*
* CRC Control 1 Register (p. 5-105)
* Control bits for the Ultra 160/m CRC facilities
*/
register CRCCONTROL1 {
address 0x09d
access_mode RW
bit CRCONSEEN 0x80 /* CRC ON Single Edge ENable */
bit CRCVALCHKEN 0x40 /* CRC Value Check Enable */
bit CRCENDCHKEN 0x20 /* CRC End Check Enable */
bit CRCREQCHKEN 0x10
bit TARGCRCENDEN 0x08 /* Enable End CRC transfer when target */
bit TARGCRCCNTEN 0x04 /* Enable CRC transfer when target */
}
/*
* Queue Out Count (p. 3-61)
* Number of queued SCBs in the Out FIFO
*/
register QOUTCNT {
address 0x09e
access_mode RO
}
/*
* SCSI Phase Register (p. 5-106)
* Current bus phase
*/
register SCSIPHASE {
address 0x09e
access_mode RO
bit SP_STATUS 0x20
bit SP_COMMAND 0x10
bit SP_MSG_IN 0x08
bit SP_MSG_OUT 0x04
bit SP_DATA_IN 0x02
bit SP_DATA_OUT 0x01
}
/*
* Special Function
*/
register SFUNCT {
address 0x09f
access_mode RW
bit ALT_MODE 0x80
}
/*
* SCB Definition (p. 5-4)
*/
scb {
address 0x0a0
SCB_CONTROL {
size 1
bit MK_MESSAGE 0x80
bit DISCENB 0x40
bit TAG_ENB 0x20
bit DISCONNECTED 0x04
mask SCB_TAG_TYPE 0x03
}
SCB_TCL {
size 1
bit SELBUSB 0x08
mask TID 0xf0
mask LID 0x07
}
SCB_TARGET_STATUS {
size 1
}
SCB_SGCOUNT {
size 1
}
SCB_SGPTR {
size 4
}
SCB_RESID_SGCNT {
size 1
}
SCB_RESID_DCNT {
size 3
}
SCB_DATAPTR {
size 4
}
SCB_DATACNT {
/*
* Really only 3 bytes, but padded to make
* the kernel's job easier.
*/
size 4
}
SCB_CMDPTR {
size 4
}
SCB_CMDLEN {
size 1
}
SCB_TAG {
size 1
}
SCB_NEXT {
size 1
}
SCB_PREV {
size 1
}
SCB_BUSYTARGETS {
size 4
}
}
const SG_SIZEOF 0x08 /* sizeof(struct ahc_dma) */
/* --------------------- AHA-2840-only definitions -------------------- */
register SEECTL_2840 {
address 0x0c0
access_mode RW
bit CS_2840 0x04
bit CK_2840 0x02
bit DO_2840 0x01
}
register STATUS_2840 {
address 0x0c1
access_mode RW
bit EEPROM_TF 0x80
mask BIOS_SEL 0x60
mask ADSEL 0x1e
bit DI_2840 0x01
}
/* --------------------- AIC-7870-only definitions -------------------- */
register DSPCISTATUS {
address 0x086
mask DFTHRSH_100 0xc0
}
register CCHADDR {
address 0x0E0
size 8
}
register CCHCNT {
address 0x0E8
}
register CCSGRAM {
address 0x0E9
}
register CCSGADDR {
address 0x0EA
}
register CCSGCTL {
address 0x0EB
bit CCSGDONE 0x80
bit CCSGEN 0x08
bit FLAG 0x02
bit CCSGRESET 0x01
}
register CCSCBCNT {
address 0xEF
}
register CCSCBCTL {
address 0x0EE
bit CCSCBDONE 0x80
bit ARRDONE 0x40 /* SCB Array prefetch done */
bit CCARREN 0x10
bit CCSCBEN 0x08
bit CCSCBDIR 0x04
bit CCSCBRESET 0x01
}
register CCSCBADDR {
address 0x0ED
}
register CCSCBRAM {
address 0xEC
}
register CCSCBPTR {
address 0x0F1
}
register HNSCB_QOFF {
address 0x0F4
}
register HESCB_QOFF {
address 0x0F5
}
register SNSCB_QOFF {
address 0x0F6
}
register SESCB_QOFF {
address 0x0F7
}
register SDSCB_QOFF {
address 0x0F8
}
register QOFF_CTLSTA {
address 0x0FA
bit ESTABLISH_SCB_AVAIL 0x80
bit SCB_AVAIL 0x40
bit SNSCB_ROLLOVER 0x20
bit SDSCB_ROLLOVER 0x10
bit SESCB_ROLLOVER 0x08
mask SCB_QSIZE 0x07
mask SCB_QSIZE_256 0x06
}
register DFF_THRSH {
address 0x0FB
mask WR_DFTHRSH 0x70
mask RD_DFTHRSH 0x07
mask RD_DFTHRSH_MIN 0x00
mask RD_DFTHRSH_25 0x01
mask RD_DFTHRSH_50 0x02
mask RD_DFTHRSH_63 0x03
mask RD_DFTHRSH_75 0x04
mask RD_DFTHRSH_85 0x05
mask RD_DFTHRSH_90 0x06
mask RD_DFTHRSH_MAX 0x07
mask WR_DFTHRSH_MIN 0x00
mask WR_DFTHRSH_25 0x10
mask WR_DFTHRSH_50 0x20
mask WR_DFTHRSH_63 0x30
mask WR_DFTHRSH_75 0x40
mask WR_DFTHRSH_85 0x50
mask WR_DFTHRSH_90 0x60
mask WR_DFTHRSH_MAX 0x70
}
register SG_CACHEPTR {
access_mode RW
address 0x0fc
mask SG_USER_DATA 0xfc
bit LAST_SEG 0x02
bit LAST_SEG_DONE 0x01
}
register BRDCTL {
address 0x01d
bit BRDDAT7 0x80
bit BRDDAT6 0x40
bit BRDDAT5 0x20
bit BRDSTB 0x10
bit BRDCS 0x08
bit BRDRW 0x04
bit BRDCTL1 0x02
bit BRDCTL0 0x01
/* 7890 Definitions */
bit BRDDAT4 0x10
bit BRDDAT3 0x08
bit BRDDAT2 0x04
bit BRDRW_ULTRA2 0x02
bit BRDSTB_ULTRA2 0x01
}
/*
* Serial EEPROM Control (p. 4-92 in 7870 Databook)
* Controls the reading and writing of an external serial 1-bit
* EEPROM Device. In order to access the serial EEPROM, you must
* first set the SEEMS bit that generates a request to the memory
* port for access to the serial EEPROM device. When the memory
* port is not busy servicing another request, it reconfigures
* to allow access to the serial EEPROM. When this happens, SEERDY
* gets set high to verify that the memory port access has been
* granted.
*
* After successful arbitration for the memory port, the SEECS bit of
* the SEECTL register is connected to the chip select. The SEECK,
* SEEDO, and SEEDI are connected to the clock, data out, and data in
* lines respectively. The SEERDY bit of SEECTL is useful in that it
* gives us an 800 nsec timer. After a write to the SEECTL register,
* the SEERDY goes high 800 nsec later. The one exception to this is
* when we first request access to the memory port. The SEERDY goes
* high to signify that access has been granted and, for this case, has
* no implied timing.
*
* See 93cx6.c for detailed information on the protocol necessary to
* read the serial EEPROM.
*/
register SEECTL {
address 0x01e
bit EXTARBACK 0x80
bit EXTARBREQ 0x40
bit SEEMS 0x20
bit SEERDY 0x10
bit SEECS 0x08
bit SEECK 0x04
bit SEEDO 0x02
bit SEEDI 0x01
}
/* ---------------------- Scratch RAM Offsets ------------------------- */
/* These offsets are either to values that are initialized by the board's
* BIOS or are specified by the sequencer code.
*
* The host adapter card (at least the BIOS) uses 20-2f for SCSI
* device information, 32-33 and 5a-5f as well. As it turns out, the
* BIOS trashes 20-2f, writing the synchronous negotiation results
* on top of the BIOS values, so we re-use those for our per-target
* scratchspace (actually a value that can be copied directly into
* SCSIRATE). The kernel driver will enable synchronous negotiation
* for all targets that have a value other than 0 in the lower four
* bits of the target scratch space. This should work regardless of
* whether the bios has been installed.
*/
scratch_ram {
address 0x020
/*
* 1 byte per target starting at this address for configuration values
*/
TARG_SCSIRATE {
size 16
}
/*
* Bit vector of targets that have ULTRA enabled.
*/
ULTRA_ENB {
size 2
}
/*
* Bit vector of targets that have disconnection disabled.
*/
DISC_DSB {
size 2
}
/*
* Single byte buffer used to designate the type or message
* to send to a target.
*/
MSG_OUT {
size 1
}
/* Parameters for DMA Logic */
DMAPARAMS {
size 1
bit PRELOADEN 0x80
bit WIDEODD 0x40
bit SCSIEN 0x20
bit SDMAEN 0x10
bit SDMAENACK 0x10
bit HDMAEN 0x08
bit HDMAENACK 0x08
bit DIRECTION 0x04
bit FIFOFLUSH 0x02
bit FIFORESET 0x01
}
SEQ_FLAGS {
size 1
bit IDENTIFY_SEEN 0x80
bit SCBPTR_VALID 0x20
bit DPHASE 0x10
bit AMTARGET 0x08
bit WIDE_BUS 0x02
bit TWIN_BUS 0x01
}
/*
* Temporary storage for the
* target/channel/lun of a
* reconnecting target
*/
SAVED_TCL {
size 1
}
/* Working value of the number of SG segments left */
SG_COUNT {
size 1
}
/* Working value of SG pointer */
SG_NEXT {
size 4
}
/*
* The last bus phase as seen by the sequencer.
*/
LASTPHASE {
size 1
bit CDI 0x80
bit IOI 0x40
bit MSGI 0x20
mask PHASE_MASK CDI|IOI|MSGI
mask P_DATAOUT 0x00
mask P_DATAIN IOI
mask P_COMMAND CDI
mask P_MESGOUT CDI|MSGI
mask P_STATUS CDI|IOI
mask P_MESGIN CDI|IOI|MSGI
mask P_BUSFREE 0x01
}
/*
* head of list of SCBs awaiting
* selection
*/
WAITING_SCBH {
size 1
}
/*
* head of list of SCBs that are
* disconnected. Used for SCB
* paging.
*/
DISCONNECTED_SCBH {
size 1
}
/*
* head of list of SCBs that are
* not in use. Used for SCB paging.
*/
FREE_SCBH {
size 1
}
/*
* Address of the hardware scb array in the host.
*/
HSCB_ADDR {
size 4
}
/*
* Address of the 256 byte array storing the SCBID of outstanding
* untagged SCBs indexed by TCL.
*/
SCBID_ADDR {
size 4
}
/*
* Address of the array of command descriptors used to store
* information about incoming selections.
*/
TMODE_CMDADDR {
size 4
}
KERNEL_QINPOS {
size 1
}
QINPOS {
size 1
}
QOUTPOS {
size 1
}
/*
* Offset into the command descriptor array for the next
* available desciptor to use.
*/
TMODE_CMDADDR_NEXT {
size 1
}
ARG_1 {
size 1
mask SEND_MSG 0x80
mask SEND_SENSE 0x40
mask SEND_REJ 0x20
mask MSGOUT_PHASEMIS 0x10
alias RETURN_1
}
ARG_2 {
size 1
alias RETURN_2
}
/*
* Snapshot of MSG_OUT taken after each message is sent.
*/
LAST_MSG {
size 1
}
/*
* Number of times we have filled the CCSGRAM with prefetched
* SG elements.
*/
PREFETCH_CNT {
size 1
}
/*
* These are reserved registers in the card's scratch ram. Some of
* the values are specified in the AHA2742 technical reference manual
* and are initialized by the BIOS at boot time.
*/
SCSICONF {
address 0x05a
size 1
bit TERM_ENB 0x80
bit RESET_SCSI 0x40
mask HSCSIID 0x07 /* our SCSI ID */
mask HWSCSIID 0x0f /* our SCSI ID if Wide Bus */
}
HOSTCONF {
address 0x05d
size 1
}
HA_274_BIOSCTRL {
address 0x05f
size 1
mask BIOSMODE 0x30
mask BIOSDISABLED 0x30
bit CHANNEL_B_PRIMARY 0x08
}
/*
* Per target SCSI offset values for Ultra2 controllers.
*/
TARG_OFFSET {
address 0x070
size 16
}
}
const SCB_LIST_NULL 0xff
const CCSGADDR_MAX 0x80
const CCSGRAM_MAXSEGS 16
/* Offsets into the SCBID array where different data is stored */
const UNTAGGEDSCB_OFFSET 0
const QOUTFIFO_OFFSET 1
const QINFIFO_OFFSET 2
/* WDTR Message values */
const BUS_8_BIT 0x00
const BUS_16_BIT 0x01
const BUS_32_BIT 0x02
/* Offset maximums */
const MAX_OFFSET_8BIT 0x0f
const MAX_OFFSET_16BIT 0x08
const MAX_OFFSET_ULTRA2 0x7f
const HOST_MSG 0xff
/* Target mode command processing constants */
const CMD_GROUP_CODE_SHIFT 0x05
const CMD_GROUP0_BYTE_DELTA -4
const CMD_GROUP2_BYTE_DELTA -6
const CMD_GROUP4_BYTE_DELTA 4
const CMD_GROUP5_BYTE_DELTA 11
/*
* Downloaded (kernel inserted) constants
*/
/*
* Number of command descriptors in the command descriptor array.
*/
const TMODE_NUMCMDS download
/*
* Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
*
* Copyright (c) 1994-1999 Justin Gibbs.
* All rights reserved.
*
* 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. 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 General 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.
*
* $Id: aic7xxx.seq,v 1.77 1998/06/28 02:58:57 gibbs Exp $
*/
#include "aic7xxx.reg"
#include "scsi_message.h"
/*
* A few words on the waiting SCB list:
* After starting the selection hardware, we check for reconnecting targets
* as well as for our selection to complete just in case the reselection wins
* bus arbitration. The problem with this is that we must keep track of the
* SCB that we've already pulled from the QINFIFO and started the selection
* on just in case the reselection wins so that we can retry the selection at
* a later time. This problem cannot be resolved by holding a single entry
* in scratch ram since a reconnecting target can request sense and this will
* create yet another SCB waiting for selection. The solution used here is to
* use byte 27 of the SCB as a pseudo-next pointer and to thread a list
* of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes,
* SCB_LIST_NULL is 0xff which is out of range. An entry is also added to
* this list every time a request sense occurs or after completing a non-tagged
* command for which a second SCB has been queued. The sequencer will
* automatically consume the entries.
*/
reset:
clr SCSISIGO; /* De-assert BSY */
and SXFRCTL1, ~BITBUCKET;
/* Always allow reselection */
mvi SCSISEQ, ENRSELI|ENAUTOATNP;
if ((p->features & AHC_CMD_CHAN) != 0) {
/* Ensure that no DMA operations are in progress */
clr CCSGCTL;
clr CCSCBCTL;
}
call clear_target_state;
poll_for_work:
and SXFRCTL0, ~SPIOEN;
if ((p->features & AHC_QUEUE_REGS) == 0) {
mov A, QINPOS;
}
poll_for_work_loop:
if ((p->features & AHC_QUEUE_REGS) == 0) {
and SEQCTL, ~PAUSEDIS;
}
test SSTAT0, SELDO|SELDI jnz selection;
test SCSISEQ, ENSELO jnz poll_for_work;
if ((p->features & AHC_TWIN) != 0) {
/*
* Twin channel devices cannot handle things like SELTO
* interrupts on the "background" channel. So, if we
* are selecting, keep polling the current channel util
* either a selection or reselection occurs.
*/
xor SBLKCTL,SELBUSB; /* Toggle to the other bus */
test SSTAT0, SELDO|SELDI jnz selection;
test SCSISEQ, ENSELO jnz poll_for_work;
xor SBLKCTL,SELBUSB; /* Toggle back */
}
cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
test_queue:
/* Has the driver posted any work for us? */
if ((p->features & AHC_QUEUE_REGS) != 0) {
test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
mov NONE, SNSCB_QOFF;
inc QINPOS;
} else {
or SEQCTL, PAUSEDIS;
cmp KERNEL_QINPOS, A je poll_for_work_loop;
inc QINPOS;
and SEQCTL, ~PAUSEDIS;
}
/*
* We have at least one queued SCB now and we don't have any
* SCBs in the list of SCBs awaiting selection. If we have
* any SCBs available for use, pull the tag from the QINFIFO
* and get to work on it.
*/
if ((p->flags & AHC_PAGESCBS) != 0) {
mov ALLZEROS call get_free_or_disc_scb;
}
dequeue_scb:
add A, -1, QINPOS;
mvi QINFIFO_OFFSET call fetch_byte;
if ((p->flags & AHC_PAGESCBS) == 0) {
/* In the non-paging case, the SCBID == hardware SCB index */
mov SCBPTR, RETURN_2;
}
dma_queued_scb:
/*
* DMA the SCB from host ram into the current SCB location.
*/
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
mov RETURN_2 call dma_scb;
/*
* Preset the residual fields in case we never go through a data phase.
* This isn't done by the host so we can avoid a DMA to clear these
* fields for the normal case of I/O that completes without underrun
* or overrun conditions.
*/
if ((p->features & AHC_CMD_CHAN) != 0) {
bmov SCB_RESID_DCNT, SCB_DATACNT, 3;
} else {
mov SCB_RESID_DCNT[0],SCB_DATACNT[0];
mov SCB_RESID_DCNT[1],SCB_DATACNT[1];
mov SCB_RESID_DCNT[2],SCB_DATACNT[2];
}
mov SCB_RESID_SGCNT, SCB_SGCOUNT;
start_scb:
/*
* Place us on the waiting list in case our selection
* doesn't win during bus arbitration.
*/
mov SCB_NEXT,WAITING_SCBH;
mov WAITING_SCBH, SCBPTR;
start_waiting:
/*
* Pull the first entry off of the waiting SCB list.
*/
mov SCBPTR, WAITING_SCBH;
call start_selection;
jmp poll_for_work;
start_selection:
if ((p->features & AHC_TWIN) != 0) {
and SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
and A,SELBUSB,SCB_TCL; /* Get new channel bit */
or SINDEX,A;
mov SBLKCTL,SINDEX; /* select channel */
}
initialize_scsiid:
if ((p->features & AHC_ULTRA2) != 0) {
and A, TID, SCB_TCL; /* Get target ID */
and SCSIID_ULTRA2, OID; /* Clear old target */
or SCSIID_ULTRA2, A;
} else {
and A, TID, SCB_TCL; /* Get target ID */
and SCSIID, OID; /* Clear old target */
or SCSIID, A;
}
mov SCSIDATL, ALLZEROS; /* clear out the latched */
/* data register, this */
/* fixes a bug on some */
/* controllers where the */
/* last byte written to */
/* this register can leak */
/* onto the data bus at */
/* bad times, such as during */
/* selection timeouts */
mvi SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;
/*
* Initialize Ultra mode setting and clear the SCSI channel.
* SINDEX should contain any additional bit's the client wants
* set in SXFRCTL0.
*/
initialize_channel:
or SXFRCTL0, CLRSTCNT|CLRCHN, SINDEX;
if ((p->features & AHC_ULTRA) != 0) {
ultra:
mvi SINDEX, ULTRA_ENB+1;
test SAVED_TCL, 0x80 jnz ultra_2; /* Target ID > 7 */
dec SINDEX;
ultra_2:
mov FUNCTION1,SAVED_TCL;
mov A,FUNCTION1;
test SINDIR, A jz ndx_dtr;
or SXFRCTL0, FAST20;
}
/*
* Initialize SCSIRATE with the appropriate value for this target.
* The SCSIRATE settings for each target are stored in an array
* based at TARG_SCSIRATE.
*/
ndx_dtr:
shr A,4,SAVED_TCL;
if ((p->features & AHC_TWIN) != 0) {
test SBLKCTL,SELBUSB jz ndx_dtr_2;
or SAVED_TCL, SELBUSB;
or A,0x08; /* Channel B entries add 8 */
ndx_dtr_2:
}
if ((p->features & AHC_ULTRA2) != 0) {
add SINDEX, TARG_OFFSET, A;
mov SCSIOFFSET, SINDIR;
}
add SINDEX,TARG_SCSIRATE,A;
mov SCSIRATE,SINDIR ret;
selection:
test SSTAT0,SELDO jnz select_out;
/*
* Reselection has been initiated by a target. Make a note that we've been
* reselected, but haven't seen an IDENTIFY message from the target yet.
*/
initiator_reselect:
mvi CLRSINT0, CLRSELDI;
/* XXX test for and handle ONE BIT condition */
and SAVED_TCL, SELID_MASK, SELID;
mvi CLRSINT1,CLRBUSFREE;
or SIMODE1, ENBUSFREE; /*
* We aren't expecting a
* bus free, so interrupt
* the kernel driver if it
* happens.
*/
mvi SPIOEN call initialize_channel;
mvi MSG_OUT, MSG_NOOP; /* No message to send */
jmp ITloop;
/*
* After the selection, remove this SCB from the "waiting SCB"
* list. This is achieved by simply moving our "next" pointer into
* WAITING_SCBH. Our next pointer will be set to null the next time this
* SCB is used, so don't bother with it now.
*/
select_out:
/* Turn off the selection hardware */
mvi SCSISEQ, ENRSELI|ENAUTOATNP; /*
* ATN on parity errors
* for "in" phases
*/
mvi CLRSINT0, CLRSELDO;
mov SCBPTR, WAITING_SCBH;
mov WAITING_SCBH,SCB_NEXT;
mov SAVED_TCL, SCB_TCL;
mvi CLRSINT1,CLRBUSFREE;
or SIMODE1, ENBUSFREE; /*
* We aren't expecting a
* bus free, so interrupt
* the kernel driver if it
* happens.
*/
mvi SPIOEN call initialize_channel;
/*
* As soon as we get a successful selection, the target should go
* into the message out phase since we have ATN asserted.
*/
mvi MSG_OUT, MSG_IDENTIFYFLAG;
or SEQ_FLAGS, IDENTIFY_SEEN;
/*
* Main loop for information transfer phases. Wait for the target
* to assert REQ before checking MSG, C/D and I/O for the bus phase.
*/
ITloop:
call phase_lock;
mov A, LASTPHASE;
test A, ~P_DATAIN jz p_data;
cmp A,P_COMMAND je p_command;
cmp A,P_MESGOUT je p_mesgout;
cmp A,P_STATUS je p_status;
cmp A,P_MESGIN je p_mesgin;
mvi INTSTAT,BAD_PHASE; /* unknown phase - signal driver */
jmp ITloop; /* Try reading the bus again. */
await_busfree:
and SIMODE1, ~ENBUSFREE;
call clear_target_state;
mov NONE, SCSIDATL; /* Ack the last byte */
and SXFRCTL0, ~SPIOEN;
test SSTAT1,REQINIT|BUSFREE jz .;
test SSTAT1, BUSFREE jnz poll_for_work;
mvi INTSTAT, BAD_PHASE;
clear_target_state:
/*
* We assume that the kernel driver may reset us
* at any time, even in the middle of a DMA, so
* clear DFCNTRL too.
*/
clr DFCNTRL;
/*
* We don't know the target we will connect to,
* so default to narrow transfers to avoid
* parity problems.
*/
if ((p->features & AHC_ULTRA2) != 0) {
bmov SCSIRATE, ALLZEROS, 2;
} else {
clr SCSIRATE;
and SXFRCTL0, ~(FAST20);
}
mvi LASTPHASE, P_BUSFREE;
/* clear target specific flags */
clr SEQ_FLAGS ret;
data_phase_reinit:
/*
* If we re-enter the data phase after going through another phase, the
* STCNT may have been cleared, so restore it from the residual field.
* On Ultra2, we have to put it into the HCNT field because we have to
* drop the data down into the shadow layer via the preload ability.
*/
if ((p->features & AHC_ULTRA2) != 0) {
bmov HADDR, SHADDR, 4;
bmov HCNT, SCB_RESID_DCNT, 3;
}
if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
bmov STCNT, SCB_RESID_DCNT, 3;
}
if ((p->features & AHC_CMD_CHAN) == 0) {
mvi DINDEX, STCNT;
mvi SCB_RESID_DCNT call bcopy_3;
}
jmp data_phase_loop;
p_data:
if ((p->features & AHC_ULTRA2) != 0) {
mvi DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
} else {
mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
}
test LASTPHASE, IOI jnz . + 2;
or DMAPARAMS, DIRECTION;
call assert; /*
* Ensure entering a data
* phase is okay - seen identify, etc.
*/
if ((p->features & AHC_CMD_CHAN) != 0) {
mvi CCSGADDR, CCSGADDR_MAX;
}
test SEQ_FLAGS, DPHASE jnz data_phase_reinit;
or SEQ_FLAGS, DPHASE; /* we've seen a data phase */
/*
* Initialize the DMA address and counter from the SCB.
* Also set SG_COUNT and SG_NEXT in memory since we cannot
* modify the values in the SCB itself until we see a
* save data pointers message.
*/
if ((p->features & AHC_CMD_CHAN) != 0) {
bmov HADDR, SCB_DATAPTR, 7;
bmov SG_COUNT, SCB_SGCOUNT, 5;
if ((p->features & AHC_ULTRA2) == 0) {
bmov STCNT, HCNT, 3;
}
} else {
mvi DINDEX, HADDR;
mvi SCB_DATAPTR call bcopy_7;
call set_stcnt_from_hcnt;
mvi DINDEX, SG_COUNT;
mvi SCB_SGCOUNT call bcopy_5;
}
data_phase_loop:
/* Guard against overruns */
test SG_COUNT, 0xff jnz data_phase_inbounds;
/*
* Turn on 'Bit Bucket' mode, set the transfer count to
* 16meg and let the target run until it changes phase.
* When the transfer completes, notify the host that we
* had an overrun.
*/
or SXFRCTL1,BITBUCKET;
and DMAPARAMS, ~(HDMAEN|SDMAEN);
if ((p->features & AHC_ULTRA2) != 0) {
bmov HCNT, ALLONES, 3;
}
if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
bmov STCNT, ALLONES, 3;
}
if ((p->features & AHC_CMD_CHAN) == 0) {
mvi STCNT[0], 0xFF;
mvi STCNT[1], 0xFF;
mvi STCNT[2], 0xFF;
}
data_phase_inbounds:
/* If we are the last SG block, tell the hardware. */
if ((p->features & AHC_ULTRA2) != 0) {
shl A, 2, SG_COUNT;
cmp SG_COUNT,0x01 jne data_phase_wideodd;
or A, LAST_SEG;
} else {
cmp SG_COUNT,0x01 jne data_phase_wideodd;
and DMAPARAMS, ~WIDEODD;
}
data_phase_wideodd:
if ((p->features & AHC_ULTRA2) != 0) {
mov SG_CACHEPTR, A;
mov DFCNTRL, DMAPARAMS; /* start the operation */
test SXFRCTL1, BITBUCKET jnz data_phase_overrun;
u2_preload_wait:
test SSTAT1, PHASEMIS jnz u2_phasemis;
test DFSTATUS, PRELOAD_AVAIL jz u2_preload_wait;
} else {
mov DMAPARAMS call dma;
data_phase_dma_done:
/* Go tell the host about any overruns */
test SXFRCTL1,BITBUCKET jnz data_phase_overrun;
/* Exit if we had an underrun. dma clears SINDEX in this case. */
test SINDEX,0xff jz data_phase_finish;
}
/*
* Advance the scatter-gather pointers
*/
sg_advance:
if ((p->features & AHC_ULTRA2) != 0) {
cmp SG_COUNT, 0x01 je u2_data_phase_finish;
} else {
dec SG_COUNT;
test SG_COUNT, 0xff jz data_phase_finish;
}
if ((p->features & AHC_CMD_CHAN) != 0) {
/*
* Do we have any prefetch left???
*/
cmp CCSGADDR, CCSGADDR_MAX jne prefetch_avail;
/*
* Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.
*/
add A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT;
mvi A, CCSGADDR_MAX;
jc . + 2;
shl A, 3, SG_COUNT;
mov CCHCNT, A;
bmov CCHADDR, SG_NEXT, 4;
mvi CCSGCTL, CCSGEN|CCSGRESET;
test CCSGCTL, CCSGDONE jz .;
and CCSGCTL, ~CCSGEN;
test CCSGCTL, CCSGEN jnz .;
mvi CCSGCTL, CCSGRESET;
prefetch_avail:
bmov HADDR, CCSGRAM, 8;
if ((p->features & AHC_ULTRA2) == 0) {
bmov STCNT, HCNT, 3;
} else {
dec SG_COUNT;
}
} else {
mvi DINDEX, HADDR;
mvi SG_NEXT call bcopy_4;
mvi HCNT[0],SG_SIZEOF;
clr HCNT[1];
clr HCNT[2];
or DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
call dma_finish;
/*
* Copy data from FIFO into SCB data pointer and data count.
* This assumes that the SG segments are of the form:
* struct ahc_dma_seg {
* u_int32_t addr; four bytes, little-endian order
* u_int32_t len; four bytes, little endian order
* };
*/
mvi DINDEX, HADDR;
call dfdat_in_7;
call set_stcnt_from_hcnt;
}
/* Advance the SG pointer */
clr A; /* add sizeof(struct scatter) */
add SG_NEXT[0],SG_SIZEOF;
adc SG_NEXT[1],A;
if ((p->features & AHC_ULTRA2) != 0) {
jmp data_phase_loop;
} else {
test SSTAT1, REQINIT jz .;
test SSTAT1,PHASEMIS jz data_phase_loop;
}
/*
* We've loaded all of our segments into the preload layer. Now, we simply
* have to wait for it to finish or for us to get a phasemis. And, since
* we'll get a phasemis if we do finish, all we really need to do is wait
* for a phasemis then check if we did actually complete all the segments.
*/
if ((p->features & AHC_ULTRA2) != 0) {
u2_data_phase_finish:
test SSTAT1, PHASEMIS jnz u2_phasemis;
test SG_CACHEPTR, LAST_SEG_DONE jz u2_data_phase_finish;
clr SG_COUNT;
test SSTAT1, REQINIT jz .;
test SSTAT1, PHASEMIS jz data_phase_loop;
u2_phasemis:
call ultra2_dmafinish;
test SG_CACHEPTR, LAST_SEG_DONE jnz data_phase_finish;
test SSTAT2, SHVALID jnz u2_fixup_residual;
mvi INTSTAT, SEQ_SG_FIXUP;
jmp data_phase_finish;
u2_fixup_residual:
shr ARG_1, 2, SG_CACHEPTR;
u2_phasemis_loop:
and A, 0x3f, SG_COUNT;
cmp ARG_1, A je data_phase_finish;
/*
* Subtract SG_SIZEOF from the SG_NEXT pointer and add 1 to the SG_COUNT
*/
clr A;
add SG_NEXT[0], -SG_SIZEOF;
adc SG_NEXT[1], 0xff;
inc SG_COUNT;
jmp u2_phasemis_loop;
}
data_phase_finish:
/*
* After a DMA finishes, save the SG and STCNT residuals back into the SCB
* We use STCNT instead of HCNT, since it's a reflection of how many bytes
* were transferred on the SCSI (as opposed to the host) bus.
*/
if ((p->features & AHC_CMD_CHAN) != 0) {
bmov SCB_RESID_DCNT, STCNT, 3;
mov SCB_RESID_SGCNT, SG_COUNT;
if ((p->features & AHC_ULTRA2) != 0) {
or SXFRCTL0, CLRSTCNT|CLRCHN;
}
} else {
mov SCB_RESID_DCNT[0],STCNT[0];
mov SCB_RESID_DCNT[1],STCNT[1];
mov SCB_RESID_DCNT[2],STCNT[2];
mov SCB_RESID_SGCNT, SG_COUNT;
}
jmp ITloop;
data_phase_overrun:
/*
* Turn off BITBUCKET mode and notify the host
*/
if ((p->features & AHC_ULTRA2) != 0) {
/*
* Wait for the target to quit transferring data on the SCSI bus
*/
test SSTAT1, PHASEMIS jz .;
call ultra2_dmafinish;
}
and SXFRCTL1, ~BITBUCKET;
mvi INTSTAT,DATA_OVERRUN;
jmp ITloop;
/*
* Actually turn off the DMA hardware, save our current position into the
* proper residual variables, wait for the next REQ signal, then jump to
* the ITloop. Jumping to the ITloop ensures that if we happen to get
* brought into the data phase again (or are still in it after our last
* segment) that we will properly signal an overrun to the kernel.
*/
if ((p->features & AHC_ULTRA2) != 0) {
ultra2_dmafinish:
test DFCNTRL, DIRECTION jnz ultra2_dmahalt;
and DFCNTRL, ~SCSIEN;
test DFCNTRL, SCSIEN jnz .;
if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) {
or DFCNTRL, FIFOFLUSH;
}
ultra2_dmafifoflush:
if ((p->bugs & AHC_BUG_AUTOFLUSH) != 0) {
/*
* hardware bug alert! This needless set of jumps
* works around a glitch in the silicon. When the
* PCI DMA fifo goes empty, but there is still SCSI
* data to be flushed into the PCI DMA fifo (and from
* there on into main memory), the FIFOEMP bit will
* come on between the time when the PCI DMA buffer
* went empty and the next bit of data is copied from
* the SCSI fifo into the PCI fifo. It should only
* come on when both FIFOs (meaning the entire FIFO
* chain) are empty. Since it can take up to 4 cycles
* for new data to be copied from the SCSI fifo into
* the PCI fifo, testing for FIFOEMP status for 4
* extra times gives the needed time for any
* remaining SCSI fifo data to be put in the PCI fifo
* before we declare it *truly* empty.
*/
test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
}
test DFSTATUS, FIFOEMP jz ultra2_dmafifoflush;
test DFSTATUS, MREQPEND jnz .;
ultra2_dmahalt:
and DFCNTRL, ~(HDMAEN|SCSIEN);
test DFCNTRL, (HDMAEN|SCSIEN) jnz .;
ret;
}
/*
* Command phase. Set up the DMA registers and let 'er rip.
*/
p_command:
call assert;
/*
* Load HADDR and HCNT.
*/
if ((p->features & AHC_CMD_CHAN) != 0) {
bmov HADDR, SCB_CMDPTR, 5;
bmov HCNT[1], ALLZEROS, 2;
if ((p->features & AHC_ULTRA2) == 0) {
bmov STCNT, HCNT, 3;
}
} else {
mvi DINDEX, HADDR;
mvi SCB_CMDPTR call bcopy_5;
clr HCNT[1];
clr HCNT[2];
call set_stcnt_from_hcnt;
}
if ((p->features & AHC_ULTRA2) == 0) {
mvi (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET) call dma;
} else {
mvi DFCNTRL, (PRELOADEN|SCSIEN|HDMAEN|DIRECTION);
test SSTAT0, SDONE jnz .;
p_command_dma_loop:
test SSTAT0, SDONE jnz p_command_ultra2_dma_done;
test SSTAT1,PHASEMIS jz p_command_dma_loop; /* ie. underrun */
p_command_ultra2_dma_done:
test SCSISIGI, REQI jz p_command_ultra2_shutdown;
test SSTAT1, (PHASEMIS|REQINIT) jz p_command_ultra2_dma_done;
p_command_ultra2_shutdown:
and DFCNTRL, ~(HDMAEN|SCSIEN);
test DFCNTRL, (HDMAEN|SCSIEN) jnz .;
or SXFRCTL0, CLRSTCNT|CLRCHN;
}
jmp ITloop;
/*
* Status phase. Wait for the data byte to appear, then read it
* and store it into the SCB.
*/
p_status:
call assert;
mov SCB_TARGET_STATUS, SCSIDATL;
jmp ITloop;
/*
* Message out phase. If MSG_OUT is 0x80, build I full indentify message
* sequence and send it to the target. In addition, if the MK_MESSAGE bit
* is set in the SCB_CONTROL byte, interrupt the host and allow it to send
* it's own message.
*
* If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.
* This is done to allow the host to send messages outside of an identify
* sequence while protecting the seqencer from testing the MK_MESSAGE bit
* on an SCB that might not be for the current nexus. (For example, a
* BDR message in response to a bad reselection would leave us pointed to
* an SCB that doesn't have anything to do with the current target).
* Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
* bus device reset).
*
* When there are no messages to send, MSG_OUT should be set to MSG_NOOP,
* in case the target decides to put us in this phase for some strange
* reason.
*/
p_mesgout_retry:
or SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */
p_mesgout:
mov SINDEX, MSG_OUT;
cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
p_mesgout_identify:
if ((p->features & AHC_WIDE) != 0) {
and SINDEX,0xf,SCB_TCL; /* lun */
} else {
and SINDEX,0x7,SCB_TCL; /* lun */
}
and A,DISCENB,SCB_CONTROL; /* mask off disconnect privilege */
or SINDEX,A; /* or in disconnect privilege */
or SINDEX,MSG_IDENTIFYFLAG;
p_mesgout_mk_message:
test SCB_CONTROL,MK_MESSAGE jz p_mesgout_tag;
mov SCSIDATL, SINDEX; /* Send the last byte */
jmp p_mesgout_from_host + 1;/* Skip HOST_MSG test */
/*
* Send a tag message if TAG_ENB is set in the SCB control block.
* Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
*/
p_mesgout_tag:
test SCB_CONTROL,TAG_ENB jz p_mesgout_onebyte;
mov SCSIDATL, SINDEX; /* Send the identify message */
call phase_lock;
cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;
and SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;
call phase_lock;
cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;
mov SCB_TAG jmp p_mesgout_onebyte;
/*
* Interrupt the driver, and allow it to send a message
* if it asks.
*/
p_mesgout_from_host:
cmp SINDEX, HOST_MSG jne p_mesgout_onebyte;
mvi INTSTAT,AWAITING_MSG;
nop;
/*
* Did the host detect a phase change?
*/
cmp RETURN_1, MSGOUT_PHASEMIS je p_mesgout_done;
p_mesgout_onebyte:
mvi CLRSINT1, CLRATNO;
mov SCSIDATL, SINDEX;
/*
* If the next bus phase after ATN drops is a message out, it means
* that the target is requesting that the last message(s) be resent.
*/
call phase_lock;
cmp LASTPHASE, P_MESGOUT je p_mesgout_retry;
p_mesgout_done:
mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */
mov LAST_MSG, MSG_OUT;
cmp MSG_OUT, MSG_IDENTIFYFLAG jne . + 2;
and SCB_CONTROL, ~MK_MESSAGE;
mvi MSG_OUT, MSG_NOOP; /* No message left */
jmp ITloop;
/*
* Message in phase. Bytes are read using Automatic PIO mode.
*/
p_mesgin:
mvi ACCUM call inb_first; /* read the 1st message byte */
test A,MSG_IDENTIFYFLAG jnz mesgin_identify;
cmp A,MSG_DISCONNECT je mesgin_disconnect;
cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs;
cmp ALLZEROS,A je mesgin_complete;
cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs;
cmp A,MSG_EXTENDED je mesgin_extended;
cmp A,MSG_MESSAGE_REJECT je mesgin_reject;
cmp A,MSG_NOOP je mesgin_done;
cmp A,MSG_IGN_WIDE_RESIDUE je mesgin_wide_residue;
rej_mesgin:
/*
* We have no idea what this message in is, so we issue a message reject
* and hope for the best. In any case, rejection should be a rare
* occurrence - signal the driver when it happens.
*/
mvi INTSTAT,SEND_REJECT; /* let driver know */
mvi MSG_MESSAGE_REJECT call mk_mesg;
mesgin_done:
mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
jmp ITloop;
mesgin_complete:
/*
* We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO,
* and trigger a completion interrupt. Before doing so, check to see if there
* is a residual or the status byte is something other than STATUS_GOOD (0).
* In either of these conditions, we upload the SCB back to the host so it can
* process this information. In the case of a non zero status byte, we
* additionally interrupt the kernel driver synchronously, allowing it to
* decide if sense should be retrieved. If the kernel driver wishes to request
* sense, it will fill the kernel SCB with a request sense command and set
* RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE we redownload
* the SCB, and process it as the next command by adding it to the waiting list.
* If the kernel driver does not wish to request sense, it need only clear
* RETURN_1, and the command is allowed to complete normally. We don't bother
* to post to the QOUTFIFO in the error cases since it would require extra
* work in the kernel driver to ensure that the entry was removed before the
* command complete code tried processing it.
*/
/*
* First check for residuals
*/
test SCB_RESID_SGCNT,0xff jnz upload_scb;
test SCB_TARGET_STATUS,0xff jz complete; /* Good Status? */
upload_scb:
mvi DMAPARAMS, FIFORESET;
mov SCB_TAG call dma_scb;
check_status:
test SCB_TARGET_STATUS,0xff jz complete; /* Just a residual? */
mvi INTSTAT,BAD_STATUS; /* let driver know */
nop;
cmp RETURN_1, SEND_SENSE jne complete;
/* This SCB becomes the next to execute as it will retrieve sense */
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
mov SCB_TAG call dma_scb;
add_to_waiting_list:
mov SCB_NEXT,WAITING_SCBH;
mov WAITING_SCBH, SCBPTR;
/*
* Prepare our selection hardware before the busfree so we have a
* high probability of winning arbitration.
*/
call start_selection;
jmp await_busfree;
complete:
/* If we are untagged, clear our address up in host ram */
test SCB_CONTROL, TAG_ENB jnz complete_post;
mov A, SAVED_TCL;
mvi UNTAGGEDSCB_OFFSET call post_byte_setup;
mvi SCB_LIST_NULL call post_byte;
complete_post:
/* Post the SCB and issue an interrupt */
if ((p->features & AHC_QUEUE_REGS) != 0) {
mov A, SDSCB_QOFF;
} else {
mov A, QOUTPOS;
}
mvi QOUTFIFO_OFFSET call post_byte_setup;
mov SCB_TAG call post_byte;
if ((p->features & AHC_QUEUE_REGS) == 0) {
inc QOUTPOS;
}
mvi INTSTAT,CMDCMPLT;
add_to_free_list:
call add_scb_to_free_list;
jmp await_busfree;
/*
* Is it an extended message? Copy the message to our message buffer and
* notify the host. The host will tell us whether to reject this message,
* respond to it with the message that the host placed in our message buffer,
* or simply to do nothing.
*/
mesgin_extended:
mvi INTSTAT,EXTENDED_MSG; /* let driver know */
jmp ITloop;
/*
* Is it a disconnect message? Set a flag in the SCB to remind us
* and await the bus going free.
*/
mesgin_disconnect:
or SCB_CONTROL,DISCONNECTED;
call add_scb_to_disc_list;
jmp await_busfree;
/*
* Save data pointers message:
* Copying RAM values back to SCB, for Save Data Pointers message, but
* only if we've actually been into a data phase to change them. This
* protects against bogus data in scratch ram and the residual counts
* since they are only initialized when we go into data_in or data_out.
*/
mesgin_sdptrs:
test SEQ_FLAGS, DPHASE jz mesgin_done;
/*
* The SCB SGPTR becomes the next one we'll download,
* and the SCB DATAPTR becomes the current SHADDR.
* Use the residual number since STCNT is corrupted by
* any message transfer.
*/
if ((p->features & AHC_CMD_CHAN) != 0) {
bmov SCB_SGCOUNT, SG_COUNT, 5;
bmov SCB_DATAPTR, SHADDR, 4;
bmov SCB_DATACNT, SCB_RESID_DCNT, 3;
} else {
mvi DINDEX, SCB_SGCOUNT;
mvi SG_COUNT call bcopy_5;
mvi DINDEX, SCB_DATAPTR;
mvi SHADDR call bcopy_4;
mvi SCB_RESID_DCNT call bcopy_3;
}
jmp mesgin_done;
/*
* Restore pointers message? Data pointers are recopied from the
* SCB anytime we enter a data phase for the first time, so all
* we need to do is clear the DPHASE flag and let the data phase
* code do the rest.
*/
mesgin_rdptrs:
and SEQ_FLAGS, ~DPHASE; /*
* We'll reload them
* the next time through
* the dataphase.
*/
jmp mesgin_done;
/*
* Identify message? For a reconnecting target, this tells us the lun
* that the reconnection is for - find the correct SCB and switch to it,
* clearing the "disconnected" bit so we don't "find" it by accident later.
*/
mesgin_identify:
if ((p->features & AHC_WIDE) != 0) {
and A,0x0f; /* lun in lower four bits */
} else {
and A,0x07; /* lun in lower three bits */
}
or SAVED_TCL,A; /* SAVED_TCL should be complete now */
mvi ARG_2, SCB_LIST_NULL; /* SCBID of prev SCB in disc List */
call get_untagged_SCBID;
cmp ARG_1, SCB_LIST_NULL je snoop_tag;
if ((p->flags & AHC_PAGESCBS) != 0) {
test SEQ_FLAGS, SCBPTR_VALID jz use_retrieveSCB;
}
/*
* If the SCB was found in the disconnected list (as is
* always the case in non-paging scenarios), SCBPTR is already
* set to the correct SCB. So, simply setup the SCB and get
* on with things.
*/
mov SCBPTR call rem_scb_from_disc_list;
jmp setup_SCB;
/*
* Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
* If we get one, we use the tag returned to find the proper
* SCB. With SCB paging, this requires using search for both tagged
* and non-tagged transactions since the SCB may exist in any slot.
* If we're not using SCB paging, we can use the tag as the direct
* index to the SCB.
*/
snoop_tag:
mov NONE,SCSIDATL; /* ACK Identify MSG */
snoop_tag_loop:
call phase_lock;
cmp LASTPHASE, P_MESGIN jne not_found;
cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;
get_tag:
mvi ARG_1 call inb_next; /* tag value */
use_retrieveSCB:
call retrieveSCB;
setup_SCB:
mov A, SAVED_TCL;
cmp SCB_TCL, A jne not_found_cleanup_scb;
test SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
and SCB_CONTROL,~DISCONNECTED;
or SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */
/* See if the host wants to send a message upon reconnection */
test SCB_CONTROL, MK_MESSAGE jz mesgin_done;
and SCB_CONTROL, ~MK_MESSAGE;
mvi HOST_MSG call mk_mesg;
jmp mesgin_done;
not_found_cleanup_scb:
test SCB_CONTROL, DISCONNECTED jz . + 3;
call add_scb_to_disc_list;
jmp not_found;
call add_scb_to_free_list;
not_found:
mvi INTSTAT, NO_MATCH;
mvi MSG_BUS_DEV_RESET call mk_mesg;
jmp mesgin_done;
/*
* Message reject? Let the kernel driver handle this. If we have an
* outstanding WDTR or SDTR negotiation, assume that it's a response from
* the target selecting 8bit or asynchronous transfer, otherwise just ignore
* it since we have no clue what it pertains to.
*/
mesgin_reject:
mvi INTSTAT, REJECT_MSG;
jmp mesgin_done;
/*
* Wide Residue. We handle the simple cases, but pass of the one hard case
* to the kernel (when the residue byte happened to cause us to advance our
* sg element array, so we know have to back that advance out).
*/
mesgin_wide_residue:
mvi ARG_1 call inb_next; /* ACK the wide_residue and get */
/* the size byte */
/*
* In order for this to be reliable, we have to do all sorts of horrible
* magic in terms of resetting the datafifo and reloading the shadow layer
* with the correct new values (so that a subsequent save data pointers
* message will do the right thing). We let the kernel do that work.
*/
mvi INTSTAT, WIDE_RESIDUE;
jmp mesgin_done;
/*
* [ ADD MORE MESSAGE HANDLING HERE ]
*/
/*
* Locking the driver out, build a one-byte message passed in SINDEX
* if there is no active message already. SINDEX is returned intact.
*/
mk_mesg:
or SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */
mov MSG_OUT,SINDEX ret;
/*
* Functions to read data in Automatic PIO mode.
*
* According to Adaptec's documentation, an ACK is not sent on input from
* the target until SCSIDATL is read from. So we wait until SCSIDATL is
* latched (the usual way), then read the data byte directly off the bus
* using SCSIBUSL. When we have pulled the ATN line, or we just want to
* acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI
* spec guarantees that the target will hold the data byte on the bus until
* we send our ACK.
*
* The assumption here is that these are called in a particular sequence,
* and that REQ is already set when inb_first is called. inb_{first,next}
* use the same calling convention as inb.
*/
inb_next:
mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
inb_next_wait:
/*
* If there is a parity error, wait for the kernel to
* see the interrupt and prepare our message response
* before continuing.
*/
test SSTAT1, REQINIT jz inb_next_wait;
test SSTAT1, SCSIPERR jnz .;
and LASTPHASE, PHASE_MASK, SCSISIGI;
cmp LASTPHASE, P_MESGIN jne mesgin_phasemis;
inb_first:
mov DINDEX,SINDEX;
mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/
inb_last:
mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/
mesgin_phasemis:
/*
* We expected to receive another byte, but the target changed phase
*/
mvi INTSTAT, MSGIN_PHASEMIS;
jmp ITloop;
/*
* DMA data transfer. HADDR and HCNT must be loaded first, and
* SINDEX should contain the value to load DFCNTRL with - 0x3d for
* host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared
* during initialization.
*/
if ((p->features & AHC_ULTRA2) == 0) {
dma:
mov DFCNTRL,SINDEX;
dma_loop:
test SSTAT0,DMADONE jnz dma_dmadone;
test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */
dma_phasemis:
test SSTAT0,SDONE jnz dma_checkfifo;
mov SINDEX,ALLZEROS; /* Notify caller of phasemiss */
/*
* We will be "done" DMAing when the transfer count goes to zero, or
* the target changes the phase (in light of this, it makes sense that
* the DMA circuitry doesn't ACK when PHASEMIS is active). If we are
* doing a SCSI->Host transfer, the data FIFO should be flushed auto-
* magically on STCNT=0 or a phase change, so just wait for FIFO empty
* status.
*/
dma_checkfifo:
test DFCNTRL,DIRECTION jnz dma_fifoempty;
dma_fifoflush:
test DFSTATUS,FIFOEMP jz dma_fifoflush;
dma_fifoempty:
/* Don't clobber an inprogress host data transfer */
test DFSTATUS, MREQPEND jnz dma_fifoempty;
/*
* Now shut the DMA enables off and make sure that the DMA enables are
* actually off first lest we get an ILLSADDR.
*/
dma_dmadone:
cmp LASTPHASE, P_COMMAND je dma_await_nreq;
test SCSIRATE, 0x0f jnz dma_shutdown;
dma_await_nreq:
test SCSISIGI, REQI jz dma_shutdown;
test SSTAT1, (PHASEMIS|REQINIT) jz dma_await_nreq;
dma_shutdown:
and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
dma_halt:
/*
* Some revisions of the aic7880 have a problem where, if the
* data fifo is full, but the PCI input latch is not empty,
* HDMAEN cannot be cleared. The fix used here is to attempt
* to drain the data fifo until there is space for the input
* latch to drain and HDMAEN de-asserts.
*/
if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) {
mov NONE, DFDAT;
}
test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
}
return:
ret;
/*
* Assert that if we've been reselected, then we've seen an IDENTIFY
* message.
*/
assert:
test SEQ_FLAGS,IDENTIFY_SEEN jnz return; /* seen IDENTIFY? */
mvi INTSTAT,NO_IDENT ret; /* no - tell the kernel */
/*
* Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL)
* or by the SCBID ARG_1. The search begins at the SCB index passed in
* via SINDEX which is an SCB that must be on the disconnected list. If
* the SCB cannot be found, SINDEX will be SCB_LIST_NULL, otherwise, SCBPTR
* is set to the proper SCB.
*/
findSCB:
mov SCBPTR,SINDEX; /* Initialize SCBPTR */
cmp ARG_1, SCB_LIST_NULL jne findSCB_by_SCBID;
mov A, SAVED_TCL;
mvi SCB_TCL jmp findSCB_loop; /* &SCB_TCL -> SINDEX */
findSCB_by_SCBID:
mov A, ARG_1; /* Tag passed in ARG_1 */
mvi SCB_TAG jmp findSCB_loop; /* &SCB_TAG -> SINDEX */
findSCB_next:
mov ARG_2, SCBPTR;
cmp SCB_NEXT, SCB_LIST_NULL je notFound;
mov SCBPTR,SCB_NEXT;
dec SINDEX; /* Last comparison moved us too far */
findSCB_loop:
cmp SINDIR, A jne findSCB_next;
mov SINDEX, SCBPTR ret;
notFound:
mvi SINDEX, SCB_LIST_NULL ret;
/*
* Retrieve an SCB by SCBID first searching the disconnected list falling
* back to DMA'ing the SCB down from the host. This routine assumes that
* ARG_1 is the SCBID of interest and that SINDEX is the position in the
* disconnected list to start the search from. If SINDEX is SCB_LIST_NULL,
* we go directly to the host for the SCB.
*/
retrieveSCB:
test SEQ_FLAGS, SCBPTR_VALID jz retrieve_from_host;
mov SCBPTR call findSCB; /* Continue the search */
cmp SINDEX, SCB_LIST_NULL je retrieve_from_host;
/*
* This routine expects SINDEX to contain the index of the SCB to be
* removed, SCBPTR to be pointing to that SCB, and ARG_2 to be the
* SCBID of the SCB just previous to this one in the list or SCB_LIST_NULL
* if it is at the head.
*/
rem_scb_from_disc_list:
/* Remove this SCB from the disconnection list */
cmp ARG_2, SCB_LIST_NULL je rHead;
mov DINDEX, SCB_NEXT;
mov SCBPTR, ARG_2;
mov SCB_NEXT, DINDEX;
mov SCBPTR, SINDEX ret;
rHead:
mov DISCONNECTED_SCBH,SCB_NEXT ret;
retrieve_from_host:
/*
* We didn't find it. Pull an SCB and DMA down the one we want.
* We should never get here in the non-paging case.
*/
mov ALLZEROS call get_free_or_disc_scb;
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
/* Jump instead of call as we want to return anyway */
mov ARG_1 jmp dma_scb;
/*
* Determine whether a target is using tagged or non-tagged transactions
* by first looking for a matching transaction based on the TCL and if
* that fails, looking up this device in the host's untagged SCB array.
* The TCL to search for is assumed to be in SAVED_TCL. The value is
* returned in ARG_1 (SCB_LIST_NULL for tagged, SCBID for non-tagged).
* The SCBPTR_VALID bit is set in SEQ_FLAGS if we found the information
* in an SCB instead of having to go to the host.
*/
get_untagged_SCBID:
cmp DISCONNECTED_SCBH, SCB_LIST_NULL je get_SCBID_from_host;
mvi ARG_1, SCB_LIST_NULL;
mov DISCONNECTED_SCBH call findSCB;
cmp SINDEX, SCB_LIST_NULL je get_SCBID_from_host;
or SEQ_FLAGS, SCBPTR_VALID;/* Was in disconnected list */
test SCB_CONTROL, TAG_ENB jnz . + 2;
mov ARG_1, SCB_TAG ret;
mvi ARG_1, SCB_LIST_NULL ret;
/*
* Fetch a byte from host memory given an index of (A + (256 * SINDEX))
* and a base address of SCBID_ADDR. The byte is returned in RETURN_2.
*/
fetch_byte:
mov ARG_2, SINDEX;
if ((p->features & AHC_CMD_CHAN) != 0) {
mvi DINDEX, CCHADDR;
mvi SCBID_ADDR call set_1byte_addr;
mvi CCHCNT, 1;
mvi CCSGCTL, CCSGEN|CCSGRESET;
test CCSGCTL, CCSGDONE jz .;
mvi CCSGCTL, CCSGRESET;
bmov RETURN_2, CCSGRAM, 1 ret;
} else {
mvi DINDEX, HADDR;
mvi SCBID_ADDR call set_1byte_addr;
mvi HCNT[0], 1;
clr HCNT[1];
clr HCNT[2];
mvi DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
call dma_finish;
mov RETURN_2, DFDAT ret;
}
/*
* Prepare the hardware to post a byte to host memory given an
* index of (A + (256 * SINDEX)) and a base address of SCBID_ADDR.
*/
post_byte_setup:
mov ARG_2, SINDEX;
if ((p->features & AHC_CMD_CHAN) != 0) {
mvi DINDEX, CCHADDR;
mvi SCBID_ADDR call set_1byte_addr;
mvi CCHCNT, 1;
mvi CCSCBCTL, CCSCBRESET ret;
} else {
mvi DINDEX, HADDR;
mvi SCBID_ADDR call set_1byte_addr;
mvi HCNT[0], 1;
clr HCNT[1];
clr HCNT[2];
mvi DFCNTRL, FIFORESET ret;
}
post_byte:
if ((p->features & AHC_CMD_CHAN) != 0) {
bmov CCSCBRAM, SINDEX, 1;
or CCSCBCTL, CCSCBEN|CCSCBRESET;
test CCSCBCTL, CCSCBDONE jz .;
clr CCSCBCTL ret;
} else {
mov DFDAT, SINDEX;
or DFCNTRL, HDMAEN|FIFOFLUSH;
jmp dma_finish;
}
get_SCBID_from_host:
mov A, SAVED_TCL;
mvi UNTAGGEDSCB_OFFSET call fetch_byte;
mov RETURN_1, RETURN_2 ret;
phase_lock:
test SSTAT1, REQINIT jz phase_lock;
test SSTAT1, SCSIPERR jnz phase_lock;
and SCSISIGO, PHASE_MASK, SCSISIGI;
and LASTPHASE, PHASE_MASK, SCSISIGI ret;
if ((p->features & AHC_CMD_CHAN) == 0) {
set_stcnt_from_hcnt:
mov STCNT[0], HCNT[0];
mov STCNT[1], HCNT[1];
mov STCNT[2], HCNT[2] ret;
bcopy_7:
mov DINDIR, SINDIR;
mov DINDIR, SINDIR;
bcopy_5:
mov DINDIR, SINDIR;
bcopy_4:
mov DINDIR, SINDIR;
bcopy_3:
mov DINDIR, SINDIR;
mov DINDIR, SINDIR;
mov DINDIR, SINDIR ret;
}
/*
* Setup addr assuming that A is an index into
* an array of 32byte objects, SINDEX contains
* the base address of that array, and DINDEX
* contains the base address of the location
* to store the indexed address.
*/
set_32byte_addr:
shr ARG_2, 3, A;
shl A, 5;
/*
* Setup addr assuming that A + (ARG_1 * 256) is an
* index into an array of 1byte objects, SINDEX contains
* the base address of that array, and DINDEX contains
* the base address of the location to store the computed
* address.
*/
set_1byte_addr:
add DINDIR, A, SINDIR;
mov A, ARG_2;
adc DINDIR, A, SINDIR;
clr A;
adc DINDIR, A, SINDIR;
adc DINDIR, A, SINDIR ret;
/*
* Either post or fetch and SCB from host memory based on the
* DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.
*/
dma_scb:
mov A, SINDEX;
if ((p->features & AHC_CMD_CHAN) != 0) {
mvi DINDEX, CCHADDR;
mvi HSCB_ADDR call set_32byte_addr;
mov CCSCBPTR, SCBPTR;
mvi CCHCNT, 32;
test DMAPARAMS, DIRECTION jz dma_scb_tohost;
mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;
cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
jmp dma_scb_finish;
dma_scb_tohost:
if ((p->features & AHC_ULTRA2) == 0) {
mvi CCSCBCTL, CCSCBRESET;
bmov CCSCBRAM, SCB_CONTROL, 32;
or CCSCBCTL, CCSCBEN|CCSCBRESET;
test CCSCBCTL, CCSCBDONE jz .;
}
if ((p->features & AHC_ULTRA2) != 0) {
if ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0) {
mvi CCSCBCTL, CCARREN|CCSCBRESET;
cmp CCSCBCTL, ARRDONE|CCARREN jne .;
mvi CCHCNT, 32;
mvi CCSCBCTL, CCSCBEN|CCSCBRESET;
cmp CCSCBCTL, CCSCBDONE|CCSCBEN jne .;
} else {
mvi CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
cmp CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
}
}
dma_scb_finish:
clr CCSCBCTL;
test CCSCBCTL, CCARREN|CCSCBEN jnz .;
ret;
}
if ((p->features & AHC_CMD_CHAN) == 0) {
mvi DINDEX, HADDR;
mvi HSCB_ADDR call set_32byte_addr;
mvi HCNT[0], 32;
clr HCNT[1];
clr HCNT[2];
mov DFCNTRL, DMAPARAMS;
test DMAPARAMS, DIRECTION jnz dma_scb_fromhost;
/* Fill it with the SCB data */
copy_scb_tofifo:
mvi SINDEX, SCB_CONTROL;
add A, 32, SINDEX;
copy_scb_tofifo_loop:
mov DFDAT,SINDIR;
mov DFDAT,SINDIR;
mov DFDAT,SINDIR;
mov DFDAT,SINDIR;
mov DFDAT,SINDIR;
mov DFDAT,SINDIR;
mov DFDAT,SINDIR;
mov DFDAT,SINDIR;
cmp SINDEX, A jne copy_scb_tofifo_loop;
or DFCNTRL, HDMAEN|FIFOFLUSH;
jmp dma_finish;
dma_scb_fromhost:
mvi DINDEX, SCB_CONTROL;
if ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0) {
/*
* Set the A to -24. It it hits 0, then we let
* our code fall through to dfdat_in_8 to complete
* the last of the copy.
*
* Also, things happen 8 bytes at a time in this
* case, so we may need to drain the fifo at most
* 3 times to keep things flowing
*/
mvi A, -24;
dma_scb_hang_fifo:
/* Wait for the first bit of data to hit the fifo */
test DFSTATUS, FIFOEMP jnz .;
dma_scb_hang_wait:
/* OK, now they've started to transfer into the fifo,
* so wait for them to stop trying to transfer any
* more data.
*/
test DFSTATUS, MREQPEND jnz .;
/*
* OK, they started, then they stopped, now see if they
* managed to complete the job before stopping. Try
* it multiple times to give the chip a few cycles to
* set the flag if it did complete.
*/
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
test DFSTATUS, HDONE jnz dma_scb_hang_dma_done;
/*
* Too bad, the chip didn't complete the DMA, but there
* aren't any more memory requests pending, so that
* means it stopped part way through and hung. That's
* our bug, so now we drain what data there is in the
* fifo in order to get things going again.
*/
dma_scb_hang_empty_fifo:
call dfdat_in_8;
add A, 8;
add SINDEX, A, HCNT;
/*
* If there are another 8 bytes of data waiting in the
* fifo, then the carry bit will be set as a result
* of the above add command (unless A is non-negative,
* in which case the carry bit won't be set).
*/
jc dma_scb_hang_empty_fifo;
/*
* We've emptied the fifo now, but we wouldn't have got
* here if the memory transfer hadn't stopped part way
* through, so go back up to the beginning of the
* loop and start over. When it succeeds in getting
* all the data down, HDONE will be set and we'll
* jump to the code just below here.
*/
jmp dma_scb_hang_fifo;
dma_scb_hang_dma_done:
and DFCNTRL, ~HDMAEN;
test DFCNTRL, HDMAEN jnz .;
call dfdat_in_8;
add A, 8;
cmp A, 8 jne . - 2;
ret;
} else {
call dma_finish;
call dfdat_in_8;
call dfdat_in_8;
call dfdat_in_8;
}
dfdat_in_8:
mov DINDIR,DFDAT;
dfdat_in_7:
mov DINDIR,DFDAT;
mov DINDIR,DFDAT;
mov DINDIR,DFDAT;
mov DINDIR,DFDAT;
mov DINDIR,DFDAT;
mov DINDIR,DFDAT;
mov DINDIR,DFDAT ret;
}
/*
* Wait for DMA from host memory to data FIFO to complete, then disable
* DMA and wait for it to acknowledge that it's off.
*/
if ((p->features & AHC_CMD_CHAN) == 0) {
dma_finish:
test DFSTATUS,HDONE jz dma_finish;
/* Turn off DMA */
and DFCNTRL, ~HDMAEN;
test DFCNTRL, HDMAEN jnz .;
ret;
}
add_scb_to_free_list:
if ((p->flags & AHC_PAGESCBS) != 0) {
mov SCB_NEXT, FREE_SCBH;
mov FREE_SCBH, SCBPTR;
}
mvi SCB_TAG, SCB_LIST_NULL ret;
if ((p->flags & AHC_PAGESCBS) != 0) {
get_free_or_disc_scb:
cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
return_error:
mvi SINDEX, SCB_LIST_NULL ret;
dequeue_disc_scb:
mov SCBPTR, DISCONNECTED_SCBH;
dma_up_scb:
mvi DMAPARAMS, FIFORESET;
mov SCB_TAG call dma_scb;
unlink_disc_scb:
mov DISCONNECTED_SCBH, SCB_NEXT ret;
dequeue_free_scb:
mov SCBPTR, FREE_SCBH;
mov FREE_SCBH, SCB_NEXT ret;
}
add_scb_to_disc_list:
/*
* Link this SCB into the DISCONNECTED list. This list holds the
* candidates for paging out an SCB if one is needed for a new command.
* Modifying the disconnected list is a critical(pause dissabled) section.
*/
mov SCB_NEXT, DISCONNECTED_SCBH;
mov DISCONNECTED_SCBH, SCBPTR ret;
/*+M*************************************************************************
* Adaptec AIC7xxx device driver proc support for Linux.
*
* Copyright (c) 1995, 1996 Dean W. Gehnert
*
* 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.
*
* ----------------------------------------------------------------
* o Modified from the EATA-DMA /proc support.
* o Additional support for device block statistics provided by
* Matthew Jacob.
* o Correction of overflow by Heinz Mauelshagen
* o Adittional corrections by Doug Ledford
*
* Dean W. Gehnert, deang@teleport.com, 05/01/96
*
* $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $
*-M*************************************************************************/
#define HDRB \
" 0 - 4K 4 - 16K 16 - 64K 64 - 256K 256K - 1M 1M+"
/*+F*************************************************************************
* Function:
* aic7xxx_show_info
*
* Description:
* Return information to handle /proc support for the driver.
*-F*************************************************************************/
int
aic7xxx_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
{
struct aic7xxx_host *p;
struct aic_dev_data *aic_dev;
struct scsi_device *sdptr;
unsigned char i;
unsigned char tindex;
for(p=first_aic7xxx; p && p->host != HBAptr; p=p->next)
;
if (!p)
{
seq_printf(m, "Can't find adapter for host number %d\n", HBAptr->host_no);
return 0;
}
p = (struct aic7xxx_host *) HBAptr->hostdata;
seq_printf(m, "Adaptec AIC7xxx driver version: ");
seq_printf(m, "%s/", AIC7XXX_C_VERSION);
seq_printf(m, "%s", AIC7XXX_H_VERSION);
seq_printf(m, "\n");
seq_printf(m, "Adapter Configuration:\n");
seq_printf(m, " SCSI Adapter: %s\n",
board_names[p->board_name_index]);
if (p->flags & AHC_TWIN)
seq_printf(m, " Twin Channel Controller ");
else
{
char *channel = "";
char *ultra = "";
char *wide = "Narrow ";
if (p->flags & AHC_MULTI_CHANNEL)
{
channel = " Channel A";
if (p->flags & (AHC_CHNLB|AHC_CHNLC))
channel = (p->flags & AHC_CHNLB) ? " Channel B" : " Channel C";
}
if (p->features & AHC_WIDE)
wide = "Wide ";
if (p->features & AHC_ULTRA3)
{
switch(p->chip & AHC_CHIPID_MASK)
{
case AHC_AIC7892:
case AHC_AIC7899:
ultra = "Ultra-160/m LVD/SE ";
break;
default:
ultra = "Ultra-3 LVD/SE ";
break;
}
}
else if (p->features & AHC_ULTRA2)
ultra = "Ultra-2 LVD/SE ";
else if (p->features & AHC_ULTRA)
ultra = "Ultra ";
seq_printf(m, " %s%sController%s ",
ultra, wide, channel);
}
switch(p->chip & ~AHC_CHIPID_MASK)
{
case AHC_VL:
seq_printf(m, "at VLB slot %d\n", p->pci_device_fn);
break;
case AHC_EISA:
seq_printf(m, "at EISA slot %d\n", p->pci_device_fn);
break;
default:
seq_printf(m, "at PCI %d/%d/%d\n", p->pci_bus,
PCI_SLOT(p->pci_device_fn), PCI_FUNC(p->pci_device_fn));
break;
}
if( !(p->maddr) )
{
seq_printf(m, " Programmed I/O Base: %lx\n", p->base);
}
else
{
seq_printf(m, " PCI MMAPed I/O Base: 0x%lx\n", p->mbase);
}
if( (p->chip & (AHC_VL | AHC_EISA)) )
{
seq_printf(m, " BIOS Memory Address: 0x%08x\n", p->bios_address);
}
seq_printf(m, " Adapter SEEPROM Config: %s\n",
(p->flags & AHC_SEEPROM_FOUND) ? "SEEPROM found and used." :
((p->flags & AHC_USEDEFAULTS) ? "SEEPROM not found, using defaults." :
"SEEPROM not found, using leftover BIOS values.") );
seq_printf(m, " Adaptec SCSI BIOS: %s\n",
(p->flags & AHC_BIOS_ENABLED) ? "Enabled" : "Disabled");
seq_printf(m, " IRQ: %d\n", HBAptr->irq);
seq_printf(m, " SCBs: Active %d, Max Active %d,\n",
p->activescbs, p->max_activescbs);
seq_printf(m, " Allocated %d, HW %d, "
"Page %d\n", p->scb_data->numscbs, p->scb_data->maxhscbs,
p->scb_data->maxscbs);
if (p->flags & AHC_EXTERNAL_SRAM)
seq_printf(m, " Using External SCB SRAM\n");
seq_printf(m, " Interrupts: %ld", p->isr_count);
if (p->chip & AHC_EISA)
{
seq_printf(m, " %s\n",
(p->pause & IRQMS) ? "(Level Sensitive)" : "(Edge Triggered)");
}
else
{
seq_printf(m, "\n");
}
seq_printf(m, " BIOS Control Word: 0x%04x\n",
p->bios_control);
seq_printf(m, " Adapter Control Word: 0x%04x\n",
p->adapter_control);
seq_printf(m, " Extended Translation: %sabled\n",
(p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis");
seq_printf(m, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
if (p->features & (AHC_ULTRA | AHC_ULTRA2))
{
seq_printf(m, " Ultra Enable Flags: 0x%04x\n", p->ultraenb);
}
seq_printf(m, "Default Tag Queue Depth: %d\n", aic7xxx_default_queue_depth);
seq_printf(m, " Tagged Queue By Device array for aic7xxx host "
"instance %d:\n", p->instance);
seq_printf(m, " {");
for(i=0; i < (MAX_TARGETS - 1); i++)
seq_printf(m, "%d,",aic7xxx_tag_info[p->instance].tag_commands[i]);
seq_printf(m, "%d}\n",aic7xxx_tag_info[p->instance].tag_commands[i]);
seq_printf(m, "\n");
seq_printf(m, "Statistics:\n\n");
list_for_each_entry(aic_dev, &p->aic_devs, list)
{
sdptr = aic_dev->SDptr;
tindex = sdptr->channel << 3 | sdptr->id;
seq_printf(m, "(scsi%d:%d:%d:%d)\n",
p->host_no, sdptr->channel, sdptr->id, sdptr->lun);
seq_printf(m, " Device using %s/%s",
(aic_dev->cur.width == MSG_EXT_WDTR_BUS_16_BIT) ?
"Wide" : "Narrow",
(aic_dev->cur.offset != 0) ?
"Sync transfers at " : "Async transfers.\n" );
if (aic_dev->cur.offset != 0)
{
struct aic7xxx_syncrate *sync_rate;
unsigned char options = aic_dev->cur.options;
int period = aic_dev->cur.period;
int rate = (aic_dev->cur.width ==
MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0;
sync_rate = aic7xxx_find_syncrate(p, &period, 0, &options);
if (sync_rate != NULL)
{
seq_printf(m, "%s MByte/sec, offset %d\n",
sync_rate->rate[rate],
aic_dev->cur.offset );
}
else
{
seq_printf(m, "3.3 MByte/sec, offset %d\n",
aic_dev->cur.offset );
}
}
seq_printf(m, " Transinfo settings: ");
seq_printf(m, "current(%d/%d/%d/%d), ",
aic_dev->cur.period,
aic_dev->cur.offset,
aic_dev->cur.width,
aic_dev->cur.options);
seq_printf(m, "goal(%d/%d/%d/%d), ",
aic_dev->goal.period,
aic_dev->goal.offset,
aic_dev->goal.width,
aic_dev->goal.options);
seq_printf(m, "user(%d/%d/%d/%d)\n",
p->user[tindex].period,
p->user[tindex].offset,
p->user[tindex].width,
p->user[tindex].options);
if(sdptr->simple_tags)
{
seq_printf(m, " Tagged Command Queueing Enabled, Ordered Tags %s, Depth %d/%d\n", sdptr->ordered_tags ? "Enabled" : "Disabled", sdptr->queue_depth, aic_dev->max_q_depth);
}
if(aic_dev->barrier_total)
seq_printf(m, " Total transfers %ld:\n (%ld/%ld/%ld/%ld reads/writes/REQ_BARRIER/Ordered Tags)\n",
aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total,
aic_dev->barrier_total, aic_dev->ordered_total);
else
seq_printf(m, " Total transfers %ld:\n (%ld/%ld reads/writes)\n",
aic_dev->r_total+aic_dev->w_total, aic_dev->r_total, aic_dev->w_total);
seq_printf(m, "%s\n", HDRB);
seq_printf(m, " Reads:");
for (i = 0; i < ARRAY_SIZE(aic_dev->r_bins); i++)
{
seq_printf(m, " %10ld", aic_dev->r_bins[i]);
}
seq_printf(m, "\n");
seq_printf(m, " Writes:");
for (i = 0; i < ARRAY_SIZE(aic_dev->w_bins); i++)
{
seq_printf(m, " %10ld", aic_dev->w_bins[i]);
}
seq_printf(m, "\n");
seq_printf(m, "\n\n");
}
return 0;
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 2
* c-brace-imaginary-offset: 0
* c-brace-offset: -2
* c-argdecl-indent: 2
* c-label-offset: -2
* c-continued-statement-offset: 2
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
/*
* DO NOT EDIT - This file is automatically generated.
*/
#define SCSISEQ 0x00
#define TEMODE 0x80
#define ENSELO 0x40
#define ENSELI 0x20
#define ENRSELI 0x10
#define ENAUTOATNO 0x08
#define ENAUTOATNI 0x04
#define ENAUTOATNP 0x02
#define SCSIRSTO 0x01
#define SXFRCTL0 0x01
#define DFON 0x80
#define DFPEXP 0x40
#define FAST20 0x20
#define CLRSTCNT 0x10
#define SPIOEN 0x08
#define SCAMEN 0x04
#define CLRCHN 0x02
#define SXFRCTL1 0x02
#define BITBUCKET 0x80
#define SWRAPEN 0x40
#define ENSPCHK 0x20
#define STIMESEL 0x18
#define ENSTIMER 0x04
#define ACTNEGEN 0x02
#define STPWEN 0x01
#define SCSISIGO 0x03
#define CDO 0x80
#define IOO 0x40
#define MSGO 0x20
#define ATNO 0x10
#define SELO 0x08
#define BSYO 0x04
#define REQO 0x02
#define ACKO 0x01
#define SCSISIGI 0x03
#define ATNI 0x10
#define SELI 0x08
#define BSYI 0x04
#define REQI 0x02
#define ACKI 0x01
#define SCSIRATE 0x04
#define WIDEXFER 0x80
#define SXFR_ULTRA2 0x7f
#define SXFR 0x70
#define SOFS 0x0f
#define SCSIID 0x05
#define SCSIOFFSET 0x05
#define SOFS_ULTRA2 0x7f
#define SCSIDATL 0x06
#define SCSIDATH 0x07
#define STCNT 0x08
#define OPTIONMODE 0x08
#define AUTORATEEN 0x80
#define AUTOACKEN 0x40
#define ATNMGMNTEN 0x20
#define BUSFREEREV 0x10
#define EXPPHASEDIS 0x08
#define SCSIDATL_IMGEN 0x04
#define AUTO_MSGOUT_DE 0x02
#define DIS_MSGIN_DUALEDGE 0x01
#define CLRSINT0 0x0b
#define CLRSELDO 0x40
#define CLRSELDI 0x20
#define CLRSELINGO 0x10
#define CLRSWRAP 0x08
#define CLRSPIORDY 0x02
#define SSTAT0 0x0b
#define TARGET 0x80
#define SELDO 0x40
#define SELDI 0x20
#define SELINGO 0x10
#define IOERR 0x08
#define SWRAP 0x08
#define SDONE 0x04
#define SPIORDY 0x02
#define DMADONE 0x01
#define CLRSINT1 0x0c
#define CLRSELTIMEO 0x80
#define CLRATNO 0x40
#define CLRSCSIRSTI 0x20
#define CLRBUSFREE 0x08
#define CLRSCSIPERR 0x04
#define CLRPHASECHG 0x02
#define CLRREQINIT 0x01
#define SSTAT1 0x0c
#define SELTO 0x80
#define ATNTARG 0x40
#define SCSIRSTI 0x20
#define PHASEMIS 0x10
#define BUSFREE 0x08
#define SCSIPERR 0x04
#define PHASECHG 0x02
#define REQINIT 0x01
#define SSTAT2 0x0d
#define OVERRUN 0x80
#define SHVALID 0x40
#define WIDE_RES 0x20
#define SFCNT 0x1f
#define EXP_ACTIVE 0x10
#define CRCVALERR 0x08
#define CRCENDERR 0x04
#define CRCREQERR 0x02
#define DUAL_EDGE_ERROR 0x01
#define SSTAT3 0x0e
#define SCSICNT 0xf0
#define OFFCNT 0x0f
#define SCSIID_ULTRA2 0x0f
#define OID 0x0f
#define SIMODE0 0x10
#define ENSELDO 0x40
#define ENSELDI 0x20
#define ENSELINGO 0x10
#define ENIOERR 0x08
#define ENSWRAP 0x08
#define ENSDONE 0x04
#define ENSPIORDY 0x02
#define ENDMADONE 0x01
#define SIMODE1 0x11
#define ENSELTIMO 0x80
#define ENATNTARG 0x40
#define ENSCSIRST 0x20
#define ENPHASEMIS 0x10
#define ENBUSFREE 0x08
#define ENSCSIPERR 0x04
#define ENPHASECHG 0x02
#define ENREQINIT 0x01
#define SCSIBUSL 0x12
#define SCSIBUSH 0x13
#define SHADDR 0x14
#define SELTIMER 0x18
#define STAGE6 0x20
#define STAGE5 0x10
#define STAGE4 0x08
#define STAGE3 0x04
#define STAGE2 0x02
#define STAGE1 0x01
#define SELID 0x19
#define SELID_MASK 0xf0
#define ONEBIT 0x08
#define SPIOCAP 0x1b
#define SOFT1 0x80
#define SOFT0 0x40
#define SOFTCMDEN 0x20
#define HAS_BRDCTL 0x10
#define SEEPROM 0x08
#define EEPROM 0x04
#define ROM 0x02
#define SSPIOCPS 0x01
#define BRDCTL 0x1d
#define BRDDAT7 0x80
#define BRDDAT6 0x40
#define BRDDAT5 0x20
#define BRDDAT4 0x10
#define BRDSTB 0x10
#define BRDCS 0x08
#define BRDDAT3 0x08
#define BRDDAT2 0x04
#define BRDRW 0x04
#define BRDRW_ULTRA2 0x02
#define BRDCTL1 0x02
#define BRDSTB_ULTRA2 0x01
#define BRDCTL0 0x01
#define SEECTL 0x1e
#define EXTARBACK 0x80
#define EXTARBREQ 0x40
#define SEEMS 0x20
#define SEERDY 0x10
#define SEECS 0x08
#define SEECK 0x04
#define SEEDO 0x02
#define SEEDI 0x01
#define SBLKCTL 0x1f
#define DIAGLEDEN 0x80
#define DIAGLEDON 0x40
#define AUTOFLUSHDIS 0x20
#define ENAB40 0x08
#define ENAB20 0x04
#define SELWIDE 0x02
#define XCVR 0x01
#define SRAM_BASE 0x20
#define TARG_SCSIRATE 0x20
#define ULTRA_ENB 0x30
#define DISC_DSB 0x32
#define MSG_OUT 0x34
#define DMAPARAMS 0x35
#define PRELOADEN 0x80
#define WIDEODD 0x40
#define SCSIEN 0x20
#define SDMAENACK 0x10
#define SDMAEN 0x10
#define HDMAEN 0x08
#define HDMAENACK 0x08
#define DIRECTION 0x04
#define FIFOFLUSH 0x02
#define FIFORESET 0x01
#define SEQ_FLAGS 0x36
#define IDENTIFY_SEEN 0x80
#define SCBPTR_VALID 0x20
#define DPHASE 0x10
#define AMTARGET 0x08
#define WIDE_BUS 0x02
#define TWIN_BUS 0x01
#define SAVED_TCL 0x37
#define SG_COUNT 0x38
#define SG_NEXT 0x39
#define LASTPHASE 0x3d
#define P_MESGIN 0xe0
#define PHASE_MASK 0xe0
#define P_STATUS 0xc0
#define P_MESGOUT 0xa0
#define P_COMMAND 0x80
#define CDI 0x80
#define IOI 0x40
#define P_DATAIN 0x40
#define MSGI 0x20
#define P_BUSFREE 0x01
#define P_DATAOUT 0x00
#define WAITING_SCBH 0x3e
#define DISCONNECTED_SCBH 0x3f
#define FREE_SCBH 0x40
#define HSCB_ADDR 0x41
#define SCBID_ADDR 0x45
#define TMODE_CMDADDR 0x49
#define KERNEL_QINPOS 0x4d
#define QINPOS 0x4e
#define QOUTPOS 0x4f
#define TMODE_CMDADDR_NEXT 0x50
#define ARG_1 0x51
#define RETURN_1 0x51
#define SEND_MSG 0x80
#define SEND_SENSE 0x40
#define SEND_REJ 0x20
#define MSGOUT_PHASEMIS 0x10
#define ARG_2 0x52
#define RETURN_2 0x52
#define LAST_MSG 0x53
#define PREFETCH_CNT 0x54
#define SCSICONF 0x5a
#define TERM_ENB 0x80
#define RESET_SCSI 0x40
#define HWSCSIID 0x0f
#define HSCSIID 0x07
#define HOSTCONF 0x5d
#define HA_274_BIOSCTRL 0x5f
#define BIOSMODE 0x30
#define BIOSDISABLED 0x30
#define CHANNEL_B_PRIMARY 0x08
#define SEQCTL 0x60
#define PERRORDIS 0x80
#define PAUSEDIS 0x40
#define FAILDIS 0x20
#define FASTMODE 0x10
#define BRKADRINTEN 0x08
#define STEP 0x04
#define SEQRESET 0x02
#define LOADRAM 0x01
#define SEQRAM 0x61
#define SEQADDR0 0x62
#define SEQADDR1 0x63
#define SEQADDR1_MASK 0x01
#define ACCUM 0x64
#define SINDEX 0x65
#define DINDEX 0x66
#define ALLONES 0x69
#define ALLZEROS 0x6a
#define NONE 0x6a
#define FLAGS 0x6b
#define ZERO 0x02
#define CARRY 0x01
#define SINDIR 0x6c
#define DINDIR 0x6d
#define FUNCTION1 0x6e
#define STACK 0x6f
#define TARG_OFFSET 0x70
#define BCTL 0x84
#define ACE 0x08
#define ENABLE 0x01
#define DSCOMMAND0 0x84
#define INTSCBRAMSEL 0x08
#define RAMPS 0x04
#define USCBSIZE32 0x02
#define CIOPARCKEN 0x01
#define DSCOMMAND 0x84
#define CACHETHEN 0x80
#define DPARCKEN 0x40
#define MPARCKEN 0x20
#define EXTREQLCK 0x10
#define BUSTIME 0x85
#define BOFF 0xf0
#define BON 0x0f
#define BUSSPD 0x86
#define DFTHRSH 0xc0
#define STBOFF 0x38
#define STBON 0x07
#define DSPCISTATUS 0x86
#define DFTHRSH_100 0xc0
#define HCNTRL 0x87
#define POWRDN 0x40
#define SWINT 0x10
#define IRQMS 0x08
#define PAUSE 0x04
#define INTEN 0x02
#define CHIPRST 0x01
#define CHIPRSTACK 0x01
#define HADDR 0x88
#define HCNT 0x8c
#define SCBPTR 0x90
#define INTSTAT 0x91
#define SEQINT_MASK 0xf1
#define DATA_OVERRUN 0xe1
#define MSGIN_PHASEMIS 0xd1
#define TRACEPOINT2 0xc1
#define SEQ_SG_FIXUP 0xb1
#define AWAITING_MSG 0xa1
#define RESIDUAL 0x81
#define BAD_STATUS 0x71
#define REJECT_MSG 0x61
#define WIDE_RESIDUE 0x51
#define EXTENDED_MSG 0x41
#define NO_MATCH 0x31
#define NO_IDENT 0x21
#define SEND_REJECT 0x11
#define INT_PEND 0x0f
#define BRKADRINT 0x08
#define SCSIINT 0x04
#define CMDCMPLT 0x02
#define BAD_PHASE 0x01
#define SEQINT 0x01
#define CLRINT 0x92
#define CLRPARERR 0x10
#define CLRBRKADRINT 0x08
#define CLRSCSIINT 0x04
#define CLRCMDINT 0x02
#define CLRSEQINT 0x01
#define ERROR 0x92
#define CIOPARERR 0x80
#define PCIERRSTAT 0x40
#define MPARERR 0x20
#define DPARERR 0x10
#define SQPARERR 0x08
#define ILLOPCODE 0x04
#define DSCTMOUT 0x02
#define ILLSADDR 0x02
#define ILLHADDR 0x01
#define DFCNTRL 0x93
#define DFSTATUS 0x94
#define PRELOAD_AVAIL 0x80
#define DWORDEMP 0x20
#define MREQPEND 0x10
#define HDONE 0x08
#define DFTHRESH 0x04
#define FIFOFULL 0x02
#define FIFOEMP 0x01
#define DFDAT 0x99
#define SCBCNT 0x9a
#define SCBAUTO 0x80
#define SCBCNT_MASK 0x1f
#define QINFIFO 0x9b
#define QINCNT 0x9c
#define SCSIDATL_IMG 0x9c
#define QOUTFIFO 0x9d
#define CRCCONTROL1 0x9d
#define CRCONSEEN 0x80
#define CRCVALCHKEN 0x40
#define CRCENDCHKEN 0x20
#define CRCREQCHKEN 0x10
#define TARGCRCENDEN 0x08
#define TARGCRCCNTEN 0x04
#define SCSIPHASE 0x9e
#define SP_STATUS 0x20
#define SP_COMMAND 0x10
#define SP_MSG_IN 0x08
#define SP_MSG_OUT 0x04
#define SP_DATA_IN 0x02
#define SP_DATA_OUT 0x01
#define QOUTCNT 0x9e
#define SFUNCT 0x9f
#define ALT_MODE 0x80
#define SCB_CONTROL 0xa0
#define MK_MESSAGE 0x80
#define DISCENB 0x40
#define TAG_ENB 0x20
#define DISCONNECTED 0x04
#define SCB_TAG_TYPE 0x03
#define SCB_BASE 0xa0
#define SCB_TCL 0xa1
#define TID 0xf0
#define SELBUSB 0x08
#define LID 0x07
#define SCB_TARGET_STATUS 0xa2
#define SCB_SGCOUNT 0xa3
#define SCB_SGPTR 0xa4
#define SCB_RESID_SGCNT 0xa8
#define SCB_RESID_DCNT 0xa9
#define SCB_DATAPTR 0xac
#define SCB_DATACNT 0xb0
#define SCB_CMDPTR 0xb4
#define SCB_CMDLEN 0xb8
#define SCB_TAG 0xb9
#define SCB_NEXT 0xba
#define SCB_PREV 0xbb
#define SCB_BUSYTARGETS 0xbc
#define SEECTL_2840 0xc0
#define CS_2840 0x04
#define CK_2840 0x02
#define DO_2840 0x01
#define STATUS_2840 0xc1
#define EEPROM_TF 0x80
#define BIOS_SEL 0x60
#define ADSEL 0x1e
#define DI_2840 0x01
#define CCHADDR 0xe0
#define CCHCNT 0xe8
#define CCSGRAM 0xe9
#define CCSGADDR 0xea
#define CCSGCTL 0xeb
#define CCSGDONE 0x80
#define CCSGEN 0x08
#define FLAG 0x02
#define CCSGRESET 0x01
#define CCSCBRAM 0xec
#define CCSCBADDR 0xed
#define CCSCBCTL 0xee
#define CCSCBDONE 0x80
#define ARRDONE 0x40
#define CCARREN 0x10
#define CCSCBEN 0x08
#define CCSCBDIR 0x04
#define CCSCBRESET 0x01
#define CCSCBCNT 0xef
#define CCSCBPTR 0xf1
#define HNSCB_QOFF 0xf4
#define HESCB_QOFF 0xf5
#define SNSCB_QOFF 0xf6
#define SESCB_QOFF 0xf7
#define SDSCB_QOFF 0xf8
#define QOFF_CTLSTA 0xfa
#define ESTABLISH_SCB_AVAIL 0x80
#define SCB_AVAIL 0x40
#define SNSCB_ROLLOVER 0x20
#define SDSCB_ROLLOVER 0x10
#define SESCB_ROLLOVER 0x08
#define SCB_QSIZE 0x07
#define SCB_QSIZE_256 0x06
#define DFF_THRSH 0xfb
#define WR_DFTHRSH 0x70
#define WR_DFTHRSH_MAX 0x70
#define WR_DFTHRSH_90 0x60
#define WR_DFTHRSH_85 0x50
#define WR_DFTHRSH_75 0x40
#define WR_DFTHRSH_63 0x30
#define WR_DFTHRSH_50 0x20
#define WR_DFTHRSH_25 0x10
#define RD_DFTHRSH_MAX 0x07
#define RD_DFTHRSH 0x07
#define RD_DFTHRSH_90 0x06
#define RD_DFTHRSH_85 0x05
#define RD_DFTHRSH_75 0x04
#define RD_DFTHRSH_63 0x03
#define RD_DFTHRSH_50 0x02
#define RD_DFTHRSH_25 0x01
#define WR_DFTHRSH_MIN 0x00
#define RD_DFTHRSH_MIN 0x00
#define SG_CACHEPTR 0xfc
#define SG_USER_DATA 0xfc
#define LAST_SEG 0x02
#define LAST_SEG_DONE 0x01
#define CMD_GROUP2_BYTE_DELTA 0xfa
#define MAX_OFFSET_8BIT 0x0f
#define BUS_16_BIT 0x01
#define QINFIFO_OFFSET 0x02
#define CMD_GROUP5_BYTE_DELTA 0x0b
#define CMD_GROUP_CODE_SHIFT 0x05
#define MAX_OFFSET_ULTRA2 0x7f
#define MAX_OFFSET_16BIT 0x08
#define BUS_8_BIT 0x00
#define QOUTFIFO_OFFSET 0x01
#define UNTAGGEDSCB_OFFSET 0x00
#define CCSGRAM_MAXSEGS 0x10
#define SCB_LIST_NULL 0xff
#define SG_SIZEOF 0x08
#define CMD_GROUP4_BYTE_DELTA 0x04
#define CMD_GROUP0_BYTE_DELTA 0xfc
#define HOST_MSG 0xff
#define BUS_32_BIT 0x02
#define CCSGADDR_MAX 0x80
/* Downloaded Constant Definitions */
#define TMODE_NUMCMDS 0x00
/*
* DO NOT EDIT - This file is automatically generated.
*/
static unsigned char seqprog[] = {
0xff, 0x6a, 0x06, 0x08,
0x7f, 0x02, 0x04, 0x08,
0x12, 0x6a, 0x00, 0x00,
0xff, 0x6a, 0xd6, 0x09,
0xff, 0x6a, 0xdc, 0x09,
0x00, 0x65, 0xca, 0x58,
0xf7, 0x01, 0x02, 0x08,
0xff, 0x4e, 0xc8, 0x08,
0xbf, 0x60, 0xc0, 0x08,
0x60, 0x0b, 0x86, 0x68,
0x40, 0x00, 0x0c, 0x68,
0x08, 0x1f, 0x3e, 0x10,
0x60, 0x0b, 0x86, 0x68,
0x40, 0x00, 0x0c, 0x68,
0x08, 0x1f, 0x3e, 0x10,
0xff, 0x3e, 0x48, 0x60,
0x40, 0xfa, 0x10, 0x78,
0xff, 0xf6, 0xd4, 0x08,
0x01, 0x4e, 0x9c, 0x18,
0x40, 0x60, 0xc0, 0x00,
0x00, 0x4d, 0x10, 0x70,
0x01, 0x4e, 0x9c, 0x18,
0xbf, 0x60, 0xc0, 0x08,
0x00, 0x6a, 0x86, 0x5c,
0xff, 0x4e, 0xc8, 0x18,
0x02, 0x6a, 0x70, 0x5b,
0xff, 0x52, 0x20, 0x09,
0x0d, 0x6a, 0x6a, 0x00,
0x00, 0x52, 0xe6, 0x5b,
0x03, 0xb0, 0x52, 0x31,
0xff, 0xb0, 0x52, 0x09,
0xff, 0xb1, 0x54, 0x09,
0xff, 0xb2, 0x56, 0x09,
0xff, 0xa3, 0x50, 0x09,
0xff, 0x3e, 0x74, 0x09,
0xff, 0x90, 0x7c, 0x08,
0xff, 0x3e, 0x20, 0x09,
0x00, 0x65, 0x4e, 0x58,
0x00, 0x65, 0x0c, 0x40,
0xf7, 0x1f, 0xca, 0x08,
0x08, 0xa1, 0xc8, 0x08,
0x00, 0x65, 0xca, 0x00,
0xff, 0x65, 0x3e, 0x08,
0xf0, 0xa1, 0xc8, 0x08,
0x0f, 0x0f, 0x1e, 0x08,
0x00, 0x0f, 0x1e, 0x00,
0xf0, 0xa1, 0xc8, 0x08,
0x0f, 0x05, 0x0a, 0x08,
0x00, 0x05, 0x0a, 0x00,
0xff, 0x6a, 0x0c, 0x08,
0x5a, 0x6a, 0x00, 0x04,
0x12, 0x65, 0x02, 0x00,
0x31, 0x6a, 0xca, 0x00,
0x80, 0x37, 0x6e, 0x68,
0xff, 0x65, 0xca, 0x18,
0xff, 0x37, 0xdc, 0x08,
0xff, 0x6e, 0xc8, 0x08,
0x00, 0x6c, 0x76, 0x78,
0x20, 0x01, 0x02, 0x00,
0x4c, 0x37, 0xc8, 0x28,
0x08, 0x1f, 0x7e, 0x78,
0x08, 0x37, 0x6e, 0x00,
0x08, 0x64, 0xc8, 0x00,
0x70, 0x64, 0xca, 0x18,
0xff, 0x6c, 0x0a, 0x08,
0x20, 0x64, 0xca, 0x18,
0xff, 0x6c, 0x08, 0x0c,
0x40, 0x0b, 0x96, 0x68,
0x20, 0x6a, 0x16, 0x00,
0xf0, 0x19, 0x6e, 0x08,
0x08, 0x6a, 0x18, 0x00,
0x08, 0x11, 0x22, 0x00,
0x08, 0x6a, 0x66, 0x58,
0x08, 0x6a, 0x68, 0x00,
0x00, 0x65, 0xaa, 0x40,
0x12, 0x6a, 0x00, 0x00,
0x40, 0x6a, 0x16, 0x00,
0xff, 0x3e, 0x20, 0x09,
0xff, 0xba, 0x7c, 0x08,
0xff, 0xa1, 0x6e, 0x08,
0x08, 0x6a, 0x18, 0x00,
0x08, 0x11, 0x22, 0x00,
0x08, 0x6a, 0x66, 0x58,
0x80, 0x6a, 0x68, 0x00,
0x80, 0x36, 0x6c, 0x00,
0x00, 0x65, 0xba, 0x5b,
0xff, 0x3d, 0xc8, 0x08,
0xbf, 0x64, 0xe2, 0x78,
0x80, 0x64, 0xc8, 0x71,
0xa0, 0x64, 0xf8, 0x71,
0xc0, 0x64, 0xf0, 0x71,
0xe0, 0x64, 0x38, 0x72,
0x01, 0x6a, 0x22, 0x01,
0x00, 0x65, 0xaa, 0x40,
0xf7, 0x11, 0x22, 0x08,
0x00, 0x65, 0xca, 0x58,
0xff, 0x06, 0xd4, 0x08,
0xf7, 0x01, 0x02, 0x08,
0x09, 0x0c, 0xc4, 0x78,
0x08, 0x0c, 0x0c, 0x68,
0x01, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0x26, 0x09,
0x02, 0x6a, 0x08, 0x30,
0xff, 0x6a, 0x08, 0x08,
0xdf, 0x01, 0x02, 0x08,
0x01, 0x6a, 0x7a, 0x00,
0xff, 0x6a, 0x6c, 0x0c,
0x04, 0x14, 0x10, 0x31,
0x03, 0xa9, 0x18, 0x31,
0x03, 0xa9, 0x10, 0x30,
0x08, 0x6a, 0xcc, 0x00,
0xa9, 0x6a, 0xd0, 0x5b,
0x00, 0x65, 0x02, 0x41,
0xa8, 0x6a, 0x6a, 0x00,
0x79, 0x6a, 0x6a, 0x00,
0x40, 0x3d, 0xea, 0x68,
0x04, 0x35, 0x6a, 0x00,
0x00, 0x65, 0x2a, 0x5b,
0x80, 0x6a, 0xd4, 0x01,
0x10, 0x36, 0xd6, 0x68,
0x10, 0x36, 0x6c, 0x00,
0x07, 0xac, 0x10, 0x31,
0x05, 0xa3, 0x70, 0x30,
0x03, 0x8c, 0x10, 0x30,
0x88, 0x6a, 0xcc, 0x00,
0xac, 0x6a, 0xc8, 0x5b,
0x00, 0x65, 0xc2, 0x5b,
0x38, 0x6a, 0xcc, 0x00,
0xa3, 0x6a, 0xcc, 0x5b,
0xff, 0x38, 0x12, 0x69,
0x80, 0x02, 0x04, 0x00,
0xe7, 0x35, 0x6a, 0x08,
0x03, 0x69, 0x18, 0x31,
0x03, 0x69, 0x10, 0x30,
0xff, 0x6a, 0x10, 0x00,
0xff, 0x6a, 0x12, 0x00,
0xff, 0x6a, 0x14, 0x00,
0x22, 0x38, 0xc8, 0x28,
0x01, 0x38, 0x1c, 0x61,
0x02, 0x64, 0xc8, 0x00,
0x01, 0x38, 0x1c, 0x61,
0xbf, 0x35, 0x6a, 0x08,
0xff, 0x64, 0xf8, 0x09,
0xff, 0x35, 0x26, 0x09,
0x80, 0x02, 0xa4, 0x69,
0x10, 0x0c, 0x7a, 0x69,
0x80, 0x94, 0x22, 0x79,
0x00, 0x35, 0x0a, 0x5b,
0x80, 0x02, 0xa4, 0x69,
0xff, 0x65, 0x94, 0x79,
0x01, 0x38, 0x70, 0x71,
0xff, 0x38, 0x70, 0x18,
0xff, 0x38, 0x94, 0x79,
0x80, 0xea, 0x4a, 0x61,
0xef, 0x38, 0xc8, 0x18,
0x80, 0x6a, 0xc8, 0x00,
0x00, 0x65, 0x3c, 0x49,
0x33, 0x38, 0xc8, 0x28,
0xff, 0x64, 0xd0, 0x09,
0x04, 0x39, 0xc0, 0x31,
0x09, 0x6a, 0xd6, 0x01,
0x80, 0xeb, 0x42, 0x79,
0xf7, 0xeb, 0xd6, 0x09,
0x08, 0xeb, 0x46, 0x69,
0x01, 0x6a, 0xd6, 0x01,
0x08, 0xe9, 0x10, 0x31,
0x03, 0x8c, 0x10, 0x30,
0xff, 0x38, 0x70, 0x18,
0x88, 0x6a, 0xcc, 0x00,
0x39, 0x6a, 0xce, 0x5b,
0x08, 0x6a, 0x18, 0x01,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0x0d, 0x93, 0x26, 0x01,
0x00, 0x65, 0x78, 0x5c,
0x88, 0x6a, 0xcc, 0x00,
0x00, 0x65, 0x6a, 0x5c,
0x00, 0x65, 0xc2, 0x5b,
0xff, 0x6a, 0xc8, 0x08,
0x08, 0x39, 0x72, 0x18,
0x00, 0x3a, 0x74, 0x20,
0x00, 0x65, 0x02, 0x41,
0x01, 0x0c, 0x6c, 0x79,
0x10, 0x0c, 0x02, 0x79,
0x10, 0x0c, 0x7a, 0x69,
0x01, 0xfc, 0x70, 0x79,
0xff, 0x6a, 0x70, 0x08,
0x01, 0x0c, 0x76, 0x79,
0x10, 0x0c, 0x02, 0x79,
0x00, 0x65, 0xae, 0x59,
0x01, 0xfc, 0x94, 0x69,
0x40, 0x0d, 0x84, 0x69,
0xb1, 0x6a, 0x22, 0x01,
0x00, 0x65, 0x94, 0x41,
0x2e, 0xfc, 0xa2, 0x28,
0x3f, 0x38, 0xc8, 0x08,
0x00, 0x51, 0x94, 0x71,
0xff, 0x6a, 0xc8, 0x08,
0xf8, 0x39, 0x72, 0x18,
0xff, 0x3a, 0x74, 0x20,
0x01, 0x38, 0x70, 0x18,
0x00, 0x65, 0x86, 0x41,
0x03, 0x08, 0x52, 0x31,
0xff, 0x38, 0x50, 0x09,
0x12, 0x01, 0x02, 0x00,
0xff, 0x08, 0x52, 0x09,
0xff, 0x09, 0x54, 0x09,
0xff, 0x0a, 0x56, 0x09,
0xff, 0x38, 0x50, 0x09,
0x00, 0x65, 0xaa, 0x40,
0x10, 0x0c, 0xa4, 0x79,
0x00, 0x65, 0xae, 0x59,
0x7f, 0x02, 0x04, 0x08,
0xe1, 0x6a, 0x22, 0x01,
0x00, 0x65, 0xaa, 0x40,
0x04, 0x93, 0xc2, 0x69,
0xdf, 0x93, 0x26, 0x09,
0x20, 0x93, 0xb2, 0x69,
0x02, 0x93, 0x26, 0x01,
0x01, 0x94, 0xb6, 0x79,
0x01, 0x94, 0xb6, 0x79,
0x01, 0x94, 0xb6, 0x79,
0x01, 0x94, 0xb6, 0x79,
0x01, 0x94, 0xb6, 0x79,
0x10, 0x94, 0xc0, 0x69,
0xd7, 0x93, 0x26, 0x09,
0x28, 0x93, 0xc4, 0x69,
0xff, 0x6a, 0xd4, 0x0c,
0x00, 0x65, 0x2a, 0x5b,
0x05, 0xb4, 0x10, 0x31,
0x02, 0x6a, 0x1a, 0x31,
0x03, 0x8c, 0x10, 0x30,
0x88, 0x6a, 0xcc, 0x00,
0xb4, 0x6a, 0xcc, 0x5b,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0x00, 0x65, 0xc2, 0x5b,
0x3d, 0x6a, 0x0a, 0x5b,
0xac, 0x6a, 0x26, 0x01,
0x04, 0x0b, 0xde, 0x69,
0x04, 0x0b, 0xe4, 0x69,
0x10, 0x0c, 0xe0, 0x79,
0x02, 0x03, 0xe8, 0x79,
0x11, 0x0c, 0xe4, 0x79,
0xd7, 0x93, 0x26, 0x09,
0x28, 0x93, 0xea, 0x69,
0x12, 0x01, 0x02, 0x00,
0x00, 0x65, 0xaa, 0x40,
0x00, 0x65, 0x2a, 0x5b,
0xff, 0x06, 0x44, 0x09,
0x00, 0x65, 0xaa, 0x40,
0x10, 0x3d, 0x06, 0x00,
0xff, 0x34, 0xca, 0x08,
0x80, 0x65, 0x1c, 0x62,
0x0f, 0xa1, 0xca, 0x08,
0x07, 0xa1, 0xca, 0x08,
0x40, 0xa0, 0xc8, 0x08,
0x00, 0x65, 0xca, 0x00,
0x80, 0x65, 0xca, 0x00,
0x80, 0xa0, 0x0c, 0x7a,
0xff, 0x65, 0x0c, 0x08,
0x00, 0x65, 0x1e, 0x42,
0x20, 0xa0, 0x24, 0x7a,
0xff, 0x65, 0x0c, 0x08,
0x00, 0x65, 0xba, 0x5b,
0xa0, 0x3d, 0x2c, 0x62,
0x23, 0xa0, 0x0c, 0x08,
0x00, 0x65, 0xba, 0x5b,
0xa0, 0x3d, 0x2c, 0x62,
0x00, 0xb9, 0x24, 0x42,
0xff, 0x65, 0x24, 0x62,
0xa1, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0x10, 0x51, 0x2c, 0x72,
0x40, 0x6a, 0x18, 0x00,
0xff, 0x65, 0x0c, 0x08,
0x00, 0x65, 0xba, 0x5b,
0xa0, 0x3d, 0xf6, 0x71,
0x40, 0x6a, 0x18, 0x00,
0xff, 0x34, 0xa6, 0x08,
0x80, 0x34, 0x34, 0x62,
0x7f, 0xa0, 0x40, 0x09,
0x08, 0x6a, 0x68, 0x00,
0x00, 0x65, 0xaa, 0x40,
0x64, 0x6a, 0x00, 0x5b,
0x80, 0x64, 0xaa, 0x6a,
0x04, 0x64, 0x8c, 0x72,
0x02, 0x64, 0x92, 0x72,
0x00, 0x6a, 0x54, 0x72,
0x03, 0x64, 0xa6, 0x72,
0x01, 0x64, 0x88, 0x72,
0x07, 0x64, 0xe8, 0x72,
0x08, 0x64, 0x50, 0x72,
0x23, 0x64, 0xec, 0x72,
0x11, 0x6a, 0x22, 0x01,
0x07, 0x6a, 0xf2, 0x5a,
0xff, 0x06, 0xd4, 0x08,
0x00, 0x65, 0xaa, 0x40,
0xff, 0xa8, 0x58, 0x6a,
0xff, 0xa2, 0x70, 0x7a,
0x01, 0x6a, 0x6a, 0x00,
0x00, 0xb9, 0xe6, 0x5b,
0xff, 0xa2, 0x70, 0x7a,
0x71, 0x6a, 0x22, 0x01,
0xff, 0x6a, 0xd4, 0x08,
0x40, 0x51, 0x70, 0x62,
0x0d, 0x6a, 0x6a, 0x00,
0x00, 0xb9, 0xe6, 0x5b,
0xff, 0x3e, 0x74, 0x09,
0xff, 0x90, 0x7c, 0x08,
0x00, 0x65, 0x4e, 0x58,
0x00, 0x65, 0xbc, 0x40,
0x20, 0xa0, 0x78, 0x6a,
0xff, 0x37, 0xc8, 0x08,
0x00, 0x6a, 0x90, 0x5b,
0xff, 0x6a, 0xa6, 0x5b,
0xff, 0xf8, 0xc8, 0x08,
0xff, 0x4f, 0xc8, 0x08,
0x01, 0x6a, 0x90, 0x5b,
0x00, 0xb9, 0xa6, 0x5b,
0x01, 0x4f, 0x9e, 0x18,
0x02, 0x6a, 0x22, 0x01,
0x00, 0x65, 0x80, 0x5c,
0x00, 0x65, 0xbc, 0x40,
0x41, 0x6a, 0x22, 0x01,
0x00, 0x65, 0xaa, 0x40,
0x04, 0xa0, 0x40, 0x01,
0x00, 0x65, 0x98, 0x5c,
0x00, 0x65, 0xbc, 0x40,
0x10, 0x36, 0x50, 0x7a,
0x05, 0x38, 0x46, 0x31,
0x04, 0x14, 0x58, 0x31,
0x03, 0xa9, 0x60, 0x31,
0xa3, 0x6a, 0xcc, 0x00,
0x38, 0x6a, 0xcc, 0x5b,
0xac, 0x6a, 0xcc, 0x00,
0x14, 0x6a, 0xce, 0x5b,
0xa9, 0x6a, 0xd0, 0x5b,
0x00, 0x65, 0x50, 0x42,
0xef, 0x36, 0x6c, 0x08,
0x00, 0x65, 0x50, 0x42,
0x0f, 0x64, 0xc8, 0x08,
0x07, 0x64, 0xc8, 0x08,
0x00, 0x37, 0x6e, 0x00,
0xff, 0x6a, 0xa4, 0x00,
0x00, 0x65, 0x60, 0x5b,
0xff, 0x51, 0xbc, 0x72,
0x20, 0x36, 0xc6, 0x7a,
0x00, 0x90, 0x4e, 0x5b,
0x00, 0x65, 0xc8, 0x42,
0xff, 0x06, 0xd4, 0x08,
0x00, 0x65, 0xba, 0x5b,
0xe0, 0x3d, 0xe2, 0x62,
0x20, 0x12, 0xe2, 0x62,
0x51, 0x6a, 0xf6, 0x5a,
0x00, 0x65, 0x48, 0x5b,
0xff, 0x37, 0xc8, 0x08,
0x00, 0xa1, 0xda, 0x62,
0x04, 0xa0, 0xda, 0x7a,
0xfb, 0xa0, 0x40, 0x09,
0x80, 0x36, 0x6c, 0x00,
0x80, 0xa0, 0x50, 0x7a,
0x7f, 0xa0, 0x40, 0x09,
0xff, 0x6a, 0xf2, 0x5a,
0x00, 0x65, 0x50, 0x42,
0x04, 0xa0, 0xe0, 0x7a,
0x00, 0x65, 0x98, 0x5c,
0x00, 0x65, 0xe2, 0x42,
0x00, 0x65, 0x80, 0x5c,
0x31, 0x6a, 0x22, 0x01,
0x0c, 0x6a, 0xf2, 0x5a,
0x00, 0x65, 0x50, 0x42,
0x61, 0x6a, 0x22, 0x01,
0x00, 0x65, 0x50, 0x42,
0x51, 0x6a, 0xf6, 0x5a,
0x51, 0x6a, 0x22, 0x01,
0x00, 0x65, 0x50, 0x42,
0x10, 0x3d, 0x06, 0x00,
0xff, 0x65, 0x68, 0x0c,
0xff, 0x06, 0xd4, 0x08,
0x01, 0x0c, 0xf8, 0x7a,
0x04, 0x0c, 0xfa, 0x6a,
0xe0, 0x03, 0x7a, 0x08,
0xe0, 0x3d, 0x06, 0x63,
0xff, 0x65, 0xcc, 0x08,
0xff, 0x12, 0xda, 0x0c,
0xff, 0x06, 0xd4, 0x0c,
0xd1, 0x6a, 0x22, 0x01,
0x00, 0x65, 0xaa, 0x40,
0xff, 0x65, 0x26, 0x09,
0x01, 0x0b, 0x1a, 0x6b,
0x10, 0x0c, 0x0c, 0x7b,
0x04, 0x0b, 0x14, 0x6b,
0xff, 0x6a, 0xca, 0x08,
0x04, 0x93, 0x18, 0x6b,
0x01, 0x94, 0x16, 0x7b,
0x10, 0x94, 0x18, 0x6b,
0x80, 0x3d, 0x1e, 0x73,
0x0f, 0x04, 0x22, 0x6b,
0x02, 0x03, 0x22, 0x7b,
0x11, 0x0c, 0x1e, 0x7b,
0xc7, 0x93, 0x26, 0x09,
0xff, 0x99, 0xd4, 0x08,
0x38, 0x93, 0x24, 0x6b,
0xff, 0x6a, 0xd4, 0x0c,
0x80, 0x36, 0x28, 0x6b,
0x21, 0x6a, 0x22, 0x05,
0xff, 0x65, 0x20, 0x09,
0xff, 0x51, 0x36, 0x63,
0xff, 0x37, 0xc8, 0x08,
0xa1, 0x6a, 0x42, 0x43,
0xff, 0x51, 0xc8, 0x08,
0xb9, 0x6a, 0x42, 0x43,
0xff, 0x90, 0xa4, 0x08,
0xff, 0xba, 0x46, 0x73,
0xff, 0xba, 0x20, 0x09,
0xff, 0x65, 0xca, 0x18,
0x00, 0x6c, 0x3a, 0x63,
0xff, 0x90, 0xca, 0x0c,
0xff, 0x6a, 0xca, 0x04,
0x20, 0x36, 0x5a, 0x7b,
0x00, 0x90, 0x2e, 0x5b,
0xff, 0x65, 0x5a, 0x73,
0xff, 0x52, 0x58, 0x73,
0xff, 0xba, 0xcc, 0x08,
0xff, 0x52, 0x20, 0x09,
0xff, 0x66, 0x74, 0x09,
0xff, 0x65, 0x20, 0x0d,
0xff, 0xba, 0x7e, 0x0c,
0x00, 0x6a, 0x86, 0x5c,
0x0d, 0x6a, 0x6a, 0x00,
0x00, 0x51, 0xe6, 0x43,
0xff, 0x3f, 0xb4, 0x73,
0xff, 0x6a, 0xa2, 0x00,
0x00, 0x3f, 0x2e, 0x5b,
0xff, 0x65, 0xb4, 0x73,
0x20, 0x36, 0x6c, 0x00,
0x20, 0xa0, 0x6e, 0x6b,
0xff, 0xb9, 0xa2, 0x0c,
0xff, 0x6a, 0xa2, 0x04,
0xff, 0x65, 0xa4, 0x08,
0xe0, 0x6a, 0xcc, 0x00,
0x45, 0x6a, 0xda, 0x5b,
0x01, 0x6a, 0xd0, 0x01,
0x09, 0x6a, 0xd6, 0x01,
0x80, 0xeb, 0x7a, 0x7b,
0x01, 0x6a, 0xd6, 0x01,
0x01, 0xe9, 0xa4, 0x34,
0x88, 0x6a, 0xcc, 0x00,
0x45, 0x6a, 0xda, 0x5b,
0x01, 0x6a, 0x18, 0x01,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0x0d, 0x6a, 0x26, 0x01,
0x00, 0x65, 0x78, 0x5c,
0xff, 0x99, 0xa4, 0x0c,
0xff, 0x65, 0xa4, 0x08,
0xe0, 0x6a, 0xcc, 0x00,
0x45, 0x6a, 0xda, 0x5b,
0x01, 0x6a, 0xd0, 0x01,
0x01, 0x6a, 0xdc, 0x05,
0x88, 0x6a, 0xcc, 0x00,
0x45, 0x6a, 0xda, 0x5b,
0x01, 0x6a, 0x18, 0x01,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0x01, 0x6a, 0x26, 0x05,
0x01, 0x65, 0xd8, 0x31,
0x09, 0xee, 0xdc, 0x01,
0x80, 0xee, 0xaa, 0x7b,
0xff, 0x6a, 0xdc, 0x0d,
0xff, 0x65, 0x32, 0x09,
0x0a, 0x93, 0x26, 0x01,
0x00, 0x65, 0x78, 0x44,
0xff, 0x37, 0xc8, 0x08,
0x00, 0x6a, 0x70, 0x5b,
0xff, 0x52, 0xa2, 0x0c,
0x01, 0x0c, 0xba, 0x7b,
0x04, 0x0c, 0xba, 0x6b,
0xe0, 0x03, 0x06, 0x08,
0xe0, 0x03, 0x7a, 0x0c,
0xff, 0x8c, 0x10, 0x08,
0xff, 0x8d, 0x12, 0x08,
0xff, 0x8e, 0x14, 0x0c,
0xff, 0x6c, 0xda, 0x08,
0xff, 0x6c, 0xda, 0x08,
0xff, 0x6c, 0xda, 0x08,
0xff, 0x6c, 0xda, 0x08,
0xff, 0x6c, 0xda, 0x08,
0xff, 0x6c, 0xda, 0x08,
0xff, 0x6c, 0xda, 0x0c,
0x3d, 0x64, 0xa4, 0x28,
0x55, 0x64, 0xc8, 0x28,
0x00, 0x6c, 0xda, 0x18,
0xff, 0x52, 0xc8, 0x08,
0x00, 0x6c, 0xda, 0x20,
0xff, 0x6a, 0xc8, 0x08,
0x00, 0x6c, 0xda, 0x20,
0x00, 0x6c, 0xda, 0x24,
0xff, 0x65, 0xc8, 0x08,
0xe0, 0x6a, 0xcc, 0x00,
0x41, 0x6a, 0xd6, 0x5b,
0xff, 0x90, 0xe2, 0x09,
0x20, 0x6a, 0xd0, 0x01,
0x04, 0x35, 0xf8, 0x7b,
0x1d, 0x6a, 0xdc, 0x01,
0xdc, 0xee, 0xf4, 0x63,
0x00, 0x65, 0x0e, 0x44,
0x01, 0x6a, 0xdc, 0x01,
0x20, 0xa0, 0xd8, 0x31,
0x09, 0xee, 0xdc, 0x01,
0x80, 0xee, 0xfe, 0x7b,
0x11, 0x6a, 0xdc, 0x01,
0x50, 0xee, 0x02, 0x64,
0x20, 0x6a, 0xd0, 0x01,
0x09, 0x6a, 0xdc, 0x01,
0x88, 0xee, 0x08, 0x64,
0x19, 0x6a, 0xdc, 0x01,
0xd8, 0xee, 0x0c, 0x64,
0xff, 0x6a, 0xdc, 0x09,
0x18, 0xee, 0x10, 0x6c,
0xff, 0x6a, 0xd4, 0x0c,
0x88, 0x6a, 0xcc, 0x00,
0x41, 0x6a, 0xd6, 0x5b,
0x20, 0x6a, 0x18, 0x01,
0xff, 0x6a, 0x1a, 0x09,
0xff, 0x6a, 0x1c, 0x09,
0xff, 0x35, 0x26, 0x09,
0x04, 0x35, 0x3c, 0x6c,
0xa0, 0x6a, 0xca, 0x00,
0x20, 0x65, 0xc8, 0x18,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
0xff, 0x6c, 0x32, 0x09,
0x00, 0x65, 0x26, 0x64,
0x0a, 0x93, 0x26, 0x01,
0x00, 0x65, 0x78, 0x44,
0xa0, 0x6a, 0xcc, 0x00,
0xe8, 0x6a, 0xc8, 0x00,
0x01, 0x94, 0x40, 0x6c,
0x10, 0x94, 0x42, 0x6c,
0x08, 0x94, 0x54, 0x6c,
0x08, 0x94, 0x54, 0x6c,
0x08, 0x94, 0x54, 0x6c,
0x00, 0x65, 0x68, 0x5c,
0x08, 0x64, 0xc8, 0x18,
0x00, 0x8c, 0xca, 0x18,
0x00, 0x65, 0x4a, 0x4c,
0x00, 0x65, 0x40, 0x44,
0xf7, 0x93, 0x26, 0x09,
0x08, 0x93, 0x56, 0x6c,
0x00, 0x65, 0x68, 0x5c,
0x08, 0x64, 0xc8, 0x18,
0x08, 0x64, 0x58, 0x64,
0xff, 0x6a, 0xd4, 0x0c,
0x00, 0x65, 0x78, 0x5c,
0x00, 0x65, 0x68, 0x5c,
0x00, 0x65, 0x68, 0x5c,
0x00, 0x65, 0x68, 0x5c,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x08,
0xff, 0x99, 0xda, 0x0c,
0x08, 0x94, 0x78, 0x7c,
0xf7, 0x93, 0x26, 0x09,
0x08, 0x93, 0x7c, 0x6c,
0xff, 0x6a, 0xd4, 0x0c,
0xff, 0x40, 0x74, 0x09,
0xff, 0x90, 0x80, 0x08,
0xff, 0x6a, 0x72, 0x05,
0xff, 0x40, 0x94, 0x64,
0xff, 0x3f, 0x8c, 0x64,
0xff, 0x6a, 0xca, 0x04,
0xff, 0x3f, 0x20, 0x09,
0x01, 0x6a, 0x6a, 0x00,
0x00, 0xb9, 0xe6, 0x5b,
0xff, 0xba, 0x7e, 0x0c,
0xff, 0x40, 0x20, 0x09,
0xff, 0xba, 0x80, 0x0c,
0xff, 0x3f, 0x74, 0x09,
0xff, 0x90, 0x7e, 0x0c,
};
static int aic7xxx_patch15_func(struct aic7xxx_host *p);
static int
aic7xxx_patch15_func(struct aic7xxx_host *p)
{
return ((p->bugs & AHC_BUG_SCBCHAN_UPLOAD) != 0);
}
static int aic7xxx_patch14_func(struct aic7xxx_host *p);
static int
aic7xxx_patch14_func(struct aic7xxx_host *p)
{
return ((p->bugs & AHC_BUG_PCI_2_1_RETRY) != 0);
}
static int aic7xxx_patch13_func(struct aic7xxx_host *p);
static int
aic7xxx_patch13_func(struct aic7xxx_host *p)
{
return ((p->features & AHC_WIDE) != 0);
}
static int aic7xxx_patch12_func(struct aic7xxx_host *p);
static int
aic7xxx_patch12_func(struct aic7xxx_host *p)
{
return ((p->bugs & AHC_BUG_AUTOFLUSH) != 0);
}
static int aic7xxx_patch11_func(struct aic7xxx_host *p);
static int
aic7xxx_patch11_func(struct aic7xxx_host *p)
{
return ((p->features & AHC_ULTRA2) == 0);
}
static int aic7xxx_patch10_func(struct aic7xxx_host *p);
static int
aic7xxx_patch10_func(struct aic7xxx_host *p)
{
return ((p->features & AHC_CMD_CHAN) == 0);
}
static int aic7xxx_patch9_func(struct aic7xxx_host *p);
static int
aic7xxx_patch9_func(struct aic7xxx_host *p)
{
return ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895);
}
static int aic7xxx_patch8_func(struct aic7xxx_host *p);
static int
aic7xxx_patch8_func(struct aic7xxx_host *p)
{
return ((p->features & AHC_ULTRA) != 0);
}
static int aic7xxx_patch7_func(struct aic7xxx_host *p);
static int
aic7xxx_patch7_func(struct aic7xxx_host *p)
{
return ((p->features & AHC_ULTRA2) != 0);
}
static int aic7xxx_patch6_func(struct aic7xxx_host *p);
static int
aic7xxx_patch6_func(struct aic7xxx_host *p)
{
return ((p->flags & AHC_PAGESCBS) == 0);
}
static int aic7xxx_patch5_func(struct aic7xxx_host *p);
static int
aic7xxx_patch5_func(struct aic7xxx_host *p)
{
return ((p->flags & AHC_PAGESCBS) != 0);
}
static int aic7xxx_patch4_func(struct aic7xxx_host *p);
static int
aic7xxx_patch4_func(struct aic7xxx_host *p)
{
return ((p->features & AHC_QUEUE_REGS) != 0);
}
static int aic7xxx_patch3_func(struct aic7xxx_host *p);
static int
aic7xxx_patch3_func(struct aic7xxx_host *p)
{
return ((p->features & AHC_TWIN) != 0);
}
static int aic7xxx_patch2_func(struct aic7xxx_host *p);
static int
aic7xxx_patch2_func(struct aic7xxx_host *p)
{
return ((p->features & AHC_QUEUE_REGS) == 0);
}
static int aic7xxx_patch1_func(struct aic7xxx_host *p);
static int
aic7xxx_patch1_func(struct aic7xxx_host *p)
{
return ((p->features & AHC_CMD_CHAN) != 0);
}
static int aic7xxx_patch0_func(struct aic7xxx_host *p);
static int
aic7xxx_patch0_func(struct aic7xxx_host *p)
{
return (0);
}
struct sequencer_patch {
int (*patch_func)(struct aic7xxx_host *);
unsigned int begin :10,
skip_instr :10,
skip_patch :12;
} sequencer_patches[] = {
{ aic7xxx_patch1_func, 3, 2, 1 },
{ aic7xxx_patch2_func, 7, 1, 1 },
{ aic7xxx_patch2_func, 8, 1, 1 },
{ aic7xxx_patch3_func, 11, 4, 1 },
{ aic7xxx_patch4_func, 16, 3, 2 },
{ aic7xxx_patch0_func, 19, 4, 1 },
{ aic7xxx_patch5_func, 23, 1, 1 },
{ aic7xxx_patch6_func, 26, 1, 1 },
{ aic7xxx_patch1_func, 29, 1, 2 },
{ aic7xxx_patch0_func, 30, 3, 1 },
{ aic7xxx_patch3_func, 39, 4, 1 },
{ aic7xxx_patch7_func, 43, 3, 2 },
{ aic7xxx_patch0_func, 46, 3, 1 },
{ aic7xxx_patch8_func, 52, 7, 1 },
{ aic7xxx_patch3_func, 60, 3, 1 },
{ aic7xxx_patch7_func, 63, 2, 1 },
{ aic7xxx_patch7_func, 102, 1, 2 },
{ aic7xxx_patch0_func, 103, 2, 1 },
{ aic7xxx_patch7_func, 107, 2, 1 },
{ aic7xxx_patch9_func, 109, 1, 1 },
{ aic7xxx_patch10_func, 110, 2, 1 },
{ aic7xxx_patch7_func, 113, 1, 2 },
{ aic7xxx_patch0_func, 114, 1, 1 },
{ aic7xxx_patch1_func, 118, 1, 1 },
{ aic7xxx_patch1_func, 121, 3, 3 },
{ aic7xxx_patch11_func, 123, 1, 1 },
{ aic7xxx_patch0_func, 124, 5, 1 },
{ aic7xxx_patch7_func, 132, 1, 1 },
{ aic7xxx_patch9_func, 133, 1, 1 },
{ aic7xxx_patch10_func, 134, 3, 1 },
{ aic7xxx_patch7_func, 137, 3, 2 },
{ aic7xxx_patch0_func, 140, 2, 1 },
{ aic7xxx_patch7_func, 142, 5, 2 },
{ aic7xxx_patch0_func, 147, 3, 1 },
{ aic7xxx_patch7_func, 150, 1, 2 },
{ aic7xxx_patch0_func, 151, 2, 1 },
{ aic7xxx_patch1_func, 153, 15, 4 },
{ aic7xxx_patch11_func, 166, 1, 2 },
{ aic7xxx_patch0_func, 167, 1, 1 },
{ aic7xxx_patch0_func, 168, 10, 1 },
{ aic7xxx_patch7_func, 181, 1, 2 },
{ aic7xxx_patch0_func, 182, 2, 1 },
{ aic7xxx_patch7_func, 184, 18, 1 },
{ aic7xxx_patch1_func, 202, 3, 3 },
{ aic7xxx_patch7_func, 204, 1, 1 },
{ aic7xxx_patch0_func, 205, 4, 1 },
{ aic7xxx_patch7_func, 210, 2, 1 },
{ aic7xxx_patch7_func, 215, 13, 3 },
{ aic7xxx_patch12_func, 218, 1, 1 },
{ aic7xxx_patch12_func, 219, 4, 1 },
{ aic7xxx_patch1_func, 229, 3, 3 },
{ aic7xxx_patch11_func, 231, 1, 1 },
{ aic7xxx_patch0_func, 232, 5, 1 },
{ aic7xxx_patch11_func, 237, 1, 2 },
{ aic7xxx_patch0_func, 238, 9, 1 },
{ aic7xxx_patch13_func, 254, 1, 2 },
{ aic7xxx_patch0_func, 255, 1, 1 },
{ aic7xxx_patch4_func, 316, 1, 2 },
{ aic7xxx_patch0_func, 317, 1, 1 },
{ aic7xxx_patch2_func, 320, 1, 1 },
{ aic7xxx_patch1_func, 330, 3, 2 },
{ aic7xxx_patch0_func, 333, 5, 1 },
{ aic7xxx_patch13_func, 341, 1, 2 },
{ aic7xxx_patch0_func, 342, 1, 1 },
{ aic7xxx_patch5_func, 347, 1, 1 },
{ aic7xxx_patch11_func, 389, 15, 2 },
{ aic7xxx_patch14_func, 402, 1, 1 },
{ aic7xxx_patch1_func, 441, 7, 2 },
{ aic7xxx_patch0_func, 448, 8, 1 },
{ aic7xxx_patch1_func, 457, 4, 2 },
{ aic7xxx_patch0_func, 461, 6, 1 },
{ aic7xxx_patch1_func, 467, 4, 2 },
{ aic7xxx_patch0_func, 471, 3, 1 },
{ aic7xxx_patch10_func, 481, 10, 1 },
{ aic7xxx_patch1_func, 500, 22, 5 },
{ aic7xxx_patch11_func, 508, 4, 1 },
{ aic7xxx_patch7_func, 512, 7, 3 },
{ aic7xxx_patch15_func, 512, 5, 2 },
{ aic7xxx_patch0_func, 517, 2, 1 },
{ aic7xxx_patch10_func, 522, 50, 3 },
{ aic7xxx_patch14_func, 543, 17, 2 },
{ aic7xxx_patch0_func, 560, 4, 1 },
{ aic7xxx_patch10_func, 572, 4, 1 },
{ aic7xxx_patch5_func, 576, 2, 1 },
{ aic7xxx_patch5_func, 579, 9, 1 },
};
/* Messages (1 byte) */ /* I/T (M)andatory or (O)ptional */
#define MSG_CMDCOMPLETE 0x00 /* M/M */
#define MSG_EXTENDED 0x01 /* O/O */
#define MSG_SAVEDATAPOINTER 0x02 /* O/O */
#define MSG_RESTOREPOINTERS 0x03 /* O/O */
#define MSG_DISCONNECT 0x04 /* O/O */
#define MSG_INITIATOR_DET_ERR 0x05 /* M/M */
#define MSG_ABORT 0x06 /* O/M */
#define MSG_MESSAGE_REJECT 0x07 /* M/M */
#define MSG_NOOP 0x08 /* M/M */
#define MSG_PARITY_ERROR 0x09 /* M/M */
#define MSG_LINK_CMD_COMPLETE 0x0a /* O/O */
#define MSG_LINK_CMD_COMPLETEF 0x0b /* O/O */
#define MSG_BUS_DEV_RESET 0x0c /* O/M */
#define MSG_ABORT_TAG 0x0d /* O/O */
#define MSG_CLEAR_QUEUE 0x0e /* O/O */
#define MSG_INIT_RECOVERY 0x0f /* O/O */
#define MSG_REL_RECOVERY 0x10 /* O/O */
#define MSG_TERM_IO_PROC 0x11 /* O/O */
/* Messages (2 byte) */
#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */
#define MSG_HEAD_OF_Q_TAG 0x21 /* O/O */
#define MSG_ORDERED_Q_TAG 0x22 /* O/O */
#define MSG_IGN_WIDE_RESIDUE 0x23 /* O/O */
/* Identify message */ /* M/M */
#define MSG_IDENTIFYFLAG 0x80
#define MSG_IDENTIFY_DISCFLAG 0x40
#define MSG_IDENTIFY(lun, disc) (((disc) ? 0xc0 : MSG_IDENTIFYFLAG) | (lun))
#define MSG_ISIDENTIFY(m) ((m) & MSG_IDENTIFYFLAG)
/* Extended messages (opcode and length) */
#define MSG_EXT_SDTR 0x01
#define MSG_EXT_SDTR_LEN 0x03
#define MSG_EXT_WDTR 0x03
#define MSG_EXT_WDTR_LEN 0x02
#define MSG_EXT_WDTR_BUS_8_BIT 0x00
#define MSG_EXT_WDTR_BUS_16_BIT 0x01
#define MSG_EXT_WDTR_BUS_32_BIT 0x02
#define MSG_EXT_PPR 0x04
#define MSG_EXT_PPR_LEN 0x06
#define MSG_EXT_PPR_OPTION_ST 0x00
#define MSG_EXT_PPR_OPTION_DT_CRC 0x02
#define MSG_EXT_PPR_OPTION_DT_UNITS 0x03
#define MSG_EXT_PPR_OPTION_DT_CRC_QUICK 0x04
#define MSG_EXT_PPR_OPTION_DT_UNITS_QUICK 0x05
/*
* Instruction formats for the sequencer program downloaded to
* Aic7xxx SCSI host adapters
*
* Copyright (c) 1997, 1998 Justin T. Gibbs.
* All rights reserved.
*
* 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. 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 General 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.
*
* $Id: sequencer.h,v 1.3 1997/09/27 19:37:31 gibbs Exp $
*/
#ifdef __LITTLE_ENDIAN_BITFIELD
struct ins_format1 {
unsigned int
immediate : 8,
source : 9,
destination : 9,
ret : 1,
opcode : 4,
parity : 1;
};
struct ins_format2 {
unsigned int
shift_control : 8,
source : 9,
destination : 9,
ret : 1,
opcode : 4,
parity : 1;
};
struct ins_format3 {
unsigned int
immediate : 8,
source : 9,
address : 10,
opcode : 4,
parity : 1;
};
#elif defined(__BIG_ENDIAN_BITFIELD)
struct ins_format1 {
unsigned int
parity : 1,
opcode : 4,
ret : 1,
destination : 9,
source : 9,
immediate : 8;
};
struct ins_format2 {
unsigned int
parity : 1,
opcode : 4,
ret : 1,
destination : 9,
source : 9,
shift_control : 8;
};
struct ins_format3 {
unsigned int
parity : 1,
opcode : 4,
address : 10,
source : 9,
immediate : 8;
};
#endif
union ins_formats {
struct ins_format1 format1;
struct ins_format2 format2;
struct ins_format3 format3;
unsigned char bytes[4];
unsigned int integer;
};
struct instruction {
union ins_formats format;
unsigned int srcline;
struct symbol *patch_label;
struct {
struct instruction *stqe_next;
} links;
};
#define AIC_OP_OR 0x0
#define AIC_OP_AND 0x1
#define AIC_OP_XOR 0x2
#define AIC_OP_ADD 0x3
#define AIC_OP_ADC 0x4
#define AIC_OP_ROL 0x5
#define AIC_OP_BMOV 0x6
#define AIC_OP_JMP 0x8
#define AIC_OP_JC 0x9
#define AIC_OP_JNC 0xa
#define AIC_OP_CALL 0xb
#define AIC_OP_JNE 0xc
#define AIC_OP_JNZ 0xd
#define AIC_OP_JE 0xe
#define AIC_OP_JZ 0xf
/* Pseudo Ops */
#define AIC_OP_SHL 0x10
#define AIC_OP_SHR 0x20
#define AIC_OP_ROR 0x30
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment