Commit Graph

256 Commits

Author SHA1 Message Date
dfr
dd8b44b395 * Completely rewrite the alpha busspace to hide the implementation from
the drivers.
* Remove legacy inx/outx support from chipset and replace with macros
  which call busspace.
* Rework pci config accesses to route through the pcib device instead of
  calling a MD function directly.

With these changes it is possible to cleanly support machines which have
more than one independantly numbered PCI busses. As a bonus, the new
busspace implementation should be measurably faster than the old one.
2000-08-28 21:48:13 +00:00
mjacob
e311b703ab remove clause 3 licence 2000-08-27 23:39:23 +00:00
mjacob
bcbec50333 various fixes 2000-08-27 23:38:44 +00:00
mjacob
8d241d25cf Add a comment as to where stdarg.h applies. 2000-08-03 03:05:50 +00:00
jhb
db236d95a5 Use <machine/stdarg.h> instead of <stdarg.h> so that this will compile.
While I'm at it, move the #include line up to the top of the file.
2000-08-03 02:47:06 +00:00
mjacob
c0c2363472 Add in macros && masks so that mailbox command errors can be
selectively printed/supressed in isp_mboxcmd.
2000-08-01 06:55:08 +00:00
mjacob
8836b07cf6 Major whacking for core version 2.0. A major motivator for 2.0 and these
changes is that there's now a Solaris port of this driver, so some things
in the core version had to change (not much, but some).

In order, from the top.....:

A lot of error strings are gathered in one place at the head of the file.
This caused me to rewrite them to look consistent (with respect to
things like 'Port 0x%' and 'Target %d' and 'Loop ID 0x%x'.

The major mailbox function, isp_mboxcmd, now takes a third argument,
which is a mask that selectively says whether mailbox command failures
will be logged. This will substantially reduce a lot of spurious noise
from the driver.

At the first run through isp_reset we used to try and get the current
running firmware's revision by issuing a mailbox command. This would
invariably fail on alpha's with anything but a Qlogic 1040 since SRM
doesn't *start* the f/w on these cards. Instead, we now see whether we're
sitting ROM state before trying to get a running BIOS loaded f/w version.

All CFGPRINTF/PRINTF/IDPRINTF macros have been replaced with calls to
isp_prt. There are seperate print levels that can be independently
set (see ispvar.h), which include debugging, etc.

All SYS_DELAY macros are now USEC_DELAY macros. RQUEST_QUEUE_LEN and
RESULT_QUEUE_LEN now take ispsoftc as a parameter- the Fibre Channel
cards and the Ultra2/Ultra3 cards can have 16 bit request queue entry
indices, so we can make a 1024 entry index for them instead of the
256 entries we've had until now.

A major change it to fix isp_fclink_test to actually only wait the
delay of time specified in the microsecond argument being passed.
The problem has always been that a call to isp_mboxcmd to get he
current firmware state takes an unknown (sometimes long) amount of
time- this is if the firmware is busy doing PLOGIs while we ask
it what's up. So, up until now, the usdelay argument has been
a joke. The net effect has been that if you boot without being plugged
into a good loop or into a switch, you hang. Massively annonying, and
hard to fix because the actual time delta was impossible to know
from just guessing. Now, using the new GET_NANOTIME macros, a precise
and measured amount of USEC_DELAY calls are done so that only the
specified usecdelay is allowed to pass. This means that if the initial
startup of the firmware if followed by a call from isp_freebsd.c:isp_attach
to isp_control(isp, ISP_FCLINK_TEST, &tdelay) where tdelay is 2 * 1000000,
no more than two seconds will actually elapse before we leave concluding
that the cable is unhooked. Jeez. About time....

Change the ispscsicmd entry point to isp_start, and the XS_CMD_DONE
macro to a call to the platform supplied isp_done (sane naming).

Limit our size of request queue completions we'll look at at interrupt
time. Since we've increased the size of the Request Queue (and the
size of the Response Queue proportionally), let's not create an
interrupt stack overflow by having to keep a max completion list
(forw links are not an option because this is common code with
some platforms that don't have link space in their XS_T structures).
A limit of 32 is not unreasonable- I doubt there'd be even this many
request queue completions at a time- remember, most boards now use
fast posting for normal command completion instead of filling out
response queue entries.

In the isp_mboxcmd cleanup, also create an array of command
names so that "ABOUT FIRMWARE" can be printed instead of "CMD #8".

Remove the isp_lostcmd function- it's been deprecated for a while.
Remove isp_dumpregs- the ISP_DUMPREGS goes to the specific bus
register dump fucntion.

Various other cleanups.
2000-08-01 06:51:05 +00:00
mjacob
7bbd9bfadc Core version 2.0 rewrite. In this file we replace isp_tdebug with
isp_prt calls. We now use an argument to the  ISPCTL_FCLINK_TEST
call. We change all IDPRINTF macros to isp_prt calls. We add
the isp_prt function here.
2000-08-01 06:31:44 +00:00
mjacob
1da31893fa Core version 2.0 cleanup/rewrite. Things get rearranged and changed
quite a bit so that all of the ports have a similar set of required
macros/definitions (and in similar places in the isp_<platform>.h
file).

Some new macros/functions added- Mailbox Acquire/Relase macros,
NANOTIME macros, SNPRINTf and STRNCAT. MemoryBarrier beomes
MEMORYBARRIER with much stronger types.
2000-08-01 06:29:55 +00:00
mjacob
90bc592459 Remove isp_prtstst (now in case statement in isp.c). Remove
isp2100_fw_statename as an INLINE (now a function in isp.c). Remove
isp2100_pdb_statename (unused). Redo all ISP_SCSI_XFER_T as XS_T types.
Change all RQUEST_QUEUE_LEN/RESULT_QUEUE_LEN macros to take a parameter.
Add isp_print_bytes function.
2000-08-01 06:26:04 +00:00
mjacob
4900d339a1 Remove isp_tdebug. Change all PRINTF macros to the now common
isp_prt logging function.
2000-08-01 06:24:01 +00:00
mjacob
6bac7972dd Fix typo. Remove isp_tdebug (we'll use ISP_LOGTDEBUG2 in isp->isp_dblev
as a selector now). Change DFLT_CMD_CNT to a fixed amount for now.
2000-08-01 06:23:24 +00:00
mjacob
ae6e6fedab Add in lengths of SBus or PCI registers. 2000-08-01 06:21:21 +00:00
mjacob
add29bbf34 Rewrite for version 2.0. Some structural changes, but also
a substantial amount of commenting about what each platform
specific definitions are supposed to be.
2000-08-01 06:10:21 +00:00
mjacob
4c7c897ac9 Part of major rewrite for core version 2.0- clarification of
mdvec structure, removal of printf/CFGPRINTF in place of isp_prt
calls. Parameterization of RQUEST_QUEUE_LEN/RESULT_QUEUE_LEN.
2000-08-01 05:16:49 +00:00
mjacob
82d6e5cbbc Add in some new IN_XXX and CT_XXXX flags in preparation
for the rototilling that !*$)~@!$_@*_(~@$*_(~@$*~@$*
Qlogic F/W changes will need.
2000-07-18 07:06:47 +00:00
mjacob
f308f1cc83 If debugging set, zero out an incoming response entry
when we're done reading it (makes checking things easier).
Before calling isp_notify_ack make sure we're at RUNSTATE-
elsewise we can be responding to LIPs or SCSI bus resets
before we've finished some of the wiring.
2000-07-18 07:05:37 +00:00
mjacob
5e02cc3eb2 The SERVICING_INTERRUPT isn't quite safe yet. 2000-07-18 07:04:07 +00:00
mjacob
f1fdd1ae53 Add a isp_target_putback_atio- we aren't using CCINCR at this time, so
we need a function that tells the Qlogic f/w that a target mode command
is done, so increase the resource count for that lun. Add in a timeout
function to kick the putback again if we fail to do it the first time (we
may not have the request queue space for ATIO push). Split the function
isp_handle_platform_ctio into two parts so that the timeout function for
the ATIO push or isp_handle_platform_ctio can inform CAM that the requested
CTIO(s) are now done.

Clean up (cough) residual handling. What we need for Fibre Channel
is to preserve the at_datalen field from the original incoming ATIO
so we can calculate a 'true' residual.  Unfortunately, we're not
guaranteed to get that back from CAM. We'll *try* to find it hiding
in the periph_priv field (layering violation)- but if an ATIO was
passed in from user land- forget it. This means that we'll probably
get residuals wrong for Fibre Channel commands we're completing
with an error. It's too late to 4.1 release to fix this- too bad.
Luckily the only device we'd really care about this occurring on
is a tape device and they're still so rare as FC attached devices
that this can be considered an untested combination anyway.

Remove all CCINCR usage (resource autoreplenish). When we've proved
to ourself that things are working properly, we can add it back
in.

Make sure we propage 'suggested' sense data from the incoming ATIO
into the created system ATIO- and set sense_len appropriately.
Correctly propagate tag values.

Fall back to the model of generating (well, the functions in isp_pci.c
do the work) multiple CTIOs based upon what we get from XPT. Instead
of being able to pair Qlogic generated ATIOs with CAM ATIOs, and then
to pair CAM CTIOs with Qlogic CTIOs, we have to take the CTIO passed
to us from XPT, and if it implies that we have to generate extra
Qlogic CTIOs, so be it. This means that we have to wait until the
last CTIO in a sequence we generated completes before calling xpt_done.

Executive summary- target mode actually now pretty much works well
enough to tell folks about.
2000-07-18 06:58:28 +00:00
mjacob
70eb60cccd Raise debug level for some messages. Fix botched inversion
about MBOX_COMMAND_ERROR vs. MBOX_COMMAND_PARAM_ERROR.
2000-07-18 06:46:48 +00:00
mjacob
e93f62fa29 Keep interrupts blocked for all of isp_pci_attach. Redo DMA routines
for target mode for cleanliness and accuracy.
2000-07-18 06:40:22 +00:00
mjacob
e51ae31c23 Oops! If we're deciding a command is now really dead, make *darned*
sure that it really is by issuing a ISPCTL_ABORT_CMD just on the
off chance the f/w will start it up again and, ha ha, start using
the DMA resources we gave it but are now taking away.
2000-07-05 06:44:17 +00:00
mjacob
ff88d7319b Clean up ISPCTL_ABORT_CMD function to not be too chatty if it succeeds,
or even if it fails with INVALID_PARM (which just means that the handle
doesn't refer to an active commane).
2000-07-05 06:41:36 +00:00
mjacob
fb6b05afaa Remove obsolete isp_dogactive tag. 2000-07-04 01:06:42 +00:00
mjacob
8df34aede7 Fix completely stupid and idiotiuc sprintfs in isp_inline.h with
with the STRNCAT function.
2000-07-04 01:06:23 +00:00
mjacob
e0a8dae616 Add in config_hook for catching when interrupts are safe- this allows
us to not the ints are ok and also to (re)ENABLE isp interrupts. Remove
all splcam()/splx() invocates and replace them with ISP_LOCK/ISP_UNLOCK
macros.
2000-07-04 01:05:43 +00:00
mjacob
22ee60424c Add in isp_lock/isp_unlock inlines. Add in an islocked/intsok flag
to isp_osinfo substructure (all in prep for SMP). Define MBOX_WAIT_COMPLETE
and MBOX_NOTIFY_COMPLETE macros so that we can now (temp) use tsleep
to wait for mailbox completion. Requires us to guess whether we're
servicing an interrupt or not- will use intr_nesting_level.

Add local strncat function.
2000-07-04 01:04:35 +00:00
mjacob
6d0b729414 Change delay loop in new isp_mboxcmd to the use of the new MBOX_WAIT_COMPLETE
macro. Change notification of completion of a mailbox command in isp_intr
to MBOX_NOTIFY_COMPLETE macro.
2000-07-04 01:02:38 +00:00
mjacob
9d667c3b82 Change startup locking. Use new isp_handle_index function
for indexing off of handles to get dma maps.
2000-07-04 01:01:15 +00:00
mjacob
e4ec9bc987 Fix usage of DELAY (SYS_DELAY is the platform independent local
define).  Fix stupidity wrt checking whether we've gone to
LOOP_PDB_RCVD loopstate- it's okay to be greater than this state.
D'oh! Protect calls to isp_pdb_sync and isp_fclink_state with IS_FC
macros.

Completely redo mailbox command routine (in preparation to make this
possibly wait rather than poll for completion).

Make a major attempt to solve the 'lost interrupt' problem

1. Problem

The Qlogic cards would appear to 'lose' interrupts, i.e., a legitimate
regular SCSI command placed on the request queue would never complete
and the watchdog routine in the driver would eventually wakeup and
catch it. This would typically only happen on Alphas, although a
couple folks with 700MHz Intel platforms have also seen this.

For a long time I thought it was a foulup with f/w negotiations of
SYNC and/or WIDE as it always seemed to happen right after the
platform it was running on had done a SET TARGET PARAMETERS mailbox
command to (re)enable sync && wide (after initially forcing
ASYNC/NARROW at startup). However, occasionally, the same thing
would also occur for the Fibre Channel cards as well (which, ahem,
have no SET TARGET PARAMETERS for transfer mode).

After finally putting in a better set of watchdog routines for the
platforms for this driver, it seemed to be the case that the command
in question (usually a READ CAPACITY) just had up and died- the
watchdog routine would catch it after ~10 seconds. For some platforms
(NetBSD/OpenBSD)- an ABORT COMMAND mailbox command was sent (which
would always fail- indicating that the f/w denied knowledge of this
command, i.e., the f/w thought it was a done command). In any case,
retrying the command worked. But this whole problem needed to be
really fixed.

2. A False Step That Went in The Right Direction

The mailbox code was completely rewritten to no longer try and grab
the mailbox semaphore register and to try and 'by hand' complete
async fast posting completions. It was also rewritten to now have
separate in && out bitpatterns for registers to load to start and
retrieve to complete. This means that isp_intr now handles mailbox
completions.

This substantially simplifies the mailbox handling code, and carries
things 90% toward getting this to be a non-polled routine for this
driver.

This did not solve the problem, though.

3. Register Debouncing

I saw some comments in some errata sheets and some notes in a Qlogic
produced Linux driver (for the Qlogic 2100) that seemed to indicate
that debouncing of reads of the mailbox registers might be needed,
so I added this.  This did not affect the problem. In fact, it made
the problem worse for non-2100 cards.

5. Interrupt masking/unmasking

The driver *used* to do a substantial amount of masking/unmasking
of the interrupt control register. This was done to make sure that
the core common code could just assume it would never get pre-empted.

This apparently substantially contributed to the lost interrupt
problem.  The rewrite of the ICR (Interrupt Control Register),
which is a separate register from the ISR (Interrupt Status Register)
should not have caused any change to interrupt assertions pending.
The manual does not state that it will, and the register layout
seems to imply that the ICR is just an active route gate. We only
enable PCI Interrupts and RISC Interrupts- this should mean that
when the f/w asserts a RISC interrupt and (and the ICR allows RISC
Interrupts) and we have PCI Interrupts enabled, we should get a
PCI interrupt. Apparently this is a latch- not a signal route.

Removing this got rid of *most* but not all, lost interrupts.

5. Watchdog Smartening

I made sure that the watchdog routine would catch cases where the
Qlogic's ISR showed an interrupt assertion. The watchdog routine
now calls the interrupt service routine if it sees this. Some
additional internal state flags were added so that the watchdog
routine could then know whether the command it was in the middle
of burying (because we had time it out) was in fact completed by
the interrupt service routine.

6. Occasional Constipation Of Commands..

In running some very strenous high IOPs tests (generating about
11000 interrupts/second across one Qlogic 1040, one Qlogic 1080
and one Qlogic 2200 on an Alpha PC164), I found that I would get
occasional but regular 'watchdog timeouts' on both the 1080 and
the 2100 cards. This is under FreeBSD, and the watchdog timeout
routine just marks the command in error and retries it.

Invariably, right after this 'watchdog timeout' error, I'd get a
command completion for the command that I had thought timed out.
That is, I'd get a command completion, but the handle returned by
the firmware mapped to no current command. The frequency of this
problem is low under such a load- it would usually take an 30
minutes per 'lost' interrupt.

I doubled the timeout for commands to see if it just was an edge
case of waiting too short a period. This has no effect.

I gathered and printed out microtimes for the watchdog completed
command and the completion that couldn't find a command- it was
always the case that the order of occurrence was "timeout, completion"
separated by a time on the order of 100 to 150 ms.

This caused me to consider 'firmware constipation' as to be a
possible culprit. That is, resubmission of a command to the device
that had suffered a watchdog timeout seemed to cause the presumed
dead command to show back up.

I added code in the watchdog routine that, when first entered for
the command, marks the command with a flag, reissues a local timeout
call for one second later, but also then issues a MARKER Request
Queue entry to the Qlogic f/w. A MARKER entry is used typically
after a Bus Reset to cause the f/w to get synchronized with respect
to either a Bus, a Nexus or a Target.

Since I've added this code, I always now see the occasional watchdog
timeout, but the command that was about to be terminated always
now seems to be completed after the MARKER entry is issued (and
before the timeout extension fires, which would come back and
*really* terminate the command).
2000-06-27 19:44:31 +00:00
mjacob
9ac6bffe81 Add in the enabling of interrupts (to isp_attach). Clean up a busted
comment. Check against firmware state- not loop state when enabling
target mode. Other changes have to do with no longer enabling/disabling
interrupts at will.

Rearchitect command watchdog timeouts-

First of all, set the timeout period for a command that has a
timeout (in isp_action) to the period of time requested *plus* two
seconds. We don't want the Qlogic firmware and the host system to
race each other to report a dead command (the watchdog is there to
catch dead and/or broken firmware).

Next, make sure that the command being watched isn't done yet. If
it's not done yet, check for INT_PENDING and call isp_intr- if that
said it serviced an interrupt, check to see whether the command is
now done (this is what the "IN WATCHDOG" private flag is for- if
isp_intr completes the command, it won't call xpt_done on it because
isp_watchdog is still looking at the command).

If no interrupt was pending, or the command wasn't completed, check
to see if we've set the private 'grace period' flag. If so, the
command really *is* dead, so report it as dead and complete it with
a CAM_CMD_TIMEOUT value.

If the grace period flag wasn't set, set it and issue a SYNCHRONIZE_ALL
Marker Request Queue entry and re-set the timeout for one second
from now (see Revision 1.45 isp.c notes for more on this) to give
the firmware a final chance to complete this command.
2000-06-27 19:31:02 +00:00
mjacob
c32e4a88bf Clean up private storage so that we can use the spriv_field0 to
store a bitmask of whether we've set a value into ccb->ccb_h.status,
whether we're in the watchdog routine for this command now, whether
we've set a grace period for this command and whether this command is
actually done.

See comments of rev 1.45 of isp.c for more complete information.
2000-06-27 19:22:13 +00:00
mjacob
51596cce55 Add 8 bits of volatile mailbox busy mask- this will be the bitmask of
output mailbox values we want to get back out of the chip once a mailbox
command is done. Add storage for the maximum number of output mailbox
registers to the softc.

Roll minor version number.
2000-06-27 19:17:39 +00:00
mjacob
c3ccd76815 Add mailbox bitmask macros (numbers of available mailbox registers
based upon Qlogic chip type). Define maximum mailboxes. Add INT_PENDING_MASK
macro. Change mailbox offset macro name.
2000-06-27 19:15:43 +00:00
mjacob
4252a0e093 Add an isp_handle_index function- this is prepatory to loading more into
the handle (i.e., generation number), so we will now need a function that
will take a handle and return a flat index [ 0 .. maxhandles-1 ] for
auxillary routines that need an index to get at buddy store values
(like dma maps or xflist pointers).
2000-06-27 19:14:14 +00:00
mjacob
a66fa325f8 Clean up firmware load issues and remove darn near all config options.
Force alphas to prefer mem mapping as the default.

Basically, we have a pointer to a function which we can call which will
return us a pointer to firmware for the card we have. We call this function
(if it's non-NULL) with the address of our mdvec f/w pointer.

The way this works is that if ispfw (as a module or a static) is loaded,
it initializes the pointer in isp_pci, so we can call into to it to fetch
a pointer to a f/w set.

If ispfw is MOD_UNLOADed, it's retained a pointer to our mdvec f/w pointers,
which then get zeroed out so we don't have any references to data that's
now gone from kernel memory. Removing the f/w saves ~360KBytes.

Alas, there is no autounload mechanism that works for is here.
2000-06-18 05:18:55 +00:00
mjacob
3500325606 Removing this bulky one large f/w file. This f/w is now in dev/ispfw. 2000-06-18 04:59:47 +00:00
mjacob
9f105f7325 Once we have firmware running (if isp_reset) and this is the first time
through, establish what our LUN width is. Unfortunately, we can't ask
the f/w. If we loaded the f/w, we'll now assume we have expanded LUNs
(SCCLUN for fibre channel, just plain 32 LUN for SCSI). If we didn't
load firmware, assume 8 LUNs for SCSI and 1 LUN for Fibre Channel. We
have to assume only one LUN for Fibre Channel because the LUN setting
in Request Queue entries is in different places whether we have SCCLUN
firmware or not, so the only LUN guaranteed to work for both is LUN 0.

Clean up the rest of isp.c so that ISP2100_SCCLUN defines aren't used-
instead use run time determinants based upon isp->isp_maxluns.

After starting firmware, delay 500us to give it a chance to get rolling.

Fix the interrupt service routine to check for both isr && sema being zero
before thinking this was a spurious interrupt.  Following the manuals,
allow for both Mailbox as well as Queue Reponse type interrupts for regular
SCSI.
2000-06-18 04:56:17 +00:00
mjacob
7376e4df8d Remove all ISP2100_SCCLUN define protected code and replace it with
runtime checks.
2000-06-18 04:50:26 +00:00
mjacob
5d92bae67f Remove all ISP2100_SCCLUN define based code and replace it with runtime
comparisons against the tag isp_maxluns- if > 16, we're SCCLUN based.

On initial regular SCSI startup, disable auto-disconnect.
2000-06-18 04:48:28 +00:00
mjacob
51579ee9d2 Roll platform minor number. Force definition of SCSI_ISP_FABRIC
(we always support fabric now). Remove SCCLUN definition (we always
support SCCLUN now, if we load the f/w). Add typedef definition of an
external firmware fetch function.
2000-06-18 04:47:12 +00:00
mjacob
0e546ae817 Roll core minor version. Set ISP_MAX_LUNS to be off of new isp_maxluns
tag in softc.
2000-06-18 04:45:51 +00:00
mjacob
9dcc007b30 add "disable autodisconnect" flags 2000-06-18 04:44:41 +00:00
mjacob
8f069362f7 cleanup i_int_X vs. uint_X definitions 2000-06-18 04:43:55 +00:00
mjacob
4fc4ea58bf add MBOX_GET_RESOURCE_COUNT command 2000-06-18 04:41:14 +00:00
mjacob
933a6392ca Fix breakage to target mode support.
What we'd like to know is whether or not we have a listener
upstream that really hasn't configured yet. If we do, then
we can give a more sensible reply here. If not, then we can
reject this out of hand.

Choices for what to send were
	Not Ready, Unit Not Self-Configured Yet
	(0x2,0x3e,0x00)
for the former and
	Illegal Request, Logical Unit Not Supported
	(0x5,0x25,0x00)
for the latter.

We used to decide whether there was at least one listener
based upon whether the black hole driver was configured.

However, recent config(8) changes have made this hard to do
at this time.

Actually, we didn't use the above quite yet, but were sure considering it.
2000-06-12 23:08:31 +00:00
mjacob
b379981090 Fix some breakage about how we build WWNs. Do some other fabric related
changes: consider a new PDB entry different if Class 3 service parameter
roles change (!!!). Do some checking as we're getting a port database
that traps whether things change while we're doing so. Handle N-port
and F-ports correctly. Fix the fabric login loop to retain a login/binding
if things haven't changed (I mean, why logout a device only to log it back
in). No longer accept, after fabric logins, garbage if we can't get a PDB
entry that matches the device we've just logged into- if it doesn't, log
it out as it is very unlikely to still be what we thought it was. Get rid
of some of the debounce loops because we could get stuck there.
2000-05-09 01:14:43 +00:00
mjacob
23202c02a2 roll platform minor 2000-05-09 01:09:46 +00:00
mjacob
97b930e597 Roll core minor version. Change our 'fabdev' tag to 'loggedin'. 2000-05-09 01:09:23 +00:00
mjacob
60a26a691a Add in a watchdog routine to catch cases where we've dropped the command.
Apparently the f/w has finished the command, but somehow an interrupt is
being lost. So, we just plain wedge when booting alphas.

This is a general routine we've needed for a while.
2000-05-09 01:08:21 +00:00